From d841ef46220f1bae3076f58c785749c99319e19a Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 21 Aug 2024 00:57:46 +0000 Subject: [PATCH] Parameterize the `OnionMessageContents` in message handler traits Our onion message handlers generally have one or more methods which return either a `ResponseInstruction` or a `PendingOnionMessage` parameterized with the expected message type (enum) of the message handler. This is generally fine, there's not much reason for a message handler of one type to return a response of a different type, but there's also not much reason to restrict it from doing so, either. Sadly, that restriction is also impossible to represent in our bindings - our bindings concretize all structs, enums, and traits into a single concrete instance with generics set to our concrete trait instances (which hold a jump table). This prevents us from having multiple instances of `ResponseInstruction` or `PendingOnionMessage` structs for different message types. Instead, we simply add an associated type to our onion message handlers, allowing them to return any type they want (or for the bindings to make them dynamic on the internal jump table but static at compile-time). --- lightning/src/ln/channelmanager.rs | 6 +++++- lightning/src/ln/peer_handler.rs | 6 ++++-- lightning/src/onion_message/async_payments.rs | 8 ++++++-- lightning/src/onion_message/functional_tests.rs | 6 ++++-- lightning/src/onion_message/offers.rs | 8 ++++++-- 5 files changed, 25 insertions(+), 9 deletions(-) diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 167ab0ac8fd..50a795a7dfd 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -10747,6 +10747,8 @@ where R::Target: Router, L::Target: Logger, { + type ResponseType = OffersMessage; + fn handle_message( &self, message: OffersMessage, context: Option, responder: Option, ) -> ResponseInstruction { @@ -10954,9 +10956,11 @@ where R::Target: Router, L::Target: Logger, { + type ResponseType = AsyncPaymentsMessage; + fn held_htlc_available( &self, _message: HeldHtlcAvailable, _responder: Option - ) -> ResponseInstruction { + ) -> ResponseInstruction { ResponseInstruction::NoResponse } diff --git a/lightning/src/ln/peer_handler.rs b/lightning/src/ln/peer_handler.rs index 6b03b365457..06d02d342c4 100644 --- a/lightning/src/ln/peer_handler.rs +++ b/lightning/src/ln/peer_handler.rs @@ -29,7 +29,7 @@ use crate::util::ser::{VecWriter, Writeable, Writer}; use crate::ln::peer_channel_encryptor::{PeerChannelEncryptor, NextNoiseStep, MessageBuf, MSG_BUF_ALLOC_SIZE}; use crate::ln::wire; use crate::ln::wire::{Encode, Type}; -use crate::onion_message::async_payments::{AsyncPaymentsMessageHandler, HeldHtlcAvailable, ReleaseHeldHtlc}; +use crate::onion_message::async_payments::{AsyncPaymentsMessage, AsyncPaymentsMessageHandler, HeldHtlcAvailable, ReleaseHeldHtlc}; use crate::onion_message::messenger::{CustomOnionMessageHandler, PendingOnionMessage, Responder, ResponseInstruction}; use crate::onion_message::offers::{OffersMessage, OffersMessageHandler}; use crate::onion_message::packet::OnionMessageContents; @@ -144,14 +144,16 @@ impl OnionMessageHandler for IgnoringMessageHandler { } impl OffersMessageHandler for IgnoringMessageHandler { + type ResponseType = OffersMessage; fn handle_message(&self, _message: OffersMessage, _context: Option, _responder: Option) -> ResponseInstruction { ResponseInstruction::NoResponse } } impl AsyncPaymentsMessageHandler for IgnoringMessageHandler { + type ResponseType = AsyncPaymentsMessage; fn held_htlc_available( &self, _message: HeldHtlcAvailable, _responder: Option, - ) -> ResponseInstruction { + ) -> ResponseInstruction { ResponseInstruction::NoResponse } fn release_held_htlc(&self, _message: ReleaseHeldHtlc) {} diff --git a/lightning/src/onion_message/async_payments.rs b/lightning/src/onion_message/async_payments.rs index 4a080101915..2eb4cfa2c6f 100644 --- a/lightning/src/onion_message/async_payments.rs +++ b/lightning/src/onion_message/async_payments.rs @@ -26,11 +26,15 @@ const RELEASE_HELD_HTLC_TLV_TYPE: u64 = 74; /// /// [`OnionMessage`]: crate::ln::msgs::OnionMessage pub trait AsyncPaymentsMessageHandler { + /// The message type for messages which are sent in response to [`Self::held_htlc_available`] + /// or sent via [`Self::release_pending_messages`]. + type ResponseType: OnionMessageContents; + /// Handle a [`HeldHtlcAvailable`] message. A [`ReleaseHeldHtlc`] should be returned to release /// the held funds. fn held_htlc_available( &self, message: HeldHtlcAvailable, responder: Option, - ) -> ResponseInstruction; + ) -> ResponseInstruction; /// Handle a [`ReleaseHeldHtlc`] message. If authentication of the message succeeds, an HTLC /// should be released to the corresponding payee. @@ -41,7 +45,7 @@ pub trait AsyncPaymentsMessageHandler { /// Typically, this is used for messages initiating an async payment flow rather than in response /// to another message. #[cfg(not(c_bindings))] - fn release_pending_messages(&self) -> Vec> { + fn release_pending_messages(&self) -> Vec> { vec![] } diff --git a/lightning/src/onion_message/functional_tests.rs b/lightning/src/onion_message/functional_tests.rs index 508e7982b40..6ec2f0deef2 100644 --- a/lightning/src/onion_message/functional_tests.rs +++ b/lightning/src/onion_message/functional_tests.rs @@ -19,7 +19,7 @@ use crate::routing::test_utils::{add_channel, add_or_update_node}; use crate::sign::{NodeSigner, Recipient}; use crate::util::ser::{FixedLengthReader, LengthReadable, Writeable, Writer}; use crate::util::test_utils; -use super::async_payments::{AsyncPaymentsMessageHandler, HeldHtlcAvailable, ReleaseHeldHtlc}; +use super::async_payments::{AsyncPaymentsMessage, AsyncPaymentsMessageHandler, HeldHtlcAvailable, ReleaseHeldHtlc}; use super::messenger::{CustomOnionMessageHandler, DefaultMessageRouter, Destination, OnionMessagePath, OnionMessenger, PendingOnionMessage, Responder, ResponseInstruction, SendError, SendSuccess}; use super::offers::{OffersMessage, OffersMessageHandler}; use super::packet::{OnionMessageContents, Packet}; @@ -76,6 +76,7 @@ impl Drop for MessengerNode { struct TestOffersMessageHandler {} impl OffersMessageHandler for TestOffersMessageHandler { + type ResponseType = OffersMessage; fn handle_message(&self, _message: OffersMessage, _context: Option, _responder: Option) -> ResponseInstruction { ResponseInstruction::NoResponse } @@ -84,9 +85,10 @@ impl OffersMessageHandler for TestOffersMessageHandler { struct TestAsyncPaymentsMessageHandler {} impl AsyncPaymentsMessageHandler for TestAsyncPaymentsMessageHandler { + type ResponseType = AsyncPaymentsMessage; fn held_htlc_available( &self, _message: HeldHtlcAvailable, _responder: Option, - ) -> ResponseInstruction { + ) -> ResponseInstruction { ResponseInstruction::NoResponse } fn release_held_htlc(&self, _message: ReleaseHeldHtlc) {} diff --git a/lightning/src/onion_message/offers.rs b/lightning/src/onion_message/offers.rs index 28f6d7d6fe7..a6e93bca1ea 100644 --- a/lightning/src/onion_message/offers.rs +++ b/lightning/src/onion_message/offers.rs @@ -39,6 +39,10 @@ const STATIC_INVOICE_TLV_TYPE: u64 = 70; /// /// [`OnionMessage`]: crate::ln::msgs::OnionMessage pub trait OffersMessageHandler { + /// The message type for messages which are sent in response to [`Self::handle_message`] or + /// sent via [`Self::release_pending_messages`]. + type ResponseType: OnionMessageContents; + /// Handles the given message by either responding with an [`Bolt12Invoice`], sending a payment, /// or replying with an error. /// @@ -47,14 +51,14 @@ pub trait OffersMessageHandler { /// [`OnionMessenger`]: crate::onion_message::messenger::OnionMessenger fn handle_message( &self, message: OffersMessage, context: Option, responder: Option, - ) -> ResponseInstruction; + ) -> ResponseInstruction; /// Releases any [`OffersMessage`]s that need to be sent. /// /// Typically, this is used for messages initiating a payment flow rather than in response to /// another message. The latter should use the return value of [`Self::handle_message`]. #[cfg(not(c_bindings))] - fn release_pending_messages(&self) -> Vec> { vec![] } + fn release_pending_messages(&self) -> Vec> { vec![] } /// Releases any [`OffersMessage`]s that need to be sent. ///