Skip to content

Commit 3c6399a

Browse files
TheBlueMattandozw
authored andcommitted
Pipe payment metadata through the HTLC send pipeline
...without exposing it to the public `send_payment` API yet.
1 parent de75b4f commit 3c6399a

File tree

5 files changed

+52
-37
lines changed

5 files changed

+52
-37
lines changed

lightning/src/ln/channel.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6500,6 +6500,7 @@ mod tests {
65006500
first_hop_htlc_msat: 548,
65016501
payment_id: PaymentId([42; 32]),
65026502
payment_secret: None,
6503+
payment_metadata: None,
65036504
payment_params: None,
65046505
}
65056506
});

lightning/src/ln/channelmanager.rs

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ pub(crate) enum HTLCSource {
210210
first_hop_htlc_msat: u64,
211211
payment_id: PaymentId,
212212
payment_secret: Option<PaymentSecret>,
213+
payment_metadata: Option<Vec<u8>>,
213214
payment_params: Option<PaymentParameters>,
214215
},
215216
}
@@ -221,12 +222,13 @@ impl core::hash::Hash for HTLCSource {
221222
0u8.hash(hasher);
222223
prev_hop_data.hash(hasher);
223224
},
224-
HTLCSource::OutboundRoute { path, session_priv, payment_id, payment_secret, first_hop_htlc_msat, payment_params } => {
225+
HTLCSource::OutboundRoute { path, session_priv, payment_id, payment_secret, payment_metadata, first_hop_htlc_msat, payment_params } => {
225226
1u8.hash(hasher);
226227
path.hash(hasher);
227228
session_priv[..].hash(hasher);
228229
payment_id.hash(hasher);
229230
payment_secret.hash(hasher);
231+
payment_metadata.hash(hasher);
230232
first_hop_htlc_msat.hash(hasher);
231233
payment_params.hash(hasher);
232234
},
@@ -243,6 +245,7 @@ impl HTLCSource {
243245
first_hop_htlc_msat: 0,
244246
payment_id: PaymentId([2; 32]),
245247
payment_secret: None,
248+
payment_metadata: None,
246249
payment_params: None,
247250
}
248251
}
@@ -468,6 +471,7 @@ pub(crate) enum PendingOutboundPayment {
468471
session_privs: HashSet<[u8; 32]>,
469472
payment_hash: PaymentHash,
470473
payment_secret: Option<PaymentSecret>,
474+
payment_metadata: Option<Vec<u8>>,
471475
pending_amt_msat: u64,
472476
/// Used to track the fee paid. Only present if the payment was serialized on 0.0.103+.
473477
pending_fee_msat: Option<u64>,
@@ -2327,15 +2331,15 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
23272331
}
23282332

