Skip to content

Commit 0136a66

Browse files
committed
Compact a BlindedPath's introduction node
Add a method to BlindedPath that given a network graph will compact the IntroductionNode as the DirectedShortChannelId variant. Call this method from DefaultMessageRouter so that Offer paths use the compact representation (along with reply paths). This leaves payment paths in Bolt12Invoice using the NodeId variant, as the compact representation isn't as useful there. WIP: Compact introduction node
1 parent 4dbb1f5 commit 0136a66

File tree

3 files changed

+62
-11
lines changed

3 files changed

+62
-11
lines changed

lightning/src/blinded_path/mod.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,30 @@ impl BlindedPath {
210210
},
211211
}
212212
}
213+
214+
/// Attempts to a use a compact representation for the [`IntroductionNode`] by using a directed
215+
/// short channel id from a channel in `network_graph` leading to the introduction node.
216+
pub fn compact_introduction_node(&mut self, network_graph: &ReadOnlyNetworkGraph) {
217+
if let IntroductionNode::NodeId(pubkey) = &self.introduction_node {
218+
let node_id = NodeId::from_pubkey(pubkey);
219+
if let Some(node_info) = network_graph.node(&node_id) {
220+
if let Some((scid, channel_info)) = node_info
221+
.channels
222+
.iter()
223+
.find_map(|scid| network_graph.channel(*scid).map(|info| (*scid, info)))
224+
{
225+
let direction = if node_id == channel_info.node_one {
226+
Direction::NodeOne
227+
} else {
228+
debug_assert_eq!(node_id, channel_info.node_two);
229+
Direction::NodeTwo
230+
};
231+
self.introduction_node =
232+
IntroductionNode::DirectedShortChannelId(direction, scid);
233+
}
234+
}
235+
}
236+
}
213237
}
214238

215239
impl Writeable for BlindedPath {

lightning/src/ln/offers_tests.rs

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
//! blinded paths are used.
4242
4343
use bitcoin::network::constants::Network;
44+
use bitcoin::secp256k1::PublicKey;
4445
use core::time::Duration;
4546
use crate::blinded_path::{BlindedPath, IntroductionNode};
4647
use crate::blinded_path::payment::{Bolt12OfferContext, Bolt12RefundContext, PaymentContext};
@@ -134,6 +135,12 @@ fn announce_node_address<'a, 'b, 'c>(
134135
}
135136
}
136137

