Skip to content

Commit 4108d03

Browse files
shaavanjkczyz
authored andcommitted
Allow create_blinded_paths Function to Take Recipient TLVs as a Field
- Enabled `create_blinded_paths` to accept `RecipientData` TLVs as an input field. - `RecipientData` is intended to be sent along with the `reply_path` to the counterparty. - Added `RecipientData` in the `create_blinded_paths` flow, optionally appending it within the `reply_path`. - Updated tests to verify the new feature.
1 parent bce6cd3 commit 4108d03

13 files changed

+117
-65
lines changed

fuzz/src/chanmon_consistency.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use bitcoin::hashes::sha256d::Hash as Sha256dHash;
3333
use bitcoin::hashes::Hash as TraitImport;
3434
use bitcoin::WPubkeyHash;
3535

36+
use lightning::blinded_path::message::MessageContext;
3637
use lightning::blinded_path::payment::ReceiveTlvs;
3738
use lightning::blinded_path::BlindedPath;
3839
use lightning::chain;
@@ -138,7 +139,8 @@ impl MessageRouter for FuzzRouter {
138139
}
139140

140141
fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
141-
&self, _recipient: PublicKey, _peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>,
142+
&self, _recipient: PublicKey, _recipient_data: Option<MessageContext>,
143+
_peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>,
142144
) -> Result<Vec<BlindedPath>, ()> {
143145
unreachable!()
144146
}

fuzz/src/full_stack.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use bitcoin::hashes::sha256d::Hash as Sha256dHash;
3030
use bitcoin::hashes::Hash as _;
3131
use bitcoin::WPubkeyHash;
3232

33+
use lightning::blinded_path::message::MessageContext;
3334
use lightning::blinded_path::payment::ReceiveTlvs;
3435
use lightning::blinded_path::BlindedPath;
3536
use lightning::chain;
@@ -175,7 +176,8 @@ impl MessageRouter for FuzzRouter {
175176
}
176177

177178
fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
178-
&self, _recipient: PublicKey, _peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>,
179+
&self, _recipient: PublicKey, _recipient_data: Option<MessageContext>,
180+
_peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>,
179181
) -> Result<Vec<BlindedPath>, ()> {
180182
unreachable!()
181183
}

fuzz/src/invoice_request_deser.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,22 @@ fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
8787
],
8888
];
8989
let paths = vec![
90-
BlindedPath::new_for_message(&intermediate_nodes[0], pubkey(42), &entropy_source, secp_ctx)
91-
.unwrap(),
92-
BlindedPath::new_for_message(&intermediate_nodes[1], pubkey(42), &entropy_source, secp_ctx)
93-
.unwrap(),
90+
BlindedPath::new_for_message(
91+
&intermediate_nodes[0],
92+
pubkey(42),
93+
None,
94+
&entropy_source,
95+
secp_ctx,
96+
)
97+
.unwrap(),
98+
BlindedPath::new_for_message(
99+
&intermediate_nodes[1],
100+
pubkey(42),
101+
None,
102+
&entropy_source,
103+
secp_ctx,
104+
)
105+
.unwrap(),
94106
];
95107

96108
let payinfo = vec![

fuzz/src/onion_message.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ impl MessageRouter for TestMessageRouter {
9595
}
9696

9797
fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
98-
&self, _recipient: PublicKey, _peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>,
98+
&self, _recipient: PublicKey, _recipient_data: Option<MessageContext>,
99+
_peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>,
99100
) -> Result<Vec<BlindedPath>, ()> {
100101
unreachable!()
101102
}

fuzz/src/refund_deser.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,22 @@ fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
7676
],
7777
];
7878
let paths = vec![
79-
BlindedPath::new_for_message(&intermediate_nodes[0], pubkey(42), &entropy_source, secp_ctx)
80-
.unwrap(),
81-
BlindedPath::new_for_message(&intermediate_nodes[1], pubkey(42), &entropy_source, secp_ctx)
82-
.unwrap(),
79+
BlindedPath::new_for_message(
80+
&intermediate_nodes[0],
81+
pubkey(42),
82+
None,
83+
&entropy_source,
84+
secp_ctx,
85+
)
86+
.unwrap(),
87+
BlindedPath::new_for_message(
88+
&intermediate_nodes[1],
89+
pubkey(42),
90+
None,
91+
&entropy_source,
92+
secp_ctx,
93+
)
94+
.unwrap(),
8395
];
8496

