Skip to content

Commit 51926f1

Browse files
Merge pull request #2975 from valentinewallace/2024-03-blinded-path-custom-tlvs
2 parents 9cc0e98 + cb022c5 commit 51926f1

File tree

6 files changed

+75
-16
lines changed

6 files changed

+75
-16
lines changed

lightning/src/ln/blinded_payment_tests.rs

+47
Original file line numberDiff line numberDiff line change
@@ -1264,3 +1264,50 @@ fn blinded_mpp_keysend() {
12641264
Some(payment_secret), ev.clone(), true, Some(keysend_preimage));
12651265
claim_payment_along_route(&nodes[0], expected_route, false, keysend_preimage);
12661266
}
1267+
1268+
#[test]
1269+
fn custom_tlvs_to_blinded_path() {
1270+
let chanmon_cfgs = create_chanmon_cfgs(2);
1271+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
1272+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
1273+
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
1274+
let chan_upd = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0).0.contents;
1275+
1276+
let amt_msat = 5000;
1277+
let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[1], Some(amt_msat), None);
1278+
let payee_tlvs = ReceiveTlvs {
1279+
payment_secret,
1280+
payment_constraints: PaymentConstraints {
1281+
max_cltv_expiry: u32::max_value(),
1282+
htlc_minimum_msat: chan_upd.htlc_minimum_msat,
1283+
},
1284+
};
1285+
let mut secp_ctx = Secp256k1::new();
1286+
let blinded_path = BlindedPath::one_hop_for_payment(
1287+
nodes[1].node.get_our_node_id(), payee_tlvs, TEST_FINAL_CLTV as u16,
1288+
&chanmon_cfgs[1].keys_manager, &secp_ctx
1289+
).unwrap();
1290+
1291+
let route_params = RouteParameters::from_payment_params_and_value(
1292+
PaymentParameters::blinded(vec![blinded_path]),
1293+
amt_msat,
1294+
);
1295+
1296+
let recipient_onion_fields = RecipientOnionFields::spontaneous_empty()
1297+
.with_custom_tlvs(vec![((1 << 16) + 1, vec![42, 42])])
1298+
.unwrap();
1299+
nodes[0].node.send_payment(payment_hash, recipient_onion_fields.clone(),
1300+
PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
1301+
check_added_monitors(&nodes[0], 1);
1302+
1303+
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
1304+
assert_eq!(events.len(), 1);
1305+
let ev = remove_first_msg_event_to_node(&nodes[1].node.get_our_node_id(), &mut events);
1306+
1307+
let path = &[&nodes[1]];
1308+
let args = PassAlongPathArgs::new(&nodes[0], path, amt_msat, payment_hash, ev)
1309+
.with_payment_secret(payment_secret)
1310+
.with_custom_tlvs(recipient_onion_fields.custom_tlvs.clone());
1311+
do_pass_along_path(args);
1312+
claim_payment(&nodes[0], &[&nodes[1]], payment_preimage);
1313+
}

lightning/src/ln/functional_test_utils.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -2507,6 +2507,7 @@ pub struct PassAlongPathArgs<'a, 'b, 'c, 'd> {
25072507
pub clear_recipient_events: bool,
25082508
pub expected_preimage: Option<PaymentPreimage>,
25092509
pub is_probe: bool,
2510+
pub custom_tlvs: Vec<(u64, Vec<u8>)>,
25102511
}
25112512