23292333
// Only public for testing, this should otherwise never be called direcly
2330-
pub(crate) fn send_payment_along_path(&self, path: &Vec<RouteHop>, payment_params: &Option<PaymentParameters>, payment_hash: &PaymentHash, payment_secret: &Option<PaymentSecret>, total_value: u64, cur_height: u32, payment_id: PaymentId, keysend_preimage: &Option<PaymentPreimage>) -> Result<(), APIError> {
2334+
pub(crate) fn send_payment_along_path(&self, path: &Vec<RouteHop>, payment_params: &Option<PaymentParameters>, payment_hash: &PaymentHash, payment_secret: &Option<PaymentSecret>, payment_metadata: &Option<Vec<u8>>, total_value: u64, cur_height: u32, payment_id: PaymentId, keysend_preimage: &Option<PaymentPreimage>) -> Result<(), APIError> {
23312335
log_trace!(self.logger, "Attempting to send payment for path with next hop {}", path.first().unwrap().short_channel_id);
23322336
let prng_seed = self.keys_manager.get_secure_random_bytes();
23332337
let session_priv_bytes = self.keys_manager.get_secure_random_bytes();
23342338
let session_priv = SecretKey::from_slice(&session_priv_bytes[..]).expect("RNG is busted");
23352339

23362340
let onion_keys = onion_utils::construct_onion_keys(&self.secp_ctx, &path, &session_priv)
23372341
.map_err(|_| APIError::RouteError{err: "Pubkey along hop was maliciously selected"})?;
2338-
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(path, total_value, payment_secret, cur_height, keysend_preimage)?;
2342+
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(path, total_value, payment_secret, payment_metadata.clone(), cur_height, keysend_preimage)?;
23392343
if onion_utils::route_size_insane(&onion_payloads) {
23402344
return Err(APIError::RouteError{err: "Route size too large considering onion data"});
23412345
}
@@ -2369,6 +2373,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
23692373
pending_fee_msat: Some(0),
23702374
payment_hash: *payment_hash,
23712375
payment_secret: *payment_secret,
2376+
payment_metadata: payment_metadata.clone(),
23722377
starting_block_height: self.best_block.read().unwrap().height(),
23732378
total_msat: total_value,
23742379
});
@@ -2392,6 +2397,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
23922397
first_hop_htlc_msat: htlc_msat,
23932398
payment_id,
23942399
payment_secret: payment_secret.clone(),
2400+
payment_metadata: payment_metadata.clone(),
23952401
payment_params: payment_params.clone(),
23962402
}, onion_packet, &self.logger),
23972403
channel_state, chan)
@@ -2476,10 +2482,10 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
24762482
/// bit set (either as required or as available). If multiple paths are present in the Route,
24772483
/// we assume the invoice had the basic_mpp feature set.
24782484
pub fn send_payment(&self, route: &Route, payment_hash: PaymentHash, payment_secret: &Option<PaymentSecret>) -> Result<PaymentId, PaymentSendFailure> {
2479-
self.send_payment_internal(route, payment_hash, payment_secret, None, None, None)
2485+
self.send_payment_internal(route, payment_hash, payment_secret, None, None, None, None)
24802486
}
24812487

2482-
fn send_payment_internal(&self, route: &Route, payment_hash: PaymentHash, payment_secret: &Option<PaymentSecret>, keysend_preimage: Option<PaymentPreimage>, payment_id: Option<PaymentId>, recv_value_msat: Option<u64>) -> Result<PaymentId, PaymentSendFailure> {
2488+
fn send_payment_internal(&self, route: &Route, payment_hash: PaymentHash, payment_secret: &Option<PaymentSecret>, payment_metadata: Option<Vec<u8>>, keysend_preimage: Option<PaymentPreimage>, payment_id: Option<PaymentId>, recv_value_msat: Option<u64>) -> Result<PaymentId, PaymentSendFailure> {
24832489
if route.paths.len() < 1 {
24842490
return Err(PaymentSendFailure::ParameterError(APIError::RouteError{err: "There must be at least one path to send over"}));
24852491
}
@@ -2521,7 +2527,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
25212527
let cur_height = self.best_block.read().unwrap().height() + 1;
25222528
let mut results = Vec::new();
25232529
for path in route.paths.iter() {
2524-
results.push(self.send_payment_along_path(&path, &route.payment_params, &payment_hash, payment_secret, total_value, cur_height, payment_id, &keysend_preimage));
2530+
results.push(self.send_payment_along_path(&path, &route.payment_params, &payment_hash, payment_secret, &payment_metadata, total_value, cur_height, payment_id, &keysend_preimage));
25252531
}
25262532
let mut has_ok = false;
25272533
let mut has_err = false;
@@ -2584,20 +2590,20 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
25842590
}
25852591
}
25862592

