]> git.bitcoin.ninja Git - rust-lightning/commitdiff
Allow create_blinded_paths functions to accept MessageContext as input field
authorshaavan <shaavan.github@gmail.com>
Sat, 15 Jun 2024 13:52:56 +0000 (19:22 +0530)
committershaavan <shaavan.github@gmail.com>
Tue, 9 Jul 2024 11:57:11 +0000 (17:27 +0530)
- Enabled `create_blinded_paths` to accept `MessageContext` TLVs as
  an input field.
- `MessageContext` is intended to be sent along with the `reply_path`
   to the counterparty.
- Added `MessageContext` in the `create_blinded_paths` flow, optionally
  appending it within the `reply_path`.
- Updated tests to verify the new feature.

14 files changed:
fuzz/src/chanmon_consistency.rs
fuzz/src/full_stack.rs
fuzz/src/invoice_request_deser.rs
fuzz/src/onion_message.rs
fuzz/src/refund_deser.rs
lightning/src/blinded_path/message.rs
lightning/src/blinded_path/mod.rs
lightning/src/ln/channelmanager.rs
lightning/src/ln/max_payment_path_len_tests.rs
lightning/src/ln/offers_tests.rs
lightning/src/onion_message/functional_tests.rs
lightning/src/onion_message/messenger.rs
lightning/src/routing/router.rs
lightning/src/util/test_utils.rs

index 39ed7300c69d6c6d158449be48cf492c2ae9f38b..7d660f459ea63ecbb724bcb68708d7197b8c8b8d 100644 (file)
@@ -33,6 +33,7 @@ use bitcoin::hashes::sha256d::Hash as Sha256dHash;
 use bitcoin::hashes::Hash as TraitImport;
 use bitcoin::WPubkeyHash;
 
+use lightning::blinded_path::message::MessageContext;
 use lightning::blinded_path::payment::ReceiveTlvs;
 use lightning::blinded_path::BlindedPath;
 use lightning::chain;
@@ -138,7 +139,8 @@ impl MessageRouter for FuzzRouter {
        }
 
        fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
-               &self, _recipient: PublicKey, _peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>,
+               &self, _recipient: PublicKey, _context: MessageContext, _peers: Vec<PublicKey>,
+               _secp_ctx: &Secp256k1<T>,
        ) -> Result<Vec<BlindedPath>, ()> {
                unreachable!()
        }
index 86f4ef4de4cbdfdff0b1453d4fe34e9c6a2846d3..9c45c66e1a4e895859b2048845a8694e063dc79d 100644 (file)
@@ -30,6 +30,7 @@ use bitcoin::hashes::sha256d::Hash as Sha256dHash;
 use bitcoin::hashes::Hash as _;
 use bitcoin::WPubkeyHash;
 
+use lightning::blinded_path::message::MessageContext;
 use lightning::blinded_path::payment::ReceiveTlvs;
 use lightning::blinded_path::BlindedPath;
 use lightning::chain;
@@ -175,7 +176,8 @@ impl MessageRouter for FuzzRouter {
        }
 
        fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
-               &self, _recipient: PublicKey, _peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>,
+               &self, _recipient: PublicKey, _context: MessageContext, _peers: Vec<PublicKey>,
+               _secp_ctx: &Secp256k1<T>,
        ) -> Result<Vec<BlindedPath>, ()> {
                unreachable!()
        }
index 642da58236f6bc5fd51ad8cbc266ff2f3aa9676c..54b842febc9c7a2d464788ecd4c488de51a149a5 100644 (file)
@@ -10,7 +10,7 @@
 use crate::utils::test_logger;
 use bitcoin::secp256k1::{self, Keypair, Parity, PublicKey, Secp256k1, SecretKey};
 use core::convert::TryFrom;
-use lightning::blinded_path::message::ForwardNode;
+use lightning::blinded_path::message::{ForwardNode, MessageContext, OffersContext};
 use lightning::blinded_path::BlindedPath;
 use lightning::ln::features::BlindedHopFeatures;
 use lightning::ln::PaymentHash;
@@ -87,10 +87,22 @@ fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
                ],
        ];
        let paths = vec![
-               BlindedPath::new_for_message(&intermediate_nodes[0], pubkey(42), &entropy_source, secp_ctx)
-                       .unwrap(),
-               BlindedPath::new_for_message(&intermediate_nodes[1], pubkey(42), &entropy_source, secp_ctx)
-                       .unwrap(),
+               BlindedPath::new_for_message(
+                       &intermediate_nodes[0],
+                       pubkey(42),
+                       MessageContext::Offers(OffersContext::Unknown {}),
+                       &entropy_source,
+                       secp_ctx,
+               )
+               .unwrap(),
+               BlindedPath::new_for_message(
+                       &intermediate_nodes[1],
+                       pubkey(42),
+                       MessageContext::Offers(OffersContext::Unknown {}),
+                       &entropy_source,
+                       secp_ctx,
+               )
+               .unwrap(),
        ];
 
        let payinfo = vec![
index e7f2c8daa818d33405c327242dc26bb1f26cc549..05ee7526faa22cbbfc231c473cf67bd9f0e498a5 100644 (file)
@@ -95,7 +95,8 @@ impl MessageRouter for TestMessageRouter {
        }
 
        fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
-               &self, _recipient: PublicKey, _peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>,
+               &self, _recipient: PublicKey, _context: MessageContext, _peers: Vec<PublicKey>,
+               _secp_ctx: &Secp256k1<T>,
        ) -> Result<Vec<BlindedPath>, ()> {
                unreachable!()
        }
