Skip to content

Commit e3297a2

Browse files
Add MppId field to HTLCSource as a way to correlate mpp payment paths
1 parent 454b213 commit e3297a2

File tree

4 files changed

+34
-8
lines changed

4 files changed

+34
-8
lines changed

lightning/src/ln/channel.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5527,7 +5527,7 @@ mod tests {
55275527
use bitcoin::hashes::hex::FromHex;
55285528
use hex;
55295529
use ln::{PaymentPreimage, PaymentHash};
5530-
use ln::channelmanager::HTLCSource;
5530+
use ln::channelmanager::{HTLCSource, MppId};
55315531
use ln::channel::{Channel,InboundHTLCOutput,OutboundHTLCOutput,InboundHTLCState,OutboundHTLCState,HTLCOutputInCommitment,HTLCCandidate,HTLCInitiator,TxCreationKeys};
55325532
use ln::channel::MAX_FUNDING_SATOSHIS;
55335533
use ln::features::InitFeatures;
@@ -5701,6 +5701,7 @@ mod tests {
57015701
path: Vec::new(),
57025702
session_priv: SecretKey::from_slice(&hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(),
57035703
first_hop_htlc_msat: 548,
5704+
mpp_id: Some(MppId([42; 32])),
57045705
}
57055706
});
57065707

lightning/src/ln/channelmanager.rs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,23 @@ struct ClaimableHTLC {
173173
onion_payload: OnionPayload,
174174
}
175175

176+
/// A payment identifier used to correlate an MPP payment's per-path HTLC sources internally.
177+
/// (C-not exported) as we just use [u8; 32] directly
178+
#[derive(Hash, Copy, Clone, PartialEq, Eq, Debug)]
179+
pub(crate) struct MppId(pub [u8; 32]);
180+
181+
impl Writeable for MppId {
182+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
183+
self.0.write(w)
184+
}
185+
}
186+
187+
impl Readable for MppId {
188+
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
189+
let buf: [u8; 32] = Readable::read(r)?;
190+
Ok(MppId(buf))
191+
}
192+
}
176193
/// Tracks the inbound corresponding to an outbound HTLC
177194
#[derive(Clone, PartialEq)]
178195
pub(crate) enum HTLCSource {
@@ -183,6 +200,7 @@ pub(crate) enum HTLCSource {
183200
/// Technically we can recalculate this from the route, but we cache it here to avoid
184201
/// doing a double-pass on route when we get a failure back
185202
first_hop_htlc_msat: u64,
203+
mpp_id: Option<MppId>,
186204
},
187205
}
188206
#[cfg(test)]
@@ -192,6 +210,7 @@ impl HTLCSource {
192210
path: Vec::new(),
193211
session_priv: SecretKey::from_slice(&[1; 32]).unwrap(),
194212
first_hop_htlc_msat: 0,
213+
mpp_id: Some(MppId([2; 32])),
195214
}
196215
}
197216
}
@@ -1820,7 +1839,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
18201839
}
18211840