2587-
let (total_msat, payment_hash, payment_secret) = {
2593+
let (total_msat, payment_hash, payment_secret, payment_metadata) = {
25882594
let outbounds = self.pending_outbound_payments.lock().unwrap();
25892595
if let Some(payment) = outbounds.get(&payment_id) {
25902596
match payment {
25912597
PendingOutboundPayment::Retryable {
2592-
total_msat, payment_hash, payment_secret, pending_amt_msat, ..
2598+
total_msat, payment_hash, payment_secret, pending_amt_msat, payment_metadata, ..
25932599
} => {
25942600
let retry_amt_msat: u64 = route.paths.iter().map(|path| path.last().unwrap().fee_msat).sum();
25952601
if retry_amt_msat + *pending_amt_msat > *total_msat * (100 + RETRY_OVERFLOW_PERCENTAGE) / 100 {
25962602
return Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError {
25972603
err: format!("retry_amt_msat of {} will put pending_amt_msat (currently: {}) more than 10% over total_payment_amt_msat of {}", retry_amt_msat, pending_amt_msat, total_msat).to_string()
25982604
}))
25992605
}
2600-
(*total_msat, *payment_hash, *payment_secret)
2606+
(*total_msat, *payment_hash, *payment_secret, payment_metadata.clone())
26012607
},
26022608
PendingOutboundPayment::Legacy { .. } => {
26032609
return Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError {
@@ -2621,7 +2627,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
26212627
}))
26222628
}
26232629
};
2624-
return self.send_payment_internal(route, payment_hash, &payment_secret, None, Some(payment_id), Some(total_msat)).map(|_| ())
2630+
return self.send_payment_internal(route, payment_hash, &payment_secret, payment_metadata, None, Some(payment_id), Some(total_msat)).map(|_| ())
26252631
}
26262632