index 11907b6d6965c121be2c6d612453d9169893b8d8..8e9e6442f4716dfb9c368bfdab178af049765333 100644 (file)
@@ -10,7 +10,7 @@
 use crate::utils::test_logger;
 use bitcoin::secp256k1::{self, Keypair, PublicKey, Secp256k1, SecretKey};
 use core::convert::TryFrom;
-use lightning::blinded_path::message::ForwardNode;
+use lightning::blinded_path::message::{ForwardNode, MessageContext, OffersContext};
 use lightning::blinded_path::BlindedPath;
 use lightning::ln::features::BlindedHopFeatures;
 use lightning::ln::PaymentHash;
@@ -76,10 +76,22 @@ fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
                ],
        ];
        let paths = vec![
-               BlindedPath::new_for_message(&intermediate_nodes[0], pubkey(42), &entropy_source, secp_ctx)
-                       .unwrap(),
-               BlindedPath::new_for_message(&intermediate_nodes[1], pubkey(42), &entropy_source, secp_ctx)
-                       .unwrap(),
+               BlindedPath::new_for_message(
+                       &intermediate_nodes[0],
+                       pubkey(42),
+                       MessageContext::Offers(OffersContext::Unknown {}),
+                       &entropy_source,
+                       secp_ctx,
+               )
+               .unwrap(),
+               BlindedPath::new_for_message(
+                       &intermediate_nodes[1],
+                       pubkey(42),
+                       MessageContext::Offers(OffersContext::Unknown {}),
+                       &entropy_source,
+                       secp_ctx,
+               )
+               .unwrap(),
        ];
 
        let payinfo = vec![
index 973df8539ce191045e928d4992b9436b5b87df62..06d535a3527e1e139a484e9482db6fe3c63a2db8 100644 (file)
@@ -12,6 +12,7 @@
 //! [`BlindedPath`]: crate::blinded_path::BlindedPath
 
 use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey};
+
 #[allow(unused_imports)]
 use crate::prelude::*;
 
@@ -133,7 +134,7 @@ impl_writeable_tlv_based_enum!(OffersContext,
 /// Construct blinded onion message hops for the given `intermediate_nodes` and `recipient_node_id`.
 pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
        secp_ctx: &Secp256k1<T>, intermediate_nodes: &[ForwardNode], recipient_node_id: PublicKey,
-       session_priv: &SecretKey
+       context: MessageContext, session_priv: &SecretKey
 ) -> Result<Vec<BlindedHop>, secp256k1::Error> {
        let pks = intermediate_nodes.iter().map(|node| &node.node_id)
                .chain(core::iter::once(&recipient_node_id));
@@ -145,7 +146,7 @@ pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
                        None => NextMessageHop::NodeId(*pubkey),
                })
                .map(|next_hop| ControlTlvs::Forward(ForwardTlvs { next_hop, next_blinding_override: None }))
-               .chain(core::iter::once(ControlTlvs::Receive(ReceiveTlvs { context: None })));
+               .chain(core::iter::once(ControlTlvs::Receive(ReceiveTlvs{ context: Some(context) })));
 
        utils::construct_blinded_hops(secp_ctx, pks, tlvs, session_priv)
 }
index 2d3d085bddf35d51a5276c5c9c048506527ac45b..db90e1659422c15af67ae07ccc7969f15724704f 100644 (file)
@@ -14,6 +14,7 @@ pub mod message;
 pub(crate) mod utils;
 
 use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey};
+use message::MessageContext;
 use core::ops::Deref;
 
 use crate::ln::msgs::DecodeError;
