Skip to content

Commit 1a0e530

Browse files
jkczyzclaude
andcommitted
Report the sending peer in Event::OnionMessageIntercepted
When the OnionMessenger intercepts an onion message to forward, it now reports which peer sent us the message via a new `prev_hop` field, so handlers can apply source-based policy when deciding whether to forward. `prev_hop` is `None` when the forward is enqueued by a message handler (the BOLT 12 static-invoice-server flow), which isn't given the sending node; otherwise it is the node we received the message from. Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 2e7cc44 commit 1a0e530

4 files changed

Lines changed: 44 additions & 23 deletions

File tree

lightning-tests/src/upgrade_downgrade_tests.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -761,7 +761,9 @@ fn test_onion_message_intercepted_upgrade_from_0_2() {
761761
let deserialized = <Event as MaybeReadable>::read(&mut reader).unwrap().unwrap();
762762

763763
match deserialized {
764-
Event::OnionMessageIntercepted { next_hop, message } => {
764+
Event::OnionMessageIntercepted { prev_hop, next_hop, message } => {
765+
// LDK 0.2 did not write a `prev_hop`, so it must default to `None`.
766+
assert_eq!(prev_hop, None);
765767
assert_eq!(next_hop, NextMessageHop::NodeId(pubkey));
766768
assert_eq!(message, dummy_onion_message());
767769
},
@@ -773,11 +775,14 @@ fn test_onion_message_intercepted_upgrade_from_0_2() {
773775
fn test_onion_message_intercepted_node_id_downgrade_to_0_2() {
774776
// Ensure that an `Event::OnionMessageIntercepted` with a `NodeId` next hop serialized by
775777
// the current version can be deserialized by LDK 0.2 (which expects `peer_node_id` in TLV
776-
// field 0).
778+
// field 0 and ignores the newer `prev_hop` in TLV field 3).
777779
let pubkey =
778780
PublicKey::from_secret_key(&Secp256k1::new(), &SecretKey::from_slice(&[42; 32]).unwrap());
781+
let prev_hop =
782+
PublicKey::from_secret_key(&Secp256k1::new(), &SecretKey::from_slice(&[43; 32]).unwrap());
779783

780784
let event = Event::OnionMessageIntercepted {
785+
prev_hop: Some(prev_hop),
781786
next_hop: NextMessageHop::NodeId(pubkey),
782787
message: dummy_onion_message(),
783788
};
@@ -802,6 +807,7 @@ fn test_onion_message_intercepted_scid_downgrade_to_0_2() {
802807
// serialized by the current version cannot be deserialized by LDK 0.2, since the
803808
// `peer_node_id` field (0) is not written for SCID variants and LDK 0.2 requires it.
804809
let event = Event::OnionMessageIntercepted {
810+
prev_hop: None,
805811
next_hop: NextMessageHop::ShortChannelId(42),
806812
message: dummy_onion_message(),
807813
};

lightning/src/events/mod.rs

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1856,6 +1856,17 @@ pub enum Event {
18561856
///
18571857
/// [`OnionMessenger::new_with_offline_peer_interception`]: crate::onion_message::messenger::OnionMessenger::new_with_offline_peer_interception
18581858
OnionMessageIntercepted {
1859+
/// The node id of the peer that sent the message, if known.
1860+
///
1861+
/// This is `None` when the message is sent with
1862+
/// [`MessageSendInstructions::ForwardedMessage`] (e.g., when calling
1863+
/// [`OffersMessageFlow::enqueue_invoice_request_to_forward`]) rather than forwarded
1864+
/// internally by the `OnionMessenger`, as well as for events serialized prior to LDK 0.3.
1865+
/// Otherwise it is the node we received the message from.
1866+
///
1867+
/// [`MessageSendInstructions::ForwardedMessage`]: crate::onion_message::messenger::MessageSendInstructions::ForwardedMessage
1868+
/// [`OffersMessageFlow::enqueue_invoice_request_to_forward`]: crate::offers::flow::OffersMessageFlow::enqueue_invoice_request_to_forward
1869+
prev_hop: Option<PublicKey>,
18591870
/// The next hop (offline peer or unknown SCID).
18601871
next_hop: NextMessageHop,
18611872
/// The onion message intended to be forwarded to the offline peer or via the unknown
@@ -2441,25 +2452,20 @@ impl Writeable for Event {
24412452
35u8.write(writer)?;
24422453
// Never write ConnectionNeeded events as buffered onion messages aren't serialized.
24432454
},
2444-
&Event::OnionMessageIntercepted { ref next_hop, ref message } => {
2455+
&Event::OnionMessageIntercepted { ref prev_hop, ref next_hop, ref message } => {
24452456
37u8.write(writer)?;
2446-
match next_hop {
2447-
NextMessageHop::NodeId(peer_node_id) => {
2448-
// If we have the node_id, we keep writing it for backwards compatibility.
2449-
write_tlv_fields!(writer, {
2450-
(0, peer_node_id, required),
2451-
(1, next_hop, required),
2452-
(2, message, required),
2453-
});
2454-
},
2455-
NextMessageHop::ShortChannelId(_) => {
2456-
write_tlv_fields!(writer, {
2457-
// 0 used to be peer_node_id in LDK v0.2 and prior.
2458-
(1, next_hop, required),
2459-
(2, message, required),
2460-
});
2461-
},
2462-
}
2457+
// 0 used to be peer_node_id in LDK v0.2 and prior; we keep writing it when the next
2458+
// hop is a node id for backwards compatibility.
2459+
let legacy_peer_node_id = match next_hop {
2460+
NextMessageHop::NodeId(node_id) => Some(node_id),
2461+
NextMessageHop::ShortChannelId(_) => None,
2462+
};
2463+
write_tlv_fields!(writer, {
2464+
(0, legacy_peer_node_id, option),
2465+
(1, next_hop, required),
2466+
(2, message, required),
2467+
(3, prev_hop, option),
2468+
});
24632469
},
24642470
&Event::OnionMessagePeerConnected { ref peer_node_id } => {
24652471
39u8.write(writer)?;
@@ -3090,12 +3096,14 @@ impl MaybeReadable for Event {
30903096
(0, peer_node_id, option),
30913097
(1, next_hop, option),
30923098
(2, message, required),
3099+
(3, prev_hop, option),
30933100
});
30943101

30953102
let next_hop = next_hop
30963103
.or(peer_node_id.map(NextMessageHop::NodeId))
30973104
.ok_or(msgs::DecodeError::InvalidValue)?;
30983105
Ok(Some(Event::OnionMessageIntercepted {
3106+
prev_hop,
30993107
next_hop,
31003108
message: message.0.unwrap(),
31013109
}))

lightning/src/onion_message/functional_tests.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1178,7 +1178,8 @@ fn intercept_offline_peer_oms() {
11781178
let mut events = release_events(&nodes[1]);
11791179
assert_eq!(events.len(), 1);
11801180
let onion_message = match events.remove(0) {
1181-
Event::OnionMessageIntercepted { next_hop, message } => {
1181+
Event::OnionMessageIntercepted { prev_hop, next_hop, message } => {
1182+
assert_eq!(prev_hop, Some(nodes[0].node_id));
11821183
if let NextMessageHop::NodeId(peer_node_id) = next_hop {
11831184
assert_eq!(peer_node_id, final_node_vec[0].node_id);
11841185
message
@@ -1265,7 +1266,8 @@ fn intercept_unknown_scid_oms() {
12651266
let mut events = release_events(&nodes[1]);
12661267
assert_eq!(events.len(), 1);
12671268
let onion_message = match events.remove(0) {
1268-
Event::OnionMessageIntercepted { next_hop, message } => {
1269+
Event::OnionMessageIntercepted { prev_hop, next_hop, message } => {
1270+
assert_eq!(prev_hop, Some(nodes[0].node_id));
12691271
if let NextMessageHop::ShortChannelId(intercepted_scid) = next_hop {
12701272
assert_eq!(intercepted_scid, scid);
12711273
message

lightning/src/onion_message/messenger.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1556,6 +1556,7 @@ impl<
15561556

15571557
let result = if is_forward {
15581558
self.enqueue_forwarded_onion_message(
1559+
None,
15591560
NextMessageHop::NodeId(first_node_id),
15601561
onion_message,
15611562
log_suffix,
@@ -1671,7 +1672,8 @@ impl<
16711672
}
16721673

16731674
fn enqueue_forwarded_onion_message(
1674-
&self, next_hop: NextMessageHop, onion_message: OnionMessage, log_suffix: fmt::Arguments,
1675+
&self, prev_hop: Option<PublicKey>, next_hop: NextMessageHop, onion_message: OnionMessage,
1676+
log_suffix: fmt::Arguments,
16751677
) -> Result<(), SendError> {
16761678
let next_node_id = match next_hop {
16771679
NextMessageHop::NodeId(pubkey) => pubkey,
@@ -1686,6 +1688,7 @@ impl<
16861688
log_suffix
16871689
);
16881690
self.enqueue_intercepted_event(Event::OnionMessageIntercepted {
1691+
prev_hop,
16891692
next_hop,
16901693
message: onion_message,
16911694
});
@@ -1734,6 +1737,7 @@ impl<
17341737
log_suffix
17351738
);
17361739
self.enqueue_intercepted_event(Event::OnionMessageIntercepted {
1740+
prev_hop,
17371741
// Report the resolved node id rather than `next_hop`, which may be a
17381742
// `ShortChannelId` that we resolved to a known-but-offline peer. The
17391743
// `ShortChannelId` variant is reserved for the unknown-SCID interception path.
@@ -2318,6 +2322,7 @@ impl<
23182322
},
23192323
Ok(PeeledOnion::Forward(next_hop, onion_message)) => {
23202324
let _ = self.enqueue_forwarded_onion_message(
2325+
Some(peer_node_id),
23212326
next_hop,
23222327
onion_message,
23232328
format_args!("when forwarding peeled onion message from {}", peer_node_id),

0 commit comments

Comments
 (0)