Skip to content

Commit 233cbfc

Browse files
committed
Add hold times to event
1 parent 1c64a50 commit 233cbfc

File tree

7 files changed

+130
-59
lines changed

7 files changed

+130
-59
lines changed

lightning/src/events/mod.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,9 @@ pub enum Event {
10801080
///
10811081
/// May contain a closed channel if the HTLC sent along the path was fulfilled on chain.
10821082
path: Path,
1083+
1084+
/// The hold times as reported by each hop.
1085+
hold_times: Option<Vec<u32>>,
10831086
},
10841087
/// Indicates an outbound HTLC we sent failed, likely due to an intermediary node being unable to
10851088
/// handle the HTLC.
@@ -1816,13 +1819,19 @@ impl Writeable for Event {
18161819
(4, funding_info, required),
18171820
})
18181821
},
1819-
&Event::PaymentPathSuccessful { ref payment_id, ref payment_hash, ref path } => {
1822+
&Event::PaymentPathSuccessful {
1823+
ref payment_id,
1824+
ref payment_hash,
1825+
ref path,
1826+
ref hold_times,
1827+
} => {
18201828
13u8.write(writer)?;
18211829
write_tlv_fields!(writer, {
18221830
(0, payment_id, required),
18231831
(2, payment_hash, option),
18241832
(4, path.hops, required_vec),
18251833
(6, path.blinded_tail, option),
1834+
(8, hold_times, option),
18261835
})
18271836
},
18281837
&Event::PaymentFailed { ref payment_id, ref payment_hash, ref reason } => {
@@ -2311,11 +2320,13 @@ impl MaybeReadable for Event {
23112320
(2, payment_hash, option),
23122321
(4, path, required_vec),
23132322
(6, blinded_tail, option),
2323+
(8, hold_times, option),
23142324
});
23152325
Ok(Some(Event::PaymentPathSuccessful {
23162326
payment_id: payment_id.0.unwrap(),
23172327
payment_hash,
23182328
path: Path { hops: path, blinded_tail },
2329+
hold_times,
23192330
}))
23202331
};
23212332
f()

lightning/src/ln/channel.rs

