Skip to content

Commit 4032289

Browse files
committed
Enhance Path Diversification by Expanding create_blinded_paths Functionality
- Previously, the `create_blinded_path` function was limited to returning a single `BlindedPath`, restricting the usage of `blinded_paths`. - This commit extends `create_blinded_path` to support returning multiple `BlindedPaths` via a new `count` parameter. - The updated functionality is integrated across the codebase, allowing sending Offers Response messages, such as `InvoiceRequest` (in `pay_for_offer`) and `Invoice` (in `request_refund_payment`), now utilizing multiple reply paths. - As a proof-of-concept, the number of `blinded_paths` used in offer and refund responders is increased to 5, showcasing the capability of multiple reply paths.
1 parent 2701bc5 commit 4032289

File tree

7 files changed

+83
-47
lines changed

7 files changed

+83
-47
lines changed

fuzz/src/chanmon_consistency.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ impl MessageRouter for FuzzRouter {
124124
}
125125

126126
fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
127-
&self, _recipient: PublicKey, _peers: Vec<ForwardNode>, _secp_ctx: &Secp256k1<T>,
127+
&self, _recipient: PublicKey, _peers: Vec<ForwardNode>, _secp_ctx: &Secp256k1<T>, count: usize,
128128
) -> Result<Vec<BlindedPath>, ()> {
129129
unreachable!()
130130
}

fuzz/src/full_stack.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ impl MessageRouter for FuzzRouter {
162162
}
163163

164164
fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
165-
&self, _recipient: PublicKey, _peers: Vec<ForwardNode>, _secp_ctx: &Secp256k1<T>,
165+
&self, _recipient: PublicKey, _peers: Vec<ForwardNode>, _secp_ctx: &Secp256k1<T>, count: usize,
166166
) -> Result<Vec<BlindedPath>, ()> {
167167
unreachable!()
168168
}

fuzz/src/onion_message.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ impl MessageRouter for TestMessageRouter {
8989
}
9090

9191
fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
92-
&self, _recipient: PublicKey, _peers: Vec<ForwardNode>, _secp_ctx: &Secp256k1<T>,
92+
&self, _recipient: PublicKey, _peers: Vec<ForwardNode>, _secp_ctx: &Secp256k1<T>, count: usize
9393
) -> Result<Vec<BlindedPath>, ()> {
9494
unreachable!()
9595
}

lightning/src/ln/channelmanager.rs

+67-30
Original file line numberDiff line numberDiff line change
@@ -8270,7 +8270,12 @@ macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
82708270
let entropy = &*$self.entropy_source;
82718271
let secp_ctx = &$self.secp_ctx;
82728272

8273-
let path = $self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?;
8273+
// TODO: Introduce a parameter to allow adding more paths to the created Offer.
8274+
let path = $self.create_blinded_path(1)
8275+
.and_then(|paths| paths.into_iter().next().ok_or(()))
8276+
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
8277+
8278+
82748279
let builder = OfferBuilder::deriving_signing_pubkey(
82758280
node_id, expanded_key, entropy, secp_ctx
82768281
)
@@ -8337,7 +8342,11 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
83378342
let entropy = &*$self.entropy_source;
83388343
let secp_ctx = &$self.secp_ctx;
83398344

