Skip to content

Commit 0b9bdfb

Browse files
committed
Allow create_blinded_paths function to take Recipient Data as a field
1. Recipient Data is intended to be sent along with the reply_path provided to the counterparty. 2. This commit introduces recipient data in the create_blinded_path flow, optionally appending it within the created reply_path. 3. Also update the test, to test the new added feature.
1 parent c7a3bf5 commit 0b9bdfb

13 files changed

+77
-49
lines changed

fuzz/src/chanmon_consistency.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use bitcoin::hashes::sha256d::Hash as Sha256dHash;
3131
use bitcoin::hash_types::{BlockHash, WPubkeyHash};
3232

3333
use lightning::blinded_path::BlindedPath;
34+
use lightning::blinded_path::message::RecipientData;
3435
use lightning::blinded_path::payment::ReceiveTlvs;
3536
use lightning::chain;
3637
use lightning::chain::{BestBlock, ChannelMonitorUpdateStatus, chainmonitor, channelmonitor, Confirm, Watch};
@@ -119,7 +120,7 @@ impl MessageRouter for FuzzRouter {
119120
}
120121

121122
fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
122-
&self, _recipient: PublicKey, _peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>,
123+
&self, _recipient: PublicKey, _recipient_data: Option<RecipientData>, _peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>,
123124
) -> Result<Vec<BlindedPath>, ()> {
124125
unreachable!()
125126
}

fuzz/src/full_stack.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use bitcoin::hashes::sha256d::Hash as Sha256dHash;
2828
use bitcoin::hash_types::{Txid, BlockHash, WPubkeyHash};
2929

3030
use lightning::blinded_path::BlindedPath;
31+
use lightning::blinded_path::message::RecipientData;
3132
use lightning::blinded_path::payment::ReceiveTlvs;
3233
use lightning::chain;
3334
use lightning::chain::{BestBlock, ChannelMonitorUpdateStatus, Confirm, Listen};
@@ -157,7 +158,7 @@ impl MessageRouter for FuzzRouter {
157158
}
158159

159160
fn create_blinded_paths<T: secp256k1::Signing + secp256k1::Verification>(
160-
&self, _recipient: PublicKey, _peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>,
161+
&self, _recipient: PublicKey, _recipient_data: Option<RecipientData>, _peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>,
161162
) -> Result<Vec<BlindedPath>, ()> {
162163
unreachable!()
163164
}