18221841
// Only public for testing, this should otherwise never be called direcly
1823-
pub(crate) fn send_payment_along_path(&self, path: &Vec<RouteHop>, payment_hash: &PaymentHash, payment_secret: &Option<PaymentSecret>, total_value: u64, cur_height: u32, keysend_preimage: &Option<PaymentPreimage>) -> Result<(), APIError> {
1842+
pub(crate) fn send_payment_along_path(&self, path: &Vec<RouteHop>, payment_hash: &PaymentHash, payment_secret: &Option<PaymentSecret>, total_value: u64, cur_height: u32, mpp_id: Option<MppId>, keysend_preimage: &Option<PaymentPreimage>) -> Result<(), APIError> {
18241843
log_trace!(self.logger, "Attempting to send payment for path with next hop {}", path.first().unwrap().short_channel_id);
18251844
let prng_seed = self.keys_manager.get_secure_random_bytes();
18261845
let session_priv_bytes = self.keys_manager.get_secure_random_bytes();
@@ -1857,6 +1876,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
18571876
path: path.clone(),
18581877
session_priv: session_priv.clone(),
18591878
first_hop_htlc_msat: htlc_msat,
1879+
mpp_id,
18601880
}, onion_packet, &self.logger), channel_state, chan)
18611881
} {
18621882
Some((update_add, commitment_signed, monitor_update)) => {
@@ -1956,6 +1976,9 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
19561976
let mut total_value = 0;
19571977
let our_node_id = self.get_our_node_id();
19581978
let mut path_errs = Vec::with_capacity(route.paths.len());
1979+
let mpp_id = if route.paths.len() == 1 { None } else {
1980+
Some(MppId(self.keys_manager.get_secure_random_bytes()))
1981+
};
19591982
'path_check: for path in route.paths.iter() {
19601983
if path.len() < 1 || path.len() > 20 {
19611984
path_errs.push(Err(APIError::RouteError{err: "Path didn't go anywhere/had bogus size"}));
@@ -1977,7 +2000,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
19772000
let cur_height = self.best_block.read().unwrap().height() + 1;
19782001
let mut results = Vec::new();
19792002
for path in route.paths.iter() {
1980-
results.push(self.send_payment_along_path(&path, &payment_hash, payment_secret, total_value, cur_height, &keysend_preimage));
2003+
results.push(self.send_payment_along_path(&path, &payment_hash, payment_secret, total_value, cur_height, mpp_id, &keysend_preimage));
19812004
}
19822005
let mut has_ok = false;
19832006
let mut has_err = false;
@@ -4918,6 +4941,7 @@ impl Readable for ClaimableHTLC {
49184941
impl_writeable_tlv_based_enum!(HTLCSource,
49194942
(0, OutboundRoute) => {
49204943
(0, session_priv, required),
4944+
(1, mpp_id, option),
49214945
(2, first_hop_htlc_msat, required),
49224946
(4, path, vec_type),
49234947
}, ;
@@ -5368,7 +5392,7 @@ mod tests {
53685392
use bitcoin::hashes::sha256::Hash as Sha256;
53695393
use core::time::Duration;
53705394
use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
5371-
use ln::channelmanager::PaymentSendFailure;
5395+
use ln::channelmanager::{MppId, PaymentSendFailure};
53725396
use ln::features::{InitFeatures, InvoiceFeatures};
53735397
use ln::functional_test_utils::*;
53745398
use ln::msgs;
@@ -5519,10 +5543,11 @@ mod tests {
55195543
let net_graph_msg_handler = &nodes[0].net_graph_msg_handler;
55205544
let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes[1].node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 100_000, TEST_FINAL_CLTV, &logger).unwrap();
55215545
let (payment_preimage, our_payment_hash, payment_secret) = get_payment_preimage_hash!(&nodes[1]);
5546+
let mpp_id = Some(MppId([42; 32]));
55225547
// Use the utility function send_payment_along_path to send the payment with MPP data which
55235548
// indicates there are more HTLCs coming.
55245549
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.
5525-
nodes[0].node.send_payment_along_path(&route.paths[0], &our_payment_hash, &Some(payment_secret), 200_000, cur_height, &None).unwrap();
5550+
nodes[0].node.send_payment_along_path(&route.paths[0], &our_payment_hash, &Some(payment_secret), 200_000, cur_height, mpp_id, &None).unwrap();
55265551
check_added_monitors!(nodes[0], 1);
55275552
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
55285553
assert_eq!(events.len(), 1);
@@ -5552,7 +5577,7 @@ mod tests {
55525577
expect_payment_failed!(nodes[0], our_payment_hash, true);
55535578

55545579
// Send the second half of the original MPP payment.
5555-
nodes[0].node.send_payment_along_path(&route.paths[0], &our_payment_hash, &Some(payment_secret), 200_000, cur_height, &None).unwrap();
5580+
nodes[0].node.send_payment_along_path(&route.paths[0], &our_payment_hash, &Some(payment_secret), 200_000, cur_height, payment_id, &None).unwrap();
55565581
check_added_monitors!(nodes[0], 1);
55575582
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
55585583
assert_eq!(events.len(), 1);

lightning/src/ln/functional_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3886,7 +3886,7 @@ fn do_test_htlc_timeout(send_partial_mpp: bool) {
38863886
// Use the utility function send_payment_along_path to send the payment with MPP data which
38873887
// indicates there are more HTLCs coming.
38883888
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.
3889-
nodes[0].node.send_payment_along_path(&route.paths[0], &our_payment_hash, &Some(payment_secret), 200000, cur_height, &None).unwrap();
3889+
nodes[0].node.send_payment_along_path(&route.paths[0], &our_payment_hash, &Some(payment_secret), 200000, cur_height, None, &None).unwrap();
38903890
check_added_monitors!(nodes[0], 1);
38913891
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
38923892
assert_eq!(events.len(), 1);

lightning/src/ln/onion_utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ pub(super) fn build_first_hop_failure_packet(shared_secret: &[u8], failure_type:
331331
/// Returns update, a boolean indicating that the payment itself failed, and the error code.
332332
#[inline]
333333
pub(super) fn process_onion_failure<T: secp256k1::Signing, L: Deref>(secp_ctx: &Secp256k1<T>, logger: &L, htlc_source: &HTLCSource, mut packet_decrypted: Vec<u8>) -> (Option<msgs::HTLCFailChannelUpdate>, bool, Option<u16>, Option<Vec<u8>>) where L::Target: Logger {
334-
if let &HTLCSource::OutboundRoute { ref path, ref session_priv, ref first_hop_htlc_msat } = htlc_source {
334+
if let &HTLCSource::OutboundRoute { ref path, ref session_priv, ref first_hop_htlc_msat, .. } = htlc_source {
335335
let mut res = None;
336336
let mut htlc_msat = *first_hop_htlc_msat;
337337
let mut error_code_ret = None;

0 commit comments

Comments
 (0)