Lines changed: 44 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -348,11 +348,11 @@ impl From<&OutboundHTLCState> for OutboundHTLCStateDetails {
348348
// the state yet.
349349
OutboundHTLCState::RemoteRemoved(_) =>
350350
OutboundHTLCStateDetails::Committed,
351-
OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(_)) =>
351+
OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(_, _)) =>
352352
OutboundHTLCStateDetails::AwaitingRemoteRevokeToRemoveSuccess,
353353
OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Failure(_)) =>
354354
OutboundHTLCStateDetails::AwaitingRemoteRevokeToRemoveFailure,
355-
OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(_)) =>
355+
OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(_, _)) =>
356356
OutboundHTLCStateDetails::AwaitingRemoteRevokeToRemoveSuccess,
357357
OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Failure(_)) =>
358358
OutboundHTLCStateDetails::AwaitingRemoteRevokeToRemoveFailure,
@@ -387,9 +387,9 @@ impl OutboundHTLCState {
387387
#[rustfmt::skip]
388388
fn preimage(&self) -> Option<PaymentPreimage> {
389389
match self {
390-
OutboundHTLCState::RemoteRemoved(OutboundHTLCOutcome::Success(preimage))
391-
| OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(preimage))
392-
| OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(preimage)) => {
390+
OutboundHTLCState::RemoteRemoved(OutboundHTLCOutcome::Success(preimage, _))
391+
| OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(preimage, _))
392+
| OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(preimage, _)) => {
393393
Some(*preimage)
394394
},
395395
_ => None,
@@ -402,14 +402,14 @@ impl OutboundHTLCState {
402402
enum OutboundHTLCOutcome {
403403
/// We started always filling in the preimages here in 0.0.105, and the requirement
404404
/// that the preimages always be filled in was added in 0.2.
405-
Success(PaymentPreimage),
405+
Success(PaymentPreimage, Option<AttributionData>),
406406
Failure(HTLCFailReason),
407407
}
408408

409409
impl<'a> Into<Option<&'a HTLCFailReason>> for &'a OutboundHTLCOutcome {
410410
fn into(self) -> Option<&'a HTLCFailReason> {
411411
match self {
412-
OutboundHTLCOutcome::Success(_) => None,
412+
OutboundHTLCOutcome::Success(__, _) => None,
413413
OutboundHTLCOutcome::Failure(ref r) => Some(r),
414414
}
415415
}
@@ -1181,7 +1181,7 @@ pub(super) struct MonitorRestoreUpdates {
11811181
pub order: RAACommitmentOrder,
11821182
pub accepted_htlcs: Vec<(PendingHTLCInfo, u64)>,
11831183
pub failed_htlcs: Vec<(HTLCSource, PaymentHash, HTLCFailReason)>,
1184-
pub finalized_claimed_htlcs: Vec<HTLCSource>,
1184+
pub finalized_claimed_htlcs: Vec<(HTLCSource, Option<AttributionData>)>,
11851185
pub pending_update_adds: Vec<msgs::UpdateAddHTLC>,
11861186
pub funding_broadcastable: Option<Transaction>,
11871187
pub channel_ready: Option<msgs::ChannelReady>,
@@ -2313,7 +2313,7 @@ where
23132313
// but need to handle this somehow or we run the risk of losing HTLCs!
23142314
monitor_pending_forwards: Vec<(PendingHTLCInfo, u64)>,
23152315
monitor_pending_failures: Vec<(HTLCSource, PaymentHash, HTLCFailReason)>,
2316-
monitor_pending_finalized_fulfills: Vec<HTLCSource>,
2316+
monitor_pending_finalized_fulfills: Vec<(HTLCSource, Option<AttributionData>)>,
23172317
monitor_pending_update_adds: Vec<msgs::UpdateAddHTLC>,
23182318
monitor_pending_tx_signatures: Option<msgs::TxSignatures>,
23192319

@@ -4160,9 +4160,9 @@ where
41604160
// transaction).
41614161
let mut removed_outbound_total_msat = 0;
41624162
for ref htlc in self.pending_outbound_htlcs.iter() {
4163-
if let OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(_)) = htlc.state {
4163+
if let OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(_, _)) = htlc.state {
41644164
removed_outbound_total_msat += htlc.amount_msat;
4165-
} else if let OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(_)) = htlc.state {
4165+
} else if let OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(_, _)) = htlc.state {
41664166
removed_outbound_total_msat += htlc.amount_msat;
41674167
}
41684168
}
@@ -4425,9 +4425,9 @@ where
44254425

