Skip to content

Commit 14b78ac

Browse files
committed
Introduce Custom Data in ReceiveTlvs.
This commit introduce the ability to add custom data in the receive tlvs of blinded path they create, which the intend to receive back when the blinded path is used. This can be used for custom analysis, and information receival. This commit, omits using the custom data in the ChannelManager's implementation of handle_message. This will be handled in a follow-up.
1 parent 9c82a1b commit 14b78ac

File tree

11 files changed

+66
-24
lines changed

11 files changed

+66
-24
lines changed

fuzz/src/onion_message.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ struct TestOffersMessageHandler {}
112112
impl OffersMessageHandler for TestOffersMessageHandler {
113113
fn handle_message(
114114
&self, _message: OffersMessage, _context: Option<OffersContext>,
115-
_responder: Option<Responder>,
115+
_custom_data: Option<Vec<u8>>, _responder: Option<Responder>,
116116
) -> Option<(OffersMessage, ResponseInstruction)> {
117117
None
118118
}

lightning-dns-resolver/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ mod test {
332332
payer.resolver.resolve_name(payment_id, name.clone(), &*payer_keys).unwrap();
333333
let query_context = ReceiveTlvs {
334334
context: Some(MessageContext::DNSResolver(context)),
335+
custom_data: None,
335336
};
336337
let reply_path =
337338
BlindedMessagePath::one_hop(payer_id, query_context, &*payer_keys, &secp_ctx).unwrap();

lightning/src/blinded_path/message.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,19 @@ pub struct ReceiveTlvs {
258258
/// sending to. This is useful for receivers to check that said blinded path is being used in
259259
/// the right context.
260260
pub context: Option<MessageContext>,
261+
262+
/// Custom data set by the user. If `custom_data` is `Some`, it will be provided to the message
263+
/// recipient when the blinded path is used.
264+
///
265+
/// This field allows encoding custom data intended to be provided back when the blinded path is used.
266+
///
267+
/// ## Note on Forward Compatibility:
268+
/// Users can encode any kind of data into the `Vec<u8>` bytes here. However, they should ensure
269+
/// that the data is structured in a forward-compatible manner. This is especially important as
270+
/// `ReceiveTlvs` created in one version of the software may still appear in messages received
271+
/// shortly after a software upgrade. Proper forward compatibility helps prevent data loss or
272+
/// misinterpretation in future versions.
273+
pub custom_data: Option<Vec<u8>>,
261274
}
262275

263276
impl Writeable for ForwardTlvs {
@@ -281,6 +294,7 @@ impl Writeable for ReceiveTlvs {
281294
// TODO: write padding
282295
encode_tlv_stream!(writer, {
283296
(65537, self.context, option),
297+
(65539, self.custom_data, option)
284298
});
285299
Ok(())
286300
}

lightning/src/ln/async_payments_tests.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ fn create_static_invoice<T: secp256k1::Signing + secp256k1::Verification>(
110110
context: Some(MessageContext::Offers(OffersContext::InvoiceRequest {
111111
nonce: Nonce([42; 16]),
112112
})),
113+
custom_data: None,
113114
};
114115

115116
let blinded_paths_to_always_online_node = always_online_counterparty
@@ -222,6 +223,7 @@ fn static_invoice_unknown_required_features() {
222223
context: Some(MessageContext::Offers(OffersContext::InvoiceRequest {
223224
nonce: Nonce([42; 16]),
224225
})),
226+
custom_data: None,
225227
};
226228

227229
let blinded_paths_to_always_online_node = nodes[1]
@@ -829,6 +831,7 @@ fn invalid_async_receive_with_retry<F1, F2>(
829831
context: Some(MessageContext::Offers(OffersContext::InvoiceRequest {
830832
nonce: Nonce([42; 16]),
831833
})),
834+
custom_data: None,
832835
};
833836

834837
let blinded_paths_to_always_online_node = nodes[1]

lightning/src/ln/channelmanager.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10599,7 +10599,8 @@ where
1059910599
.collect::<Vec<_>>();
1060010600

1060110601
let recipient_tlvs = message::ReceiveTlvs {
10602-
context: Some(context)
10602+
context: Some(context),
10603+
custom_data: None,
1060310604
};
1060410605

1060510606
self.message_router
@@ -10631,7 +10632,8 @@ where
1063110632
.collect::<Vec<_>>();
1063210633

1063310634
let recipient_tlvs = message::ReceiveTlvs {
10634-
context: Some(MessageContext::Offers(context))
10635+
context: Some(MessageContext::Offers(context)),
10636+
custom_data: None,
1063510637
};
1063610638

1063710639
self.message_router
@@ -12150,7 +12152,8 @@ where
1215012152
L::Target: Logger,
1215112153
{
1215212154
fn handle_message(
12153-
&self, message: OffersMessage, context: Option<OffersContext>, responder: Option<Responder>,
12155+
// todo: Allow user to analyse `custom_data`.
12156+
&self, message: OffersMessage, context: Option<OffersContext>, _custom_data: Option<Vec<u8>>, responder: Option<Responder>,
1215412157
) -> Option<(OffersMessage, ResponseInstruction)> {
1215512158
let secp_ctx = &self.secp_ctx;
1215612159
let expanded_key = &self.inbound_payment_key;

lightning/src/ln/offers_tests.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,8 @@ fn claim_bolt12_payment<'a, 'b, 'c>(
193193

194194
fn extract_offer_nonce<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, message: &OnionMessage) -> Nonce {
195195
match node.onion_messenger.peel_onion_message(message) {
196-
Ok(PeeledOnion::Receive(_, Some(MessageContext::Offers(OffersContext::InvoiceRequest { nonce })), _)) => nonce,
197-
Ok(PeeledOnion::Receive(_, context, _)) => panic!("Unexpected onion message context: {:?}", context),
196+
Ok(PeeledOnion::Receive(_, Some(MessageContext::Offers(OffersContext::InvoiceRequest { nonce })), _, _)) => nonce,
197+
Ok(PeeledOnion::Receive(_, context, _, _)) => panic!("Unexpected onion message context: {:?}", context),
198198
Ok(PeeledOnion::Forward(_, _)) => panic!("Unexpected onion message forward"),
199199
Err(e) => panic!("Failed to process onion message {:?}", e),
200200
}
@@ -204,7 +204,7 @@ pub(super) fn extract_invoice_request<'a, 'b, 'c>(
204204
node: &Node<'a, 'b, 'c>, message: &OnionMessage
205205
) -> (InvoiceRequest, BlindedMessagePath) {
206206
match node.onion_messenger.peel_onion_message(message) {
207-
Ok(PeeledOnion::Receive(message, _, reply_path)) => match message {
207+
Ok(PeeledOnion::Receive(message, _, _, reply_path)) => match message {
208208
ParsedOnionMessageContents::Offers(offers_message) => match offers_message {
209209
OffersMessage::InvoiceRequest(invoice_request) => (invoice_request, reply_path.unwrap()),
210210
OffersMessage::Invoice(invoice) => panic!("Unexpected invoice: {:?}", invoice),
@@ -221,7 +221,7 @@ pub(super) fn extract_invoice_request<'a, 'b, 'c>(
221221

222222
fn extract_invoice<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, message: &OnionMessage) -> (Bolt12Invoice, BlindedMessagePath) {
223223
match node.onion_messenger.peel_onion_message(message) {
224-
Ok(PeeledOnion::Receive(message, _, reply_path)) => match message {
224+
Ok(PeeledOnion::Receive(message, _, _, reply_path)) => match message {
225225
ParsedOnionMessageContents::Offers(offers_message) => match offers_message {
226226
OffersMessage::InvoiceRequest(invoice_request) => panic!("Unexpected invoice_request: {:?}", invoice_request),
227227
OffersMessage::Invoice(invoice) => (invoice, reply_path.unwrap()),
@@ -240,7 +240,7 @@ fn extract_invoice_error<'a, 'b, 'c>(
240240
node: &Node<'a, 'b, 'c>, message: &OnionMessage
241241
) -> InvoiceError {
242242
match node.onion_messenger.peel_onion_message(message) {
243-
Ok(PeeledOnion::Receive(message, _, _)) => match message {
243+
Ok(PeeledOnion::Receive(message, _, _, _)) => match message {
244244
ParsedOnionMessageContents::Offers(offers_message) => match offers_message {
245245
OffersMessage::InvoiceRequest(invoice_request) => panic!("Unexpected invoice_request: {:?}", invoice_request),
246246
OffersMessage::Invoice(invoice) => panic!("Unexpected invoice: {:?}", invoice),

lightning/src/ln/peer_handler.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ impl OnionMessageHandler for IgnoringMessageHandler {
146146
}
147147

148148
impl OffersMessageHandler for IgnoringMessageHandler {
149-
fn handle_message(&self, _message: OffersMessage, _context: Option<OffersContext>, _responder: Option<Responder>) -> Option<(OffersMessage, ResponseInstruction)> {
149+
fn handle_message(&self, _message: OffersMessage, _context: Option<OffersContext>, _custom_data: Option<Vec<u8>>, _responder: Option<Responder>) -> Option<(OffersMessage, ResponseInstruction)> {
150150
None
151151
}
152152
}

lightning/src/onion_message/functional_tests.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ struct TestOffersMessageHandler {}
8080

8181
impl OffersMessageHandler for TestOffersMessageHandler {
8282
fn handle_message(
83-
&self, _message: OffersMessage, _context: Option<OffersContext>,
83+
&self, _message: OffersMessage, _context: Option<OffersContext>, _custom_data: Option<Vec<u8>>,
8484
_responder: Option<Responder>,
8585
) -> Option<(OffersMessage, ResponseInstruction)> {
8686
None
@@ -408,6 +408,7 @@ fn one_blinded_hop() {
408408
let secp_ctx = Secp256k1::new();
409409
let recipient_tlvs = ReceiveTlvs {
410410
context: Some(MessageContext::Custom(Vec::new())),
411+
custom_data: None,
411412
};
412413
let entropy = &*nodes[1].entropy_source;
413414

@@ -430,6 +431,7 @@ fn two_unblinded_two_blinded() {
430431
[MessageForwardNode { node_id: nodes[3].node_id, short_channel_id: None }];
431432
let recipient_tlvs = ReceiveTlvs {
432433
context: Some(MessageContext::Custom(Vec::new())),
434+
custom_data: None,
433435
};
434436
let entropy = &*nodes[4].entropy_source;
435437
let blinded_path =
@@ -458,6 +460,7 @@ fn three_blinded_hops() {
458460
];
459461
let recipient_tlvs = ReceiveTlvs {
460462
context: Some(MessageContext::Custom(Vec::new())),
463+
custom_data: None,
461464
};
462465
let entropy = &*nodes[3].entropy_source;
463466
let blinded_path =
@@ -487,6 +490,7 @@ fn async_response_over_one_blinded_hop() {
487490
let secp_ctx = Secp256k1::new();
488491
let recipient_tlvs = ReceiveTlvs {
489492
context: Some(MessageContext::Custom(Vec::new())),
493+
custom_data: None,
490494
};
491495
let entropy = &*nodes[1].entropy_source;
492496
let reply_path =
@@ -529,6 +533,7 @@ fn async_response_with_reply_path_succeeds() {
529533
let message = TestCustomMessage::Ping;
530534
let recipient_tlvs = ReceiveTlvs {
531535
context: Some(MessageContext::Custom(Vec::new())),
536+
custom_data: None,
532537
};
533538
let reply_path =
534539
BlindedMessagePath::new(&[], bob.node_id, recipient_tlvs, &*bob.entropy_source, &secp_ctx)
@@ -572,6 +577,7 @@ fn async_response_with_reply_path_fails() {
572577
let message = TestCustomMessage::Ping;
573578
let recipient_tlvs = ReceiveTlvs {
574579
context: Some(MessageContext::Custom(Vec::new())),
580+
custom_data: None,
575581
};
576582
let reply_path =
577583
BlindedMessagePath::new(&[], bob.node_id, recipient_tlvs, &*bob.entropy_source, &secp_ctx)
@@ -623,6 +629,7 @@ fn we_are_intro_node() {
623629
];
624630
let recipient_tlvs = ReceiveTlvs {
625631
context: Some(MessageContext::Custom(Vec::new())),
632+
custom_data: None,
626633
};
627634
let entropy = &*nodes[2].entropy_source;
628635
let blinded_path =
@@ -640,6 +647,7 @@ fn we_are_intro_node() {
640647
[MessageForwardNode { node_id: nodes[0].node_id, short_channel_id: None }];
641648
let recipient_tlvs = ReceiveTlvs {
642649
context: Some(MessageContext::Custom(Vec::new())),
650+
custom_data: None,
643651
};
644652
let entropy = &*nodes[1].entropy_source;
645653
let blinded_path =
@@ -665,6 +673,7 @@ fn invalid_blinded_path_error() {
665673
[MessageForwardNode { node_id: nodes[1].node_id, short_channel_id: None }];
666674
let recipient_tlvs = ReceiveTlvs {
667675
context: Some(MessageContext::Custom(Vec::new())),
676+
custom_data: None,
668677
};
669678
let entropy = &*nodes[2].entropy_source;
670679
let mut blinded_path =
@@ -696,6 +705,7 @@ fn reply_path() {
696705
];
697706
let recipient_tlvs = ReceiveTlvs {
698707
context: Some(MessageContext::Custom(Vec::new())),
708+
custom_data: None,
699709
};
700710
let entropy = &*nodes[0].entropy_source;
701711
let reply_path =
@@ -719,6 +729,7 @@ fn reply_path() {
719729
];
720730
let recipient_tlvs = ReceiveTlvs {
721731
context: Some(MessageContext::Custom(Vec::new())),
732+
custom_data: None,
722733
};
723734
let entropy = &*nodes[3].entropy_source;
724735
let blinded_path =
@@ -731,6 +742,7 @@ fn reply_path() {
731742
];
732743
let recipient_tlvs = ReceiveTlvs {
733744
context: Some(MessageContext::Custom(Vec::new())),
745+
custom_data: None,
734746
};
735747
let entropy = &*nodes[0].entropy_source;
736748
let reply_path =
@@ -831,6 +843,7 @@ fn requests_peer_connection_for_buffered_messages() {
831843
[MessageForwardNode { node_id: nodes[1].node_id, short_channel_id: None }];
832844
let recipient_tlvs = ReceiveTlvs {
833845
context: Some(MessageContext::Custom(Vec::new())),
846+
custom_data: None,
834847
};
835848
let entropy = &*nodes[0].entropy_source;
836849
let blinded_path =
@@ -875,6 +888,7 @@ fn drops_buffered_messages_waiting_for_peer_connection() {
875888
[MessageForwardNode { node_id: nodes[1].node_id, short_channel_id: None }];
876889
let recipient_tlvs = ReceiveTlvs {
877890
context: Some(MessageContext::Custom(Vec::new())),
891+
custom_data: None,
878892
};
879893
let entropy = &*nodes[0].entropy_source;
880894
let blinded_path =
@@ -935,6 +949,7 @@ fn intercept_offline_peer_oms() {
935949
[MessageForwardNode { node_id: nodes[1].node_id, short_channel_id: None }];
936950
let recipient_tlvs = ReceiveTlvs {
937951
context: Some(MessageContext::Custom(Vec::new())),
952+
custom_data: None,
938953
};
939954
let entropy = &*nodes[2].entropy_source;
940955
let blinded_path =

lightning/src/onion_message/messenger.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ where
270270
/// ];
271271
/// let recipient_tlvs = ReceiveTlvs {
272272
/// context: Some(MessageContext::Custom(Vec::new())),
273+
/// custom_data: None,
273274
/// };
274275
/// let blinded_path = BlindedMessagePath::new(&hops, your_node_id, recipient_tlvs, &keys_manager, &secp_ctx).unwrap();
275276
///
@@ -898,7 +899,7 @@ pub enum PeeledOnion<T: OnionMessageContents> {
898899
/// Forwarded onion, with the next node id and a new onion
899900
Forward(NextMessageHop, OnionMessage),
900901
/// Received onion message, with decrypted contents, context, and reply path
901-
Receive(ParsedOnionMessageContents<T>, Option<MessageContext>, Option<BlindedMessagePath>),
902+
Receive(ParsedOnionMessageContents<T>, Option<MessageContext>, Option<Vec<u8>>, Option<BlindedMessagePath>),
902903
}
903904

904905
/// Creates an [`OnionMessage`] with the given `contents` for sending to the destination of
@@ -1069,25 +1070,25 @@ where
10691070
Ok((
10701071
Payload::Receive {
10711072
message,
1072-
control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs { context }),
1073+
control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs { context , custom_data}),
10731074
reply_path,
10741075
},
10751076
None,
10761077
)) => match (&message, &context) {
1077-
(_, None) => Ok(PeeledOnion::Receive(message, None, reply_path)),
1078+
(_, None) => Ok(PeeledOnion::Receive(message, None, custom_data, reply_path)),
10781079
(ParsedOnionMessageContents::Offers(_), Some(MessageContext::Offers(_))) => {
1079-
Ok(PeeledOnion::Receive(message, context, reply_path))
1080+
Ok(PeeledOnion::Receive(message, context, custom_data, reply_path))
10801081
},
10811082
#[cfg(async_payments)]
10821083
(
10831084
ParsedOnionMessageContents::AsyncPayments(_),
10841085
Some(MessageContext::AsyncPayments(_)),
1085-
) => Ok(PeeledOnion::Receive(message, context, reply_path)),
1086+
) => Ok(PeeledOnion::Receive(message, context, custom_data, reply_path)),
10861087
(ParsedOnionMessageContents::Custom(_), Some(MessageContext::Custom(_))) => {
1087-
Ok(PeeledOnion::Receive(message, context, reply_path))
1088+
Ok(PeeledOnion::Receive(message, context, custom_data, reply_path))
10881089
},
10891090
(ParsedOnionMessageContents::DNSResolver(_), Some(MessageContext::DNSResolver(_))) => {
1090-
Ok(PeeledOnion::Receive(message, context, reply_path))
1091+
Ok(PeeledOnion::Receive(message, context, custom_data, reply_path))
10911092
},
10921093
_ => {
10931094
log_trace!(
@@ -1407,7 +1408,8 @@ where
14071408
};
14081409

14091410
let recipient_tlvs = ReceiveTlvs {
1410-
context: Some(context)
1411+
context: Some(context),
1412+
custom_data: None,
14111413
};
14121414

14131415
self.message_router
@@ -1827,7 +1829,7 @@ where
18271829
fn handle_onion_message(&self, peer_node_id: PublicKey, msg: &OnionMessage) {
18281830
let logger = WithContext::from(&self.logger, Some(peer_node_id), None, None);
18291831
match self.peel_onion_message(msg) {
1830-
Ok(PeeledOnion::Receive(message, context, reply_path)) => {
1832+
Ok(PeeledOnion::Receive(message, context, custom_data, reply_path)) => {
18311833
log_trace!(
18321834
logger,
18331835
"Received an onion message with {} reply_path: {:?}",
@@ -1847,7 +1849,7 @@ where
18471849
},
18481850
};
18491851
let response_instructions =
1850-
self.offers_handler.handle_message(msg, context, responder);
1852+
self.offers_handler.handle_message(msg, context, custom_data, responder);
18511853
if let Some((msg, instructions)) = response_instructions {
18521854
let _ = self.handle_onion_message_response(msg, instructions);
18531855
}
@@ -2276,7 +2278,7 @@ fn packet_payloads_and_keys<
22762278
} else {
22772279
payloads.push((
22782280
Payload::Receive {
2279-
control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs { context: None }),
2281+
control_tlvs: ReceiveControlTlvs::Unblinded(ReceiveTlvs { context: None, custom_data: None }),
22802282
reply_path: reply_path.take(),
22812283
message,
22822284
},

lightning/src/onion_message/offers.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ pub trait OffersMessageHandler {
4444
///
4545
/// [`OnionMessenger`]: crate::onion_message::messenger::OnionMessenger
4646
fn handle_message(
47-
&self, message: OffersMessage, context: Option<OffersContext>, responder: Option<Responder>,
47+
&self, message: OffersMessage, context: Option<OffersContext>, custom_data: Option<Vec<u8>>, responder: Option<Responder>,
4848
) -> Option<(OffersMessage, ResponseInstruction)>;
4949

5050
/// Releases any [`OffersMessage`]s that need to be sent.

0 commit comments

Comments
 (0)