Skip to content

Commit 2c40555

Browse files
committed
WIP: Multi-hop blinded paths
1 parent 3afda34 commit 2c40555

File tree

1 file changed

+47
-16
lines changed

1 file changed

+47
-16
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ use crate::offers::merkle::SignError;
6565
use crate::offers::offer::{DerivedMetadata, Offer, OfferBuilder};
6666
use crate::offers::parse::Bolt12SemanticError;
6767
use crate::offers::refund::{Refund, RefundBuilder};
68-
use crate::onion_message::{Destination, OffersMessage, OffersMessageHandler, PendingOnionMessage, new_pending_onion_message};
68+
use crate::onion_message::{Destination, MessageRouter, OffersMessage, OffersMessageHandler, PendingOnionMessage, new_pending_onion_message};
6969
use crate::sign::{EntropySource, KeysManager, NodeSigner, Recipient, SignerProvider};
7070
use crate::sign::ecdsa::WriteableEcdsaChannelSigner;
7171
use crate::util::config::{UserConfig, ChannelConfig, ChannelConfigUpdate};
@@ -7416,10 +7416,13 @@ where
74167416
///
74177417
/// # Privacy
74187418
///
7419-
/// Uses a one-hop [`BlindedPath`] for the offer with [`ChannelManager::get_our_node_id`] as the
7420-
/// introduction node and a derived signing pubkey for recipient privacy. As such, currently,
7421-
/// the node must be announced. Otherwise, there is no way to find a path to the introduction
7422-
/// node in order to send the [`InvoiceRequest`].
7419+
/// Uses [`MessageRouter::create_blinded_paths`] to construct a [`BlindedPath`] for the offer.
7420+
/// However, if one is not found, uses a one-hop [`BlindedPath`] with
7421+
/// [`ChannelManager::get_our_node_id`] as the introduction node instead. In the latter case,
7422+
/// the node must be announced, otherwise, there is no way to find a path to the introduction in
7423+
/// order to send the [`InvoiceRequest`].
7424+
///
7425+
/// Also, uses a derived signing pubkey in the offer for recipient privacy.
74237426
///
74247427
/// # Limitations
74257428
///
@@ -7437,11 +7440,10 @@ where
74377440
let expanded_key = &self.inbound_payment_key;
74387441
let entropy = &*self.entropy_source;
74397442
let secp_ctx = &self.secp_ctx;
7440-
let path = self.create_one_hop_blinded_path();
74417443

74427444
OfferBuilder::deriving_signing_pubkey(description, node_id, expanded_key, entropy, secp_ctx)
74437445
.chain_hash(self.chain_hash)
7444-
.path(path)
7446+
.path(self.create_blinded_path())
74457447
}
74467448

74477449
/// Creates a [`RefundBuilder`] such that the [`Refund`] it builds is recognized by the
@@ -7466,10 +7468,13 @@ where
74667468
///
74677469
/// # Privacy
74687470
///
7469-
/// Uses a one-hop [`BlindedPath`] for the refund with [`ChannelManager::get_our_node_id`] as
7470-
/// the introduction node and a derived payer id for payer privacy. As such, currently, the
7471-
/// node must be announced. Otherwise, there is no way to find a path to the introduction node
7472-
/// in order to send the [`Bolt12Invoice`].
7471+
/// Uses [`MessageRouter::create_blinded_paths`] to construct a [`BlindedPath`] for the refund.
7472+
/// However, if one is not found, uses a one-hop [`BlindedPath`] with
7473+
/// [`ChannelManager::get_our_node_id`] as the introduction node instead. In the latter case,
7474+
/// the node must be announced, otherwise, there is no way to find a path to the introduction in
7475+
/// order to send the [`Bolt12Invoice`].
7476+
///
7477+
/// Also, uses a derived payer id in the refund for payer privacy.
74737478
///
74747479
/// # Limitations
74757480
///
@@ -7494,14 +7499,13 @@ where
74947499
let expanded_key = &self.inbound_payment_key;
74957500
let entropy = &*self.entropy_source;
74967501
let secp_ctx = &self.secp_ctx;
7497-
let path = self.create_one_hop_blinded_path();
74987502