44264426
let mut removed_outbound_total_msat = 0;
44274427
for ref htlc in self.pending_outbound_htlcs.iter() {
4428-
if let OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(_)) = htlc.state {
4428+
if let OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(_, _)) = htlc.state {
44294429
removed_outbound_total_msat += htlc.amount_msat;
4430-
} else if let OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(_)) = htlc.state {
4430+
} else if let OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(_, _)) = htlc.state {
44314431
removed_outbound_total_msat += htlc.amount_msat;
44324432
}
44334433
}
@@ -6705,7 +6705,7 @@ where
67056705
fn mark_outbound_htlc_removed(&mut self, htlc_id: u64, outcome: OutboundHTLCOutcome) -> Result<&OutboundHTLCOutput, ChannelError> {
67066706
for htlc in self.context.pending_outbound_htlcs.iter_mut() {
67076707
if htlc.htlc_id == htlc_id {
6708-
if let OutboundHTLCOutcome::Success(ref payment_preimage) = outcome {
6708+
if let OutboundHTLCOutcome::Success(ref payment_preimage, ..) = outcome {
67096709
let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0[..]).to_byte_array());
67106710
if payment_hash != htlc.payment_hash {
67116711
return Err(ChannelError::close(format!("Remote tried to fulfill HTLC ({}) with an incorrect preimage", htlc_id)));
@@ -6749,7 +6749,7 @@ where
67496749

67506750
self.mark_outbound_htlc_removed(
67516751
msg.htlc_id,
6752-
OutboundHTLCOutcome::Success(msg.payment_preimage),
6752+
OutboundHTLCOutcome::Success(msg.payment_preimage, msg.attribution_data.clone()),
67536753
)
67546754
.map(|htlc| {
67556755
(htlc.source.clone(), htlc.amount_msat, htlc.skimmed_fee_msat, htlc.send_timestamp)
@@ -7091,9 +7091,9 @@ where
70917091
log_trace!(logger, "Updating HTLC {} to AwaitingRemoteRevokeToRemove due to commitment_signed in channel {}.",
70927092
&htlc.payment_hash, &self.context.channel_id);
70937093
// Swap against a dummy variant to avoid a potentially expensive clone of `OutboundHTLCOutcome::Failure(HTLCFailReason)`
7094-
let mut reason = OutboundHTLCOutcome::Success(PaymentPreimage([0u8; 32]));
7094+
let mut reason = OutboundHTLCOutcome::Success(PaymentPreimage([0u8; 32]), None);
70957095
mem::swap(outcome, &mut reason);
7096-
if let OutboundHTLCOutcome::Success(preimage) = reason {
7096+
if let OutboundHTLCOutcome::Success(preimage, _) = reason {
70977097
// If a user (a) receives an HTLC claim using LDK 0.0.104 or before, then (b)
70987098
// upgrades to LDK 0.0.114 or later before the HTLC is fully resolved, we could
70997099
// have a `Success(None)` reason. In this case we could forget some HTLC
@@ -7547,19 +7547,21 @@ where
75477547
&htlc.payment_hash
75487548
);
75497549
// We really want take() here, but, again, non-mut ref :(
7550-
if let OutboundHTLCOutcome::Failure(mut reason) = outcome.clone() {
7551-
if let (Some(timestamp), Some(now)) = (htlc.send_timestamp, now) {
7552-
let elapsed_millis = now.saturating_sub(timestamp).as_millis();
7553-
let elapsed_units = elapsed_millis / HOLD_TIME_UNIT_MILLIS;
7554-
let hold_time = u32::try_from(elapsed_units).unwrap_or(u32::MAX);
7555-
reason.set_hold_time(hold_time);
7556-
}
7557-
7558-
revoked_htlcs.push((htlc.source.clone(), htlc.payment_hash, reason));
7559-
} else {
7560-
finalized_claimed_htlcs.push(htlc.source.clone());
7561-
// They fulfilled, so we sent them money
7562-
value_to_self_msat_diff -= htlc.amount_msat as i64;
7550+
match outcome.clone() {
7551+
OutboundHTLCOutcome::Failure(mut reason) => {
7552+
if let (Some(timestamp), Some(now)) = (htlc.send_timestamp, now) {
7553+
let elapsed_millis = now.saturating_sub(timestamp).as_millis();
7554+
let elapsed_units = elapsed_millis / HOLD_TIME_UNIT_MILLIS;
7555+
let hold_time = u32::try_from(elapsed_units).unwrap_or(u32::MAX);
7556+
reason.set_hold_time(hold_time);
7557+
}
7558+
revoked_htlcs.push((htlc.source.clone(), htlc.payment_hash, reason));
7559+
},
7560+
OutboundHTLCOutcome::Success(_, attribution_data) => {
7561+
finalized_claimed_htlcs.push((htlc.source.clone(), attribution_data));
7562+
// They fulfilled, so we sent them money
7563+
value_to_self_msat_diff -= htlc.amount_msat as i64;
7564+
},
75637565
}
75647566
false
75657567
} else {
@@ -7643,7 +7645,7 @@ where
76437645
{
76447646
log_trace!(logger, " ...promoting outbound AwaitingRemoteRevokeToRemove {} to AwaitingRemovedRemoteRevoke", &htlc.payment_hash);
76457647
// Swap against a dummy variant to avoid a potentially expensive clone of `OutboundHTLCOutcome::Failure(HTLCFailReason)`
7646-
let mut reason = OutboundHTLCOutcome::Success(PaymentPreimage([0u8; 32]));
7648+
let mut reason = OutboundHTLCOutcome::Success(PaymentPreimage([0u8; 32]), None);
76477649
mem::swap(outcome, &mut reason);
76487650
htlc.state = OutboundHTLCState::AwaitingRemovedRemoteRevoke(reason);
76497651
require_commitment = true;
@@ -8049,7 +8051,7 @@ where
80498051
&mut self, resend_raa: bool, resend_commitment: bool, resend_channel_ready: bool,
80508052
mut pending_forwards: Vec<(PendingHTLCInfo, u64)>,
80518053
mut pending_fails: Vec<(HTLCSource, PaymentHash, HTLCFailReason)>,
8052-
mut pending_finalized_claimed_htlcs: Vec<HTLCSource>,
8054+
mut pending_finalized_claimed_htlcs: Vec<(HTLCSource, Option<AttributionData>)>,
80538055
) {
80548056
self.context.monitor_pending_revoke_and_ack |= resend_raa;
80558057
self.context.monitor_pending_commitment_signed |= resend_commitment;
@@ -10776,7 +10778,7 @@ where
1077610778
if let &mut OutboundHTLCState::AwaitingRemoteRevokeToRemove(ref mut outcome) = &mut htlc.state {
1077710779
log_trace!(logger, " ...promoting outbound AwaitingRemoteRevokeToRemove {} to AwaitingRemovedRemoteRevoke", &htlc.payment_hash);
1077810780
// Swap against a dummy variant to avoid a potentially expensive clone of `OutboundHTLCOutcome::Failure(HTLCFailReason)`
10779-
let mut reason = OutboundHTLCOutcome::Success(PaymentPreimage([0u8; 32]));
10781+
let mut reason = OutboundHTLCOutcome::Success(PaymentPreimage([0u8; 32]), None);
1078010782
mem::swap(outcome, &mut reason);
1078110783
htlc.state = OutboundHTLCState::AwaitingRemovedRemoteRevoke(reason);
1078210784
}
@@ -12520,10 +12522,10 @@ where
1252012522
1u8.write(writer)?;
1252112523
(hash, code).write(writer)?;
1252212524
},
12523-
InboundHTLCRemovalReason::Fulfill(preimage, _) => {
12524-
// TODO: Persistence
12525+
InboundHTLCRemovalReason::Fulfill(preimage, attribution_data) => {
1252512526
2u8.write(writer)?;
1252612527
preimage.write(writer)?;
12528+
removed_htlc_attribution_data.push(&attribution_data);
1252712529
},
1252812530
}
1252912531
},
@@ -12558,15 +12560,15 @@ where
1255812560
},
1255912561
&OutboundHTLCState::AwaitingRemoteRevokeToRemove(ref outcome) => {
1256012562
3u8.write(writer)?;
12561-
if let OutboundHTLCOutcome::Success(preimage) = outcome {
12563+
if let OutboundHTLCOutcome::Success(preimage, _) = outcome {
1256212564
preimages.push(Some(preimage));
1256312565
}
1256412566
let reason: Option<&HTLCFailReason> = outcome.into();
1256512567
reason.write(writer)?;
1256612568
},
1256712569
&OutboundHTLCState::AwaitingRemovedRemoteRevoke(ref outcome) => {
1256812570
4u8.write(writer)?;
12569-
if let OutboundHTLCOutcome::Success(preimage) = outcome {
12571+
if let OutboundHTLCOutcome::Success(preimage, _) = outcome {
1257012572
preimages.push(Some(preimage));
1257112573
}
1257212574
let reason: Option<&HTLCFailReason> = outcome.into();
@@ -12972,7 +12974,7 @@ where
1297212974
let outcome = match option {
1297312975
Some(r) => OutboundHTLCOutcome::Failure(r),
1297412976
// Initialize this variant with a dummy preimage, the actual preimage will be filled in further down
12975-
None => OutboundHTLCOutcome::Success(PaymentPreimage([0u8; 32])),
12977+
None => OutboundHTLCOutcome::Success(PaymentPreimage([0u8; 32]), None),
1297612978
};
1297712979
OutboundHTLCState::RemoteRemoved(outcome)
1297812980
},
@@ -12981,7 +12983,7 @@ where
1298112983
let outcome = match option {
1298212984
Some(r) => OutboundHTLCOutcome::Failure(r),
1298312985
// Initialize this variant with a dummy preimage, the actual preimage will be filled in further down
12984-
None => OutboundHTLCOutcome::Success(PaymentPreimage([0u8; 32])),
12986+
None => OutboundHTLCOutcome::Success(PaymentPreimage([0u8; 32]), None),
1298512987
};
1298612988
OutboundHTLCState::AwaitingRemoteRevokeToRemove(outcome)
1298712989
},
@@ -12990,7 +12992,7 @@ where
1299012992
let outcome = match option {
1299112993
Some(r) => OutboundHTLCOutcome::Failure(r),
1299212994
// Initialize this variant with a dummy preimage, the actual preimage will be filled in further down
12993-
None => OutboundHTLCOutcome::Success(PaymentPreimage([0u8; 32])),
12995+
None => OutboundHTLCOutcome::Success(PaymentPreimage([0u8; 32]), None),
1299412996
};
1299512997
OutboundHTLCState::AwaitingRemovedRemoteRevoke(outcome)
1299612998
},
@@ -13260,6 +13262,7 @@ where
1326013262
match &mut htlc.state {
1326113263
OutboundHTLCState::AwaitingRemoteRevokeToRemove(OutboundHTLCOutcome::Success(
1326213264
ref mut preimage,
13265+
..,
1326313266
)) => {
1326413267
// This variant was initialized like this further above
1326513268
debug_assert_eq!(preimage, &PaymentPreimage([0u8; 32]));
@@ -13268,6 +13271,7 @@ where
1326813271
},
1326913272
OutboundHTLCState::AwaitingRemovedRemoteRevoke(OutboundHTLCOutcome::Success(
1327013273
ref mut preimage,
13274+
..,
1327113275
)) => {
1327213276
// This variant was initialized like this further above
1327313277
debug_assert_eq!(preimage, &PaymentPreimage([0u8; 32]));

lightning/src/ln/channelmanager.rs

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ use crate::events::{
5656
InboundChannelFunds, PaymentFailureReason, ReplayEvent,
5757
};
5858
use crate::events::{FundingInfo, PaidBolt12Invoice};
59-
use crate::ln::onion_utils::process_onion_success;
6059
// Since this struct is returned in `list_channels` methods, expose it here in case users want to
6160
// construct one themselves.
6261
use crate::ln::channel::{
@@ -79,7 +78,7 @@ use crate::ln::onion_payment::{
7978
};
8079
use crate::ln::onion_utils::AttributionData;
8180
use crate::ln::onion_utils::{self};
82-
use crate::ln::onion_utils::{HTLCFailReason, LocalHTLCFailureReason};
81+
use crate::ln::onion_utils::{process_onion_success, HTLCFailReason, LocalHTLCFailureReason};
8382
use crate::ln::our_peer_storage::EncryptedOurPeerStorage;
8483
#[cfg(test)]
8584
use crate::ln::outbound_payment;
@@ -7972,8 +7971,30 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
79727971
);
79737972
}
79747973

7975-
fn finalize_claims(&self, sources: Vec<HTLCSource>) {
7976-
self.pending_outbound_payments.finalize_claims(sources, &self.pending_events);
7974+
fn finalize_claims(&self, sources: Vec<(HTLCSource, Option<AttributionData>)>) {
7975+
// Decode attribution data to hold times.
7976+
let hold_times = sources
7977+
.into_iter()
7978+
.filter_map(|(source, attribution_data)| {
7979+
if let HTLCSource::OutboundRoute { ref session_priv, ref path, .. } = source {
7980+
let hold_times = attribution_data.map(|attribution_data| {
7981+
process_onion_success(
7982+
&self.secp_ctx,
7983+
&self.logger,
7984+
path,
7985+
session_priv,
7986+
attribution_data,
7987+
)
7988+
});
7989+
7990+
Some((source, hold_times))
7991+
} else {
7992+
None
7993+
}
7994+
})
7995+
.collect();
7996+
7997+
self.pending_outbound_payments.finalize_claims(hold_times, &self.pending_events);
79777998
}
79787999

79798000
#[rustfmt::skip]
@@ -7985,16 +8006,10 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
79858006
) {
79868007
match source {
79878008
HTLCSource::OutboundRoute { session_priv, payment_id, path, bolt12_invoice, .. } => {
7988-
// Extract the hold times for this fulfilled HTLC, if available.
7989-
if let Some(attribution_data) = attribution_data {
7990-
let _ = process_onion_success(&self.secp_ctx, &self.logger, &path,
7991-
&session_priv, attribution_data.clone());
7992-
}
7993-
79948009
debug_assert!(self.background_events_processed_since_startup.load(Ordering::Acquire),
79958010
"We don't support claim_htlc claims during startup - monitors may not be available yet");
79968011
debug_assert_eq!(next_channel_counterparty_node_id, path.hops[0].pubkey);
7997-
let ev_completion_action = EventCompletionAction::ReleaseRAAChannelMonitorUpdate {
8012+
let ev_completion_action = EventCompletionAction::ReleaseRAAChannelMonitorUpdate {
79988013
channel_funding_outpoint: next_channel_outpoint, channel_id: next_channel_id,
79998014
counterparty_node_id: path.hops[0].pubkey,
80008015
};
@@ -16570,15 +16585,15 @@ mod tests {
1657016585
let events = nodes[0].node.get_and_clear_pending_events();
1657116586
assert_eq!(events.len(), 2);
1657216587
match events[0] {
16573-
Event::PaymentPathSuccessful { payment_id: ref actual_payment_id, ref payment_hash, ref path } => {
16588+
Event::PaymentPathSuccessful { payment_id: ref actual_payment_id, ref payment_hash, ref path, .. } => {
1657416589
assert_eq!(payment_id, *actual_payment_id);
1657516590
assert_eq!(our_payment_hash, *payment_hash.as_ref().unwrap());
1657616591
assert_eq!(route.paths[0], *path);
1657716592
},
1657816593
_ => panic!("Unexpected event"),
1657916594
}
1658016595
match events[1] {
16581-
Event::PaymentPathSuccessful { payment_id: ref actual_payment_id, ref payment_hash, ref path } => {
16596+
Event::PaymentPathSuccessful { payment_id: ref actual_payment_id, ref payment_hash, ref path, ..} => {
1658216597
assert_eq!(payment_id, *actual_payment_id);
1658316598
assert_eq!(our_payment_hash, *payment_hash.as_ref().unwrap());
1658416599
assert_eq!(route.paths[0], *path);

lightning/src/ln/onion_utils.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1494,8 +1494,6 @@ where
14941494
if let Some(hold_time) = hold_time {
14951495
hold_times.push(hold_time);
14961496

1497-
log_debug!(logger, "Htlc hold time at pos {}: {} ms", route_hop_idx, hold_time);
1498-
14991497
// Shift attribution data to prepare for processing the next hop.
15001498
attribution_data.shift_left();
15011499
} else {

0 commit comments

Comments
 (0)