From 4014246e540ce11bbad8c1060074ed766c124269 Mon Sep 17 00:00:00 2001 From: shaavan Date: Thu, 19 Sep 2024 17:24:30 +0530 Subject: [PATCH] Introduce a Unified Function Flow for Creating Blinded Paths This refactor simplifies the codebase while ensuring that the existing functionality is maintained. --- fuzz/src/chanmon_consistency.rs | 8 +- fuzz/src/full_stack.rs | 8 +- fuzz/src/onion_message.rs | 8 +- lightning/src/ln/channelmanager.rs | 98 +++++++----------------- lightning/src/onion_message/messenger.rs | 81 ++++++-------------- lightning/src/routing/router.rs | 15 +--- lightning/src/util/test_utils.rs | 26 ++----- 7 files changed, 72 insertions(+), 172 deletions(-) diff --git a/fuzz/src/chanmon_consistency.rs b/fuzz/src/chanmon_consistency.rs index 1605af69a82..ebde87d2ded 100644 --- a/fuzz/src/chanmon_consistency.rs +++ b/fuzz/src/chanmon_consistency.rs @@ -58,7 +58,9 @@ use lightning::ln::script::ShutdownScript; use lightning::ln::types::{ChannelId, PaymentHash, PaymentPreimage, PaymentSecret}; use lightning::offers::invoice::UnsignedBolt12Invoice; use lightning::offers::invoice_request::UnsignedInvoiceRequest; -use lightning::onion_message::messenger::{Destination, MessageRouter, OnionMessagePath}; +use lightning::onion_message::messenger::{ + BlindedPathType, Destination, MessageRouter, OnionMessagePath, +}; use lightning::routing::router::{InFlightHtlcs, Path, Route, RouteHop, RouteParameters, Router}; use lightning::sign::{ EntropySource, InMemorySigner, KeyMaterial, NodeSigner, Recipient, SignerProvider, @@ -141,8 +143,8 @@ impl MessageRouter for FuzzRouter { } fn create_blinded_paths( - &self, _recipient: PublicKey, _context: MessageContext, _peers: Vec, - _secp_ctx: &Secp256k1, + &self, _recipient: PublicKey, _context: MessageContext, _blinded_path: BlindedPathType, + _peers: Vec, _secp_ctx: &Secp256k1, ) -> Result, ()> { unreachable!() } diff --git a/fuzz/src/full_stack.rs b/fuzz/src/full_stack.rs index 90449248e32..4d1f2a7fbc1 100644 --- a/fuzz/src/full_stack.rs +++ b/fuzz/src/full_stack.rs @@ -51,7 +51,9 @@ use lightning::ln::script::ShutdownScript; use lightning::ln::types::{ChannelId, PaymentHash, PaymentPreimage, PaymentSecret}; use lightning::offers::invoice::UnsignedBolt12Invoice; use lightning::offers::invoice_request::UnsignedInvoiceRequest; -use lightning::onion_message::messenger::{Destination, MessageRouter, OnionMessagePath}; +use lightning::onion_message::messenger::{ + BlindedPathType, Destination, MessageRouter, OnionMessagePath, +}; use lightning::routing::gossip::{NetworkGraph, P2PGossipSync}; use lightning::routing::router::{ InFlightHtlcs, PaymentParameters, Route, RouteParameters, Router, @@ -176,8 +178,8 @@ impl MessageRouter for FuzzRouter { } fn create_blinded_paths( - &self, _recipient: PublicKey, _context: MessageContext, _peers: Vec, - _secp_ctx: &Secp256k1, + &self, _recipient: PublicKey, _context: MessageContext, _blinded_path: BlindedPathType, + _peers: Vec, _secp_ctx: &Secp256k1, ) -> Result, ()> { unreachable!() } diff --git a/fuzz/src/onion_message.rs b/fuzz/src/onion_message.rs index 5cd45238df2..8f9c384f1ff 100644 --- a/fuzz/src/onion_message.rs +++ b/fuzz/src/onion_message.rs @@ -18,8 +18,8 @@ use lightning::onion_message::async_payments::{ AsyncPaymentsMessageHandler, HeldHtlcAvailable, ReleaseHeldHtlc, }; use lightning::onion_message::messenger::{ - CustomOnionMessageHandler, Destination, MessageRouter, MessageSendInstructions, - OnionMessagePath, OnionMessenger, Responder, ResponseInstruction, + BlindedPathType, CustomOnionMessageHandler, Destination, MessageRouter, + MessageSendInstructions, OnionMessagePath, OnionMessenger, Responder, ResponseInstruction, }; use lightning::onion_message::offers::{OffersMessage, OffersMessageHandler}; use lightning::onion_message::packet::OnionMessageContents; @@ -98,8 +98,8 @@ impl MessageRouter for TestMessageRouter { } fn create_blinded_paths( - &self, _recipient: PublicKey, _context: MessageContext, _peers: Vec, - _secp_ctx: &Secp256k1, + &self, _recipient: PublicKey, _context: MessageContext, _blinded_path: BlindedPathType, + _peers: Vec, _secp_ctx: &Secp256k1, ) -> Result, ()> { unreachable!() } diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index d323a57dabb..dac5149f78c 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -2554,9 +2554,7 @@ const MAX_NO_CHANNEL_PEERS: usize = 250; /// short-lived, while anything with a greater expiration is considered long-lived. /// /// Using [`ChannelManager::create_offer_builder`] or [`ChannelManager::create_refund_builder`], -/// will included a [`BlindedMessagePath`] created using: -/// - [`MessageRouter::create_compact_blinded_paths`] when short-lived, and -/// - [`MessageRouter::create_blinded_paths`] when long-lived. +/// will included a [`BlindedMessagePath`] created using [`MessageRouter::create_blinded_paths`]. /// /// Using compact [`BlindedMessagePath`]s may provide better privacy as the [`MessageRouter`] could select /// more hops. However, since they use short channel ids instead of pubkeys, they are more likely to @@ -9042,21 +9040,9 @@ macro_rules! create_offer_builder { ($self: ident, $builder: ty) => { let nonce = Nonce::from_entropy_source(entropy); let context = OffersContext::InvoiceRequest { nonce }; let builder = match blinded_path { - Some(BlindedPathType::Compact) => { + Some(blinded_path) => { let path = $self - .create_compact_blinded_paths(context) - .and_then(|paths| paths.into_iter().next().ok_or(())) - .map_err(|_| Bolt12SemanticError::MissingPaths)?; - - OfferBuilder::deriving_signing_pubkey(node_id, expanded_key, nonce, secp_ctx) - .chain_hash($self.chain_hash) - .path(path) - } - - Some(BlindedPathType::Full) => { - let context = MessageContext::Offers(context); - let path = $self - .create_blinded_paths(context) + .create_blinded_paths(context, blinded_path) .and_then(|paths| paths.into_iter().next().ok_or(())) .map_err(|_| Bolt12SemanticError::MissingPaths)?; @@ -9132,25 +9118,9 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => { let context = OffersContext::OutboundPayment { payment_id, nonce, hmac: None }; let builder = match blinded_path { - Some(BlindedPathType::Compact) => { - let path = $self - .create_compact_blinded_paths(context) - .and_then(|paths| paths.into_iter().next().ok_or(())) - .map_err(|_| Bolt12SemanticError::MissingPaths)?; - - RefundBuilder::deriving_signing_pubkey( - node_id, expanded_key, nonce, secp_ctx, - amount_msats, payment_id, - )? - .chain_hash($self.chain_hash) - .absolute_expiry(absolute_expiry) - .path(path) - } - - Some(BlindedPathType::Full) => { - let context = MessageContext::Offers(context); + Some(blinded_path) => { let path = $self - .create_blinded_paths(context) + .create_blinded_paths(context, blinded_path) .and_then(|paths| paths.into_iter().next().ok_or(())) .map_err(|_| Bolt12SemanticError::MissingPaths)?; @@ -9299,7 +9269,7 @@ where let context = MessageContext::Offers( OffersContext::OutboundPayment { payment_id, nonce, hmac: Some(hmac) } ); - let reply_paths = self.create_blinded_paths(context) + let reply_paths = self.create_blinded_paths(context, BlindedPathType::Full) .map_err(|_| Bolt12SemanticError::MissingPaths)?; let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); @@ -9421,7 +9391,7 @@ where let context = MessageContext::Offers(OffersContext::InboundPayment { payment_hash: invoice.payment_hash(), nonce, hmac }); - let reply_paths = self.create_blinded_paths(context) + let reply_paths = self.create_blinded_paths(context, BlindedPathType::Full) .map_err(|_| Bolt12SemanticError::MissingPaths)?; let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap(); @@ -9571,7 +9541,7 @@ where /// [`MessageRouter::create_blinded_paths`]. /// /// Errors if the `MessageRouter` errors. - fn create_blinded_paths(&self, context: MessageContext) -> Result, ()> { + fn create_blinded_paths(&self, context: MessageContext, blinded_path: BlindedPathType) -> Result, ()> { let recipient = self.get_our_node_id(); let secp_ctx = &self.secp_ctx; @@ -9580,44 +9550,30 @@ where .map(|(node_id, peer_state)| (node_id, peer_state.lock().unwrap())) .filter(|(_, peer)| peer.is_connected) .filter(|(_, peer)| peer.latest_features.supports_onion_messages()) - .map(|(node_id, _)| { - MessageForwardNode { - node_id: *node_id, - short_channel_id: None, + .map(|(node_id, peer)| { + match blinded_path { + BlindedPathType::Full => { + MessageForwardNode { + node_id: *node_id, + short_channel_id: None, + } + } + BlindedPathType::Compact => { + MessageForwardNode { + node_id: *node_id, + short_channel_id: peer.channel_by_id + .iter() + .filter(|(_, channel)| channel.context().is_usable()) + .min_by_key(|(_, channel)| channel.context().channel_creation_height) + .and_then(|(_, channel)| channel.context().get_short_channel_id()), + } + } } }) .collect::>(); self.router - .create_blinded_paths(recipient, context, peers, secp_ctx) - .and_then(|paths| (!paths.is_empty()).then(|| paths).ok_or(())) - } - - /// Creates a collection of blinded paths by delegating to - /// [`MessageRouter::create_compact_blinded_paths`]. - /// - /// Errors if the `MessageRouter` errors. - fn create_compact_blinded_paths(&self, context: OffersContext) -> Result, ()> { - let recipient = self.get_our_node_id(); - let secp_ctx = &self.secp_ctx; - - let peers = self.per_peer_state.read().unwrap() - .iter() - .map(|(node_id, peer_state)| (node_id, peer_state.lock().unwrap())) - .filter(|(_, peer)| peer.is_connected) - .filter(|(_, peer)| peer.latest_features.supports_onion_messages()) - .map(|(node_id, peer)| MessageForwardNode { - node_id: *node_id, - short_channel_id: peer.channel_by_id - .iter() - .filter(|(_, channel)| channel.context().is_usable()) - .min_by_key(|(_, channel)| channel.context().channel_creation_height) - .and_then(|(_, channel)| channel.context().get_short_channel_id()), - }) - .collect::>(); - - self.router - .create_compact_blinded_paths(recipient, MessageContext::Offers(context), peers, secp_ctx) + .create_blinded_paths(recipient, MessageContext::Offers(context), blinded_path, peers, secp_ctx) .and_then(|paths| (!paths.is_empty()).then(|| paths).ok_or(())) } diff --git a/lightning/src/onion_message/messenger.rs b/lightning/src/onion_message/messenger.rs index 457e2e082b0..19e24ac818b 100644 --- a/lightning/src/onion_message/messenger.rs +++ b/lightning/src/onion_message/messenger.rs @@ -151,7 +151,7 @@ for OnionMessenger where /// # use lightning::blinded_path::message::{BlindedMessagePath, MessageForwardNode, MessageContext}; /// # use lightning::sign::{EntropySource, KeysManager}; /// # use lightning::ln::peer_handler::IgnoringMessageHandler; -/// # use lightning::onion_message::messenger::{Destination, MessageRouter, MessageSendInstructions, OnionMessagePath, OnionMessenger}; +/// # use lightning::onion_message::messenger::{BlindedPathType, Destination, MessageRouter, MessageSendInstructions, OnionMessagePath, OnionMessenger}; /// # use lightning::onion_message::packet::OnionMessageContents; /// # use lightning::util::logger::{Logger, Record}; /// # use lightning::util::ser::{Writeable, Writer}; @@ -175,7 +175,7 @@ for OnionMessenger where /// # }) /// # } /// # fn create_blinded_paths( -/// # &self, _recipient: PublicKey, _context: MessageContext, _peers: Vec, _secp_ctx: &Secp256k1 +/// # &self, _recipient: PublicKey, _context: MessageContext, _blinded_path: BlindedPathType, _peers: Vec, _secp_ctx: &Secp256k1 /// # ) -> Result, ()> { /// # unreachable!() /// # } @@ -449,14 +449,9 @@ pub trait MessageRouter { /// Creates [`BlindedMessagePath`]s to the `recipient` node. The nodes in `peers` are assumed to /// be direct peers with the `recipient`. - fn create_blinded_paths< - T: secp256k1::Signing + secp256k1::Verification - >( - &self, recipient: PublicKey, context: MessageContext, peers: Vec, secp_ctx: &Secp256k1, - ) -> Result, ()>; - - /// Creates compact [`BlindedMessagePath`]s to the `recipient` node. The nodes in `peers` are - /// assumed to be direct peers with the `recipient`. + /// + /// # Note of compact blinded path: + /// User can decide to create compact blinded path by specifying the appropirate [`BlindedPathType`]. /// /// Compact blinded paths use short channel ids instead of pubkeys for a smaller serialization, /// which is beneficial when a QR code is used to transport the data. The SCID is passed using @@ -465,24 +460,12 @@ pub trait MessageRouter { /// Implementations using additional intermediate nodes are responsible for using a /// [`MessageForwardNode`] with `Some` short channel id, if possible. Similarly, implementations /// should call [`BlindedMessagePath::use_compact_introduction_node`]. - /// - /// The provided implementation simply delegates to [`MessageRouter::create_blinded_paths`], - /// ignoring the short channel ids. - fn create_compact_blinded_paths< + fn create_blinded_paths< T: secp256k1::Signing + secp256k1::Verification >( - &self, recipient: PublicKey, context: MessageContext, + &self, recipient: PublicKey, context: MessageContext, blinded_path: BlindedPathType, peers: Vec, secp_ctx: &Secp256k1, - ) -> Result, ()> { - let peers = peers - .into_iter() - .map(|mut node| { - node.short_channel_id = None; - node - }) - .collect(); - self.create_blinded_paths(recipient, context, peers, secp_ctx) - } + ) -> Result, ()>; } /// A [`MessageRouter`] that can only route to a directly connected [`Destination`]. @@ -516,8 +499,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, blinded_path: BlindedPathType, + peers: I, entropy_source: &ES, secp_ctx: &Secp256k1 ) -> Result, ()> { // Limit the number of blinded paths that are computed. const MAX_PATHS: usize = 3; @@ -573,10 +556,13 @@ where }, }?; - if compact_paths { - for path in &mut paths { - path.use_compact_introduction_node(&network_graph); + match blinded_path { + BlindedPathType::Compact => { + for path in &mut paths { + path.use_compact_introduction_node(&network_graph); + } } + BlindedPathType::Full => {} } Ok(paths) @@ -618,25 +604,10 @@ 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, blinded_path: BlindedPathType, peers: Vec, entropy_source: &ES, secp_ctx: &Secp256k1, ) -> Result, ()> { - let peers = peers - .into_iter() - .map(|mut node| { - node.short_channel_id = None; - node - }); - Self::create_blinded_paths_from_iter(network_graph, recipient, context, 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, - 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, blinded_path, peers.into_iter(), entropy_source, secp_ctx) } } @@ -654,19 +625,11 @@ where fn create_blinded_paths< T: secp256k1::Signing + secp256k1::Verification >( - &self, recipient: PublicKey, context: MessageContext, peers: Vec, secp_ctx: &Secp256k1, - ) -> Result, ()> { - Self::create_blinded_paths(&self.network_graph, recipient, context, 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, blinded_path: BlindedPathType, + peers: Vec, secp_ctx: &Secp256k1, ) -> Result, ()> { - Self::create_compact_blinded_paths(&self.network_graph, recipient, context, peers, &self.entropy_source, secp_ctx) + Self::create_blinded_paths(&self.network_graph, recipient, context, blinded_path, peers, &self.entropy_source, secp_ctx) } - } /// A path for sending an [`OnionMessage`]. @@ -1270,7 +1233,7 @@ where .collect::>(); self.message_router - .create_blinded_paths(recipient, context, peers, secp_ctx) + .create_blinded_paths(recipient, context, BlindedPathType::Full, peers, secp_ctx) .and_then(|paths| paths.into_iter().next().ok_or(())) .map_err(|_| SendError::PathNotFound) } diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index a8d12b5e1eb..86295636b21 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -23,7 +23,7 @@ use crate::ln::onion_utils; #[cfg(async_payments)] use crate::offers::static_invoice::StaticInvoice; use crate::offers::invoice::Bolt12Invoice; -use crate::onion_message::messenger::{DefaultMessageRouter, Destination, MessageRouter, OnionMessagePath}; +use crate::onion_message::messenger::{BlindedPathType, DefaultMessageRouter, Destination, MessageRouter, OnionMessagePath}; use crate::routing::gossip::{DirectedChannelInfo, EffectiveCapacity, ReadOnlyNetworkGraph, NetworkGraph, NodeId}; use crate::routing::scoring::{ChannelUsage, LockableScore, ScoreLookUp}; use crate::sign::EntropySource; @@ -199,17 +199,10 @@ impl< G: Deref>, L: Deref, ES: Deref, S: Deref, SP: Siz fn create_blinded_paths< T: secp256k1::Signing + secp256k1::Verification > ( - &self, recipient: PublicKey, context: MessageContext, peers: Vec, secp_ctx: &Secp256k1, + &self, recipient: PublicKey, context: MessageContext, blinded_path: BlindedPathType, peers: Vec, + secp_ctx: &Secp256k1, ) -> Result, ()> { - DefaultMessageRouter::create_blinded_paths(&self.network_graph, recipient, context, 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, - ) -> Result, ()> { - DefaultMessageRouter::create_compact_blinded_paths(&self.network_graph, recipient, context, peers, &self.entropy_source, secp_ctx) + DefaultMessageRouter::create_blinded_paths(&self.network_graph, recipient, context, blinded_path, peers, &self.entropy_source, secp_ctx) } } diff --git a/lightning/src/util/test_utils.rs b/lightning/src/util/test_utils.rs index 8691bec7d96..4807dc6ff0a 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -35,7 +35,7 @@ use crate::ln::msgs::LightningError; use crate::ln::script::ShutdownScript; use crate::offers::invoice::UnsignedBolt12Invoice; use crate::offers::invoice_request::UnsignedInvoiceRequest; -use crate::onion_message::messenger::{DefaultMessageRouter, Destination, MessageRouter, OnionMessagePath}; +use crate::onion_message::messenger::{BlindedPathType, DefaultMessageRouter, Destination, MessageRouter, OnionMessagePath}; use crate::routing::gossip::{EffectiveCapacity, NetworkGraph, NodeId, RoutingFees}; use crate::routing::utxo::{UtxoLookup, UtxoLookupError, UtxoResult}; use crate::routing::router::{DefaultRouter, InFlightHtlcs, Path, Route, RouteParameters, RouteHintHop, Router, ScorerAccountingForInFlightHtlcs}; @@ -275,19 +275,10 @@ impl<'a> MessageRouter for TestRouter<'a> { fn create_blinded_paths< T: secp256k1::Signing + secp256k1::Verification >( - &self, recipient: PublicKey, context: MessageContext, + &self, recipient: PublicKey, context: MessageContext, blinded_path: BlindedPathType, peers: Vec, secp_ctx: &Secp256k1, ) -> Result, ()> { - self.router.create_blinded_paths(recipient, context, peers, secp_ctx) - } - - fn create_compact_blinded_paths< - T: secp256k1::Signing + secp256k1::Verification - >( - &self, recipient: PublicKey, context: MessageContext, - peers: Vec, secp_ctx: &Secp256k1, - ) -> Result, ()> { - self.router.create_compact_blinded_paths(recipient, context, peers, secp_ctx) + self.router.create_blinded_paths(recipient, context, blinded_path, peers, secp_ctx) } } @@ -318,17 +309,10 @@ impl<'a> MessageRouter for TestMessageRouter<'a> { } fn create_blinded_paths( - &self, recipient: PublicKey, context: MessageContext, - peers: Vec, secp_ctx: &Secp256k1, - ) -> Result, ()> { - self.inner.create_blinded_paths(recipient, context, peers, secp_ctx) - } - - fn create_compact_blinded_paths( - &self, recipient: PublicKey, context: MessageContext, + &self, recipient: PublicKey, context: MessageContext, blinded_path: BlindedPathType, peers: Vec, secp_ctx: &Secp256k1, ) -> Result, ()> { - self.inner.create_compact_blinded_paths(recipient, context, peers, secp_ctx) + self.inner.create_blinded_paths(recipient, context, blinded_path, peers, secp_ctx) } }