25122513
impl<'a, 'b, 'c, 'd> PassAlongPathArgs<'a, 'b, 'c, 'd> {
@@ -2517,7 +2518,7 @@ impl<'a, 'b, 'c, 'd> PassAlongPathArgs<'a, 'b, 'c, 'd> {
25172518
Self {
25182519
origin_node, expected_path, recv_value, payment_hash, payment_secret: None, event,
25192520
payment_claimable_expected: true, clear_recipient_events: true, expected_preimage: None,
2520-
is_probe: false,
2521+
is_probe: false, custom_tlvs: Vec::new(),
25212522
}
25222523
}
25232524
pub fn without_clearing_recipient_events(mut self) -> Self {
@@ -2541,13 +2542,17 @@ impl<'a, 'b, 'c, 'd> PassAlongPathArgs<'a, 'b, 'c, 'd> {
25412542
self.expected_preimage = Some(payment_preimage);
25422543
self
25432544
}
2545+
pub fn with_custom_tlvs(mut self, custom_tlvs: Vec<(u64, Vec<u8>)>) -> Self {
2546+
self.custom_tlvs = custom_tlvs;
2547+
self
2548+
}
25442549
}
25452550

25462551
pub fn do_pass_along_path<'a, 'b, 'c>(args: PassAlongPathArgs) -> Option<Event> {
25472552
let PassAlongPathArgs {
25482553
origin_node, expected_path, recv_value, payment_hash: our_payment_hash,
25492554
payment_secret: our_payment_secret, event: ev, payment_claimable_expected,
2550-
clear_recipient_events, expected_preimage, is_probe
2555+
clear_recipient_events, expected_preimage, is_probe, custom_tlvs
25512556
} = args;
25522557

25532558
let mut payment_event = SendEvent::from_event(ev);
@@ -2580,6 +2585,7 @@ pub fn do_pass_along_path<'a, 'b, 'c>(args: PassAlongPathArgs) -> Option<Event>
25802585
assert_eq!(our_payment_hash, *payment_hash);
25812586
assert_eq!(node.node.get_our_node_id(), receiver_node_id.unwrap());
25822587
assert!(onion_fields.is_some());
2588+
assert_eq!(onion_fields.as_ref().unwrap().custom_tlvs, custom_tlvs);
25832589
match &purpose {
25842590
PaymentPurpose::InvoicePayment { payment_preimage, payment_secret, .. } => {
25852591
assert_eq!(expected_preimage, *payment_preimage);

lightning/src/ln/msgs.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -1711,6 +1711,7 @@ mod fuzzy_internal_msgs {
17111711
payment_constraints: PaymentConstraints,
17121712
intro_node_blinding_point: Option<PublicKey>,
17131713
keysend_preimage: Option<PaymentPreimage>,
1714+
custom_tlvs: Vec<(u64, Vec<u8>)>,
17141715
}
17151716
}
17161717

@@ -1747,6 +1748,7 @@ mod fuzzy_internal_msgs {
17471748
encrypted_tlvs: Vec<u8>,
17481749
intro_node_blinding_point: Option<PublicKey>, // Set if the introduction node of the blinded path is the final node
17491750
keysend_preimage: Option<PaymentPreimage>,
1751+
custom_tlvs: Vec<(u64, Vec<u8>)>,
17501752
}
17511753
}
17521754

@@ -2603,16 +2605,21 @@ impl Writeable for OutboundOnionPayload {
26032605
},
26042606
Self::BlindedReceive {
26052607
sender_intended_htlc_amt_msat, total_msat, cltv_expiry_height, encrypted_tlvs,
2606-
intro_node_blinding_point, keysend_preimage,
2608+
intro_node_blinding_point, keysend_preimage, ref custom_tlvs,
26072609
} => {
2610+
// We need to update [`ln::outbound_payment::RecipientOnionFields::with_custom_tlvs`]
2611+
// to reject any reserved types in the experimental range if new ones are ever
2612+
// standardized.
2613+
let keysend_tlv = keysend_preimage.map(|preimage| (5482373484, preimage.encode()));
2614+
let mut custom_tlvs: Vec<&(u64, Vec<u8>)> = custom_tlvs.iter().chain(keysend_tlv.iter()).collect();
2615+
custom_tlvs.sort_unstable_by_key(|(typ, _)| *typ);
26082616
_encode_varint_length_prefixed_tlv!(w, {
26092617
(2, HighZeroBytesDroppedBigSize(*sender_intended_htlc_amt_msat), required),
26102618
(4, HighZeroBytesDroppedBigSize(*cltv_expiry_height), required),
26112619
(10, *encrypted_tlvs, required_vec),
26122620
(12, intro_node_blinding_point, option),
2613-
(18, HighZeroBytesDroppedBigSize(*total_msat), required),
2614-
(5482373484, keysend_preimage, option)
2615-
});
2621+
(18, HighZeroBytesDroppedBigSize(*total_msat), required)
2622+
}, custom_tlvs.iter());
26162623
},
26172624
}
26182625
Ok(())
@@ -2715,6 +2722,7 @@ impl<NS: Deref> ReadableArgs<(Option<PublicKey>, &NS)> for InboundOnionPayload w
27152722
payment_constraints,
27162723
intro_node_blinding_point,
27172724
keysend_preimage,
2725+
custom_tlvs,
27182726
})
27192727
},
27202728
}

