Skip to content

Commit a666401

Browse files
authored
Merge pull request #3037 from TheBlueMatt/2024-05-close-on-stale-fees
Force-close channels if their feerate gets stale without any update
2 parents f2237a7 + 17b77e0 commit a666401

File tree

6 files changed

+367
-170
lines changed

6 files changed

+367
-170
lines changed

fuzz/src/full_stack.rs

+28-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ use std::cell::RefCell;
7171
use std::convert::TryInto;
7272
use std::cmp;
7373
use std::sync::{Arc, Mutex};
74-
use std::sync::atomic::{AtomicU64,AtomicUsize,Ordering};
74+
use std::sync::atomic::{AtomicU64,AtomicUsize,AtomicBool,Ordering};
7575
use bech32::u5;
7676

7777
#[inline]
@@ -98,6 +98,7 @@ pub fn slice_to_be24(v: &[u8]) -> u32 {
9898
struct InputData {
9999
data: Vec<u8>,
100100
read_pos: AtomicUsize,
101+
halt_fee_est_reads: AtomicBool,
101102
}
102103
impl InputData {
103104
fn get_slice(&self, len: usize) -> Option<&[u8]> {
@@ -124,6 +125,9 @@ struct FuzzEstimator {
124125
}
125126
impl FeeEstimator for FuzzEstimator {
126127
fn get_est_sat_per_1000_weight(&self, _: ConfirmationTarget) -> u32 {
128+
if self.input.halt_fee_est_reads.load(Ordering::Acquire) {
129+
return 253;
130+
}
127131
//TODO: We should actually be testing at least much more than 64k...
128132
match self.input.get_slice(2) {
129133
Some(slice) => cmp::max(slice_to_be16(slice) as u32, 253),
@@ -446,6 +450,7 @@ pub fn do_test(mut data: &[u8], logger: &Arc<dyn Logger>) {
446450
let input = Arc::new(InputData {
447451
data: data.to_vec(),
448452
read_pos: AtomicUsize::new(0),
453+
halt_fee_est_reads: AtomicBool::new(false),
449454
});
450455
let fee_est = Arc::new(FuzzEstimator {
451456
input: input.clone(),
@@ -703,10 +708,12 @@ pub fn do_test(mut data: &[u8], logger: &Arc<dyn Logger>) {
703708
11 => {
704709
let mut txn = broadcast.txn_broadcasted.lock().unwrap().split_off(0);
705710
if !txn.is_empty() {
711+
input.halt_fee_est_reads.store(true, Ordering::Release);
706712
loss_detector.connect_block(&txn[..]);
707713
for _ in 2..100 {
708714
loss_detector.connect_block(&[]);
709715
}
716+
input.halt_fee_est_reads.store(false, Ordering::Release);
710717
}
711718
for tx in txn.drain(..) {
712719
loss_detector.funding_txn.push(tx);
@@ -914,19 +921,32 @@ mod tests {
914921
ext_from_hex("0c005e", &mut test);
915922
// the funding transaction
916923
ext_from_hex("020000000100000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0150c3000000000000220020ae0000000000000000000000000000000000000000000000000000000000000000000000", &mut test);
924+
ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
917925
// connect a block with no transactions, one per line
918926
ext_from_hex("0c0000", &mut test);
927+
ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
919928
ext_from_hex("0c0000", &mut test);
929+
ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
920930
ext_from_hex("0c0000", &mut test);
931+
ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
921932
ext_from_hex("0c0000", &mut test);
933+
ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
922934
ext_from_hex("0c0000", &mut test);
935+
ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
923936
ext_from_hex("0c0000", &mut test);
937+
ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
924938
ext_from_hex("0c0000", &mut test);
939+
ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
925940
ext_from_hex("0c0000", &mut test);
941+
ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
926942
ext_from_hex("0c0000", &mut test);
943+
ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
927944
ext_from_hex("0c0000", &mut test);
945+
ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
928946
ext_from_hex("0c0000", &mut test);
947+
ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
929948
ext_from_hex("0c0000", &mut test);
949+
ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
930950
// by now client should have sent a channel_ready (CHECK 3: SendChannelReady to 03000000 for chan 3d000000)
931951

932952
// inbound read from peer id 0 of len 18
@@ -1296,21 +1316,28 @@ mod tests {
12961316
ext_from_hex("0c007d", &mut test);
12971317
// the commitment transaction for channel 3f00000000000000000000000000000000000000000000000000000000000000
12981318
ext_from_hex("02000000013a000000000000000000000000000000000000000000000000000000000000000000000000000000800258020000000000002200204b0000000000000000000000000000000000000000000000000000000000000014c0000000000000160014280000000000000000000000000000000000000005000020", &mut test);
1319+
ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
12991320
//
13001321
// connect a block with one transaction of len 94
13011322
ext_from_hex("0c005e", &mut test);
13021323
// the HTLC timeout transaction
13031324
ext_from_hex("0200000001730000000000000000000000000000000000000000000000000000000000000000000000000000000001a701000000000000220020b20000000000000000000000000000000000000000000000000000000000000000000000", &mut test);
1325+
ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
13041326
// connect a block with no transactions
13051327
ext_from_hex("0c0000", &mut test);
1328+
ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
13061329
// connect a block with no transactions
13071330
ext_from_hex("0c0000", &mut test);
1331+
ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
13081332
// connect a block with no transactions
13091333
ext_from_hex("0c0000", &mut test);
1334+
ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
13101335
// connect a block with no transactions
13111336
ext_from_hex("0c0000", &mut test);
1337+
ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
13121338
// connect a block with no transactions
13131339
ext_from_hex("0c0000", &mut test);
1340+
ext_from_hex("00fd00fd", &mut test); // Two feerate requests during block connection
13141341

13151342
// process the now-pending HTLC forward
13161343
ext_from_hex("07", &mut test);

lightning/src/events/mod.rs

+24
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,21 @@ pub enum ClosureReason {
331331
FundingBatchClosure,
332332
/// One of our HTLCs timed out in a channel, causing us to force close the channel.
333333
HTLCsTimedOut,
334+
/// Our peer provided a feerate which violated our required minimum (fetched from our
335+
/// [`FeeEstimator`] either as [`ConfirmationTarget::MinAllowedAnchorChannelRemoteFee`] or
336+
/// [`ConfirmationTarget::MinAllowedNonAnchorChannelRemoteFee`]).
337+
///
338+
/// [`FeeEstimator`]: crate::chain::chaininterface::FeeEstimator
339+
/// [`ConfirmationTarget::MinAllowedAnchorChannelRemoteFee`]: crate::chain::chaininterface::ConfirmationTarget::MinAllowedAnchorChannelRemoteFee
340+
/// [`ConfirmationTarget::MinAllowedNonAnchorChannelRemoteFee`]: crate::chain::chaininterface::ConfirmationTarget::MinAllowedNonAnchorChannelRemoteFee
341+
PeerFeerateTooLow {
342+
/// The feerate on our channel set by our peer.
343+
peer_feerate_sat_per_kw: u32,
344+
/// The required feerate we enforce, from our [`FeeEstimator`].
345+
///
346+
/// [`FeeEstimator`]: crate::chain::chaininterface::FeeEstimator
347+
required_feerate_sat_per_kw: u32,
348+
},
334349
}
335350

336351
impl core::fmt::Display for ClosureReason {
@@ -355,6 +370,11 @@ impl core::fmt::Display for ClosureReason {
355370
ClosureReason::CounterpartyCoopClosedUnfundedChannel => f.write_str("the peer requested the unfunded channel be closed"),
356371
ClosureReason::FundingBatchClosure => f.write_str("another channel in the same funding batch closed"),
357372
ClosureReason::HTLCsTimedOut => f.write_str("htlcs on the channel timed out"),
373+
ClosureReason::PeerFeerateTooLow { peer_feerate_sat_per_kw, required_feerate_sat_per_kw } =>
374+
f.write_fmt(format_args!(
375+
"peer provided a feerate ({} sat/kw) which was below our lower bound ({} sat/kw)",
376+
peer_feerate_sat_per_kw, required_feerate_sat_per_kw,
377+
)),
358378
}
359379
}
360380
}
@@ -373,6 +393,10 @@ impl_writeable_tlv_based_enum_upgradable!(ClosureReason,
373393
(17, CounterpartyInitiatedCooperativeClosure) => {},
374394
(19, LocallyInitiatedCooperativeClosure) => {},
375395
(21, HTLCsTimedOut) => {},
396+
(23, PeerFeerateTooLow) => {
397+
(0, peer_feerate_sat_per_kw, required),
398+
(2, required_feerate_sat_per_kw, required),
399+
},
376400
);
377401

378402
/// Intended destination of a failed HTLC as indicated in [`Event::HTLCHandlingFailed`].

0 commit comments

Comments
 (0)