Skip to content

Commit ab57a05

Browse files
committed
Store Payee information in HTLCSource::OutboundRoute.
This stores and tracks HTLC payee information with HTLCSource info, allowing us to provide it back to the user if the HTLC fails and ensuring persistence by keeping it with the HTLC itself as it passes between Channel and ChannelMonitor.
1 parent fe237f9 commit ab57a05

File tree

3 files changed

+37
-14
lines changed

3 files changed

+37
-14
lines changed

lightning/src/ln/channel.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5768,6 +5768,7 @@ mod tests {
57685768
first_hop_htlc_msat: 548,
57695769
payment_id: PaymentId([42; 32]),
57705770
payment_secret: None,
5771+
payee: None,
57715772
}
57725773
});
57735774

lightning/src/ln/channelmanager.rs

+35-13
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ use chain::transaction::{OutPoint, TransactionData};
4545
use ln::{PaymentHash, PaymentPreimage, PaymentSecret};
4646
use ln::channel::{Channel, ChannelError, ChannelUpdateStatus, UpdateFulfillCommitFetch};
4747
use ln::features::{InitFeatures, NodeFeatures};
48-
use routing::router::{Route, RouteHop};
48+
use routing::router::{Payee, PaymentPathRetry, Route, RouteHop};
4949
use ln::msgs;
5050
use ln::msgs::NetAddress;
5151
use ln::onion_utils;
@@ -201,6 +201,7 @@ pub(crate) enum HTLCSource {
201201
first_hop_htlc_msat: u64,
202202
payment_id: PaymentId,
203203
payment_secret: Option<PaymentSecret>,
204+
payee: Option<Payee>,
204205
},
205206
}
206207
#[allow(clippy::derive_hash_xor_eq)] // Our Hash is faithful to the data, we just don't have SecretKey::hash
@@ -211,13 +212,14 @@ impl core::hash::Hash for HTLCSource {
211212
0u8.hash(hasher);
212213
prev_hop_data.hash(hasher);
213214
},
214-
HTLCSource::OutboundRoute { path, session_priv, payment_id, payment_secret, first_hop_htlc_msat } => {
215+
HTLCSource::OutboundRoute { path, session_priv, payment_id, payment_secret, first_hop_htlc_msat, payee } => {
215216
1u8.hash(hasher);
216217
path.hash(hasher);
217218
session_priv[..].hash(hasher);
218219
payment_id.hash(hasher);
219220
payment_secret.hash(hasher);
220221
first_hop_htlc_msat.hash(hasher);
222+
payee.hash(hasher);
221223
},
222224
}
223225
}
@@ -231,6 +233,7 @@ impl HTLCSource {
231233
first_hop_htlc_msat: 0,
232234
payment_id: PaymentId([2; 32]),
233235
payment_secret: None,
236+
payee: None,
234237
}
235238
}
236239
}
@@ -2021,7 +2024,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
20212024
}
20222025

20232026
// Only public for testing, this should otherwise never be called direcly
2024-
pub(crate) fn send_payment_along_path(&self, path: &Vec<RouteHop>, payment_hash: &PaymentHash, payment_secret: &Option<PaymentSecret>, total_value: u64, cur_height: u32, payment_id: PaymentId, keysend_preimage: &Option<PaymentPreimage>) -> Result<(), APIError> {
2027+
pub(crate) fn send_payment_along_path(&self, path: &Vec<RouteHop>, payee: &Option<Payee>, payment_hash: &PaymentHash, payment_secret: &Option<PaymentSecret>, total_value: u64, cur_height: u32, payment_id: PaymentId, keysend_preimage: &Option<PaymentPreimage>) -> Result<(), APIError> {
20252028
log_trace!(self.logger, "Attempting to send payment for path with next hop {}", path.first().unwrap().short_channel_id);
20262029
let prng_seed = self.keys_manager.get_secure_random_bytes();
20272030
let session_priv_bytes = self.keys_manager.get_secure_random_bytes();
@@ -2071,6 +2074,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
20712074
first_hop_htlc_msat: htlc_msat,
20722075
payment_id,
20732076
payment_secret: payment_secret.clone(),
2077+
payee: payee.clone(),
20742078
}, onion_packet, &self.logger),
20752079
channel_state, chan);
20762080

