From 07e73c58ca95771ff709b901c83d4f15f8ee9387 Mon Sep 17 00:00:00 2001 From: shaavan Date: Fri, 25 Oct 2024 20:32:16 +0530 Subject: [PATCH] Introduce Custom Tlvs more message::ReceiveTlvs --- fuzz/src/chanmon_consistency.rs | 4 +- fuzz/src/full_stack.rs | 4 +- fuzz/src/onion_message.rs | 6 +- lightning/src/blinded_path/message.rs | 18 +++-- lightning/src/ln/channelmanager.rs | 8 +- lightning/src/ln/offers_tests.rs | 10 +-- lightning/src/ln/peer_handler.rs | 2 +- .../src/onion_message/functional_tests.rs | 34 ++++---- lightning/src/onion_message/messenger.rs | 77 ++++++++++--------- lightning/src/onion_message/offers.rs | 2 +- lightning/src/onion_message/packet.rs | 2 + lightning/src/util/test_utils.rs | 8 +- 12 files changed, 92 insertions(+), 83 deletions(-) diff --git a/fuzz/src/chanmon_consistency.rs b/fuzz/src/chanmon_consistency.rs index f897ba6e092..41c3ae2b4d8 100644 --- a/fuzz/src/chanmon_consistency.rs +++ b/fuzz/src/chanmon_consistency.rs @@ -142,8 +142,8 @@ impl MessageRouter for FuzzRouter { } fn create_blinded_paths( - &self, _recipient: PublicKey, _context: MessageContext, _peers: Vec, - _secp_ctx: &Secp256k1, + &self, _recipient: PublicKey, _context: MessageContext, _custom_tlvs: Vec, + _peers: Vec, _secp_ctx: &Secp256k1, ) -> Result, ()> { unreachable!() } diff --git a/fuzz/src/full_stack.rs b/fuzz/src/full_stack.rs index 59f1275a600..15f4d1486ae 100644 --- a/fuzz/src/full_stack.rs +++ b/fuzz/src/full_stack.rs @@ -177,8 +177,8 @@ impl MessageRouter for FuzzRouter { } fn create_blinded_paths( - &self, _recipient: PublicKey, _context: MessageContext, _peers: Vec, - _secp_ctx: &Secp256k1, + &self, _recipient: PublicKey, _context: MessageContext, _custom_tlvs: Vec, + _peers: Vec, _secp_ctx: &Secp256k1, ) -> Result, ()> { unreachable!() } diff --git a/fuzz/src/onion_message.rs b/fuzz/src/onion_message.rs index 09d1d9b6ba8..68fee9a42e4 100644 --- a/fuzz/src/onion_message.rs +++ b/fuzz/src/onion_message.rs @@ -100,8 +100,8 @@ impl MessageRouter for TestMessageRouter { } fn create_blinded_paths( - &self, _recipient: PublicKey, _context: MessageContext, _peers: Vec, - _secp_ctx: &Secp256k1, + &self, _recipient: PublicKey, _context: MessageContext, _custom_tlvs: Vec, + _peers: Vec, _secp_ctx: &Secp256k1, ) -> Result, ()> { unreachable!() } @@ -112,7 +112,7 @@ struct TestOffersMessageHandler {} impl OffersMessageHandler for TestOffersMessageHandler { fn handle_message( &self, _message: OffersMessage, _context: Option, - _responder: Option, + _custom_tlvs: Option>, _responder: Option, ) -> Option<(OffersMessage, ResponseInstruction)> { None } diff --git a/lightning/src/blinded_path/message.rs b/lightning/src/blinded_path/message.rs index 4d96434dd63..9a1357110d4 100644 --- a/lightning/src/blinded_path/message.rs +++ b/lightning/src/blinded_path/message.rs @@ -55,9 +55,9 @@ impl Readable for BlindedMessagePath { impl BlindedMessagePath { /// Create a one-hop blinded path for a message. pub fn one_hop( - recipient_node_id: PublicKey, context: MessageContext, entropy_source: ES, secp_ctx: &Secp256k1 + recipient_node_id: PublicKey, context: MessageContext, custom_tlvs: Vec, entropy_source: ES, secp_ctx: &Secp256k1 ) -> Result where ES::Target: EntropySource { - Self::new(&[], recipient_node_id, context, entropy_source, secp_ctx) + Self::new(&[], recipient_node_id, context, custom_tlvs, entropy_source, secp_ctx) } /// Create a path for an onion message, to be forwarded along `node_pks`. The last node @@ -67,7 +67,7 @@ impl BlindedMessagePath { // TODO: make all payloads the same size with padding + add dummy hops pub fn new( intermediate_nodes: &[MessageForwardNode], recipient_node_id: PublicKey, - context: MessageContext, entropy_source: ES, secp_ctx: &Secp256k1, + context: MessageContext, custom_tlvs: Vec, entropy_source: ES, secp_ctx: &Secp256k1, ) -> Result where ES::Target: EntropySource { let introduction_node = IntroductionNode::NodeId( intermediate_nodes.first().map_or(recipient_node_id, |n| n.node_id) @@ -80,7 +80,7 @@ impl BlindedMessagePath { blinding_point: PublicKey::from_secret_key(secp_ctx, &blinding_secret), blinded_hops: blinded_hops( secp_ctx, intermediate_nodes, recipient_node_id, - context, &blinding_secret, + context, custom_tlvs, &blinding_secret, ).map_err(|_| ())?, })) } @@ -241,7 +241,10 @@ pub(crate) struct ReceiveTlvs { /// If `context` is `Some`, it is used to identify the blinded path that this onion message is /// sending to. This is useful for receivers to check that said blinded path is being used in /// the right context. - pub context: Option + pub context: Option, + + /// Custom Tlvs. A user can use this to send custom tlvs information back to themself. + pub custom_tlvs: Option>, } impl Writeable for ForwardTlvs { @@ -265,6 +268,7 @@ impl Writeable for ReceiveTlvs { // TODO: write padding encode_tlv_stream!(writer, { (65537, self.context, option), + (65539, self.custom_tlvs, option), }); Ok(()) } @@ -456,7 +460,7 @@ impl_writeable_tlv_based!(DNSResolverContext, { /// Construct blinded onion message hops for the given `intermediate_nodes` and `recipient_node_id`. pub(super) fn blinded_hops( secp_ctx: &Secp256k1, intermediate_nodes: &[MessageForwardNode], - recipient_node_id: PublicKey, context: MessageContext, session_priv: &SecretKey, + recipient_node_id: PublicKey, context: MessageContext, custom_tlvs: Vec, session_priv: &SecretKey, ) -> Result, secp256k1::Error> { let pks = intermediate_nodes.iter().map(|node| node.node_id) .chain(core::iter::once(recipient_node_id)); @@ -468,7 +472,7 @@ pub(super) fn blinded_hops( None => NextMessageHop::NodeId(pubkey), }) .map(|next_hop| ControlTlvs::Forward(ForwardTlvs { next_hop, next_blinding_override: None })) - .chain(core::iter::once(ControlTlvs::Receive(ReceiveTlvs{ context: Some(context) }))); + .chain(core::iter::once(ControlTlvs::Receive(ReceiveTlvs{ context: Some(context), custom_tlvs: Some(custom_tlvs) }))); let path = pks.zip(tlvs); diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 3914384ca82..9ac318bf96d 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -9645,7 +9645,7 @@ where .collect::>(); self.message_router - .create_blinded_paths(recipient, context, peers, secp_ctx) + .create_blinded_paths(recipient, context, Vec::new(), peers, secp_ctx) .and_then(|paths| (!paths.is_empty()).then(|| paths).ok_or(())) } @@ -9673,7 +9673,7 @@ where .collect::>(); self.message_router - .create_compact_blinded_paths(recipient, MessageContext::Offers(context), peers, secp_ctx) + .create_compact_blinded_paths(recipient, MessageContext::Offers(context), Vec::new(), peers, secp_ctx) .and_then(|paths| (!paths.is_empty()).then(|| paths).ok_or(())) } @@ -11096,7 +11096,7 @@ where L::Target: Logger, { fn handle_message( - &self, message: OffersMessage, context: Option, responder: Option, + &self, message: OffersMessage, context: Option, custom_tlvs: Option>, responder: Option, ) -> Option<(OffersMessage, ResponseInstruction)> { let secp_ctx = &self.secp_ctx; let expanded_key = &self.inbound_payment_key; @@ -11239,7 +11239,7 @@ where let nonce = Nonce::from_entropy_source(&*self.entropy_source); let hmac = payment_hash.hmac_for_offer_payment(nonce, expanded_key); let context = MessageContext::Offers(OffersContext::InboundPayment { payment_hash, nonce, hmac }); - Some((OffersMessage::Invoice(invoice), responder.respond_with_reply_path(context))) + Some((OffersMessage::Invoice(invoice), responder.respond_with_reply_path(context, custom_tlvs))) }, Err(error) => Some((OffersMessage::InvoiceError(error.into()), responder.respond())), } diff --git a/lightning/src/ln/offers_tests.rs b/lightning/src/ln/offers_tests.rs index b667ce2c05d..44f718b57ba 100644 --- a/lightning/src/ln/offers_tests.rs +++ b/lightning/src/ln/offers_tests.rs @@ -193,8 +193,8 @@ fn claim_bolt12_payment<'a, 'b, 'c>( fn extract_offer_nonce<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, message: &OnionMessage) -> Nonce { match node.onion_messenger.peel_onion_message(message) { - Ok(PeeledOnion::Receive(_, Some(MessageContext::Offers(OffersContext::InvoiceRequest { nonce })), _)) => nonce, - Ok(PeeledOnion::Receive(_, context, _)) => panic!("Unexpected onion message context: {:?}", context), + Ok(PeeledOnion::Receive(_, Some(MessageContext::Offers(OffersContext::InvoiceRequest { nonce })), _, _)) => nonce, + Ok(PeeledOnion::Receive(_, context, _, _)) => panic!("Unexpected onion message context: {:?}", context), Ok(PeeledOnion::Forward(_, _)) => panic!("Unexpected onion message forward"), Err(e) => panic!("Failed to process onion message {:?}", e), } @@ -204,7 +204,7 @@ fn extract_invoice_request<'a, 'b, 'c>( node: &Node<'a, 'b, 'c>, message: &OnionMessage ) -> (InvoiceRequest, BlindedMessagePath) { match node.onion_messenger.peel_onion_message(message) { - Ok(PeeledOnion::Receive(message, _, reply_path)) => match message { + Ok(PeeledOnion::Receive(message, _, _, reply_path)) => match message { ParsedOnionMessageContents::Offers(offers_message) => match offers_message { OffersMessage::InvoiceRequest(invoice_request) => (invoice_request, reply_path.unwrap()), OffersMessage::Invoice(invoice) => panic!("Unexpected invoice: {:?}", invoice), @@ -221,7 +221,7 @@ fn extract_invoice_request<'a, 'b, 'c>( fn extract_invoice<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, message: &OnionMessage) -> (Bolt12Invoice, BlindedMessagePath) { match node.onion_messenger.peel_onion_message(message) { - Ok(PeeledOnion::Receive(message, _, reply_path)) => match message { + Ok(PeeledOnion::Receive(message, _, _, reply_path)) => match message { ParsedOnionMessageContents::Offers(offers_message) => match offers_message { OffersMessage::InvoiceRequest(invoice_request) => panic!("Unexpected invoice_request: {:?}", invoice_request), OffersMessage::Invoice(invoice) => (invoice, reply_path.unwrap()), @@ -240,7 +240,7 @@ fn extract_invoice_error<'a, 'b, 'c>( node: &Node<'a, 'b, 'c>, message: &OnionMessage ) -> InvoiceError { match node.onion_messenger.peel_onion_message(message) { - Ok(PeeledOnion::Receive(message, _, _)) => match message { + Ok(PeeledOnion::Receive(message, _, _, _)) => match message { ParsedOnionMessageContents::Offers(offers_message) => match offers_message { OffersMessage::InvoiceRequest(invoice_request) => panic!("Unexpected invoice_request: {:?}", invoice_request), OffersMessage::Invoice(invoice) => panic!("Unexpected invoice: {:?}", invoice), diff --git a/lightning/src/ln/peer_handler.rs b/lightning/src/ln/peer_handler.rs index b5fc3443be5..1e91d550d0e 100644 --- a/lightning/src/ln/peer_handler.rs +++ b/lightning/src/ln/peer_handler.rs @@ -143,7 +143,7 @@ impl OnionMessageHandler for IgnoringMessageHandler { } impl OffersMessageHandler for IgnoringMessageHandler { - fn handle_message(&self, _message: OffersMessage, _context: Option, _responder: Option) -> Option<(OffersMessage, ResponseInstruction)> { + fn handle_message(&self, _message: OffersMessage, _context: Option, _custom_tlvs: Option>, _responder: Option) -> Option<(OffersMessage, ResponseInstruction)> { None } } diff --git a/lightning/src/onion_message/functional_tests.rs b/lightning/src/onion_message/functional_tests.rs index 23fd30c9ec8..964d6e11ed0 100644 --- a/lightning/src/onion_message/functional_tests.rs +++ b/lightning/src/onion_message/functional_tests.rs @@ -76,7 +76,7 @@ impl Drop for MessengerNode { struct TestOffersMessageHandler {} impl OffersMessageHandler for TestOffersMessageHandler { - fn handle_message(&self, _message: OffersMessage, _context: Option, _responder: Option) -> Option<(OffersMessage, ResponseInstruction)> { + fn handle_message(&self, _message: OffersMessage, _context: Option, _custom_tlvs: Option>, _responder: Option) -> Option<(OffersMessage, ResponseInstruction)> { None } } @@ -204,7 +204,7 @@ impl CustomOnionMessageHandler for TestCustomMessageHandler { match responder { Some(responder) if expectation.include_reply_path => { - Some((response, responder.respond_with_reply_path(MessageContext::Custom(context.unwrap_or_else(Vec::new))))) + Some((response, responder.respond_with_reply_path(MessageContext::Custom(context.unwrap_or_else(Vec::new)), None))) }, Some(responder) => Some((response, responder.respond())), None => None @@ -391,7 +391,7 @@ fn one_blinded_hop() { let secp_ctx = Secp256k1::new(); let context = MessageContext::Custom(Vec::new()); - let blinded_path = BlindedMessagePath::new(&[], nodes[1].node_id, context, &*nodes[1].entropy_source, &secp_ctx).unwrap(); + let blinded_path = BlindedMessagePath::new(&[], nodes[1].node_id, context, Vec::new(), &*nodes[1].entropy_source, &secp_ctx).unwrap(); let destination = Destination::BlindedPath(blinded_path); let instructions = MessageSendInstructions::WithoutReplyPath { destination }; nodes[0].messenger.send_onion_message(test_msg, instructions).unwrap(); @@ -407,7 +407,7 @@ fn two_unblinded_two_blinded() { let secp_ctx = Secp256k1::new(); let intermediate_nodes = [MessageForwardNode { node_id: nodes[3].node_id, short_channel_id: None }]; let context = MessageContext::Custom(Vec::new()); - let blinded_path = BlindedMessagePath::new(&intermediate_nodes, nodes[4].node_id, context, &*nodes[4].entropy_source, &secp_ctx).unwrap(); + let blinded_path = BlindedMessagePath::new(&intermediate_nodes, nodes[4].node_id, context, Vec::new(), &*nodes[4].entropy_source, &secp_ctx).unwrap(); let path = OnionMessagePath { intermediate_nodes: vec![nodes[1].node_id, nodes[2].node_id], destination: Destination::BlindedPath(blinded_path), @@ -430,7 +430,7 @@ fn three_blinded_hops() { MessageForwardNode { node_id: nodes[2].node_id, short_channel_id: None }, ]; let context = MessageContext::Custom(Vec::new()); - let blinded_path = BlindedMessagePath::new(&intermediate_nodes, nodes[3].node_id, context, &*nodes[3].entropy_source, &secp_ctx).unwrap(); + let blinded_path = BlindedMessagePath::new(&intermediate_nodes, nodes[3].node_id, context, Vec::new(), &*nodes[3].entropy_source, &secp_ctx).unwrap(); let destination = Destination::BlindedPath(blinded_path); let instructions = MessageSendInstructions::WithoutReplyPath { destination }; @@ -454,7 +454,7 @@ fn async_response_over_one_blinded_hop() { // 3. Simulate the creation of a Blinded Reply path provided by Bob. let secp_ctx = Secp256k1::new(); let context = MessageContext::Custom(Vec::new()); - let reply_path = BlindedMessagePath::new(&[], nodes[1].node_id, context, &*nodes[1].entropy_source, &secp_ctx).unwrap(); + let reply_path = BlindedMessagePath::new(&[], nodes[1].node_id, context, Vec::new(), &*nodes[1].entropy_source, &secp_ctx).unwrap(); // 4. Create a responder using the reply path for Alice. let responder = Some(Responder::new(reply_path)); @@ -491,7 +491,7 @@ fn async_response_with_reply_path_succeeds() { // Alice receives a message from Bob with an added reply_path for responding back. let message = TestCustomMessage::Ping; let context = MessageContext::Custom(Vec::new()); - let reply_path = BlindedMessagePath::new(&[], bob.node_id, context, &*bob.entropy_source, &secp_ctx).unwrap(); + let reply_path = BlindedMessagePath::new(&[], bob.node_id, context, Vec::new(), &*bob.entropy_source, &secp_ctx).unwrap(); // Alice asynchronously responds to Bob, expecting a response back from him. let responder = Responder::new(reply_path); @@ -529,7 +529,7 @@ fn async_response_with_reply_path_fails() { // Alice receives a message from Bob with an added reply_path for responding back. let message = TestCustomMessage::Ping; let context = MessageContext::Custom(Vec::new()); - let reply_path = BlindedMessagePath::new(&[], bob.node_id, context, &*bob.entropy_source, &secp_ctx).unwrap(); + let reply_path = BlindedMessagePath::new(&[], bob.node_id, context, Vec::new(), &*bob.entropy_source, &secp_ctx).unwrap(); // Alice tries to asynchronously respond to Bob, but fails because the nodes are unannounced and // disconnected. Thus, a reply path could no be created for the response. @@ -575,7 +575,7 @@ fn we_are_intro_node() { MessageForwardNode { node_id: nodes[1].node_id, short_channel_id: None }, ]; let context = MessageContext::Custom(Vec::new()); - let blinded_path = BlindedMessagePath::new(&intermediate_nodes, nodes[2].node_id, context, &*nodes[2].entropy_source, &secp_ctx).unwrap(); + let blinded_path = BlindedMessagePath::new(&intermediate_nodes, nodes[2].node_id, context, Vec::new(), &*nodes[2].entropy_source, &secp_ctx).unwrap(); let destination = Destination::BlindedPath(blinded_path); let instructions = MessageSendInstructions::WithoutReplyPath { destination }; @@ -586,7 +586,7 @@ fn we_are_intro_node() { // Try with a two-hop blinded path where we are the introduction node. let intermediate_nodes = [MessageForwardNode { node_id: nodes[0].node_id, short_channel_id: None }]; let context = MessageContext::Custom(Vec::new()); - let blinded_path = BlindedMessagePath::new(&intermediate_nodes, nodes[1].node_id, context, &*nodes[1].entropy_source, &secp_ctx).unwrap(); + let blinded_path = BlindedMessagePath::new(&intermediate_nodes, nodes[1].node_id, context, Vec::new(), &*nodes[1].entropy_source, &secp_ctx).unwrap(); let destination = Destination::BlindedPath(blinded_path); let instructions = MessageSendInstructions::WithoutReplyPath { destination }; @@ -605,7 +605,7 @@ fn invalid_blinded_path_error() { let secp_ctx = Secp256k1::new(); let intermediate_nodes = [MessageForwardNode { node_id: nodes[1].node_id, short_channel_id: None }]; let context = MessageContext::Custom(Vec::new()); - let mut blinded_path = BlindedMessagePath::new(&intermediate_nodes, nodes[2].node_id, context, &*nodes[2].entropy_source, &secp_ctx).unwrap(); + let mut blinded_path = BlindedMessagePath::new(&intermediate_nodes, nodes[2].node_id, context, Vec::new(), &*nodes[2].entropy_source, &secp_ctx).unwrap(); blinded_path.clear_blinded_hops(); let destination = Destination::BlindedPath(blinded_path); let instructions = MessageSendInstructions::WithoutReplyPath { destination }; @@ -631,7 +631,7 @@ fn reply_path() { MessageForwardNode { node_id: nodes[1].node_id, short_channel_id: None }, ]; let context = MessageContext::Custom(Vec::new()); - let reply_path = BlindedMessagePath::new(&intermediate_nodes, nodes[0].node_id, context, &*nodes[0].entropy_source, &secp_ctx).unwrap(); + let reply_path = BlindedMessagePath::new(&intermediate_nodes, nodes[0].node_id, context, Vec::new(), &*nodes[0].entropy_source, &secp_ctx).unwrap(); nodes[0].messenger.send_onion_message_using_path(path, test_msg.clone(), Some(reply_path)).unwrap(); nodes[3].custom_message_handler.expect_message(TestCustomMessage::Ping); pass_along_path(&nodes); @@ -646,14 +646,14 @@ fn reply_path() { MessageForwardNode { node_id: nodes[2].node_id, short_channel_id: None }, ]; let context = MessageContext::Custom(Vec::new()); - let blinded_path = BlindedMessagePath::new(&intermediate_nodes, nodes[3].node_id, context, &*nodes[3].entropy_source, &secp_ctx).unwrap(); + let blinded_path = BlindedMessagePath::new(&intermediate_nodes, nodes[3].node_id, context, Vec::new(), &*nodes[3].entropy_source, &secp_ctx).unwrap(); let destination = Destination::BlindedPath(blinded_path); let intermediate_nodes = [ MessageForwardNode { node_id: nodes[2].node_id, short_channel_id: None }, MessageForwardNode { node_id: nodes[1].node_id, short_channel_id: None }, ]; let context = MessageContext::Custom(Vec::new()); - let reply_path = BlindedMessagePath::new(&intermediate_nodes, nodes[0].node_id, context, &*nodes[0].entropy_source, &secp_ctx).unwrap(); + let reply_path = BlindedMessagePath::new(&intermediate_nodes, nodes[0].node_id, context, Vec::new(), &*nodes[0].entropy_source, &secp_ctx).unwrap(); let instructions = MessageSendInstructions::WithSpecifiedReplyPath { destination, reply_path }; nodes[0].messenger.send_onion_message(test_msg, instructions).unwrap(); @@ -746,7 +746,7 @@ fn requests_peer_connection_for_buffered_messages() { let intermediate_nodes = [MessageForwardNode { node_id: nodes[1].node_id, short_channel_id: None }]; let context = MessageContext::Custom(Vec::new()); let blinded_path = BlindedMessagePath::new( - &intermediate_nodes, nodes[2].node_id, context, &*nodes[0].entropy_source, &secp_ctx + &intermediate_nodes, nodes[2].node_id, context, Vec::new(), &*nodes[0].entropy_source, &secp_ctx ).unwrap(); let destination = Destination::BlindedPath(blinded_path); let instructions = MessageSendInstructions::WithoutReplyPath { destination }; @@ -786,7 +786,7 @@ fn drops_buffered_messages_waiting_for_peer_connection() { let intermediate_nodes = [MessageForwardNode { node_id: nodes[1].node_id, short_channel_id: None }]; let context = MessageContext::Custom(Vec::new()); let blinded_path = BlindedMessagePath::new( - &intermediate_nodes, nodes[2].node_id, context, &*nodes[0].entropy_source, &secp_ctx + &intermediate_nodes, nodes[2].node_id, context, Vec::new(), &*nodes[0].entropy_source, &secp_ctx ).unwrap(); let destination = Destination::BlindedPath(blinded_path); let instructions = MessageSendInstructions::WithoutReplyPath { destination }; @@ -838,7 +838,7 @@ fn intercept_offline_peer_oms() { let intermediate_nodes = [MessageForwardNode { node_id: nodes[1].node_id, short_channel_id: None }]; let context = MessageContext::Custom(Vec::new()); let blinded_path = BlindedMessagePath::new( - &intermediate_nodes, nodes[2].node_id, context, &*nodes[2].entropy_source, &secp_ctx + &intermediate_nodes, nodes[2].node_id, context, Vec::new(), &*nodes[2].entropy_source, &secp_ctx ).unwrap(); let destination = Destination::BlindedPath(blinded_path); let instructions = MessageSendInstructions::WithoutReplyPath { destination }; diff --git a/lightning/src/onion_message/messenger.rs b/lightning/src/onion_message/messenger.rs index 8162c55ac08..50aa6f4e270 100644 --- a/lightning/src/onion_message/messenger.rs +++ b/lightning/src/onion_message/messenger.rs @@ -183,7 +183,7 @@ for OnionMessenger where /// # }) /// # } /// # fn create_blinded_paths( -/// # &self, _recipient: PublicKey, _context: MessageContext, _peers: Vec, _secp_ctx: &Secp256k1 +/// # &self, _recipient: PublicKey, _context: MessageContext, _custom_tlvs: Vec, _peers: Vec, _secp_ctx: &Secp256k1 /// # ) -> Result, ()> { /// # unreachable!() /// # } @@ -239,7 +239,8 @@ for OnionMessenger where /// MessageForwardNode { node_id: hop_node_id4, short_channel_id: None }, /// ]; /// let context = MessageContext::Custom(Vec::new()); -/// let blinded_path = BlindedMessagePath::new(&hops, your_node_id, context, &keys_manager, &secp_ctx).unwrap(); +/// let custom_tlvs = Vec::new(); +/// let blinded_path = BlindedMessagePath::new(&hops, your_node_id, context, custom_tlvs, &keys_manager, &secp_ctx).unwrap(); /// /// // Send a custom onion message to a blinded path. /// let destination = Destination::BlindedPath(blinded_path); @@ -380,17 +381,17 @@ impl Responder { pub fn respond(self) -> ResponseInstruction { ResponseInstruction { destination: Destination::BlindedPath(self.reply_path), - context: None, + reply_data: None, } } /// Creates a [`ResponseInstruction`] for responding including a reply path. /// /// Use when the recipient needs to send back a reply to us. - pub fn respond_with_reply_path(self, context: MessageContext) -> ResponseInstruction { + pub fn respond_with_reply_path(self, context: MessageContext, custom_tlvs: Option>) -> ResponseInstruction { ResponseInstruction { destination: Destination::BlindedPath(self.reply_path), - context: Some(context), + reply_data: Some((context, custom_tlvs.unwrap_or_default())), } } } @@ -402,7 +403,7 @@ pub struct ResponseInstruction { /// [`Destination`] rather than an explicit [`BlindedMessagePath`] simplifies the logic in /// [`OnionMessenger::send_onion_message_internal`] somewhat. destination: Destination, - context: Option, + reply_data: Option<(MessageContext, Vec)>, } impl ResponseInstruction { @@ -430,6 +431,8 @@ pub enum MessageSendInstructions { /// The context to include in the reply path we'll give the recipient so they can respond /// to us. context: MessageContext, + /// Custom Tlvs included by user as they want + custom_tlvs: Vec, }, /// Indicates that a message should be sent without including a reply path, preventing the /// recipient from responding. @@ -456,7 +459,7 @@ pub trait MessageRouter { fn create_blinded_paths< T: secp256k1::Signing + secp256k1::Verification >( - &self, recipient: PublicKey, context: MessageContext, peers: Vec, secp_ctx: &Secp256k1, + &self, recipient: PublicKey, context: MessageContext, custom_tlvs: Vec, peers: Vec, secp_ctx: &Secp256k1, ) -> Result, ()>; /// Creates compact [`BlindedMessagePath`]s to the `recipient` node. The nodes in `peers` are @@ -475,14 +478,14 @@ pub trait MessageRouter { fn create_compact_blinded_paths< T: secp256k1::Signing + secp256k1::Verification >( - &self, recipient: PublicKey, context: MessageContext, + &self, recipient: PublicKey, context: MessageContext, custom_tlvs: Vec, peers: Vec, secp_ctx: &Secp256k1, ) -> Result, ()> { let peers = peers .into_iter() .map(|MessageForwardNode { node_id, short_channel_id: _ }| node_id) .collect(); - self.create_blinded_paths(recipient, context, peers, secp_ctx) + self.create_blinded_paths(recipient, context, custom_tlvs, peers, secp_ctx) } } @@ -517,8 +520,8 @@ where I: ExactSizeIterator, T: secp256k1::Signing + secp256k1::Verification >( - network_graph: &G, recipient: PublicKey, context: MessageContext, peers: I, - entropy_source: &ES, secp_ctx: &Secp256k1, compact_paths: bool, + network_graph: &G, recipient: PublicKey, context: MessageContext, custom_tlvs: Vec, + peers: I, entropy_source: &ES, secp_ctx: &Secp256k1, compact_paths: bool, ) -> Result, ()> { // Limit the number of blinded paths that are computed. const MAX_PATHS: usize = 3; @@ -557,7 +560,7 @@ where let paths = peer_info.into_iter() .map(|(peer, _, _)| { - BlindedMessagePath::new(&[peer], recipient, context.clone(), &**entropy_source, secp_ctx) + BlindedMessagePath::new(&[peer], recipient, context.clone(), custom_tlvs.clone(), &**entropy_source, secp_ctx) }) .take(MAX_PATHS) .collect::, _>>(); @@ -566,7 +569,7 @@ where Ok(paths) if !paths.is_empty() => Ok(paths), _ => { if is_recipient_announced { - BlindedMessagePath::new(&[], recipient, context, &**entropy_source, secp_ctx) + BlindedMessagePath::new(&[], recipient, context, Vec::new(), &**entropy_source, secp_ctx) .map(|path| vec![path]) } else { Err(()) @@ -619,22 +622,22 @@ where pub(crate) fn create_blinded_paths< T: secp256k1::Signing + secp256k1::Verification >( - network_graph: &G, recipient: PublicKey, context: MessageContext, + network_graph: &G, recipient: PublicKey, context: MessageContext, custom_tlvs: Vec, peers: Vec, entropy_source: &ES, secp_ctx: &Secp256k1, ) -> Result, ()> { let peers = peers .into_iter() .map(|node_id| MessageForwardNode { node_id, short_channel_id: None }); - Self::create_blinded_paths_from_iter(network_graph, recipient, context, peers.into_iter(), entropy_source, secp_ctx, false) + Self::create_blinded_paths_from_iter(network_graph, recipient, context, custom_tlvs, peers.into_iter(), entropy_source, secp_ctx, false) } pub(crate) fn create_compact_blinded_paths< T: secp256k1::Signing + secp256k1::Verification >( - network_graph: &G, recipient: PublicKey, context: MessageContext, + network_graph: &G, recipient: PublicKey, context: MessageContext, custom_tlvs: Vec, peers: Vec, entropy_source: &ES, secp_ctx: &Secp256k1, ) -> Result, ()> { - Self::create_blinded_paths_from_iter(network_graph, recipient, context, peers.into_iter(), entropy_source, secp_ctx, true) + Self::create_blinded_paths_from_iter(network_graph, recipient, context, custom_tlvs, peers.into_iter(), entropy_source, secp_ctx, true) } } @@ -652,17 +655,17 @@ where fn create_blinded_paths< T: secp256k1::Signing + secp256k1::Verification >( - &self, recipient: PublicKey, context: MessageContext, peers: Vec, secp_ctx: &Secp256k1, + &self, recipient: PublicKey, context: MessageContext, custom_tlvs: Vec, peers: Vec, secp_ctx: &Secp256k1, ) -> Result, ()> { - Self::create_blinded_paths(&self.network_graph, recipient, context, peers, &self.entropy_source, secp_ctx) + Self::create_blinded_paths(&self.network_graph, recipient, context, custom_tlvs, peers, &self.entropy_source, secp_ctx) } fn create_compact_blinded_paths< T: secp256k1::Signing + secp256k1::Verification >( - &self, recipient: PublicKey, context: MessageContext, peers: Vec, secp_ctx: &Secp256k1, + &self, recipient: PublicKey, context: MessageContext, custom_tlvs: Vec, peers: Vec, secp_ctx: &Secp256k1, ) -> Result, ()> { - Self::create_compact_blinded_paths(&self.network_graph, recipient, context, peers, &self.entropy_source, secp_ctx) + Self::create_compact_blinded_paths(&self.network_graph, recipient, context, custom_tlvs, peers, &self.entropy_source, secp_ctx) } } @@ -832,7 +835,7 @@ pub enum PeeledOnion { /// Forwarded onion, with the next node id and a new onion Forward(NextMessageHop, OnionMessage), /// Received onion message, with decrypted contents, context, and reply path - Receive(ParsedOnionMessageContents, Option, Option) + Receive(ParsedOnionMessageContents, Option, Option>, Option) } @@ -982,24 +985,24 @@ where (control_tlvs_ss, custom_handler.deref(), logger.deref()) ) { Ok((Payload::Receive::::Target as CustomOnionMessageHandler>::CustomMessage>> { - message, control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs { context }), reply_path, + message, control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs { context, custom_tlvs }), reply_path, }, None)) => { match (&message, &context) { (_, None) => { - Ok(PeeledOnion::Receive(message, None, reply_path)) + Ok(PeeledOnion::Receive(message, None, custom_tlvs, reply_path)) } (ParsedOnionMessageContents::Offers(_), Some(MessageContext::Offers(_))) => { - Ok(PeeledOnion::Receive(message, context, reply_path)) + Ok(PeeledOnion::Receive(message, context, custom_tlvs, reply_path)) } #[cfg(async_payments)] (ParsedOnionMessageContents::AsyncPayments(_), Some(MessageContext::AsyncPayments(_))) => { - Ok(PeeledOnion::Receive(message, context, reply_path)) + Ok(PeeledOnion::Receive(message, context, custom_tlvs, reply_path)) } (ParsedOnionMessageContents::Custom(_), Some(MessageContext::Custom(_))) => { - Ok(PeeledOnion::Receive(message, context, reply_path)) + Ok(PeeledOnion::Receive(message, context, custom_tlvs, reply_path)) } (ParsedOnionMessageContents::DNSResolver(_), Some(MessageContext::DNSResolver(_))) => { - Ok(PeeledOnion::Receive(message, context, reply_path)) + Ok(PeeledOnion::Receive(message, context, custom_tlvs, reply_path)) } _ => { log_trace!(logger, "Received message was sent on a blinded path with the wrong context."); @@ -1188,10 +1191,10 @@ where let (destination, reply_path) = match instructions { MessageSendInstructions::WithSpecifiedReplyPath { destination, reply_path } => (destination, Some(reply_path)), - MessageSendInstructions::WithReplyPath { destination, context } - |MessageSendInstructions::ForReply { instructions: ResponseInstruction { destination, context: Some(context) } } => + MessageSendInstructions::WithReplyPath { destination, context, custom_tlvs } + |MessageSendInstructions::ForReply { instructions: ResponseInstruction { destination, reply_data: Some((context, custom_tlvs)) } } => { - match self.create_blinded_path(context) { + match self.create_blinded_path(context, custom_tlvs) { Ok(reply_path) => (destination, Some(reply_path)), Err(err) => { log_trace!( @@ -1204,7 +1207,7 @@ where } }, MessageSendInstructions::WithoutReplyPath { destination } - |MessageSendInstructions::ForReply { instructions: ResponseInstruction { destination, context: None } } => + |MessageSendInstructions::ForReply { instructions: ResponseInstruction { destination, reply_data: None } } => (destination, None), }; @@ -1256,7 +1259,7 @@ where .map_err(|_| SendError::PathNotFound) } - fn create_blinded_path(&self, context: MessageContext) -> Result { + fn create_blinded_path(&self, context: MessageContext, custom_tlvs: Vec) -> Result { let recipient = self.node_signer .get_node_id(Recipient::Node) .map_err(|_| SendError::GetNodeIdFailed)?; @@ -1269,7 +1272,7 @@ where .collect::>(); self.message_router - .create_blinded_paths(recipient, context, peers, secp_ctx) + .create_blinded_paths(recipient, context, custom_tlvs, peers, secp_ctx) .and_then(|paths| paths.into_iter().next().ok_or(())) .map_err(|_| SendError::PathNotFound) } @@ -1599,7 +1602,7 @@ where fn handle_onion_message(&self, peer_node_id: PublicKey, msg: &OnionMessage) { let logger = WithContext::from(&self.logger, Some(peer_node_id), None, None); match self.peel_onion_message(msg) { - Ok(PeeledOnion::Receive(message, context, reply_path)) => { + Ok(PeeledOnion::Receive(message, context, custom_tlvs, reply_path)) => { log_trace!( logger, "Received an onion message with {} reply_path: {:?}", @@ -1616,7 +1619,7 @@ where return } }; - let response_instructions = self.offers_handler.handle_message(msg, context, responder); + let response_instructions = self.offers_handler.handle_message(msg, context, custom_tlvs, responder); if let Some((msg, instructions)) = response_instructions { let _ = self.handle_onion_message_response(msg, instructions); } @@ -1950,7 +1953,7 @@ fn packet_payloads_and_keys, responder: Option, + &self, message: OffersMessage, context: Option, custom_tlvs: Option>, responder: Option, ) -> Option<(OffersMessage, ResponseInstruction)>; /// Releases any [`OffersMessage`]s that need to be sent. diff --git a/lightning/src/onion_message/packet.rs b/lightning/src/onion_message/packet.rs index 8ec85a6bed7..8006f27bd0b 100644 --- a/lightning/src/onion_message/packet.rs +++ b/lightning/src/onion_message/packet.rs @@ -347,6 +347,7 @@ impl Readable for ControlTlvs { (4, next_node_id, option), (8, next_blinding_override, option), (65537, context, option), + (65539, custom_tlvs, option), }); let _padding: Option = _padding; @@ -368,6 +369,7 @@ impl Readable for ControlTlvs { } else if valid_recv_fmt { ControlTlvs::Receive(ReceiveTlvs { context, + custom_tlvs, }) } else { return Err(DecodeError::InvalidValue) diff --git a/lightning/src/util/test_utils.rs b/lightning/src/util/test_utils.rs index 122d7f0af48..3ea61ac9010 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -292,17 +292,17 @@ impl<'a> MessageRouter for TestMessageRouter<'a> { } fn create_blinded_paths( - &self, recipient: PublicKey, context: MessageContext, + &self, recipient: PublicKey, context: MessageContext, custom_tlvs: Vec, peers: Vec, secp_ctx: &Secp256k1, ) -> Result, ()> { - self.inner.create_blinded_paths(recipient, context, peers, secp_ctx) + self.inner.create_blinded_paths(recipient, context, custom_tlvs, peers, secp_ctx) } fn create_compact_blinded_paths( - &self, recipient: PublicKey, context: MessageContext, + &self, recipient: PublicKey, context: MessageContext, custom_tlvs: Vec, peers: Vec, secp_ctx: &Secp256k1, ) -> Result, ()> { - self.inner.create_compact_blinded_paths(recipient, context, peers, secp_ctx) + self.inner.create_compact_blinded_paths(recipient, context, custom_tlvs, peers, secp_ctx) } }