fuzz/src/invoice_request_deser.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
7474
) -> Result<UnsignedBolt12Invoice, Bolt12SemanticError> {
7575
let entropy_source = Randomness {};
7676
let paths = vec![
77-
BlindedPath::new_for_message(&[pubkey(43), pubkey(44), pubkey(42)], &entropy_source, secp_ctx).unwrap(),
78-
BlindedPath::new_for_message(&[pubkey(45), pubkey(46), pubkey(42)], &entropy_source, secp_ctx).unwrap(),
77+
BlindedPath::new_for_message(&[pubkey(43), pubkey(44), pubkey(42)], None, &entropy_source, secp_ctx).unwrap(),
78+
BlindedPath::new_for_message(&[pubkey(45), pubkey(46), pubkey(42)], None, &entropy_source, secp_ctx).unwrap(),
7979
];
8080

8181
let payinfo = vec![

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<PublicKey>, _secp_ctx: &Secp256k1<T>,
92+
&self, _recipient: PublicKey, _recipient_data: Option<RecipientData>, _peers: Vec<PublicKey>, _secp_ctx: &Secp256k1<T>,
9393
) -> Result<Vec<BlindedPath>, ()> {
9494
unreachable!()
9595
}

fuzz/src/refund_deser.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ fn build_response<T: secp256k1::Signing + secp256k1::Verification>(
6363
) -> Result<UnsignedBolt12Invoice, Bolt12SemanticError> {
6464
let entropy_source = Randomness {};
6565
let paths = vec![
66-
BlindedPath::new_for_message(&[pubkey(43), pubkey(44), pubkey(42)], &entropy_source, secp_ctx).unwrap(),
67-
BlindedPath::new_for_message(&[pubkey(45), pubkey(46), pubkey(42)], &entropy_source, secp_ctx).unwrap(),
66+
BlindedPath::new_for_message(&[pubkey(43), pubkey(44), pubkey(42)], None, &entropy_source, secp_ctx).unwrap(),
67+
BlindedPath::new_for_message(&[pubkey(45), pubkey(46), pubkey(42)], None, &entropy_source, secp_ctx).unwrap(),
6868
];
6969

7070
let payinfo = vec![

lightning/src/blinded_path/message.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,15 @@ impl Writeable for ReceiveTlvs {
9191

9292
/// Construct blinded onion message hops for the given `unblinded_path`.
9393
pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
94-
secp_ctx: &Secp256k1<T>, unblinded_path: &[PublicKey], session_priv: &SecretKey
94+
secp_ctx: &Secp256k1<T>, unblinded_path: &[PublicKey], recipient_data: Option<RecipientData>,
95+
session_priv: &SecretKey
9596
) -> Result<Vec<BlindedHop>, secp256k1::Error> {
97+
let recipient_data = recipient_data.unwrap_or(RecipientData::new());
9698
let blinded_tlvs = unblinded_path.iter()
9799
.skip(1) // The first node's TLVs contains the next node's pubkey
98100
.map(|pk| ForwardTlvs { next_hop: NextMessageHop::NodeId(*pk), next_blinding_override: None })
99101
.map(|tlvs| ControlTlvs::Forward(tlvs))
100-
.chain(core::iter::once(ControlTlvs::Receive(ReceiveTlvs { path_id: None, recipient_data: RecipientData::new() })));
102+
.chain(core::iter::once(ControlTlvs::Receive(ReceiveTlvs { path_id: None, recipient_data })));
101103

102104
utils::construct_blinded_hops(secp_ctx, unblinded_path.iter(), blinded_tlvs, session_priv)
103105
}

lightning/src/blinded_path/mod.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use crate::offers::invoice::BlindedPayInfo;
2121
use crate::routing::gossip::{NodeId, ReadOnlyNetworkGraph};
2222
use crate::sign::EntropySource;
2323
use crate::util::ser::{Readable, Writeable, Writer};
24+
use crate::blinded_path::message::RecipientData;
2425

2526
use crate::io;
2627
use crate::prelude::*;
@@ -122,9 +123,9 @@ pub struct BlindedHop {
122123
impl BlindedPath {
123124
/// Create a one-hop blinded path for a message.
124125
pub fn one_hop_for_message<ES: Deref, T: secp256k1::Signing + secp256k1::Verification>(
125-
recipient_node_id: PublicKey, entropy_source: ES, secp_ctx: &Secp256k1<T>
126+
recipient_node_id: PublicKey, recipient_data: Option<RecipientData>, entropy_source: ES, secp_ctx: &Secp256k1<T>
126127
) -> Result<Self, ()> where ES::Target: EntropySource {
127-
Self::new_for_message(&[recipient_node_id], entropy_source, secp_ctx)
128+
Self::new_for_message(&[recipient_node_id], recipient_data, entropy_source, secp_ctx)
128129
}
129130

130131
/// Create a blinded path for an onion message, to be forwarded along `node_pks`. The last node
@@ -133,7 +134,7 @@ impl BlindedPath {
133134
/// Errors if no hops are provided or if `node_pk`(s) are invalid.
134135
// TODO: make all payloads the same size with padding + add dummy hops
135136
pub fn new_for_message<ES: Deref, T: secp256k1::Signing + secp256k1::Verification>(
136-
node_pks: &[PublicKey], entropy_source: ES, secp_ctx: &Secp256k1<T>
137+
node_pks: &[PublicKey], recipient_data: Option<RecipientData>, entropy_source: ES, secp_ctx: &Secp256k1<T>
137138
) -> Result<Self, ()> where ES::Target: EntropySource {
138139
if node_pks.is_empty() { return Err(()) }
139140
let blinding_secret_bytes = entropy_source.get_secure_random_bytes();
@@ -143,7 +144,7 @@ impl BlindedPath {
143144
Ok(BlindedPath {
144145
introduction_node,
145146
blinding_point: PublicKey::from_secret_key(secp_ctx, &blinding_secret),
146-
blinded_hops: message::blinded_hops(secp_ctx, node_pks, &blinding_secret).map_err(|_| ())?,
147+
blinded_hops: message::blinded_hops(secp_ctx, node_pks, recipient_data, &blinding_secret).map_err(|_| ())?,
147148
})
148149
}
149150

lightning/src/ln/channelmanager.rs

+13-6
Original file line numberDiff line numberDiff line change
@@ -8572,7 +8572,7 @@ macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
85728572
let entropy = &*$self.entropy_source;
85738573
let secp_ctx = &$self.secp_ctx;
85748574

8575-
let path = $self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?;
8575+
let path = $self.create_blinded_path(None).map_err(|_| Bolt12SemanticError::MissingPaths)?;
85768576
let builder = OfferBuilder::deriving_signing_pubkey(
85778577
node_id, expanded_key, entropy, secp_ctx
85788578
)
@@ -8639,7 +8639,11 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
86398639
let entropy = &*$self.entropy_source;
86408640
let secp_ctx = &$self.secp_ctx;
86418641

8642-
let path = $self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?;
8642+
let recipient_data = RecipientData {
8643+
payment_id: Some(payment_id)
8644+
};
8645+
8646+
let path = $self.create_blinded_path(Some(recipient_data)).map_err(|_| Bolt12SemanticError::MissingPaths)?;
86438647
let builder = RefundBuilder::deriving_payer_id(
86448648
node_id, expanded_key, entropy, secp_ctx, amount_msats, payment_id
86458649
)?
@@ -8762,7 +8766,10 @@ where
87628766
Some(payer_note) => builder.payer_note(payer_note),
87638767
};
87648768
let invoice_request = builder.build_and_sign()?;
8765-
let reply_path = self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?;
8769+
let recipient_data = RecipientData {
8770+
payment_id: Some(payment_id)
8771+
};
8772+
let reply_path = self.create_blinded_path(Some(recipient_data)).map_err(|_| Bolt12SemanticError::MissingPaths)?;
87668773

87678774
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
87688775

@@ -8862,7 +8869,7 @@ where
88628869
)?;
88638870
let builder: InvoiceBuilder<DerivedSigningPubkey> = builder.into();
88648871
let invoice = builder.allow_mpp().build_and_sign(secp_ctx)?;
8865-
let reply_path = self.create_blinded_path()
8872+
let reply_path = self.create_blinded_path(None)
88668873
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
88678874

88688875
let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap();
@@ -8991,7 +8998,7 @@ where
89918998
/// Creates a blinded path by delegating to [`MessageRouter::create_blinded_paths`].
89928999
///
89939000
/// Errors if the `MessageRouter` errors or returns an empty `Vec`.
8994-
fn create_blinded_path(&self) -> Result<BlindedPath, ()> {
9001+
fn create_blinded_path(&self, recipient_data: Option<RecipientData>) -> Result<BlindedPath, ()> {
89959002
let recipient = self.get_our_node_id();
89969003
let secp_ctx = &self.secp_ctx;
89979004

@@ -9002,7 +9009,7 @@ where
90029009
.collect::<Vec<_>>();
90039010

90049011
self.router
9005-
.create_blinded_paths(recipient, peers, secp_ctx)
9012+
.create_blinded_paths(recipient, recipient_data, peers, secp_ctx)
90069013
.and_then(|paths| paths.into_iter().next().ok_or(()))
90079014
}
90089015

lightning/src/ln/offers_tests.rs

+10
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,16 @@ fn fails_sending_invoice_without_blinded_payment_paths_for_offer() {
996996

997997
let invoice_error = extract_invoice_error(david, &onion_message);
998998
assert_eq!(invoice_error, InvoiceError::from(Bolt12SemanticError::MissingPaths));
999+
1000+
// Confirm that david drops this failed payment from his pending outbound payments.
1001+
let events = david.node.get_and_clear_pending_events();
1002+
assert_eq!(events.len(), 1);
1003+
match events[0] {
1004+
Event::InvoiceRequestFailed { payment_id: pay_id} => {
1005+
assert_eq!(pay_id, payment_id)
1006+
},
1007+
_ => panic!("Unexpected Event"),
1008+
}
9991009
}
10001010

10011011
#[test]

lightning/src/onion_message/functional_tests.rs

+17-15
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ fn one_blinded_hop() {
358358
let test_msg = TestCustomMessage::Pong;
359359

360360
let secp_ctx = Secp256k1::new();
361-
let blinded_path = BlindedPath::new_for_message(&[nodes[1].node_id], &*nodes[1].entropy_source, &secp_ctx).unwrap();
361+
let blinded_path = BlindedPath::new_for_message(&[nodes[1].node_id], None, &*nodes[1].entropy_source, &secp_ctx).unwrap();
362362
let destination = Destination::BlindedPath(blinded_path);
363363
nodes[0].messenger.send_onion_message(test_msg, destination, None).unwrap();
364364
nodes[1].custom_message_handler.expect_message(TestCustomMessage::Pong);
@@ -371,7 +371,7 @@ fn two_unblinded_two_blinded() {
371371
let test_msg = TestCustomMessage::Pong;
372372

373373
let secp_ctx = Secp256k1::new();
374-
let blinded_path = BlindedPath::new_for_message(&[nodes[3].node_id, nodes[4].node_id], &*nodes[4].entropy_source, &secp_ctx).unwrap();
374+
let blinded_path = BlindedPath::new_for_message(&[nodes[3].node_id, nodes[4].node_id], None, &*nodes[4].entropy_source, &secp_ctx).unwrap();
375375
let path = OnionMessagePath {
376376
intermediate_nodes: vec![nodes[1].node_id, nodes[2].node_id],
377377
destination: Destination::BlindedPath(blinded_path),
@@ -389,7 +389,7 @@ fn three_blinded_hops() {
389389
let test_msg = TestCustomMessage::Pong;
390390

391391
let secp_ctx = Secp256k1::new();
392-
let blinded_path = BlindedPath::new_for_message(&[nodes[1].node_id, nodes[2].node_id, nodes[3].node_id], &*nodes[3].entropy_source, &secp_ctx).unwrap();
392+
let blinded_path = BlindedPath::new_for_message(&[nodes[1].node_id, nodes[2].node_id, nodes[3].node_id], None, &*nodes[3].entropy_source, &secp_ctx).unwrap();
393393
let destination = Destination::BlindedPath(blinded_path);
394394

395395
nodes[0].messenger.send_onion_message(test_msg, destination, None).unwrap();
@@ -412,7 +412,7 @@ fn async_response_over_one_blinded_hop() {
412412

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

417417
// 4. Create a responder using the reply path for Alice.
418418
let responder = Some(Responder::new(reply_path, path_id));
@@ -448,7 +448,9 @@ fn async_response_with_reply_path_succeeds() {
448448
// Alice receives a message from Bob with an added reply_path for responding back.
449449
let message = TestCustomMessage::Ping;
450450
let path_id = Some([2; 32]);
451-
let reply_path = BlindedPath::new_for_message(&[bob.node_id], &*bob.entropy_source, &secp_ctx).unwrap();
451+
452+
let secp_ctx = Secp256k1::new();
453+
let reply_path = BlindedPath::new_for_message(&[bob.node_id], None, &*bob.entropy_source, &secp_ctx).unwrap();
452454

453455
// Alice asynchronously responds to Bob, expecting a response back from him.
454456
let responder = Responder::new(reply_path, path_id);
@@ -485,7 +487,7 @@ fn async_response_with_reply_path_fails() {
485487
// Alice receives a message from Bob with an added reply_path for responding back.
486488
let message = TestCustomMessage::Ping;
487489
let path_id = Some([2; 32]);
488-
let reply_path = BlindedPath::new_for_message(&[bob.node_id], &*bob.entropy_source, &secp_ctx).unwrap();
490+
let reply_path = BlindedPath::new_for_message(&[bob.node_id], None, &*bob.entropy_source, &secp_ctx).unwrap();
489491

490492
// Alice tries to asynchronously respond to Bob, but fails because the nodes are unannounced.
491493
// Therefore, the reply_path cannot be used for the response.
@@ -524,15 +526,15 @@ fn we_are_intro_node() {
524526
let test_msg = TestCustomMessage::Pong;
525527

526528
let secp_ctx = Secp256k1::new();
527-
let blinded_path = BlindedPath::new_for_message(&[nodes[0].node_id, nodes[1].node_id, nodes[2].node_id], &*nodes[2].entropy_source, &secp_ctx).unwrap();
529+
let blinded_path = BlindedPath::new_for_message(&[nodes[0].node_id, nodes[1].node_id, nodes[2].node_id], None, &*nodes[2].entropy_source, &secp_ctx).unwrap();
528530
let destination = Destination::BlindedPath(blinded_path);
529531

530532
nodes[0].messenger.send_onion_message(test_msg.clone(), destination, None).unwrap();
531533
nodes[2].custom_message_handler.expect_message(TestCustomMessage::Pong);
532534
pass_along_path(&nodes);
533535

534536
// Try with a two-hop blinded path where we are the introduction node.
535-
let blinded_path = BlindedPath::new_for_message(&[nodes[0].node_id, nodes[1].node_id], &*nodes[1].entropy_source, &secp_ctx).unwrap();
537+
let blinded_path = BlindedPath::new_for_message(&[nodes[0].node_id, nodes[1].node_id], None, &*nodes[1].entropy_source, &secp_ctx).unwrap();
536538
let destination = Destination::BlindedPath(blinded_path);
537539
nodes[0].messenger.send_onion_message(test_msg, destination, None).unwrap();
538540
nodes[1].custom_message_handler.expect_message(TestCustomMessage::Pong);
@@ -547,7 +549,7 @@ fn invalid_blinded_path_error() {
547549
let test_msg = TestCustomMessage::Pong;
548550

549551
let secp_ctx = Secp256k1::new();
550-
let mut blinded_path = BlindedPath::new_for_message(&[nodes[1].node_id, nodes[2].node_id], &*nodes[2].entropy_source, &secp_ctx).unwrap();
552+
let mut blinded_path = BlindedPath::new_for_message(&[nodes[1].node_id, nodes[2].node_id], None, &*nodes[2].entropy_source, &secp_ctx).unwrap();
551553
blinded_path.blinded_hops.clear();
552554
let destination = Destination::BlindedPath(blinded_path);
553555
let err = nodes[0].messenger.send_onion_message(test_msg, destination, None).unwrap_err();
@@ -566,7 +568,7 @@ fn reply_path() {
566568
destination: Destination::Node(nodes[3].node_id),
567569
first_node_addresses: None,
568570
};
569-
let reply_path = BlindedPath::new_for_message(&[nodes[2].node_id, nodes[1].node_id, nodes[0].node_id], &*nodes[0].entropy_source, &secp_ctx).unwrap();
571+
let reply_path = BlindedPath::new_for_message(&[nodes[2].node_id, nodes[1].node_id, nodes[0].node_id], None, &*nodes[0].entropy_source, &secp_ctx).unwrap();
570572
nodes[0].messenger.send_onion_message_using_path(path, test_msg.clone(), Some(reply_path)).unwrap();
571573
nodes[3].custom_message_handler.expect_message(TestCustomMessage::Ping);
572574
pass_along_path(&nodes);
@@ -576,9 +578,9 @@ fn reply_path() {
576578
pass_along_path(&nodes);
577579

578580
// Destination::BlindedPath
579-
let blinded_path = BlindedPath::new_for_message(&[nodes[1].node_id, nodes[2].node_id, nodes[3].node_id], &*nodes[3].entropy_source, &secp_ctx).unwrap();
581+
let blinded_path = BlindedPath::new_for_message(&[nodes[1].node_id, nodes[2].node_id, nodes[3].node_id], None, &*nodes[3].entropy_source, &secp_ctx).unwrap();
580582
let destination = Destination::BlindedPath(blinded_path);
581-
let reply_path = BlindedPath::new_for_message(&[nodes[2].node_id, nodes[1].node_id, nodes[0].node_id], &*nodes[0].entropy_source, &secp_ctx).unwrap();
583+
let reply_path = BlindedPath::new_for_message(&[nodes[2].node_id, nodes[1].node_id, nodes[0].node_id], None, &*nodes[0].entropy_source, &secp_ctx).unwrap();
582584

583585
nodes[0].messenger.send_onion_message(test_msg, destination, Some(reply_path)).unwrap();
584586
nodes[3].custom_message_handler.expect_message(TestCustomMessage::Ping);
@@ -659,7 +661,7 @@ fn requests_peer_connection_for_buffered_messages() {
659661
add_channel_to_graph(&nodes[0], &nodes[1], &secp_ctx, 42);
660662

661663
let blinded_path = BlindedPath::new_for_message(
662-
&[nodes[1].node_id, nodes[2].node_id], &*nodes[0].entropy_source, &secp_ctx
664+
&[nodes[1].node_id, nodes[2].node_id], None, &*nodes[0].entropy_source, &secp_ctx
663665
).unwrap();
664666
let destination = Destination::BlindedPath(blinded_path);
665667

@@ -696,7 +698,7 @@ fn drops_buffered_messages_waiting_for_peer_connection() {
696698
add_channel_to_graph(&nodes[0], &nodes[1], &secp_ctx, 42);
697699

698700
let blinded_path = BlindedPath::new_for_message(
699-
&[nodes[1].node_id, nodes[2].node_id], &*nodes[0].entropy_source, &secp_ctx
701+
&[nodes[1].node_id, nodes[2].node_id], None, &*nodes[0].entropy_source, &secp_ctx
700702
).unwrap();
701703
let destination = Destination::BlindedPath(blinded_path);
702704

@@ -745,7 +747,7 @@ fn intercept_offline_peer_oms() {
745747
let message = TestCustomMessage::Pong;
746748
let secp_ctx = Secp256k1::new();
747749
let blinded_path = BlindedPath::new_for_message(
748-
&[nodes[1].node_id, nodes[2].node_id], &*nodes[2].entropy_source, &secp_ctx
750+
&[nodes[1].node_id, nodes[2].node_id], None, &*nodes[2].entropy_source, &secp_ctx
749751
).unwrap();
750752
let destination = Destination::BlindedPath(blinded_path);
751753

0 commit comments

Comments
 (0)