@@ -2209,7 +2213,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
22092213
let cur_height = self.best_block.read().unwrap().height() + 1;
22102214
let mut results = Vec::new();
22112215
for path in route.paths.iter() {
2212-
results.push(self.send_payment_along_path(&path, &payment_hash, payment_secret, total_value, cur_height, payment_id, &keysend_preimage));
2216+
results.push(self.send_payment_along_path(&path, &route.payee, &payment_hash, payment_secret, total_value, cur_height, payment_id, &keysend_preimage));
22132217
}
22142218
let mut has_ok = false;
22152219
let mut has_err = false;
@@ -3098,14 +3102,21 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
30983102
self.fail_htlc_backwards_internal(channel_state,
30993103
htlc_src, &payment_hash, HTLCFailReason::Reason { failure_code, data: onion_failure_data});
31003104
},
3101-
HTLCSource::OutboundRoute { session_priv, payment_id, path, .. } => {
3105+
HTLCSource::OutboundRoute { session_priv, payment_id, path, payee, .. } => {
31023106
let mut session_priv_bytes = [0; 32];
31033107
session_priv_bytes.copy_from_slice(&session_priv[..]);
31043108
let mut outbounds = self.pending_outbound_payments.lock().unwrap();
31053109
if let hash_map::Entry::Occupied(mut payment) = outbounds.entry(payment_id) {
31063110
if payment.get_mut().remove(&session_priv_bytes, Some(path.last().unwrap().fee_msat)) &&
31073111
!payment.get().is_fulfilled()
31083112
{
3113+
let retry = if let Some(payee_data) = payee {
3114+
Some(PaymentPathRetry {
3115+
payee: payee_data,
3116+
final_value_msat: path.last().expect("Outbound payments must have had a valid path").fee_msat,
3117+
final_cltv_expiry_delta: path.last().expect("Outbound payments must have had a valid path").cltv_expiry_delta,
3118+
})
3119+
} else { None };
31093120
self.pending_events.lock().unwrap().push(
31103121
events::Event::PaymentPathFailed {
31113122
payment_hash,
@@ -3114,7 +3125,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
31143125
all_paths_failed: payment.get().remaining_parts() == 0,
31153126
path: path.clone(),
31163127
short_channel_id: None,
3117-
retry: None,
3128+
retry,
31183129
#[cfg(test)]
31193130
error_code: None,
31203131
#[cfg(test)]
@@ -3146,7 +3157,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
31463157
// from block_connected which may run during initialization prior to the chain_monitor
31473158
// being fully configured. See the docs for `ChannelManagerReadArgs` for more.
31483159
match source {
3149-
HTLCSource::OutboundRoute { ref path, session_priv, payment_id, .. } => {
3160+
HTLCSource::OutboundRoute { ref path, session_priv, payment_id, ref payee, .. } => {
31503161
let mut session_priv_bytes = [0; 32];
31513162
session_priv_bytes.copy_from_slice(&session_priv[..]);
31523163
let mut outbounds = self.pending_outbound_payments.lock().unwrap();
@@ -3167,8 +3178,15 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
31673178
log_trace!(self.logger, "Received duplicative fail for HTLC with payment_hash {}", log_bytes!(payment_hash.0));
31683179
return;
31693180
}
3170-
log_trace!(self.logger, "Failing outbound payment HTLC with payment_hash {}", log_bytes!(payment_hash.0));
31713181
mem::drop(channel_state_lock);
3182+
let retry = if let Some(payee_data) = payee {
3183+
Some(PaymentPathRetry {
3184+
payee: payee_data.clone(),
3185+
final_value_msat: path.last().expect("Outbound payments must have had a valid path").fee_msat,
3186+
final_cltv_expiry_delta: path.last().expect("Outbound payments must have had a valid path").cltv_expiry_delta,
3187+
})
3188+
} else { None };
3189+
log_trace!(self.logger, "Failing outbound payment HTLC with payment_hash {}", log_bytes!(payment_hash.0));
31723190
match &onion_error {
31733191
&HTLCFailReason::LightningError { ref err } => {
31743192
#[cfg(test)]
@@ -3186,7 +3204,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
31863204
all_paths_failed,
31873205
path: path.clone(),
31883206
short_channel_id,
3189-
retry: None,
3207+
retry,
31903208
#[cfg(test)]
31913209
error_code: onion_error_code,
31923210
#[cfg(test)]
@@ -3215,7 +3233,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
32153233
all_paths_failed,
32163234
path: path.clone(),
32173235
short_channel_id: Some(path.first().unwrap().short_channel_id),
3218-
retry: None,
3236+
retry,
32193237
#[cfg(test)]
32203238
error_code: Some(*failure_code),
32213239
#[cfg(test)]
@@ -5378,12 +5396,14 @@ impl Readable for HTLCSource {
53785396
let mut path = Some(Vec::new());
53795397
let mut payment_id = None;
53805398
let mut payment_secret = None;
5399+
let mut payee = None;
53815400
read_tlv_fields!(reader, {
53825401
(0, session_priv, required),
53835402
(1, payment_id, option),
53845403
(2, first_hop_htlc_msat, required),
53855404
(3, payment_secret, option),
53865405
(4, path, vec_type),
5406+
(5, payee, option),
53875407
});
53885408
if payment_id.is_none() {
53895409
// For backwards compat, if there was no payment_id written, use the session_priv bytes
@@ -5396,6 +5416,7 @@ impl Readable for HTLCSource {
53965416
path: path.unwrap(),
53975417
payment_id: payment_id.unwrap(),
53985418
payment_secret,
5419+
payee,
53995420
})
54005421
}
54015422
1 => Ok(HTLCSource::PreviousHopData(Readable::read(reader)?)),
@@ -5407,7 +5428,7 @@ impl Readable for HTLCSource {
54075428
impl Writeable for HTLCSource {
54085429
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::io::Error> {
54095430
match self {
5410-
HTLCSource::OutboundRoute { ref session_priv, ref first_hop_htlc_msat, ref path, payment_id, payment_secret } => {
5431+
HTLCSource::OutboundRoute { ref session_priv, ref first_hop_htlc_msat, ref path, payment_id, payment_secret, payee } => {
54115432
0u8.write(writer)?;
54125433
let payment_id_opt = Some(payment_id);
54135434
write_tlv_fields!(writer, {
@@ -5416,6 +5437,7 @@ impl Writeable for HTLCSource {
54165437
(2, first_hop_htlc_msat, required),
54175438
(3, payment_secret, option),
54185439
(4, path, vec_type),
5440+
(5, payee, option),
54195441
});
54205442
}
54215443
HTLCSource::PreviousHopData(ref field) => {
@@ -6160,7 +6182,7 @@ mod tests {
61606182
// Use the utility function send_payment_along_path to send the payment with MPP data which
61616183
// indicates there are more HTLCs coming.
61626184
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.
6163-
nodes[0].node.send_payment_along_path(&route.paths[0], &our_payment_hash, &Some(payment_secret), 200_000, cur_height, payment_id, &None).unwrap();
6185+
nodes[0].node.send_payment_along_path(&route.paths[0], &route.payee, &our_payment_hash, &Some(payment_secret), 200_000, cur_height, payment_id, &None).unwrap();
61646186
check_added_monitors!(nodes[0], 1);
61656187
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
61666188
assert_eq!(events.len(), 1);
@@ -6190,7 +6212,7 @@ mod tests {
61906212
expect_payment_failed!(nodes[0], our_payment_hash, true);
61916213

61926214
// Send the second half of the original MPP payment.
6193-
nodes[0].node.send_payment_along_path(&route.paths[0], &our_payment_hash, &Some(payment_secret), 200_000, cur_height, payment_id, &None).unwrap();
6215+
nodes[0].node.send_payment_along_path(&route.paths[0], &route.payee, &our_payment_hash, &Some(payment_secret), 200_000, cur_height, payment_id, &None).unwrap();
61946216
check_added_monitors!(nodes[0], 1);
61956217
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
61966218
assert_eq!(events.len(), 1);

lightning/src/ln/functional_tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3912,7 +3912,7 @@ fn do_test_htlc_timeout(send_partial_mpp: bool) {
39123912
// indicates there are more HTLCs coming.
39133913
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.
39143914
let payment_id = PaymentId([42; 32]);
3915-
nodes[0].node.send_payment_along_path(&route.paths[0], &our_payment_hash, &Some(payment_secret), 200000, cur_height, payment_id, &None).unwrap();
3915+
nodes[0].node.send_payment_along_path(&route.paths[0], &route.payee, &our_payment_hash, &Some(payment_secret), 200000, cur_height, payment_id, &None).unwrap();
39163916
check_added_monitors!(nodes[0], 1);
39173917
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
39183918
assert_eq!(events.len(), 1);

0 commit comments

Comments
 (0)