From: Jeffrey Czyz Date: Thu, 13 Jun 2024 22:15:19 +0000 (-0500) Subject: Advance self blinded payment paths X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=642913c586fc71b0e413532e7dedcd19cfd4815c;p=rust-lightning Advance self blinded payment paths DefaultRouter will ignore blinded paths where the sender is the introduction node. Similar to message paths, advance such paths by one so that payments may be sent to them. --- diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 508d13a1..9e573a70 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -4031,8 +4031,8 @@ where self.pending_outbound_payments .send_payment_for_bolt12_invoice( invoice, payment_id, &self.router, self.list_usable_channels(), - || self.compute_inflight_htlcs(), &self.entropy_source, &self.node_signer, - best_block_height, &self.logger, &self.pending_events, + || self.compute_inflight_htlcs(), &self.entropy_source, &self.node_signer, &self, + &self.secp_ctx, best_block_height, &self.logger, &self.pending_events, |args| self.send_payment_along_path(args) ) } diff --git a/lightning/src/ln/offers_tests.rs b/lightning/src/ln/offers_tests.rs index 1922ef71..52375f72 100644 --- a/lightning/src/ln/offers_tests.rs +++ b/lightning/src/ln/offers_tests.rs @@ -986,10 +986,19 @@ fn creates_offer_with_blinded_path_using_unannounced_introduction_node() { alice.onion_messenger.handle_onion_message(&bob_id, &onion_message); let (invoice_request, reply_path) = extract_invoice_request(alice, &onion_message); + let payment_context = PaymentContext::Bolt12Offer(Bolt12OfferContext { + offer_id: offer.id(), + invoice_request: InvoiceRequestFields { + payer_id: invoice_request.payer_id(), + quantity: None, + payer_note_truncated: None, + }, + }); assert_ne!(invoice_request.payer_id(), bob_id); assert_eq!(reply_path.introduction_node, IntroductionNode::NodeId(alice_id)); let onion_message = alice.onion_messenger.next_onion_message_for_peer(bob_id).unwrap(); + bob.onion_messenger.handle_onion_message(&alice_id, &onion_message); let invoice = extract_invoice(bob, &onion_message); assert_ne!(invoice.signing_pubkey(), alice_id); @@ -997,6 +1006,12 @@ fn creates_offer_with_blinded_path_using_unannounced_introduction_node() { for (_, path) in invoice.payment_paths() { assert_eq!(path.introduction_node, IntroductionNode::NodeId(bob_id)); } + + route_bolt12_payment(bob, &[alice], &invoice); + expect_recent_payment!(bob, RecentPaymentDetails::Pending, payment_id); + + claim_bolt12_payment(bob, &[alice], payment_context); + expect_recent_payment!(bob, RecentPaymentDetails::Fulfilled, payment_id); } /// Checks that a refund can be created using an unannounced node as a blinded path's introduction diff --git a/lightning/src/ln/outbound_payment.rs b/lightning/src/ln/outbound_payment.rs index 906f4c58..1915a4c5 100644 --- a/lightning/src/ln/outbound_payment.rs +++ b/lightning/src/ln/outbound_payment.rs @@ -13,6 +13,8 @@ use bitcoin::hashes::Hash; use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::secp256k1::{self, Secp256k1, SecretKey}; +use crate::blinded_path::{IntroductionNode, NodeIdLookUp}; +use crate::blinded_path::payment::advance_path_by_one; use crate::events::{self, PaymentFailureReason}; use crate::ln::types::{PaymentHash, PaymentPreimage, PaymentSecret}; use crate::ln::channel_state::ChannelDetails; @@ -775,10 +777,13 @@ impl OutboundPayments { } } - pub(super) fn send_payment_for_bolt12_invoice( + pub(super) fn send_payment_for_bolt12_invoice< + R: Deref, ES: Deref, NS: Deref, NL: Deref, IH, SP, L: Deref + >( &self, invoice: &Bolt12Invoice, payment_id: PaymentId, router: &R, first_hops: Vec, inflight_htlcs: IH, entropy_source: &ES, node_signer: &NS, - best_block_height: u32, logger: &L, + node_id_lookup: &NL, secp_ctx: &Secp256k1, best_block_height: u32, + logger: &L, pending_events: &Mutex)>>, send_payment_along_path: SP, ) -> Result<(), Bolt12PaymentError> @@ -786,6 +791,7 @@ impl OutboundPayments { R::Target: Router, ES::Target: EntropySource, NS::Target: NodeSigner, + NL::Target: NodeIdLookUp, L::Target: Logger, IH: Fn() -> InFlightHtlcs, SP: Fn(SendAlongPathArgs) -> Result<(), APIError>, @@ -807,7 +813,26 @@ impl OutboundPayments { hash_map::Entry::Vacant(_) => return Err(Bolt12PaymentError::UnexpectedInvoice), }; - let payment_params = PaymentParameters::from_bolt12_invoice(&invoice); + let mut payment_params = PaymentParameters::from_bolt12_invoice(&invoice); + + // Advance any blinded path where the introduction node is our node. + if let Ok(our_node_id) = node_signer.get_node_id(Recipient::Node) { + for (_, path) in payment_params.payee.blinded_route_hints_mut().iter_mut() { + let introduction_node_id = match path.introduction_node { + IntroductionNode::NodeId(pubkey) => pubkey, + IntroductionNode::DirectedShortChannelId(direction, scid) => { + match node_id_lookup.next_node_id(scid) { + Some(next_node_id) => *direction.select_pubkey(&our_node_id, &next_node_id), + None => continue, + } + }, + }; + if introduction_node_id == our_node_id { + let _ = advance_path_by_one(path, node_signer, node_id_lookup, secp_ctx); + } + } + } + let amount_msat = invoice.amount_msats(); let mut route_params = RouteParameters::from_payment_params_and_value( payment_params, amount_msat @@ -1858,6 +1883,7 @@ mod tests { use core::time::Duration; + use crate::blinded_path::EmptyNodeIdLookUp; use crate::events::{Event, PathFailure, PaymentFailureReason}; use crate::ln::types::PaymentHash; use crate::ln::channelmanager::{PaymentId, RecipientOnionFields}; @@ -2201,6 +2227,7 @@ mod tests { let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, &logger)); let scorer = RwLock::new(test_utils::TestScorer::new()); let router = test_utils::TestRouter::new(network_graph, &logger, &scorer); + let secp_ctx = Secp256k1::new(); let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet); let pending_events = Mutex::new(VecDeque::new()); @@ -2229,7 +2256,8 @@ mod tests { assert_eq!( outbound_payments.send_payment_for_bolt12_invoice( &invoice, payment_id, &&router, vec![], || InFlightHtlcs::new(), &&keys_manager, - &&keys_manager, 0, &&logger, &pending_events, |_| panic!() + &&keys_manager, &EmptyNodeIdLookUp {}, &secp_ctx, 0, &&logger, &pending_events, + |_| panic!() ), Ok(()), ); @@ -2252,6 +2280,7 @@ mod tests { let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, &logger)); let scorer = RwLock::new(test_utils::TestScorer::new()); let router = test_utils::TestRouter::new(network_graph, &logger, &scorer); + let secp_ctx = Secp256k1::new(); let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet); let pending_events = Mutex::new(VecDeque::new()); @@ -2288,7 +2317,8 @@ mod tests { assert_eq!( outbound_payments.send_payment_for_bolt12_invoice( &invoice, payment_id, &&router, vec![], || InFlightHtlcs::new(), &&keys_manager, - &&keys_manager, 0, &&logger, &pending_events, |_| panic!() + &&keys_manager, &EmptyNodeIdLookUp {}, &secp_ctx, 0, &&logger, &pending_events, + |_| panic!() ), Ok(()), ); @@ -2311,6 +2341,7 @@ mod tests { let network_graph = Arc::new(NetworkGraph::new(Network::Testnet, &logger)); let scorer = RwLock::new(test_utils::TestScorer::new()); let router = test_utils::TestRouter::new(network_graph, &logger, &scorer); + let secp_ctx = Secp256k1::new(); let keys_manager = test_utils::TestKeysInterface::new(&[0; 32], Network::Testnet); let pending_events = Mutex::new(VecDeque::new()); @@ -2360,7 +2391,8 @@ mod tests { assert_eq!( outbound_payments.send_payment_for_bolt12_invoice( &invoice, payment_id, &&router, vec![], || InFlightHtlcs::new(), &&keys_manager, - &&keys_manager, 0, &&logger, &pending_events, |_| panic!() + &&keys_manager, &EmptyNodeIdLookUp {}, &secp_ctx, 0, &&logger, &pending_events, + |_| panic!() ), Err(Bolt12PaymentError::UnexpectedInvoice), ); @@ -2377,7 +2409,8 @@ mod tests { assert_eq!( outbound_payments.send_payment_for_bolt12_invoice( &invoice, payment_id, &&router, vec![], || InFlightHtlcs::new(), &&keys_manager, - &&keys_manager, 0, &&logger, &pending_events, |_| Ok(()) + &&keys_manager, &EmptyNodeIdLookUp {}, &secp_ctx, 0, &&logger, &pending_events, + |_| Ok(()) ), Ok(()), ); @@ -2387,7 +2420,8 @@ mod tests { assert_eq!( outbound_payments.send_payment_for_bolt12_invoice( &invoice, payment_id, &&router, vec![], || InFlightHtlcs::new(), &&keys_manager, - &&keys_manager, 0, &&logger, &pending_events, |_| panic!() + &&keys_manager, &EmptyNodeIdLookUp {}, &secp_ctx, 0, &&logger, &pending_events, + |_| panic!() ), Err(Bolt12PaymentError::DuplicateInvoice), ); diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index 19931d5c..036d6372 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -1045,6 +1045,13 @@ impl Payee { } } + pub(crate) fn blinded_route_hints_mut(&mut self) -> &mut [(BlindedPayInfo, BlindedPath)] { + match self { + Self::Blinded { route_hints, .. } => &mut route_hints[..], + Self::Clear { .. } => &mut [] + } + } + fn unblinded_route_hints(&self) -> &[RouteHint] { match self { Self::Blinded { .. } => &[],