8597
let payinfo = vec![

lightning/src/blinded_path/message.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
//! [`BlindedPath`]: crate::blinded_path::BlindedPath
1313
1414
use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey};
15+
1516
#[allow(unused_imports)]
1617
use crate::prelude::*;
1718

@@ -155,7 +156,7 @@ impl_writeable_tlv_based_enum!(OffersContext,
155156
/// Construct blinded onion message hops for the given `intermediate_nodes` and `recipient_node_id`.
156157
pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
157158
secp_ctx: &Secp256k1<T>, intermediate_nodes: &[ForwardNode], recipient_node_id: PublicKey,
158-
session_priv: &SecretKey
159+
context: Option<MessageContext>, session_priv: &SecretKey
159160
) -> Result<Vec<BlindedHop>, secp256k1::Error> {
160161
let pks = intermediate_nodes.iter().map(|node| &node.node_id)
161162
.chain(core::iter::once(&recipient_node_id));
@@ -167,7 +168,7 @@ pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
167168
None => NextMessageHop::NodeId(*pubkey),
168169
})
169170
.map(|next_hop| ControlTlvs::Forward(ForwardTlvs { next_hop, next_blinding_override: None }))
170-
.chain(core::iter::once(ControlTlvs::Receive(ReceiveTlvs { context: None })));
171+
.chain(core::iter::once(ControlTlvs::Receive(ReceiveTlvs{ context })));
171172

172173
utils::construct_blinded_hops(secp_ctx, pks, tlvs, session_priv)
173174
}

lightning/src/blinded_path/mod.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pub mod message;
1414
pub(crate) mod utils;
1515

1616
use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey};
17+
use message::MessageContext;
1718
use core::ops::Deref;
1819