138+
fn resolve_introduction_node<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, path: &BlindedPath) -> PublicKey {
139+
path.public_introduction_node_id(&node.network_graph.read_only())
140+
.and_then(|node_id| node_id.as_pubkey().ok())
141+
.unwrap()
142+
}
143+
137144
fn route_bolt12_payment<'a, 'b, 'c>(
138145
node: &Node<'a, 'b, 'c>, path: &[&Node<'a, 'b, 'c>], invoice: &Bolt12Invoice
139146
) {
@@ -274,8 +281,9 @@ fn prefers_non_tor_nodes_in_blinded_paths() {
274281
assert_ne!(offer.signing_pubkey(), bob_id);
275282
assert!(!offer.paths().is_empty());
276283
for path in offer.paths() {
277-
assert_ne!(path.introduction_node, IntroductionNode::NodeId(bob_id));
278-
assert_ne!(path.introduction_node, IntroductionNode::NodeId(charlie_id));
284+
let introduction_node_id = resolve_introduction_node(david, &path);
285+
assert_ne!(introduction_node_id, bob_id);
286+
assert_ne!(introduction_node_id, charlie_id);
279287
}
280288

281289
// Use a one-hop blinded path when Bob is announced and all his peers are Tor-only.
@@ -289,7 +297,8 @@ fn prefers_non_tor_nodes_in_blinded_paths() {
289297
assert_ne!(offer.signing_pubkey(), bob_id);
290298
assert!(!offer.paths().is_empty());
291299
for path in offer.paths() {
292-
assert_eq!(path.introduction_node, IntroductionNode::NodeId(bob_id));
300+
let introduction_node_id = resolve_introduction_node(david, &path);
301+
assert_eq!(introduction_node_id, bob_id);
293302
}
294303
}
295304

@@ -339,7 +348,8 @@ fn prefers_more_connected_nodes_in_blinded_paths() {
339348
assert_ne!(offer.signing_pubkey(), bob_id);
340349
assert!(!offer.paths().is_empty());
341350
for path in offer.paths() {
342-
assert_eq!(path.introduction_node, IntroductionNode::NodeId(nodes[4].node.get_our_node_id()));
351+
let introduction_node_id = resolve_introduction_node(david, &path);
352+
assert_eq!(introduction_node_id, nodes[4].node.get_our_node_id());
343353
}
344354
}
345355

@@ -389,7 +399,9 @@ fn creates_and_pays_for_offer_using_two_hop_blinded_path() {
389399
assert_ne!(offer.signing_pubkey(), alice_id);
390400
assert!(!offer.paths().is_empty());
391401
for path in offer.paths() {
392-
assert_eq!(path.introduction_node, IntroductionNode::NodeId(bob_id));
402+
let introduction_node_id = resolve_introduction_node(david, &path);
403+
assert_eq!(introduction_node_id, bob_id);
404+
assert!(matches!(path.introduction_node, IntroductionNode::DirectedShortChannelId(..)));
393405
}
394406

395407
let payment_id = PaymentId([1; 32]);
@@ -418,9 +430,11 @@ fn creates_and_pays_for_offer_using_two_hop_blinded_path() {
418430
payer_note_truncated: None,
419431
},
420432
});
433+
let introduction_node_id = resolve_introduction_node(alice, &reply_path);
421434
assert_eq!(invoice_request.amount_msats(), None);
422435
assert_ne!(invoice_request.payer_id(), david_id);
423-
assert_eq!(reply_path.introduction_node, IntroductionNode::NodeId(charlie_id));
436+
assert_eq!(introduction_node_id, charlie_id);
437+
assert!(matches!(reply_path.introduction_node, IntroductionNode::DirectedShortChannelId(..)));
424438

425439
let onion_message = alice.onion_messenger.next_onion_message_for_peer(charlie_id).unwrap();
426440
charlie.onion_messenger.handle_onion_message(&alice_id, &onion_message);
@@ -494,7 +508,9 @@ fn creates_and_pays_for_refund_using_two_hop_blinded_path() {
494508
assert_ne!(refund.payer_id(), david_id);
495509
assert!(!refund.paths().is_empty());
496510
for path in refund.paths() {
497-
assert_eq!(path.introduction_node, IntroductionNode::NodeId(charlie_id));
511+
let introduction_node_id = resolve_introduction_node(alice, &path);
512+
assert_eq!(introduction_node_id, charlie_id);
513+
assert!(matches!(path.introduction_node, IntroductionNode::DirectedShortChannelId(..)));
498514
}
499515
expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id);
500516

@@ -550,7 +566,9 @@ fn creates_and_pays_for_offer_using_one_hop_blinded_path() {
550566
assert_ne!(offer.signing_pubkey(), alice_id);
551567
assert!(!offer.paths().is_empty());
552568
for path in offer.paths() {
553-
assert_eq!(path.introduction_node, IntroductionNode::NodeId(alice_id));
569+
let introduction_node_id = resolve_introduction_node(bob, &path);
570+
assert_eq!(introduction_node_id, alice_id);
571+
assert!(matches!(path.introduction_node, IntroductionNode::DirectedShortChannelId(..)));
554572
}
555573

556574
let payment_id = PaymentId([1; 32]);
@@ -571,9 +589,11 @@ fn creates_and_pays_for_offer_using_one_hop_blinded_path() {
571589
payer_note_truncated: None,
572590
},
573591
});
592+
let introduction_node_id = resolve_introduction_node(alice, &reply_path);
574593
assert_eq!(invoice_request.amount_msats(), None);
575594
assert_ne!(invoice_request.payer_id(), bob_id);
576-
assert_eq!(reply_path.introduction_node, IntroductionNode::NodeId(bob_id));
595+
assert_eq!(introduction_node_id, bob_id);
596+
assert!(matches!(reply_path.introduction_node, IntroductionNode::DirectedShortChannelId(..)));
577597

578598
let onion_message = alice.onion_messenger.next_onion_message_for_peer(bob_id).unwrap();
579599
bob.onion_messenger.handle_onion_message(&alice_id, &onion_message);
@@ -623,7 +643,9 @@ fn creates_and_pays_for_refund_using_one_hop_blinded_path() {
623643
assert_ne!(refund.payer_id(), bob_id);
624644
assert!(!refund.paths().is_empty());
625645
for path in refund.paths() {
626-
assert_eq!(path.introduction_node, IntroductionNode::NodeId(bob_id));
646+
let introduction_node_id = resolve_introduction_node(alice, &path);
647+
assert_eq!(introduction_node_id, bob_id);
648+
assert!(matches!(path.introduction_node, IntroductionNode::DirectedShortChannelId(..)));
627649
}
628650
expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id);
629651

lightning/src/onion_message/messenger.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ where
414414
.take(MAX_PATHS)
415415
.collect::<Result<Vec<_>, _>>();
416416

417-
match paths {
417+
let mut paths = match paths {
418418
Ok(paths) if !paths.is_empty() => Ok(paths),
419419
_ => {
420420
if is_recipient_announced {
@@ -424,7 +424,12 @@ where
424424
Err(())
425425
}
426426
},
427+
}?;
428+
for path in &mut paths {
429+
path.compact_introduction_node(&network_graph);
427430
}
431+
432+
Ok(paths)
428433
}
429434
}
430435

0 commit comments

Comments
 (0)