@@ -123,9 +124,9 @@ pub struct BlindedHop {
 impl BlindedPath {
        /// Create a one-hop blinded path for a message.
        pub fn one_hop_for_message<ES: Deref, T: secp256k1::Signing + secp256k1::Verification>(
-               recipient_node_id: PublicKey, entropy_source: ES, secp_ctx: &Secp256k1<T>
+               recipient_node_id: PublicKey, context: MessageContext, entropy_source: ES, secp_ctx: &Secp256k1<T>
        ) -> Result<Self, ()> where ES::Target: EntropySource {
-               Self::new_for_message(&[], recipient_node_id, entropy_source, secp_ctx)
+               Self::new_for_message(&[], recipient_node_id, context, entropy_source, secp_ctx)
        }
 
        /// Create a blinded path for an onion message, to be forwarded along `node_pks`. The last node
@@ -135,7 +136,7 @@ impl BlindedPath {
        //  TODO: make all payloads the same size with padding + add dummy hops
        pub fn new_for_message<ES: Deref, T: secp256k1::Signing + secp256k1::Verification>(
                intermediate_nodes: &[message::ForwardNode], recipient_node_id: PublicKey,
-               entropy_source: ES, secp_ctx: &Secp256k1<T>
+               context: MessageContext, entropy_source: ES, secp_ctx: &Secp256k1<T>
        ) -> Result<Self, ()> where ES::Target: EntropySource {
                let introduction_node = IntroductionNode::NodeId(
                        intermediate_nodes.first().map_or(recipient_node_id, |n| n.node_id)
@@ -147,7 +148,8 @@ impl BlindedPath {
                        introduction_node,
                        blinding_point: PublicKey::from_secret_key(secp_ctx, &blinding_secret),
                        blinded_hops: message::blinded_hops(
-                               secp_ctx, intermediate_nodes, recipient_node_id, &blinding_secret,
+                               secp_ctx, intermediate_nodes, recipient_node_id,
+                               context, &blinding_secret,
                        ).map_err(|_| ())?,
                })
        }
index a5c32897d383f176657c0383b810cdfe169a3ef3..7794d118a7ba1165480737a409253c6317b0af12 100644 (file)
@@ -31,7 +31,7 @@ use bitcoin::secp256k1::{SecretKey,PublicKey};
 use bitcoin::secp256k1::Secp256k1;
 use bitcoin::{secp256k1, Sequence};
 
-use crate::blinded_path::message::OffersContext;
+use crate::blinded_path::message::{MessageContext, OffersContext};
 use crate::blinded_path::{BlindedPath, NodeIdLookUp};
 use crate::blinded_path::message::ForwardNode;
 use crate::blinded_path::payment::{Bolt12OfferContext, Bolt12RefundContext, PaymentConstraints, PaymentContext, ReceiveTlvs};
@@ -8377,7 +8377,7 @@ macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
                let entropy = &*$self.entropy_source;
                let secp_ctx = &$self.secp_ctx;
 
-               let path = $self.create_blinded_path_using_absolute_expiry(absolute_expiry)
+               let path = $self.create_blinded_path_using_absolute_expiry(OffersContext::Unknown {}, absolute_expiry)
                        .map_err(|_| Bolt12SemanticError::MissingPaths)?;
                let builder = OfferBuilder::deriving_signing_pubkey(
                        node_id, expanded_key, entropy, secp_ctx
@@ -8449,7 +8449,8 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
                let entropy = &*$self.entropy_source;
                let secp_ctx = &$self.secp_ctx;
 
-               let path = $self.create_blinded_path_using_absolute_expiry(Some(absolute_expiry))
+               let context = OffersContext::OutboundPayment { payment_id };
+               let path = $self.create_blinded_path_using_absolute_expiry(context, Some(absolute_expiry))
                        .map_err(|_| Bolt12SemanticError::MissingPaths)?;
                let builder = RefundBuilder::deriving_payer_id(
                        node_id, expanded_key, entropy, secp_ctx, amount_msats, payment_id
@@ -8572,7 +8573,9 @@ where
                        Some(payer_note) => builder.payer_note(payer_note),
                };
                let invoice_request = builder.build_and_sign()?;
-               let reply_path = self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?;
+
+               let context = OffersContext::OutboundPayment { payment_id };
+               let reply_path = self.create_blinded_path(context).map_err(|_| Bolt12SemanticError::MissingPaths)?;
 
                let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
 
@@ -8672,7 +8675,7 @@ where
                                )?;
                                let builder: InvoiceBuilder<DerivedSigningPubkey> = builder.into();
                                let invoice = builder.allow_mpp().build_and_sign(secp_ctx)?;
-                               let reply_path = self.create_blinded_path()
+                               let reply_path = self.create_blinded_path(OffersContext::Unknown {})
                                        .map_err(|_| Bolt12SemanticError::MissingPaths)?;
 
                                let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap();
@@ -8805,15 +8808,15 @@ where
        /// respectively, based on the given `absolute_expiry` as seconds since the Unix epoch. See
        /// [`MAX_SHORT_LIVED_RELATIVE_EXPIRY`].
        fn create_blinded_path_using_absolute_expiry(
-               &self, absolute_expiry: Option<Duration>
+               &self, context: OffersContext, absolute_expiry: Option<Duration>,
        ) -> Result<BlindedPath, ()> {
                let now = self.duration_since_epoch();
                let max_short_lived_absolute_expiry = now.saturating_add(MAX_SHORT_LIVED_RELATIVE_EXPIRY);
 
                if absolute_expiry.unwrap_or(Duration::MAX) <= max_short_lived_absolute_expiry {
-                       self.create_compact_blinded_path()
+                       self.create_compact_blinded_path(context)
                } else {
-                       self.create_blinded_path()
+                       self.create_blinded_path(context)
                }
        }
 
@@ -8833,7 +8836,7 @@ where
        /// Creates a blinded path by delegating to [`MessageRouter::create_blinded_paths`].
        ///
        /// Errors if the `MessageRouter` errors or returns an empty `Vec`.
-       fn create_blinded_path(&self) -> Result<BlindedPath, ()> {
+       fn create_blinded_path(&self, context: OffersContext) -> Result<BlindedPath, ()> {
                let recipient = self.get_our_node_id();
                let secp_ctx = &self.secp_ctx;
 
@@ -8846,14 +8849,14 @@ where
                        .collect::<Vec<_>>();
 
                self.router
-                       .create_blinded_paths(recipient, peers, secp_ctx)
+                       .create_blinded_paths(recipient, MessageContext::Offers(context), peers, secp_ctx)
                        .and_then(|paths| paths.into_iter().next().ok_or(()))
        }
 
        /// Creates a blinded path by delegating to [`MessageRouter::create_compact_blinded_paths`].
        ///
        /// Errors if the `MessageRouter` errors or returns an empty `Vec`.
-       fn create_compact_blinded_path(&self) -> Result<BlindedPath, ()> {
+       fn create_compact_blinded_path(&self, context: OffersContext) -> Result<BlindedPath, ()> {
                let recipient = self.get_our_node_id();
                let secp_ctx = &self.secp_ctx;
 
@@ -8873,7 +8876,7 @@ where
                        .collect::<Vec<_>>();
 
                self.router
-                       .create_compact_blinded_paths(recipient, peers, secp_ctx)
+                       .create_compact_blinded_paths(recipient, MessageContext::Offers(context), peers, secp_ctx)
                        .and_then(|paths| paths.into_iter().next().ok_or(()))
        }
 
index a77d91e89c7447239f1ed6d05eae67dcc02d6e8b..096bcf9633c64e45238714b8cafa4a54ec63f3f6 100644 (file)
@@ -13,7 +13,7 @@
 use bitcoin::secp256k1::{Secp256k1, PublicKey};
 use crate::blinded_path::{BlindedHop, BlindedPath, IntroductionNode};
 use crate::blinded_path::payment::{PaymentConstraints, PaymentContext, ReceiveTlvs};
-use crate::events::MessageSendEventsProvider;
+use crate::events::{Event, MessageSendEventsProvider};
 use crate::ln::PaymentSecret;
 use crate::ln::blinded_payment_tests::get_blinded_route_parameters;
 use crate::ln::channelmanager::PaymentId;
@@ -389,4 +389,13 @@ fn bolt12_invoice_too_large_blinded_paths() {
        nodes[0].onion_messenger.handle_onion_message(&nodes[1].node.get_our_node_id(), &invoice_om);
        // TODO: assert on the invoice error once we support replying to invoice OMs with failure info
        nodes[0].logger.assert_log_contains("lightning::ln::channelmanager", "Failed paying invoice: OnionPacketSizeExceeded", 1);
+
+       let events = nodes[0].node.get_and_clear_pending_events();
+       assert_eq!(events.len(), 1);
+       match events[0] {
+               Event::PaymentFailed { payment_id: id, .. } => {
+                       assert_eq!(id, payment_id)
+               },
+               _ => panic!("Unexpected event"),
+       }
 }
index 405ab87be3f11fb25c99a13960d854e6253f2cbe..83ff8ce6d5c9516ea38d499c5f6b25ec046f7672 100644 (file)
@@ -1412,6 +1412,14 @@ fn fails_sending_invoice_without_blinded_payment_paths_for_offer() {
 
        let invoice_error = extract_invoice_error(david, &onion_message);
        assert_eq!(invoice_error, InvoiceError::from(Bolt12SemanticError::MissingPaths));
+
+       // Confirm that david drops this failed payment from his pending outbound payments.
+       match get_event!(david, Event::InvoiceRequestFailed) {
+               Event::InvoiceRequestFailed { payment_id: pay_id } => {
+                       assert_eq!(pay_id, payment_id)
+               },
+               _ => panic!("No Event::InvoiceRequestFailed"),
+       }
 }
 
 #[test]
index 2851cfed1a4c1e9ff1fd37e2faabb9c568f79912..371b4f5879dd521f365771a9b5d55649bb92f404 100644 (file)
@@ -10,7 +10,7 @@
 //! Onion message testing and test utilities live here.
 
 use crate::blinded_path::{BlindedPath, EmptyNodeIdLookUp};
-use crate::blinded_path::message::{ForwardNode, OffersContext};
+use crate::blinded_path::message::{ForwardNode, MessageContext, OffersContext};
 use crate::events::{Event, EventsProvider};
 use crate::ln::features::{ChannelFeatures, InitFeatures};
 use crate::ln::msgs::{self, DecodeError, OnionMessageHandler};
@@ -174,7 +174,7 @@ impl Drop for TestCustomMessageHandler {
 
 impl CustomOnionMessageHandler for TestCustomMessageHandler {
        type CustomMessage = TestCustomMessage;
-       fn handle_custom_message(&self, msg: Self::CustomMessage, _context: Option<Vec<u8>>, responder: Option<Responder>) -> ResponseInstruction<Self::CustomMessage> {
+       fn handle_custom_message(&self, msg: Self::CustomMessage, context: Option<Vec<u8>>, responder: Option<Responder>) -> ResponseInstruction<Self::CustomMessage> {
                let expectation = self.get_next_expectation();
                assert_eq!(msg, expectation.expect);
 
@@ -190,7 +190,7 @@ impl CustomOnionMessageHandler for TestCustomMessageHandler {
 
                match responder {
                        Some(responder) if expectation.include_reply_path => {
-                               responder.respond_with_reply_path(response)
+                               responder.respond_with_reply_path(response, MessageContext::Custom(context.unwrap_or_else(Vec::new)))
                        },
                        Some(responder) => responder.respond(response),
                        None => ResponseInstruction::NoResponse,
@@ -372,7 +372,8 @@ fn one_blinded_hop() {
        let test_msg = TestCustomMessage::Pong;
 
        let secp_ctx = Secp256k1::new();
-       let blinded_path = BlindedPath::new_for_message(&[], nodes[1].node_id, &*nodes[1].entropy_source, &secp_ctx).unwrap();
+       let context = MessageContext::Custom(Vec::new());
+       let blinded_path = BlindedPath::new_for_message(&[], nodes[1].node_id, context, &*nodes[1].entropy_source, &secp_ctx).unwrap();
        let destination = Destination::BlindedPath(blinded_path);
        nodes[0].messenger.send_onion_message(test_msg, destination, None).unwrap();
        nodes[1].custom_message_handler.expect_message(TestCustomMessage::Pong);
@@ -386,7 +387,8 @@ fn two_unblinded_two_blinded() {
 
        let secp_ctx = Secp256k1::new();
        let intermediate_nodes = [ForwardNode { node_id: nodes[3].node_id, short_channel_id: None }];
-       let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[4].node_id, &*nodes[4].entropy_source, &secp_ctx).unwrap();
+       let context = MessageContext::Custom(Vec::new());
+       let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[4].node_id, context, &*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),
@@ -408,7 +410,8 @@ fn three_blinded_hops() {
                ForwardNode { node_id: nodes[1].node_id, short_channel_id: None },
                ForwardNode { node_id: nodes[2].node_id, short_channel_id: None },
        ];
-       let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[3].node_id, &*nodes[3].entropy_source, &secp_ctx).unwrap();
+       let context = MessageContext::Custom(Vec::new());
+       let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[3].node_id, context, &*nodes[3].entropy_source, &secp_ctx).unwrap();
        let destination = Destination::BlindedPath(blinded_path);
 
        nodes[0].messenger.send_onion_message(test_msg, destination, None).unwrap();
@@ -430,7 +433,8 @@ 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 reply_path = BlindedPath::new_for_message(&[], nodes[1].node_id, &*nodes[1].entropy_source, &secp_ctx).unwrap();
+       let context = MessageContext::Custom(Vec::new());
+       let reply_path = BlindedPath::new_for_message(&[], nodes[1].node_id, context, &*nodes[1].entropy_source, &secp_ctx).unwrap();
 
        // 4. Create a responder using the reply path for Alice.
        let responder = Some(Responder::new(reply_path));
@@ -465,7 +469,8 @@ 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 reply_path = BlindedPath::new_for_message(&[], bob.node_id, &*bob.entropy_source, &secp_ctx).unwrap();
+       let context = MessageContext::Custom(Vec::new());
+       let reply_path = BlindedPath::new_for_message(&[], bob.node_id, context, &*bob.entropy_source, &secp_ctx).unwrap();
 
        // Alice asynchronously responds to Bob, expecting a response back from him.
        let responder = Responder::new(reply_path);
@@ -501,7 +506,8 @@ 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 reply_path = BlindedPath::new_for_message(&[], bob.node_id, &*bob.entropy_source, &secp_ctx).unwrap();
+       let context = MessageContext::Custom(Vec::new());
+       let reply_path = BlindedPath::new_for_message(&[], bob.node_id, context, &*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.
@@ -545,7 +551,8 @@ fn we_are_intro_node() {
                ForwardNode { node_id: nodes[0].node_id, short_channel_id: None },
                ForwardNode { node_id: nodes[1].node_id, short_channel_id: None },
        ];
-       let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[2].node_id, &*nodes[2].entropy_source, &secp_ctx).unwrap();
+       let context = MessageContext::Custom(Vec::new());
+       let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[2].node_id, context, &*nodes[2].entropy_source, &secp_ctx).unwrap();
        let destination = Destination::BlindedPath(blinded_path);
 
        nodes[0].messenger.send_onion_message(test_msg.clone(), destination, None).unwrap();
@@ -554,7 +561,8 @@ fn we_are_intro_node() {
 
        // Try with a two-hop blinded path where we are the introduction node.
        let intermediate_nodes = [ForwardNode { node_id: nodes[0].node_id, short_channel_id: None }];
-       let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[1].node_id, &*nodes[1].entropy_source, &secp_ctx).unwrap();
+       let context = MessageContext::Custom(Vec::new());
+       let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[1].node_id, context, &*nodes[1].entropy_source, &secp_ctx).unwrap();
        let destination = Destination::BlindedPath(blinded_path);
        nodes[0].messenger.send_onion_message(test_msg, destination, None).unwrap();
        nodes[1].custom_message_handler.expect_message(TestCustomMessage::Pong);
@@ -570,7 +578,8 @@ fn invalid_blinded_path_error() {
 
        let secp_ctx = Secp256k1::new();
        let intermediate_nodes = [ForwardNode { node_id: nodes[1].node_id, short_channel_id: None }];
-       let mut blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[2].node_id, &*nodes[2].entropy_source, &secp_ctx).unwrap();
+       let context = MessageContext::Custom(Vec::new());
+       let mut blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[2].node_id, context, &*nodes[2].entropy_source, &secp_ctx).unwrap();
        blinded_path.blinded_hops.clear();
        let destination = Destination::BlindedPath(blinded_path);
        let err = nodes[0].messenger.send_onion_message(test_msg, destination, None).unwrap_err();
@@ -593,7 +602,8 @@ fn reply_path() {
                ForwardNode { node_id: nodes[2].node_id, short_channel_id: None },
                ForwardNode { node_id: nodes[1].node_id, short_channel_id: None },
        ];
-       let reply_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[0].node_id, &*nodes[0].entropy_source, &secp_ctx).unwrap();
+       let context = MessageContext::Custom(Vec::new());
+       let reply_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[0].node_id, context, &*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);
@@ -607,13 +617,15 @@ fn reply_path() {
                ForwardNode { node_id: nodes[1].node_id, short_channel_id: None },
                ForwardNode { node_id: nodes[2].node_id, short_channel_id: None },
        ];
-       let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[3].node_id, &*nodes[3].entropy_source, &secp_ctx).unwrap();
+       let context = MessageContext::Custom(Vec::new());
+       let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[3].node_id, context, &*nodes[3].entropy_source, &secp_ctx).unwrap();
        let destination = Destination::BlindedPath(blinded_path);
        let intermediate_nodes = [
                ForwardNode { node_id: nodes[2].node_id, short_channel_id: None },
                ForwardNode { node_id: nodes[1].node_id, short_channel_id: None },
        ];
-       let reply_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[0].node_id, &*nodes[0].entropy_source, &secp_ctx).unwrap();
+       let context = MessageContext::Custom(Vec::new());
+       let reply_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[0].node_id, context, &*nodes[0].entropy_source, &secp_ctx).unwrap();
 
        nodes[0].messenger.send_onion_message(test_msg, destination, Some(reply_path)).unwrap();
        nodes[3].custom_message_handler.expect_message(TestCustomMessage::Ping);