74997503
let builder = RefundBuilder::deriving_payer_id(
75007504
description, node_id, expanded_key, entropy, secp_ctx, amount_msats, payment_id
75017505
)?
75027506
.chain_hash(self.chain_hash)
75037507
.absolute_expiry(absolute_expiry)
7504-
.path(path);
7508+
.path(self.create_blinded_path());
75057509

75067510
let expiration = StaleExpiration::AbsoluteTimeout(absolute_expiry);
75077511
self.pending_outbound_payments
@@ -7587,9 +7591,8 @@ where
75877591
None => builder,
75887592
Some(payer_note) => builder.payer_note(payer_note),
75897593
};
7590-
75917594
let invoice_request = builder.build_and_sign()?;
7592-
let reply_path = self.create_one_hop_blinded_path();
7595+
let reply_path = self.create_blinded_path();
75937596

75947597
let expiration = StaleExpiration::TimerTicks(1);
75957598
self.pending_outbound_payments
@@ -7665,7 +7668,7 @@ where
76657668
payment_paths, payment_hash, created_at, expanded_key, entropy
76667669
)?;
76677670
let invoice = builder.allow_mpp().build_and_sign(secp_ctx)?;
7668-
let reply_path = self.create_one_hop_blinded_path();
7671+
let reply_path = self.create_blinded_path();
76697672

76707673
let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap();
76717674
if refund.paths().is_empty() {
@@ -7792,6 +7795,15 @@ where
77927795
inbound_payment::get_payment_preimage(payment_hash, payment_secret, &self.inbound_payment_key)
77937796
}
77947797

7798+
/// Creates a multi-hop blinded path by delegating to [`MessageRouter::create_blinded_paths`].
7799+
/// If the router returns an error or no paths, creates a one-hop blinded path instead.
7800+
fn create_blinded_path(&self) -> BlindedPath {
7801+
self.create_multi_hop_blinded_paths(1)
7802+
.ok()
7803+
.and_then(|paths| paths.into_iter().next())
7804+
.unwrap_or_else(|| self.create_one_hop_blinded_path())
7805+
}
7806+
77957807
/// Creates a one-hop blinded path with [`ChannelManager::get_our_node_id`] as the introduction
77967808
/// node.
77977809
fn create_one_hop_blinded_path(&self) -> BlindedPath {
@@ -7800,6 +7812,25 @@ where
78007812
BlindedPath::one_hop_for_message(self.get_our_node_id(), entropy_source, secp_ctx).unwrap()
78017813
}
78027814

7815+
/// Creates `count` blinded paths by delegating to [`MessageRouter::create_blinded_paths`].
7816+
///
7817+
/// May return fewer paths if there are fewer than `count` peers that [support onion messages].
7818+
///
7819+
/// [support onion messages]: crate::ln::features::InitFeatures::supports_onion_messages
7820+
fn create_multi_hop_blinded_paths(&self, count: usize) -> Result<Vec<BlindedPath>, ()> {
7821+
let recipient = self.get_our_node_id();
7822+
let entropy_source = self.entropy_source.deref();
7823+
let secp_ctx = &self.secp_ctx;
7824+
7825+
let peers = self.per_peer_state.read().unwrap()
7826+
.iter()
7827+
.filter(|(_, peer)| peer.lock().unwrap().latest_features.supports_onion_messages())
7828+
.map(|(node_id, _)| *node_id)
7829+
.collect::<Vec<_>>();
7830+
7831+
self.router.create_blinded_paths(recipient, peers, count, entropy_source, secp_ctx)
7832+
}
7833+
78037834
/// Creates a one-hop blinded payment path with [`ChannelManager::get_our_node_id`] as the
78047835
/// introduction node.
78057836
fn create_one_hop_blinded_payment_path(

0 commit comments

Comments
 (0)