1920
use crate::ln::msgs::DecodeError;
@@ -123,9 +124,9 @@ pub struct BlindedHop {
123124
impl BlindedPath {
124125
/// Create a one-hop blinded path for a message.
125126
pub fn one_hop_for_message<ES: Deref, T: secp256k1::Signing + secp256k1::Verification>(
126-
recipient_node_id: PublicKey, entropy_source: ES, secp_ctx: &Secp256k1<T>
127+
recipient_node_id: PublicKey, context: Option<MessageContext>, entropy_source: ES, secp_ctx: &Secp256k1<T>
127128
) -> Result<Self, ()> where ES::Target: EntropySource {
128-
Self::new_for_message(&[], recipient_node_id, entropy_source, secp_ctx)
129+
Self::new_for_message(&[], recipient_node_id, context, entropy_source, secp_ctx)
129130
}
130131

131132
/// Create a blinded path for an onion message, to be forwarded along `node_pks`. The last node
@@ -135,7 +136,7 @@ impl BlindedPath {
135136
// TODO: make all payloads the same size with padding + add dummy hops
136137
pub fn new_for_message<ES: Deref, T: secp256k1::Signing + secp256k1::Verification>(
137138
intermediate_nodes: &[message::ForwardNode], recipient_node_id: PublicKey,
138-
entropy_source: ES, secp_ctx: &Secp256k1<T>
139+
context: Option<MessageContext>, entropy_source: ES, secp_ctx: &Secp256k1<T>
139140
) -> Result<Self, ()> where ES::Target: EntropySource {
140141
let introduction_node = IntroductionNode::NodeId(
141142
intermediate_nodes.first().map_or(recipient_node_id, |n| n.node_id)
@@ -147,7 +148,8 @@ impl BlindedPath {
147148
introduction_node,
148149
blinding_point: PublicKey::from_secret_key(secp_ctx, &blinding_secret),
149150
blinded_hops: message::blinded_hops(
150-
secp_ctx, intermediate_nodes, recipient_node_id, &blinding_secret,
151+
secp_ctx, intermediate_nodes, recipient_node_id,
152+
context, &blinding_secret,
151153
).map_err(|_| ())?,
152154
})
153155
}

lightning/src/ln/channelmanager.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use bitcoin::secp256k1::Secp256k1;
3232
use bitcoin::{secp256k1, Sequence};
3333

3434
use crate::blinded_path::{BlindedPath, NodeIdLookUp};
35-
use crate::blinded_path::message::{ForwardNode, OffersContext};
35+
use crate::blinded_path::message::{ForwardNode, MessageContext, OffersContext};
3636
use crate::blinded_path::payment::{Bolt12OfferContext, Bolt12RefundContext, PaymentConstraints, PaymentContext, ReceiveTlvs};
3737
use crate::chain;
3838
use crate::chain::{Confirm, ChannelMonitorUpdateStatus, Watch, BestBlock};
@@ -8814,7 +8814,7 @@ where
88148814
let max_short_lived_absolute_expiry = now.saturating_add(MAX_SHORT_LIVED_RELATIVE_EXPIRY);
88158815

88168816
if absolute_expiry.unwrap_or(Duration::MAX) <= max_short_lived_absolute_expiry {
8817-
self.create_compact_blinded_path()
8817+
self.create_compact_blinded_path(context)
88188818
} else {
88198819
self.create_blinded_path(context)
88208820
}
@@ -8836,7 +8836,7 @@ where
88368836
/// Creates a blinded path by delegating to [`MessageRouter::create_blinded_paths`].
88378837
///
88388838
/// Errors if the `MessageRouter` errors or returns an empty `Vec`.
8839-
fn create_blinded_path(&self, _context: OffersContext) -> Result<BlindedPath, ()> {
8839+
fn create_blinded_path(&self, context: OffersContext) -> Result<BlindedPath, ()> {
88408840
let recipient = self.get_our_node_id();
88418841
let secp_ctx = &self.secp_ctx;
88428842

@@ -8848,15 +8848,16 @@ where
88488848
.map(|(node_id, _)| *node_id)
88498849
.collect::<Vec<_>>();
88508850

8851+
let context = Some(MessageContext::Offers(context));
88518852
self.router
8852-
.create_blinded_paths(recipient, peers, secp_ctx)
8853+
.create_blinded_paths(recipient, context, peers, secp_ctx)
88538854
.and_then(|paths| paths.into_iter().next().ok_or(()))
88548855
}
88558856

88568857
/// Creates a blinded path by delegating to [`MessageRouter::create_compact_blinded_paths`].
88578858
///
88588859
/// Errors if the `MessageRouter` errors or returns an empty `Vec`.
8859-
fn create_compact_blinded_path(&self) -> Result<BlindedPath, ()> {
8860+
fn create_compact_blinded_path(&self, context: OffersContext) -> Result<BlindedPath, ()> {
88608861
let recipient = self.get_our_node_id();
88618862
let secp_ctx = &self.secp_ctx;
88628863

@@ -8875,8 +8876,9 @@ where
88758876
})
88768877
.collect::<Vec<_>>();
88778878

8879+
let context = Some(MessageContext::Offers(context));
88788880
self.router
8879-
.create_compact_blinded_paths(recipient, peers, secp_ctx)
8881+
.create_compact_blinded_paths(recipient, context, peers, secp_ctx)
88808882
.and_then(|paths| paths.into_iter().next().ok_or(()))
88818883
}
88828884

lightning/src/ln/offers_tests.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1412,6 +1412,14 @@ fn fails_sending_invoice_without_blinded_payment_paths_for_offer() {
14121412

14131413
let invoice_error = extract_invoice_error(david, &onion_message);
14141414
assert_eq!(invoice_error, InvoiceError::from(Bolt12SemanticError::MissingPaths));
1415+
1416+
// Confirm that david drops this failed payment from his pending outbound payments.
1417+
match get_event!(david, Event::InvoiceRequestFailed) {
1418+
Event::InvoiceRequestFailed { payment_id: pay_id } => {
1419+
assert_eq!(pay_id, payment_id)
1420+
},
1421+
_ => panic!("No Event::InvoiceRequestFailed"),
1422+
}
14151423
}
14161424

14171425
#[test]

lightning/src/onion_message/functional_tests.rs

+15-15
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ fn one_blinded_hop() {
372372
let test_msg = TestCustomMessage::Pong;
373373

374374
let secp_ctx = Secp256k1::new();
375-
let blinded_path = BlindedPath::new_for_message(&[], nodes[1].node_id, &*nodes[1].entropy_source, &secp_ctx).unwrap();
375+
let blinded_path = BlindedPath::new_for_message(&[], nodes[1].node_id, None, &*nodes[1].entropy_source, &secp_ctx).unwrap();
376376
let destination = Destination::BlindedPath(blinded_path);
377377
nodes[0].messenger.send_onion_message(test_msg, destination, None).unwrap();
378378
nodes[1].custom_message_handler.expect_message(TestCustomMessage::Pong);
@@ -386,7 +386,7 @@ fn two_unblinded_two_blinded() {
386386

387387
let secp_ctx = Secp256k1::new();
388388
let intermediate_nodes = [ForwardNode { node_id: nodes[3].node_id, short_channel_id: None }];
389-
let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[4].node_id, &*nodes[4].entropy_source, &secp_ctx).unwrap();
389+
let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[4].node_id, None, &*nodes[4].entropy_source, &secp_ctx).unwrap();
390390
let path = OnionMessagePath {
391391
intermediate_nodes: vec![nodes[1].node_id, nodes[2].node_id],
392392
destination: Destination::BlindedPath(blinded_path),
@@ -408,7 +408,7 @@ fn three_blinded_hops() {
408408
ForwardNode { node_id: nodes[1].node_id, short_channel_id: None },
409409
ForwardNode { node_id: nodes[2].node_id, short_channel_id: None },
410410
];
411-
let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[3].node_id, &*nodes[3].entropy_source, &secp_ctx).unwrap();
411+
let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[3].node_id, None, &*nodes[3].entropy_source, &secp_ctx).unwrap();
412412
let destination = Destination::BlindedPath(blinded_path);
413413

414414
nodes[0].messenger.send_onion_message(test_msg, destination, None).unwrap();
@@ -430,7 +430,7 @@ fn async_response_over_one_blinded_hop() {
430430

431431
// 3. Simulate the creation of a Blinded Reply path provided by Bob.
432432
let secp_ctx = Secp256k1::new();
433-
let reply_path = BlindedPath::new_for_message(&[], nodes[1].node_id, &*nodes[1].entropy_source, &secp_ctx).unwrap();
433+
let reply_path = BlindedPath::new_for_message(&[], nodes[1].node_id, None, &*nodes[1].entropy_source, &secp_ctx).unwrap();
434434

435435
// 4. Create a responder using the reply path for Alice.
436436
let responder = Some(Responder::new(reply_path));
@@ -465,7 +465,7 @@ fn async_response_with_reply_path_succeeds() {
465465

466466
// Alice receives a message from Bob with an added reply_path for responding back.
467467
let message = TestCustomMessage::Ping;
468-
let reply_path = BlindedPath::new_for_message(&[], bob.node_id, &*bob.entropy_source, &secp_ctx).unwrap();
468+
let reply_path = BlindedPath::new_for_message(&[], bob.node_id, None, &*bob.entropy_source, &secp_ctx).unwrap();
469469

470470
// Alice asynchronously responds to Bob, expecting a response back from him.
471471
let responder = Responder::new(reply_path);
@@ -501,7 +501,7 @@ fn async_response_with_reply_path_fails() {
501501

502502
// Alice receives a message from Bob with an added reply_path for responding back.
503503
let message = TestCustomMessage::Ping;
504-
let reply_path = BlindedPath::new_for_message(&[], bob.node_id, &*bob.entropy_source, &secp_ctx).unwrap();
504+
let reply_path = BlindedPath::new_for_message(&[], bob.node_id, None, &*bob.entropy_source, &secp_ctx).unwrap();
505505

506506
// Alice tries to asynchronously respond to Bob, but fails because the nodes are unannounced and
507507
// disconnected. Thus, a reply path could no be created for the response.
@@ -545,7 +545,7 @@ fn we_are_intro_node() {
545545
ForwardNode { node_id: nodes[0].node_id, short_channel_id: None },
546546
ForwardNode { node_id: nodes[1].node_id, short_channel_id: None },
547547
];
548-
let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[2].node_id, &*nodes[2].entropy_source, &secp_ctx).unwrap();
548+
let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[2].node_id, None, &*nodes[2].entropy_source, &secp_ctx).unwrap();
549549
let destination = Destination::BlindedPath(blinded_path);
550550

551551
nodes[0].messenger.send_onion_message(test_msg.clone(), destination, None).unwrap();
@@ -554,7 +554,7 @@ fn we_are_intro_node() {
554554

555555
// Try with a two-hop blinded path where we are the introduction node.
556556
let intermediate_nodes = [ForwardNode { node_id: nodes[0].node_id, short_channel_id: None }];
557-
let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[1].node_id, &*nodes[1].entropy_source, &secp_ctx).unwrap();
557+
let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[1].node_id, None, &*nodes[1].entropy_source, &secp_ctx).unwrap();
558558
let destination = Destination::BlindedPath(blinded_path);
559559
nodes[0].messenger.send_onion_message(test_msg, destination, None).unwrap();
560560
nodes[1].custom_message_handler.expect_message(TestCustomMessage::Pong);
@@ -570,7 +570,7 @@ fn invalid_blinded_path_error() {
570570

571571
let secp_ctx = Secp256k1::new();
572572
let intermediate_nodes = [ForwardNode { node_id: nodes[1].node_id, short_channel_id: None }];
573-
let mut blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[2].node_id, &*nodes[2].entropy_source, &secp_ctx).unwrap();
573+
let mut blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[2].node_id, None, &*nodes[2].entropy_source, &secp_ctx).unwrap();
574574
blinded_path.blinded_hops.clear();
575575
let destination = Destination::BlindedPath(blinded_path);
576576
let err = nodes[0].messenger.send_onion_message(test_msg, destination, None).unwrap_err();
@@ -593,7 +593,7 @@ fn reply_path() {
593593
ForwardNode { node_id: nodes[2].node_id, short_channel_id: None },
594594
ForwardNode { node_id: nodes[1].node_id, short_channel_id: None },
595595
];
596-
let reply_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[0].node_id, &*nodes[0].entropy_source, &secp_ctx).unwrap();
596+
let reply_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[0].node_id, None, &*nodes[0].entropy_source, &secp_ctx).unwrap();
597597
nodes[0].messenger.send_onion_message_using_path(path, test_msg.clone(), Some(reply_path)).unwrap();
598598
nodes[3].custom_message_handler.expect_message(TestCustomMessage::Ping);
599599
pass_along_path(&nodes);
@@ -607,13 +607,13 @@ fn reply_path() {
607607
ForwardNode { node_id: nodes[1].node_id, short_channel_id: None },
608608
ForwardNode { node_id: nodes[2].node_id, short_channel_id: None },
609609
];
610-
let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[3].node_id, &*nodes[3].entropy_source, &secp_ctx).unwrap();
610+
let blinded_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[3].node_id, None, &*nodes[3].entropy_source, &secp_ctx).unwrap();
611611
let destination = Destination::BlindedPath(blinded_path);
612612
let intermediate_nodes = [
613613
ForwardNode { node_id: nodes[2].node_id, short_channel_id: None },
614614
ForwardNode { node_id: nodes[1].node_id, short_channel_id: None },
615615
];
616-
let reply_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[0].node_id, &*nodes[0].entropy_source, &secp_ctx).unwrap();
616+
let reply_path = BlindedPath::new_for_message(&intermediate_nodes, nodes[0].node_id, None, &*nodes[0].entropy_source, &secp_ctx).unwrap();
617617