26272633
/// Signals that no further retries for the given payment will occur.
@@ -2675,7 +2681,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
26752681
None => PaymentPreimage(self.keys_manager.get_secure_random_bytes()),
26762682
};
26772683
let payment_hash = PaymentHash(Sha256::hash(&preimage.0).into_inner());
2678-
match self.send_payment_internal(route, payment_hash, &None, Some(preimage), None, None) {
2684+
match self.send_payment_internal(route, payment_hash, &None, None, Some(preimage), None, None) {
26792685
Ok(payment_id) => Ok((payment_hash, payment_id)),
26802686
Err(e) => Err(e)
26812687
}
@@ -6147,13 +6153,15 @@ impl Readable for HTLCSource {
61476153
let mut payment_id = None;
61486154
let mut payment_secret = None;
61496155
let mut payment_params = None;
6156+
let mut payment_metadata = None;
61506157
read_tlv_fields!(reader, {
61516158
(0, session_priv, required),
61526159
(1, payment_id, option),
61536160
(2, first_hop_htlc_msat, required),
61546161
(3, payment_secret, option),
61556162
(4, path, vec_type),
61566163
(5, payment_params, option),
6164+
(7, payment_metadata, option),
61576165
});
61586166
if payment_id.is_none() {
61596167
// For backwards compat, if there was no payment_id written, use the session_priv bytes
@@ -6167,6 +6175,7 @@ impl Readable for HTLCSource {
61676175
payment_id: payment_id.unwrap(),
61686176
payment_secret,
61696177
payment_params,
6178+
payment_metadata,
61706179
})
61716180
}
61726181
1 => Ok(HTLCSource::PreviousHopData(Readable::read(reader)?)),
@@ -6178,7 +6187,7 @@ impl Readable for HTLCSource {
61786187
impl Writeable for HTLCSource {
61796188
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::io::Error> {
61806189
match self {
6181-
HTLCSource::OutboundRoute { ref session_priv, ref first_hop_htlc_msat, ref path, payment_id, payment_secret, payment_params } => {
6190+
HTLCSource::OutboundRoute { ref session_priv, ref first_hop_htlc_msat, ref path, payment_id, payment_secret, ref payment_metadata, payment_params } => {
61826191
0u8.write(writer)?;
61836192
let payment_id_opt = Some(payment_id);
61846193
write_tlv_fields!(writer, {
@@ -6188,6 +6197,7 @@ impl Writeable for HTLCSource {
61886197
(3, payment_secret, option),
61896198
(4, path, vec_type),
61906199
(5, payment_params, option),
6200+
(7, payment_metadata, option),
61916201
});
61926202
}
61936203
HTLCSource::PreviousHopData(ref field) => {
@@ -6242,6 +6252,7 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
62426252
(0, session_privs, required),
62436253
(1, pending_fee_msat, option),
62446254
(2, payment_hash, required),
6255+
(3, payment_metadata, option),
62456256
(4, payment_secret, option),
62466257
(6, total_msat, required),
62476258
(8, pending_amt_msat, required),
@@ -6704,7 +6715,7 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
67046715
for (_, monitor) in args.channel_monitors {
67056716
if by_id.get(&monitor.get_funding_txo().0.to_channel_id()).is_none() {
67066717
for (htlc_source, htlc) in monitor.get_pending_outbound_htlcs() {
6707-
if let HTLCSource::OutboundRoute { payment_id, session_priv, path, payment_secret, .. } = htlc_source {
6718+
if let HTLCSource::OutboundRoute { payment_id, session_priv, path, payment_secret, payment_metadata, .. } = htlc_source {
67086719
if path.is_empty() {
67096720
log_error!(args.logger, "Got an empty path for a pending payment");
67106721
return Err(DecodeError::InvalidValue);
@@ -6724,6 +6735,7 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
67246735
session_privs: [session_priv_bytes].iter().map(|a| *a).collect(),
67256736
payment_hash: htlc.payment_hash,
67266737
payment_secret,
6738+
payment_metadata,
67276739
pending_amt_msat: path_amt,
67286740
pending_fee_msat: Some(path_fee),
67296741
total_msat: path_amt,
@@ -6999,7 +7011,7 @@ mod tests {
69997011
// Use the utility function send_payment_along_path to send the payment with MPP data which
70007012
// indicates there are more HTLCs coming.
70017013
let cur_height = CHAN_CONFIRM_DEPTH + 1; // route_payment calls send_payment, which adds 1 to the current height. So we do the same here to match.
7002-
nodes[0].node.send_payment_along_path(&route.paths[0], &route.payment_params, &our_payment_hash, &Some(payment_secret), 200_000, cur_height, payment_id, &None).unwrap();
7014+
nodes[0].node.send_payment_along_path(&route.paths[0], &route.payment_params, &our_payment_hash, &Some(payment_secret), &None, 200_000, cur_height, payment_id, &None).unwrap();
70037015
check_added_monitors!(nodes[0], 1);
70047016
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
70057017
assert_eq!(events.len(), 1);
@@ -7029,7 +7041,7 @@ mod tests {
70297041
expect_payment_failed!(nodes[0], our_payment_hash, true);
70307042

70317043
// Send the second half of the original MPP payment.
7032-
nodes[0].node.send_payment_along_path(&route.paths[0], &route.payment_params, &our_payment_hash, &Some(payment_secret), 200_000, cur_height, payment_id, &None).unwrap();
7044+
nodes[0].node.send_payment_along_path(&route.paths[0], &route.payment_params, &our_payment_hash, &Some(payment_secret), &None, 200_000, cur_height, payment_id, &None).unwrap();
70337045
check_added_monitors!(nodes[0], 1);
70347046
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
70357047
assert_eq!(events.len(), 1);
@@ -7223,7 +7235,7 @@ mod tests {
72237235

72247236
let test_preimage = PaymentPreimage([42; 32]);
72257237
let mismatch_payment_hash = PaymentHash([43; 32]);
7226-
let _ = nodes[0].node.send_payment_internal(&route, mismatch_payment_hash, &None, Some(test_preimage), None, None).unwrap();
7238+
let _ = nodes[0].node.send_payment_internal(&route, mismatch_payment_hash, &None, None, Some(test_preimage), None, None).unwrap();
72277239
check_added_monitors!(nodes[0], 1);
72287240

72297241
let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
@@ -7268,7 +7280,7 @@ mod tests {
72687280
let test_preimage = PaymentPreimage([42; 32]);
72697281
let test_secret = PaymentSecret([43; 32]);
72707282
let payment_hash = PaymentHash(Sha256::hash(&test_preimage.0).into_inner());
7271-
let _ = nodes[0].node.send_payment_internal(&route, payment_hash, &Some(test_secret), Some(test_preimage), None, None).unwrap();
7283+
let _ = nodes[0].node.send_payment_internal(&route, payment_hash, &Some(test_secret), None, Some(test_preimage), None, None).unwrap();
72727284
check_added_monitors!(nodes[0], 1);
72737285

72747286
let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());

lightning/src/ln/functional_tests.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1349,7 +1349,7 @@ fn test_fee_spike_violation_fails_htlc() {
13491349
let cur_height = nodes[1].node.best_block.read().unwrap().height() + 1;
13501350

13511351
let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv).unwrap();
1352-
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 3460001, &Some(payment_secret), cur_height, &None).unwrap();
1352+
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 3460001, &Some(payment_secret), None, cur_height, &None).unwrap();
13531353
let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash);
13541354
let msg = msgs::UpdateAddHTLC {
13551355
channel_id: chan.2,
@@ -1526,7 +1526,7 @@ fn test_chan_reserve_violation_inbound_htlc_outbound_channel() {
15261526
let session_priv = SecretKey::from_slice(&[42; 32]).unwrap();
15271527
let cur_height = nodes[1].node.best_block.read().unwrap().height() + 1;
15281528
let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv).unwrap();
1529-
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 700_000, &Some(payment_secret), cur_height, &None).unwrap();
1529+
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 700_000, &Some(payment_secret), None, cur_height, &None).unwrap();
15301530
let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash);
15311531
let msg = msgs::UpdateAddHTLC {
15321532
channel_id: chan.2,
@@ -1696,7 +1696,7 @@ fn test_chan_reserve_violation_inbound_htlc_inbound_chan() {
16961696
let session_priv = SecretKey::from_slice(&[42; 32]).unwrap();
16971697
let cur_height = nodes[0].node.best_block.read().unwrap().height() + 1;
16981698
let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route_2.paths[0], &session_priv).unwrap();
1699-
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route_2.paths[0], recv_value_2, &None, cur_height, &None).unwrap();
1699+
let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route_2.paths[0], recv_value_2, &None, None, cur_height, &None).unwrap();
17001700
let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &our_payment_hash_1);
17011701
let msg = msgs::UpdateAddHTLC {
17021702
channel_id: chan.2,
@@ -3295,7 +3295,7 @@ fn fail_backward_pending_htlc_upon_channel_failure() {
32953295
let secp_ctx = Secp256k1::new();
32963296
let session_priv = SecretKey::from_slice(&[42; 32]).unwrap();
32973297
let current_height = nodes[1].node.best_block.read().unwrap().height() + 1;
3298-
let (onion_payloads, _amount_msat, cltv_expiry) = onion_utils::build_onion_payloads(&route.paths[0], 50_000, &Some(payment_secret), current_height, &None).unwrap();
3298+
let (onion_payloads, _amount_msat, cltv_expiry) = onion_utils::build_onion_payloads(&route.paths[0], 50_000, &Some(payment_secret), None, current_height, &None).unwrap();
32993299
let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv).unwrap();
33003300
let onion_routing_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash);
33013301

@@ -4144,7 +4144,7 @@ fn do_test_htlc_timeout(send_partial_mpp: bool) {
41444144
// indicates there are more HTLCs coming.
41454145
let cur_height = CHAN_CONFIRM_DEPTH + 1; // route_payment calls send_payment, which adds 1 to the current height. So we do the same here to match.
41464146
let payment_id = PaymentId([42; 32]);
4147-
nodes[0].node.send_payment_along_path(&route.paths[0], &route.payment_params, &our_payment_hash, &Some(payment_secret), 200000, cur_height, payment_id, &None).unwrap();
4147+
nodes[0].node.send_payment_along_path(&route.paths[0], &route.payment_params, &our_payment_hash, &Some(payment_secret), &None, 200000, cur_height, payment_id, &None).unwrap();
41484148
check_added_monitors!(nodes[0], 1);
41494149
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
41504150
assert_eq!(events.len(), 1);
@@ -6607,7 +6607,7 @@ fn test_update_add_htlc_bolt2_receiver_check_max_htlc_limit() {
66076607
let session_priv = SecretKey::from_slice(&[42; 32]).unwrap();
66086608
let cur_height = nodes[0].node.best_block.read().unwrap().height() + 1;
66096609
let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::signing_only(), &route.paths[0], &session_priv).unwrap();
6610-
let (onion_payloads, _htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 3999999, &Some(our_payment_secret), cur_height, &None).unwrap();
6610+
let (onion_payloads, _htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 3999999, &Some(our_payment_secret), None, cur_height, &None).unwrap();
66116611
let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &our_payment_hash);
66126612

66136613
let mut msg = msgs::UpdateAddHTLC {

0 commit comments

Comments
 (0)