lightning/src/ln/onion_payment.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ pub(super) fn create_recv_pending_htlc_info(
139139
cltv_expiry_height, payment_metadata, false),
140140
msgs::InboundOnionPayload::BlindedReceive {
141141
sender_intended_htlc_amt_msat, total_msat, cltv_expiry_height, payment_secret,
142-
intro_node_blinding_point, payment_constraints, keysend_preimage, ..
142+
intro_node_blinding_point, payment_constraints, keysend_preimage, custom_tlvs
143143
} => {
144144
check_blinded_payment_constraints(
145145
sender_intended_htlc_amt_msat, cltv_expiry, &payment_constraints
@@ -152,7 +152,7 @@ pub(super) fn create_recv_pending_htlc_info(
152152
}
153153
})?;
154154
let payment_data = msgs::FinalOnionHopData { payment_secret, total_msat };
155-
(Some(payment_data), keysend_preimage, Vec::new(),
155+
(Some(payment_data), keysend_preimage, custom_tlvs,
156156
sender_intended_htlc_amt_msat, cltv_expiry_height, None,
157157
intro_node_blinding_point.is_none())
158158
}

lightning/src/ln/onion_utils.rs

+1
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ pub(super) fn build_onion_payloads(
214214
encrypted_tlvs: blinded_hop.encrypted_payload.clone(),
215215
intro_node_blinding_point: blinding_point.take(),
216216
keysend_preimage: *keysend_preimage,
217+
custom_tlvs: recipient_onion.custom_tlvs.clone(),
217218
});
218219
} else {
219220
res.push(msgs::OutboundOnionPayload::BlindedForward {

lightning/src/ln/payment_tests.rs

+5-8
Original file line numberDiff line numberDiff line change
@@ -3813,14 +3813,11 @@ fn test_retry_custom_tlvs() {
38133813
check_added_monitors!(nodes[0], 1);
38143814
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
38153815
assert_eq!(events.len(), 1);
3816-
let payment_claimable = pass_along_path(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000,
3817-
payment_hash, Some(payment_secret), events.pop().unwrap(), true, None).unwrap();
3818-
match payment_claimable {
3819-
Event::PaymentClaimable { onion_fields, .. } => {
3820-
assert_eq!(&onion_fields.unwrap().custom_tlvs()[..], &custom_tlvs[..]);
3821-
},
3822-
_ => panic!("Unexpected event"),
3823-
};
3816+
let path = &[&nodes[1], &nodes[2]];
3817+
let args = PassAlongPathArgs::new(&nodes[0], path, 1_000_000, payment_hash, events.pop().unwrap())
3818+
.with_payment_secret(payment_secret)
3819+
.with_custom_tlvs(custom_tlvs);
3820+
do_pass_along_path(args);
38243821
claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], false, payment_preimage);
38253822
}
38263823

0 commit comments

Comments
 (0)