618618
nodes[0].messenger.send_onion_message(test_msg, destination, Some(reply_path)).unwrap();
619619
nodes[3].custom_message_handler.expect_message(TestCustomMessage::Ping);
@@ -695,7 +695,7 @@ fn requests_peer_connection_for_buffered_messages() {
695695

696696
let intermediate_nodes = [ForwardNode { node_id: nodes[1].node_id, short_channel_id: None }];
697697
let blinded_path = BlindedPath::new_for_message(
698-
&intermediate_nodes, nodes[2].node_id, &*nodes[0].entropy_source, &secp_ctx
698+
&intermediate_nodes, nodes[2].node_id, None, &*nodes[0].entropy_source, &secp_ctx
699699
).unwrap();
700700
let destination = Destination::BlindedPath(blinded_path);
701701

@@ -733,7 +733,7 @@ fn drops_buffered_messages_waiting_for_peer_connection() {
733733

734734
let intermediate_nodes = [ForwardNode { node_id: nodes[1].node_id, short_channel_id: None }];
735735
let blinded_path = BlindedPath::new_for_message(
736-
&intermediate_nodes, nodes[2].node_id, &*nodes[0].entropy_source, &secp_ctx
736+
&intermediate_nodes, nodes[2].node_id, None, &*nodes[0].entropy_source, &secp_ctx
737737
).unwrap();
738738
let destination = Destination::BlindedPath(blinded_path);
739739

@@ -783,7 +783,7 @@ fn intercept_offline_peer_oms() {
783783
let secp_ctx = Secp256k1::new();
784784
let intermediate_nodes = [ForwardNode { node_id: nodes[1].node_id, short_channel_id: None }];
785785
let blinded_path = BlindedPath::new_for_message(
786-
&intermediate_nodes, nodes[2].node_id, &*nodes[2].entropy_source, &secp_ctx
786+
&intermediate_nodes, nodes[2].node_id, None, &*nodes[2].entropy_source, &secp_ctx
787787
).unwrap();
788788
let destination = Destination::BlindedPath(blinded_path);
789789

0 commit comments

Comments
 (0)