8340-
let path = $self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?;
8345+
// TODO: Introduce a parameter to allow adding more paths to the created Refund.
8346+
let path = $self.create_blinded_path(1)
8347+
.and_then(|paths| paths.into_iter().next().ok_or(()))
8348+
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
8349+
83418350
let builder = RefundBuilder::deriving_payer_id(
83428351
node_id, expanded_key, entropy, secp_ctx, amount_msats, payment_id
83438352
)?
@@ -8438,6 +8447,11 @@ where
84388447
payer_note: Option<String>, payment_id: PaymentId, retry_strategy: Retry,
84398448
max_total_routing_fee_msat: Option<u64>
84408449
) -> Result<(), Bolt12SemanticError> {
8450+
8451+
// Maximum number of unique reply paths to be calculated for use
8452+
// with the generated InvoiceRequest messages.
8453+
const MAX_REPLY_PATHS: usize = 5;
8454+
84418455
let expanded_key = &self.inbound_payment_key;
84428456
let entropy = &*self.entropy_source;
84438457
let secp_ctx = &self.secp_ctx;
@@ -8460,7 +8474,8 @@ where
84608474
Some(payer_note) => builder.payer_note(payer_note),
84618475
};
84628476
let invoice_request = builder.build_and_sign()?;
8463-
let reply_path = self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?;
8477+
let reply_paths = self.create_blinded_path(MAX_REPLY_PATHS)
8478+
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
84648479

84658480
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
84668481

@@ -8473,25 +8488,32 @@ where
84738488

