From 80ae66ac17266cc0f68f054d4547da5db0973e40 Mon Sep 17 00:00:00 2001 From: Jeffrey Czyz Date: Fri, 3 Mar 2023 09:38:45 -0600 Subject: [PATCH] Include a one-hop blinded path in Offer and Refund While this doesn't add much privacy over not including any blinded paths, it allows us to exercise code for receiving on blinded paths. --- lightning/src/blinded_path/mod.rs | 4 ++-- lightning/src/ln/channelmanager.rs | 27 ++++++++++++++++++++++++--- lightning/src/routing/router.rs | 1 + 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/lightning/src/blinded_path/mod.rs b/lightning/src/blinded_path/mod.rs index 896999799..1415836c0 100644 --- a/lightning/src/blinded_path/mod.rs +++ b/lightning/src/blinded_path/mod.rs @@ -57,7 +57,7 @@ pub struct BlindedHop { impl BlindedPath { /// Create a one-hop blinded path for a message. - pub fn one_hop_for_message( + pub fn one_hop_for_message( recipient_node_id: PublicKey, entropy_source: &ES, secp_ctx: &Secp256k1 ) -> Result { Self::new_for_message(&[recipient_node_id], entropy_source, secp_ctx) @@ -68,7 +68,7 @@ impl BlindedPath { /// /// Errors if no hops are provided or if `node_pk`(s) are invalid. // TODO: make all payloads the same size with padding + add dummy hops - pub fn new_for_message( + pub fn new_for_message( node_pks: &[PublicKey], entropy_source: &ES, secp_ctx: &Secp256k1 ) -> Result { if node_pks.is_empty() { return Err(()) } diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 3810cfb81..113d69021 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -30,6 +30,7 @@ use bitcoin::secp256k1::{SecretKey,PublicKey}; use bitcoin::secp256k1::Secp256k1; use bitcoin::{LockTime, secp256k1, Sequence}; +use crate::blinded_path::BlindedPath; use crate::chain; use crate::chain::{Confirm, ChannelMonitorUpdateStatus, Watch, BestBlock}; use crate::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator, LowerBoundedFeeEstimator}; @@ -7130,6 +7131,11 @@ where /// [`ChannelManager`] when handling [`InvoiceRequest`] messages for the offer. The offer will /// not have an expiration unless otherwise set on the builder. /// + /// Uses a one-hop [`BlindedPath`] for the offer with [`ChannelManager::get_our_node_id`] as the + /// introduction node and a derived signing pubkey for recipient privacy. As such, currently, + /// the node must be announced. Otherwise, there is no way to find a path to the introduction + /// node in order to send the [`InvoiceRequest`]. + /// /// [`Offer`]: crate::offers::offer::Offer /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest pub fn create_offer_builder( @@ -7139,10 +7145,11 @@ where let expanded_key = &self.inbound_payment_key; let entropy = &*self.entropy_source; let secp_ctx = &self.secp_ctx; + let path = self.create_one_hop_blinded_path(); - // TODO: Set blinded paths OfferBuilder::deriving_signing_pubkey(description, node_id, expanded_key, entropy, secp_ctx) .chain_hash(self.chain_hash) + .path(path) } /// Creates a [`RefundBuilder`] such that the [`Refund`] it builds is recognized by the @@ -7152,6 +7159,11 @@ where /// /// The provided `payment_id` is used to ensure that only one invoice is paid for the refund. /// + /// Uses a one-hop [`BlindedPath`] for the refund with [`ChannelManager::get_our_node_id`] as + /// the introduction node and a derived payer id for sender privacy. As such, currently, the + /// node must be announced. Otherwise, there is no way to find a path to the introduction node + /// in order to send the [`Bolt12Invoice`]. + /// /// [`Refund`]: crate::offers::refund::Refund /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice pub fn create_refund_builder( @@ -7162,13 +7174,14 @@ where let expanded_key = &self.inbound_payment_key; let entropy = &*self.entropy_source; let secp_ctx = &self.secp_ctx; + let path = self.create_one_hop_blinded_path(); - // TODO: Set blinded paths let builder = RefundBuilder::deriving_payer_id( description, node_id, expanded_key, entropy, secp_ctx, amount_msats, payment_id )? .chain_hash(self.chain_hash) - .absolute_expiry(absolute_expiry); + .absolute_expiry(absolute_expiry) + .path(path); self.pending_outbound_payments .add_new_awaiting_invoice( @@ -7279,6 +7292,14 @@ where inbound_payment::get_payment_preimage(payment_hash, payment_secret, &self.inbound_payment_key) } + /// Creates a one-hop blinded path with [`ChannelManager::get_our_node_id`] as the introduction + /// node. + fn create_one_hop_blinded_path(&self) -> BlindedPath { + let entropy_source = self.entropy_source.deref(); + let secp_ctx = &self.secp_ctx; + BlindedPath::one_hop_for_message(self.get_our_node_id(), entropy_source, secp_ctx).unwrap() + } + /// Gets a fake short channel id for use in receiving [phantom node payments]. These fake scids /// are used when constructing the phantom invoice's route hints. /// diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index 4c8a31bd7..104f4c93c 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -90,6 +90,7 @@ pub trait Router { &self, payer: &PublicKey, route_params: &RouteParameters, first_hops: Option<&[&ChannelDetails]>, inflight_htlcs: InFlightHtlcs ) -> Result; + /// Finds a [`Route`] for a payment between the given `payer` and a payee. /// /// The `payee` and the payment's value are given in [`RouteParameters::payment_params`] -- 2.39.5