@@ -68,6 +68,7 @@ use crate::util::scid_utils::scid_from_parts;
6868
6969use crate::io;
7070use crate::prelude::*;
71+ use core::time::Duration;
7172use core::{cmp,mem,fmt};
7273use core::ops::Deref;
7374#[cfg(any(test, fuzzing, debug_assertions))]
@@ -323,6 +324,7 @@ struct OutboundHTLCOutput {
323324 source: HTLCSource,
324325 blinding_point: Option<PublicKey>,
325326 skimmed_fee_msat: Option<u64>,
327+ send_timestamp: Option<Duration>,
326328}
327329
328330/// See AwaitingRemoteRevoke ChannelState for more info
@@ -6095,10 +6097,16 @@ impl<SP: Deref> FundedChannel<SP> where
60956097 false
60966098 } else { true }
60976099 });
6100+ let now = duration_since_epoch();
60986101 pending_outbound_htlcs.retain(|htlc| {
60996102 if let &OutboundHTLCState::AwaitingRemovedRemoteRevoke(ref outcome) = &htlc.state {
61006103 log_trace!(logger, " ...removing outbound AwaitingRemovedRemoteRevoke {}", &htlc.payment_hash);
6101- if let OutboundHTLCOutcome::Failure(reason) = outcome.clone() { // We really want take() here, but, again, non-mut ref :(
6104+ if let OutboundHTLCOutcome::Failure(mut reason) = outcome.clone() { // We really want take() here, but, again, non-mut ref :(
6105+ if let (Some(timestamp), Some(now)) = (htlc.send_timestamp, now) {
6106+ let hold_time = u32::try_from((now - timestamp).as_millis()).unwrap_or(u32::MAX);
6107+ reason.set_hold_time(hold_time);
6108+ }
6109+
61026110 revoked_htlcs.push((htlc.source.clone(), htlc.payment_hash, reason));
61036111 } else {
61046112 finalized_claimed_htlcs.push(htlc.source.clone());
@@ -8667,6 +8675,7 @@ impl<SP: Deref> FundedChannel<SP> where
86678675 return Ok(None);
86688676 }
86698677
8678+ let timestamp = duration_since_epoch();
86708679 self.context.pending_outbound_htlcs.push(OutboundHTLCOutput {
86718680 htlc_id: self.context.next_holder_htlc_id,
86728681 amount_msat,
@@ -8676,6 +8685,7 @@ impl<SP: Deref> FundedChannel<SP> where
86768685 source,
86778686 blinding_point,
86788687 skimmed_fee_msat,
8688+ send_timestamp: timestamp,
86798689 });
86808690
86818691 let res = msgs::UpdateAddHTLC {
@@ -10673,6 +10683,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1067310683 },
1067410684 skimmed_fee_msat: None,
1067510685 blinding_point: None,
10686+ send_timestamp: None,
1067610687 });
1067710688 }
1067810689
@@ -11191,6 +11202,18 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1119111202 }
1119211203}
1119311204
11205+ fn duration_since_epoch() -> Option<Duration> {
11206+ #[cfg(not(feature = "std"))]
11207+ let now = None;
11208+
11209+ #[cfg(feature = "std")]
11210+ let now = Some(std::time::SystemTime::now()
11211+ .duration_since(std::time::SystemTime::UNIX_EPOCH)
11212+ .expect("SystemTime::now() should come after SystemTime::UNIX_EPOCH"));
11213+
11214+ now
11215+ }
11216+
1119411217#[cfg(test)]
1119511218mod tests {
1119611219 use std::cmp;
@@ -11426,6 +11449,7 @@ mod tests {
1142611449 },
1142711450 skimmed_fee_msat: None,
1142811451 blinding_point: None,
11452+ send_timestamp: None,
1142911453 });
1143011454
1143111455 // Make sure when Node A calculates their local commitment transaction, none of the HTLCs pass
@@ -11810,6 +11834,7 @@ mod tests {
1181011834 source: dummy_htlc_source.clone(),
1181111835 skimmed_fee_msat: None,
1181211836 blinding_point: None,
11837+ send_timestamp: None,
1181311838 };
1181411839 let mut pending_outbound_htlcs = vec![dummy_outbound_output.clone(); 10];
1181511840 for (idx, htlc) in pending_outbound_htlcs.iter_mut().enumerate() {
@@ -12132,6 +12157,7 @@ mod tests {
1213212157 source: HTLCSource::dummy(),
1213312158 skimmed_fee_msat: None,
1213412159 blinding_point: None,
12160+ timestamp: None,
1213512161 };
1213612162 out.payment_hash.0 = Sha256::hash(&<Vec<u8>>::from_hex("0202020202020202020202020202020202020202020202020202020202020202").unwrap()).to_byte_array();
1213712163 out
@@ -12146,6 +12172,7 @@ mod tests {
1214612172 source: HTLCSource::dummy(),
1214712173 skimmed_fee_msat: None,
1214812174 blinding_point: None,
12175+ timestamp: None,
1214912176 };
1215012177 out.payment_hash.0 = Sha256::hash(&<Vec<u8>>::from_hex("0303030303030303030303030303030303030303030303030303030303030303").unwrap()).to_byte_array();
1215112178 out
@@ -12558,6 +12585,7 @@ mod tests {
1255812585 source: HTLCSource::dummy(),
1255912586 skimmed_fee_msat: None,
1256012587 blinding_point: None,
12588+ timestamp: None,
1256112589 };
1256212590 out.payment_hash.0 = Sha256::hash(&<Vec<u8>>::from_hex("0505050505050505050505050505050505050505050505050505050505050505").unwrap()).to_byte_array();
1256312591 out
@@ -12572,6 +12600,7 @@ mod tests {
1257212600 source: HTLCSource::dummy(),
1257312601 skimmed_fee_msat: None,
1257412602 blinding_point: None,
12603+ timestamp: None,
1257512604 };
1257612605 out.payment_hash.0 = Sha256::hash(&<Vec<u8>>::from_hex("0505050505050505050505050505050505050505050505050505050505050505").unwrap()).to_byte_array();
1257712606 out
0 commit comments