84748489
let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap();
84758490
if !offer.paths().is_empty() {
8476-
// Send as many invoice requests as there are paths in the offer (with an upper bound).
8477-
// Using only one path could result in a failure if the path no longer exists. But only
8478-
// one invoice for a given payment id will be paid, even if more than one is received.
8491+
// Send as many invoice requests as there are paths in the offer using as many different
8492+
// reply_paths possible (with an upper bound).
8493+
// Using only one path could result in a failure if the path no longer exists.
8494+
// But only one invoice for a given payment ID will be paid, even if more than one is received.
84798495
const REQUEST_LIMIT: usize = 10;
8480-
for path in offer.paths().into_iter().take(REQUEST_LIMIT) {
8496+
reply_paths
8497+
.iter()
8498+
.flat_map(|reply_path| offer.paths().iter().map(move |path| (path, reply_path)))
8499+
.take(REQUEST_LIMIT)
8500+
.for_each(|(path, reply_path)| {
8501+
let message = new_pending_onion_message(
8502+
OffersMessage::InvoiceRequest(invoice_request.clone()),
8503+
Destination::BlindedPath(path.clone()),
8504+
Some(reply_path.clone()),
8505+
);
8506+
pending_offers_messages.push(message);
8507+
});
8508+
} else if let Some(signing_pubkey) = offer.signing_pubkey() {
8509+
for reply_path in reply_paths {
84818510
let message = new_pending_onion_message(
84828511
OffersMessage::InvoiceRequest(invoice_request.clone()),
8483-
Destination::BlindedPath(path.clone()),
8484-
Some(reply_path.clone()),
8512+
Destination::Node(signing_pubkey),
8513+
Some(reply_path),
84858514
);
84868515
pending_offers_messages.push(message);
84878516
}
8488-
} else if let Some(signing_pubkey) = offer.signing_pubkey() {
8489-
let message = new_pending_onion_message(
8490-
OffersMessage::InvoiceRequest(invoice_request),
8491-
Destination::Node(signing_pubkey),
8492-
Some(reply_path),
8493-
);
8494-
pending_offers_messages.push(message);
84958517
} else {
84968518
debug_assert!(false);
84978519
return Err(Bolt12SemanticError::MissingSigningPubkey);
@@ -8525,6 +8547,11 @@ where
85258547
pub fn request_refund_payment(
85268548
&self, refund: &Refund
85278549
) -> Result<Bolt12Invoice, Bolt12SemanticError> {
8550+
8551+
// Maximum number of unique reply paths to be calculated for use
8552+
// with the generated BOLT12Invoice messages.
8553+
const MAX_REPLY_PATHS: usize = 5;
8554+
85288555
let expanded_key = &self.inbound_payment_key;
85298556
let entropy = &*self.entropy_source;
85308557
let secp_ctx = &self.secp_ctx;
@@ -8560,26 +8587,37 @@ where
85608587
)?;
85618588
let builder: InvoiceBuilder<DerivedSigningPubkey> = builder.into();
85628589
let invoice = builder.allow_mpp().build_and_sign(secp_ctx)?;
8563-
let reply_path = self.create_blinded_path()
8590+
let reply_paths = self.create_blinded_path(MAX_REPLY_PATHS)
85648591
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
85658592

85668593
let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap();
85678594
if refund.paths().is_empty() {
8568-
let message = new_pending_onion_message(
8569-
OffersMessage::Invoice(invoice.clone()),
8570-
Destination::Node(refund.payer_id()),
8571-
Some(reply_path),
8572-
);
8573-
pending_offers_messages.push(message);
8574-
} else {
8575-
for path in refund.paths() {
8595+
for reply_path in reply_paths {
85768596
let message = new_pending_onion_message(
85778597
OffersMessage::Invoice(invoice.clone()),
8578-
Destination::BlindedPath(path.clone()),
8579-
Some(reply_path.clone()),
8598+
Destination::Node(refund.payer_id()),
8599+
Some(reply_path),
85808600
);
85818601
pending_offers_messages.push(message);
85828602
}
8603+
} else {
8604+
// Send as many BOLT12Invoices as there are paths in the refund using as many different
8605+
// reply_paths possible (with an upper bound).
8606+
// Using only one path could result in a failure if the path no longer exists.
8607+
// But only one invoice for a given payment ID will be paid, even if more than one is received.
8608+
const REQUEST_LIMIT: usize = 10;
8609+
reply_paths
8610+
.iter()
8611+
.flat_map(|reply_path| refund.paths().iter().map(move |path| (path, reply_path)))
8612+
.take(REQUEST_LIMIT)
8613+
.for_each(|(path, reply_path)| {
8614+
let message = new_pending_onion_message(
8615+
OffersMessage::Invoice(invoice.clone()),
8616+
Destination::BlindedPath(path.clone()),
8617+
Some(reply_path.clone()),
8618+
);
8619+
pending_offers_messages.push(message);
8620+
});
85838621
}
85848622

85858623
Ok(invoice)
@@ -8689,7 +8727,7 @@ where
86898727
/// Creates a blinded path by delegating to [`MessageRouter::create_blinded_paths`].
86908728
///
86918729
/// Errors if the `MessageRouter` errors or returns an empty `Vec`.
8692-
fn create_blinded_path(&self) -> Result<BlindedPath, ()> {
8730+
fn create_blinded_path(&self, count: usize) -> Result<Vec<BlindedPath>, ()> {
86938731
let recipient = self.get_our_node_id();
86948732
let secp_ctx = &self.secp_ctx;
86958733

@@ -8708,8 +8746,7 @@ where
87088746
.collect::<Vec<_>>();
87098747

87108748
self.router
8711-
.create_blinded_paths(recipient, peers, secp_ctx)
8712-
.and_then(|paths| paths.into_iter().next().ok_or(()))
8749+
.create_blinded_paths(recipient, peers, secp_ctx, count)
87138750
}
87148751

87158752
/// Creates multi-hop blinded payment paths for the given `amount_msats` by delegating to

lightning/src/onion_message/messenger.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ for OnionMessenger<ES, NS, L, NL, MR, OMH, CMH> where
162162
/// # })
163163
/// # }
164164
/// # fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
165-
/// # &self, _recipient: PublicKey, _peers: Vec<ForwardNode>, _secp_ctx: &Secp256k1<T>
165+
/// # &self, _recipient: PublicKey, _peers: Vec<ForwardNode>, _secp_ctx: &Secp256k1<T>, count: usize
166166
/// # ) -> Result<Vec<BlindedPath>, ()> {
167167
/// # unreachable!()
168168
/// # }
@@ -426,7 +426,7 @@ pub trait MessageRouter {
426426
fn create_blinded_paths<
427427
T: secp256k1::Signing + secp256k1::Verification
428428
>(
429-
&self, recipient: PublicKey, peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
429+
&self, recipient: PublicKey, peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>, count: usize,
430430
) -> Result<Vec<BlindedPath>, ()>;
431431
}
432432

@@ -492,11 +492,8 @@ where
492492
fn create_blinded_paths<
493493
T: secp256k1::Signing + secp256k1::Verification
494494
>(
495-
&self, recipient: PublicKey, peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
495+
&self, recipient: PublicKey, peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>, count: usize
496496
) -> Result<Vec<BlindedPath>, ()> {
497-
// Limit the number of blinded paths that are computed.
498-
const MAX_PATHS: usize = 3;
499-
500497
// Ensure peers have at least three channels so that it is more difficult to infer the
501498
// recipient's node_id.
502499
const MIN_PEER_CHANNELS: usize = 3;
@@ -526,7 +523,7 @@ where
526523
.map(|(peer, _, _)| {
527524
BlindedPath::new_for_message(&[peer], recipient, &*self.entropy_source, secp_ctx)
528525
})
529-
.take(MAX_PATHS)
526+
.take(count)
530527
.collect::<Result<Vec<_>, _>>();
531528

532529
let mut paths = match paths {
@@ -1073,6 +1070,8 @@ where
10731070
}
10741071

10751072
fn create_blinded_path(&self) -> Result<BlindedPath, SendError> {
1073+
// Maximum number of unique reply paths to be calculated.
1074+
const MAX_REPLY_PATHS: usize = 1;
10761075
let recipient = self.node_signer
10771076
.get_node_id(Recipient::Node)
10781077
.map_err(|_| SendError::GetNodeIdFailed)?;
@@ -1088,7 +1087,7 @@ where
10881087
.collect::<Vec<_>>();
10891088

10901089
self.message_router
1091-
.create_blinded_paths(recipient, peers, secp_ctx)
1090+
.create_blinded_paths(recipient, peers, secp_ctx, MAX_REPLY_PATHS)
10921091
.and_then(|paths| paths.into_iter().next().ok_or(()))
10931092
.map_err(|_| SendError::PathNotFound)
10941093
}

lightning/src/routing/router.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,9 @@ impl< G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, ES: Deref, S: Deref,
173173
fn create_blinded_paths<
174174
T: secp256k1::Signing + secp256k1::Verification
175175
> (
176-
&self, recipient: PublicKey, peers: Vec<message::ForwardNode>, secp_ctx: &Secp256k1<T>,
176+
&self, recipient: PublicKey, peers: Vec<message::ForwardNode>, secp_ctx: &Secp256k1<T>, count: usize,
177177
) -> Result<Vec<BlindedPath>, ()> {
178-
self.message_router.create_blinded_paths(recipient, peers, secp_ctx)
178+
self.message_router.create_blinded_paths(recipient, peers, secp_ctx, count)
179179
}
180180
}
181181

lightning/src/util/test_utils.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -250,9 +250,9 @@ impl<'a> MessageRouter for TestRouter<'a> {
250250
fn create_blinded_paths<
251251
T: secp256k1::Signing + secp256k1::Verification
252252
>(
253-
&self, recipient: PublicKey, peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
253+
&self, recipient: PublicKey, peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>, count: usize
254254
) -> Result<Vec<BlindedPath>, ()> {
255-
self.router.create_blinded_paths(recipient, peers, secp_ctx)
255+
self.router.create_blinded_paths(recipient, peers, secp_ctx, count)
256256
}
257257
}
258258

@@ -285,9 +285,9 @@ impl<'a> MessageRouter for TestMessageRouter<'a> {
285285
}
286286

287287
fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
288-
&self, recipient: PublicKey, peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>,
288+
&self, recipient: PublicKey, peers: Vec<ForwardNode>, secp_ctx: &Secp256k1<T>, count: usize,
289289
) -> Result<Vec<BlindedPath>, ()> {
290-
self.inner.create_blinded_paths(recipient, peers, secp_ctx)
290+
self.inner.create_blinded_paths(recipient, peers, secp_ctx, count)
291291
}
292292
}
293293

0 commit comments

Comments
 (0)