@@ -694,8 +706,9 @@ fn requests_peer_connection_for_buffered_messages() {
        add_channel_to_graph(&nodes[0], &nodes[1], &secp_ctx, 42);
 
        let intermediate_nodes = [ForwardNode { node_id: nodes[1].node_id, short_channel_id: None }];
+       let context = MessageContext::Custom(Vec::new());
        let blinded_path = BlindedPath::new_for_message(
-               &intermediate_nodes, nodes[2].node_id, &*nodes[0].entropy_source, &secp_ctx
+               &intermediate_nodes, nodes[2].node_id, context, &*nodes[0].entropy_source, &secp_ctx
        ).unwrap();
        let destination = Destination::BlindedPath(blinded_path);
 
@@ -732,8 +745,9 @@ fn drops_buffered_messages_waiting_for_peer_connection() {
        add_channel_to_graph(&nodes[0], &nodes[1], &secp_ctx, 42);
 
        let intermediate_nodes = [ForwardNode { node_id: nodes[1].node_id, short_channel_id: None }];
+       let context = MessageContext::Custom(Vec::new());
        let blinded_path = BlindedPath::new_for_message(
-               &intermediate_nodes, nodes[2].node_id, &*nodes[0].entropy_source, &secp_ctx
+               &intermediate_nodes, nodes[2].node_id, context, &*nodes[0].entropy_source, &secp_ctx
        ).unwrap();
        let destination = Destination::BlindedPath(blinded_path);
 
@@ -782,8 +796,9 @@ fn intercept_offline_peer_oms() {
        let message = TestCustomMessage::Pong;
        let secp_ctx = Secp256k1::new();
        let intermediate_nodes = [ForwardNode { node_id: nodes[1].node_id, short_channel_id: None }];
+       let context = MessageContext::Custom(Vec::new());
        let blinded_path = BlindedPath::new_for_message(
-               &intermediate_nodes, nodes[2].node_id, &*nodes[2].entropy_source, &secp_ctx
+               &intermediate_nodes, nodes[2].node_id, context, &*nodes[2].entropy_source, &secp_ctx
        ).unwrap();
        let destination = Destination::BlindedPath(blinded_path);
 
index f96937fd909db56ee802033984a3a8adeeb8e63b..28f1bc79253eec20bda086f2a14850c4ed261b85 100644 (file)
@@ -145,7 +145,7 @@ for OnionMessenger<ES, NS, L, NL, MR, OMH, APH, CMH> where
 /// # use bitcoin::hashes::hex::FromHex;
 /// # use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey, self};
 /// # use lightning::blinded_path::{BlindedPath, EmptyNodeIdLookUp};
-/// # use lightning::blinded_path::message::ForwardNode;
+/// # use lightning::blinded_path::message::{ForwardNode, MessageContext};
 /// # use lightning::sign::{EntropySource, KeysManager};
 /// # use lightning::ln::peer_handler::IgnoringMessageHandler;
 /// # use lightning::onion_message::messenger::{Destination, MessageRouter, OnionMessagePath, OnionMessenger};
@@ -172,7 +172,7 @@ for OnionMessenger<ES, NS, L, NL, MR, OMH, APH, CMH> where
 /// #         })
 /// #     }
 /// #     fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
-/// #         &self, _recipient: PublicKey, _peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>
+/// #         &self, _recipient: PublicKey, _context: MessageContext, _peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>
 /// #     ) -> Result<Vec<BlindedPath>, ()> {
 /// #         unreachable!()
 /// #     }
@@ -225,7 +225,8 @@ for OnionMessenger<ES, NS, L, NL, MR, OMH, APH, CMH> where
 ///    ForwardNode { node_id: hop_node_id3, short_channel_id: None },
 ///    ForwardNode { node_id: hop_node_id4, short_channel_id: None },
 /// ];
-/// let blinded_path = BlindedPath::new_for_message(&hops, your_node_id, &keys_manager, &secp_ctx).unwrap();
+/// let context = MessageContext::Custom(Vec::new());
+/// let blinded_path = BlindedPath::new_for_message(&hops, your_node_id, context, &keys_manager, &secp_ctx).unwrap();
 ///
 /// // Send a custom onion message to a blinded path.
 /// let destination = Destination::BlindedPath(blinded_path);
@@ -371,11 +372,11 @@ impl Responder {
        /// Creates a [`ResponseInstruction::WithReplyPath`] for a given response.
        ///
        /// Use when the recipient needs to send back a reply to us.
-       pub fn respond_with_reply_path<T: OnionMessageContents>(self, response: T) -> ResponseInstruction<T> {
+       pub fn respond_with_reply_path<T: OnionMessageContents>(self, response: T, context: MessageContext) -> ResponseInstruction<T> {
                ResponseInstruction::WithReplyPath(OnionMessageResponse {
                        message: response,
                        reply_path: self.reply_path,
-               })
+               }, context)
        }
 }
 
@@ -389,7 +390,7 @@ pub struct OnionMessageResponse<T: OnionMessageContents> {
 pub enum ResponseInstruction<T: OnionMessageContents> {
        /// Indicates that a response should be sent including a reply path for
        /// the recipient to respond back.
-       WithReplyPath(OnionMessageResponse<T>),
+       WithReplyPath(OnionMessageResponse<T>, MessageContext),
        /// Indicates that a response should be sent without including a reply path
        /// for the recipient to respond back.
        WithoutReplyPath(OnionMessageResponse<T>),
@@ -441,7 +442,7 @@ pub trait MessageRouter {
        fn create_blinded_paths<
                T: secp256k1::Signing + secp256k1::Verification
        >(
-               &self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
+               &self, recipient: PublicKey, context: MessageContext, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
        ) -> Result<Vec<BlindedPath>, ()>;
 
        /// Creates compact [`BlindedPath`]s to the `recipient` node. The nodes in `peers` are assumed
@@ -460,13 +461,14 @@ pub trait MessageRouter {
        fn create_compact_blinded_paths<
                T: secp256k1::Signing + secp256k1::Verification
        >(
-               &self, recipient: PublicKey, peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
+               &self, recipient: PublicKey, context: MessageContext,
+               peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
        ) -> Result<Vec<BlindedPath>, ()> {
                let peers = peers
                        .into_iter()
                        .map(|ForwardNode { node_id, short_channel_id: _ }| node_id)
                        .collect();
-               self.create_blinded_paths(recipient, peers, secp_ctx)
+               self.create_blinded_paths(recipient, context, peers, secp_ctx)
        }
 }
 
@@ -501,7 +503,8 @@ where
                I: ExactSizeIterator<Item = ForwardNode>,
                T: secp256k1::Signing + secp256k1::Verification
        >(
-               &self, recipient: PublicKey, peers: I, secp_ctx: &Secp256k1<T>, compact_paths: bool
+               &self, recipient: PublicKey, context: MessageContext, peers: I,
+               secp_ctx: &Secp256k1<T>, compact_paths: bool
        ) -> Result<Vec<BlindedPath>, ()> {
                // Limit the number of blinded paths that are computed.
                const MAX_PATHS: usize = 3;
@@ -540,7 +543,7 @@ where
 
                let paths = peer_info.into_iter()
                        .map(|(peer, _, _)| {
-                               BlindedPath::new_for_message(&[peer], recipient, &*self.entropy_source, secp_ctx)
+                               BlindedPath::new_for_message(&[peer], recipient, context.clone(), &*self.entropy_source, secp_ctx)
                        })
                        .take(MAX_PATHS)
                        .collect::<Result<Vec<_>, _>>();
@@ -549,7 +552,7 @@ where
                        Ok(paths) if !paths.is_empty() => Ok(paths),
                        _ => {
                                if is_recipient_announced {
-                                       BlindedPath::one_hop_for_message(recipient, &*self.entropy_source, secp_ctx)
+                                       BlindedPath::one_hop_for_message(recipient, context, &*self.entropy_source, secp_ctx)
                                                .map(|path| vec![path])
                                } else {
                                        Err(())
@@ -608,20 +611,22 @@ where
        fn create_blinded_paths<
                T: secp256k1::Signing + secp256k1::Verification
        >(
-               &self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
+               &self, recipient: PublicKey, context: MessageContext,
+               peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
        ) -> Result<Vec<BlindedPath>, ()> {
                let peers = peers
                        .into_iter()
                        .map(|node_id| ForwardNode { node_id, short_channel_id: None });
-               self.create_blinded_paths_from_iter(recipient, peers, secp_ctx, false)
+               self.create_blinded_paths_from_iter(recipient, context, peers, secp_ctx, false)
        }
 
        fn create_compact_blinded_paths<
                T: secp256k1::Signing + secp256k1::Verification
        >(
-               &self, recipient: PublicKey, peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
+               &self, recipient: PublicKey, context: MessageContext,
+               peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
        ) -> Result<Vec<BlindedPath>, ()> {
-               self.create_blinded_paths_from_iter(recipient, peers.into_iter(), secp_ctx, true)
+               self.create_blinded_paths_from_iter(recipient, context, peers.into_iter(), secp_ctx, true)
        }
 }
 
@@ -1165,7 +1170,7 @@ where
                        .map_err(|_| SendError::PathNotFound)
        }
 
-       fn create_blinded_path(&self) -> Result<BlindedPath, SendError> {
+       fn create_blinded_path(&self, context: MessageContext) -> Result<BlindedPath, SendError> {
                let recipient = self.node_signer
                        .get_node_id(Recipient::Node)
                        .map_err(|_| SendError::GetNodeIdFailed)?;
@@ -1178,7 +1183,7 @@ where
                        .collect::<Vec<_>>();
 
                self.message_router
-                       .create_blinded_paths(recipient, peers, secp_ctx)
+                       .create_blinded_paths(recipient, context, peers, secp_ctx)
                        .and_then(|paths| paths.into_iter().next().ok_or(()))
                        .map_err(|_| SendError::PathNotFound)
        }
@@ -1267,15 +1272,15 @@ where
        pub fn handle_onion_message_response<T: OnionMessageContents>(
                &self, response: ResponseInstruction<T>
        ) -> Result<Option<SendSuccess>, SendError> {
-               let (response, create_reply_path) = match response {
-                       ResponseInstruction::WithReplyPath(response) => (response, true),
-                       ResponseInstruction::WithoutReplyPath(response) => (response, false),
+               let (response, context) = match response {
+                       ResponseInstruction::WithReplyPath(response, context) => (response, Some(context)),
+                       ResponseInstruction::WithoutReplyPath(response) => (response, None),
                        ResponseInstruction::NoResponse => return Ok(None),
                };
 
                let message_type = response.message.msg_type();
-               let reply_path = if create_reply_path {
-                       match self.create_blinded_path() {
+               let reply_path = if let Some(context) = context {
+                       match self.create_blinded_path(context) {
                                Ok(reply_path) => Some(reply_path),
                                Err(err) => {
                                        log_trace!(
index 8062f598392677ba32447022cb3df18223b1ff43..46d79854a6775a06ffa50254ce21ecbd9418faca 100644 (file)
@@ -12,7 +12,7 @@
 use bitcoin::secp256k1::{PublicKey, Secp256k1, self};
 
 use crate::blinded_path::{BlindedHop, BlindedPath, Direction, IntroductionNode};
-use crate::blinded_path::message;
+use crate::blinded_path::message::{self, MessageContext};
 use crate::blinded_path::payment::{ForwardTlvs, PaymentConstraints, PaymentRelay, ReceiveTlvs, self};
 use crate::ln::{PaymentHash, PaymentPreimage};
 use crate::ln::channel_state::ChannelDetails;
@@ -193,17 +193,17 @@ impl< G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, ES: Deref, S: Deref,
        fn create_blinded_paths<
                T: secp256k1::Signing + secp256k1::Verification
        > (
-               &self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
+               &self, recipient: PublicKey, context: MessageContext, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
        ) -> Result<Vec<BlindedPath>, ()> {
-               self.message_router.create_blinded_paths(recipient, peers, secp_ctx)
+               self.message_router.create_blinded_paths(recipient, context, peers, secp_ctx)
        }
 
        fn create_compact_blinded_paths<
                T: secp256k1::Signing + secp256k1::Verification
        > (
-               &self, recipient: PublicKey, peers: Vec<message::ForwardNode>, secp_ctx: &Secp256k1<T>,
+               &self, recipient: PublicKey, context: MessageContext, peers: Vec<message::ForwardNode>, secp_ctx: &Secp256k1<T>,
        ) -> Result<Vec<BlindedPath>, ()> {
-               self.message_router.create_compact_blinded_paths(recipient, peers, secp_ctx)
+               self.message_router.create_compact_blinded_paths(recipient, context, peers, secp_ctx)
        }
 }
 
index 4c4df2688a59b7496d31cd3fae110bed4232e77b..f734f7f94d40038fd6899de0c2fa6981f169ed0a 100644 (file)
@@ -7,6 +7,7 @@
 // You may not use this file except in accordance with one or both of these
 // licenses.
 
+use crate::blinded_path::message::MessageContext;
 use crate::blinded_path::BlindedPath;
 use crate::blinded_path::message::ForwardNode;
 use crate::blinded_path::payment::ReceiveTlvs;
@@ -263,17 +264,19 @@ impl<'a> MessageRouter for TestRouter<'a> {
        fn create_blinded_paths<
                T: secp256k1::Signing + secp256k1::Verification
        >(
-               &self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
+               &self, recipient: PublicKey, context: MessageContext,
+               peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
        ) -> Result<Vec<BlindedPath>, ()> {
-               self.router.create_blinded_paths(recipient, peers, secp_ctx)
+               self.router.create_blinded_paths(recipient, context, peers, secp_ctx)
        }
 
        fn create_compact_blinded_paths<
                T: secp256k1::Signing + secp256k1::Verification
        >(
-               &self, recipient: PublicKey, peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
+               &self, recipient: PublicKey, context: MessageContext,
+               peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
        ) -> Result<Vec<BlindedPath>, ()> {
-               self.router.create_compact_blinded_paths(recipient, peers, secp_ctx)
+               self.router.create_compact_blinded_paths(recipient, context, peers, secp_ctx)
        }
 }
 
@@ -306,15 +309,17 @@ impl<'a> MessageRouter for TestMessageRouter<'a> {
        }
 
        fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
-               &self, recipient: PublicKey, peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
+               &self, recipient: PublicKey, context: MessageContext,
+               peers: Vec<PublicKey>, secp_ctx: &Secp256k1<T>,
        ) -> Result<Vec<BlindedPath>, ()> {
-               self.inner.create_blinded_paths(recipient, peers, secp_ctx)
+               self.inner.create_blinded_paths(recipient, context, peers, secp_ctx)
        }
 
        fn create_compact_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
-               &self, recipient: PublicKey, peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
+               &self, recipient: PublicKey, context: MessageContext,
+               peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
        ) -> Result<Vec<BlindedPath>, ()> {
-               self.inner.create_compact_blinded_paths(recipient, peers, secp_ctx)
+               self.inner.create_compact_blinded_paths(recipient, context, peers, secp_ctx)
        }
 }