@@ -68,6 +68,7 @@ use crate::util::scid_utils::scid_from_parts;
68
68
69
69
use crate::io;
70
70
use crate::prelude::*;
71
+ use core::time::Duration;
71
72
use core::{cmp,mem,fmt};
72
73
use core::ops::Deref;
73
74
#[cfg(any(test, fuzzing, debug_assertions))]
@@ -323,6 +324,7 @@ struct OutboundHTLCOutput {
323
324
source: HTLCSource,
324
325
blinding_point: Option<PublicKey>,
325
326
skimmed_fee_msat: Option<u64>,
327
+ send_timestamp: Option<Duration>,
326
328
}
327
329
328
330
/// See AwaitingRemoteRevoke ChannelState for more info
@@ -6073,10 +6075,16 @@ impl<SP: Deref> FundedChannel<SP> where
6073
6075
false
6074
6076
} else { true }
6075
6077
});
6078
+ let now = duration_since_epoch();
6076
6079
pending_outbound_htlcs.retain(|htlc| {
6077
6080
if let &OutboundHTLCState::AwaitingRemovedRemoteRevoke(ref outcome) = &htlc.state {
6078
6081
log_trace!(logger, " ...removing outbound AwaitingRemovedRemoteRevoke {}", &htlc.payment_hash);
6079
- if let OutboundHTLCOutcome::Failure(reason) = outcome.clone() { // We really want take() here, but, again, non-mut ref :(
6082
+ if let OutboundHTLCOutcome::Failure(mut reason) = outcome.clone() { // We really want take() here, but, again, non-mut ref :(
6083
+ if let (Some(timestamp), Some(now)) = (htlc.send_timestamp, now) {
6084
+ let hold_time = u32::try_from(now.saturating_sub(timestamp).as_millis()).unwrap_or(u32::MAX);
6085
+ reason.set_hold_time(hold_time);
6086
+ }
6087
+
6080
6088
revoked_htlcs.push((htlc.source.clone(), htlc.payment_hash, reason));
6081
6089
} else {
6082
6090
finalized_claimed_htlcs.push(htlc.source.clone());
@@ -8648,6 +8656,13 @@ impl<SP: Deref> FundedChannel<SP> where
8648
8656
return Ok(None);
8649
8657
}
8650
8658
8659
+ // Record the approximate time when the HTLC is sent to the peer. This timestamp is later used to calculate the
8660
+ // htlc hold time for reporting back to the sender. There is some freedom to report a time including or
8661
+ // excluding our own processing time. What we choose here doesn't matter all that much, because it will probably
8662
+ // just shift sender-applied penalties between our incoming and outgoing side. So we choose measuring points
8663
+ // that are simple to implement, and we do it on the outgoing side because then the failure message that encodes
8664
+ // the hold time still needs to be built in channel manager.
8665
+ let timestamp = duration_since_epoch();
8651
8666
self.context.pending_outbound_htlcs.push(OutboundHTLCOutput {
8652
8667
htlc_id: self.context.next_holder_htlc_id,
8653
8668
amount_msat,
@@ -8657,6 +8672,7 @@ impl<SP: Deref> FundedChannel<SP> where
8657
8672
source,
8658
8673
blinding_point,
8659
8674
skimmed_fee_msat,
8675
+ send_timestamp: timestamp,
8660
8676
});
8661
8677
8662
8678
let res = msgs::UpdateAddHTLC {
@@ -10657,6 +10673,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
10657
10673
},
10658
10674
skimmed_fee_msat: None,
10659
10675
blinding_point: None,
10676
+ send_timestamp: None,
10660
10677
});
10661
10678
}
10662
10679
@@ -11175,6 +11192,18 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
11175
11192
}
11176
11193
}
11177
11194
11195
+ fn duration_since_epoch() -> Option<Duration> {
11196
+ #[cfg(not(feature = "std"))]
11197
+ let now = None;
11198
+
11199
+ #[cfg(feature = "std")]
11200
+ let now = Some(std::time::SystemTime::now()
11201
+ .duration_since(std::time::SystemTime::UNIX_EPOCH)
11202
+ .expect("SystemTime::now() should come after SystemTime::UNIX_EPOCH"));
11203
+
11204
+ now
11205
+ }
11206
+
11178
11207
#[cfg(test)]
11179
11208
mod tests {
11180
11209
use std::cmp;
@@ -11410,6 +11439,7 @@ mod tests {
11410
11439
},
11411
11440
skimmed_fee_msat: None,
11412
11441
blinding_point: None,
11442
+ send_timestamp: None,
11413
11443
});
11414
11444
11415
11445
// Make sure when Node A calculates their local commitment transaction, none of the HTLCs pass
@@ -11794,6 +11824,7 @@ mod tests {
11794
11824
source: dummy_htlc_source.clone(),
11795
11825
skimmed_fee_msat: None,
11796
11826
blinding_point: None,
11827
+ send_timestamp: None,
11797
11828
};
11798
11829
let mut pending_outbound_htlcs = vec![dummy_outbound_output.clone(); 10];
11799
11830
for (idx, htlc) in pending_outbound_htlcs.iter_mut().enumerate() {
@@ -12107,6 +12138,7 @@ mod tests {
12107
12138
source: HTLCSource::dummy(),
12108
12139
skimmed_fee_msat: None,
12109
12140
blinding_point: None,
12141
+ send_timestamp: None,
12110
12142
};
12111
12143
out.payment_hash.0 = Sha256::hash(&<Vec<u8>>::from_hex("0202020202020202020202020202020202020202020202020202020202020202").unwrap()).to_byte_array();
12112
12144
out
@@ -12121,6 +12153,7 @@ mod tests {
12121
12153
source: HTLCSource::dummy(),
12122
12154
skimmed_fee_msat: None,
12123
12155
blinding_point: None,
12156
+ send_timestamp: None,
12124
12157
};
12125
12158
out.payment_hash.0 = Sha256::hash(&<Vec<u8>>::from_hex("0303030303030303030303030303030303030303030303030303030303030303").unwrap()).to_byte_array();
12126
12159
out
@@ -12533,6 +12566,7 @@ mod tests {
12533
12566
source: HTLCSource::dummy(),
12534
12567
skimmed_fee_msat: None,
12535
12568
blinding_point: None,
12569
+ send_timestamp: None,
12536
12570
};
12537
12571
out.payment_hash.0 = Sha256::hash(&<Vec<u8>>::from_hex("0505050505050505050505050505050505050505050505050505050505050505").unwrap()).to_byte_array();
12538
12572
out
@@ -12547,6 +12581,7 @@ mod tests {
12547
12581
source: HTLCSource::dummy(),
12548
12582
skimmed_fee_msat: None,
12549
12583
blinding_point: None,
12584
+ send_timestamp: None,
12550
12585
};
12551
12586
out.payment_hash.0 = Sha256::hash(&<Vec<u8>>::from_hex("0505050505050505050505050505050505050505050505050505050505050505").unwrap()).to_byte_array();
12552
12587
out
0 commit comments