Skip to content

Commit 2a3bf03

Browse files
authored
Merge pull request #1552 from dunxen/2022-06-checkminrelayfee
Add min feerate checks
2 parents fda3819 + 7bc6d0e commit 2a3bf03

File tree

7 files changed

+163
-74
lines changed

7 files changed

+163
-74
lines changed

lightning/src/chain/chaininterface.rs

Lines changed: 72 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
//! Includes traits for monitoring and receiving notifications of new blocks and block
1414
//! disconnections, transaction broadcasting, and feerate information requests.
1515
16+
use core::{cmp, ops::Deref};
17+
1618
use bitcoin::blockdata::transaction::Transaction;
1719

1820
/// An interface to send a transaction to the Bitcoin network.
@@ -41,14 +43,79 @@ pub enum ConfirmationTarget {
4143
pub trait FeeEstimator {
4244
/// Gets estimated satoshis of fee required per 1000 Weight-Units.
4345
///
44-
/// Must return a value no smaller than 253 (ie 1 satoshi-per-byte rounded up to ensure later
45-
/// round-downs don't put us below 1 satoshi-per-byte).
46+
/// LDK will wrap this method and ensure that the value returned is no smaller than 253
47+
/// (ie 1 satoshi-per-byte rounded up to ensure later round-downs don't put us below 1 satoshi-per-byte).
4648
///
47-
/// This method can be implemented with the following unit conversions:
48-
/// * max(satoshis-per-byte * 250, 253)
49-
/// * max(satoshis-per-kbyte / 4, 253)
49+
/// The following unit conversions can be used to convert to sats/KW:
50+
/// * satoshis-per-byte * 250
51+
/// * satoshis-per-kbyte / 4
5052
fn get_est_sat_per_1000_weight(&self, confirmation_target: ConfirmationTarget) -> u32;
5153
}
5254

55+
// We need `FeeEstimator` implemented so that in some places where we only have a shared
56+
// reference to a `Deref` to a `FeeEstimator`, we can still wrap it.
57+
impl<D: Deref> FeeEstimator for D where D::Target: FeeEstimator {
58+
fn get_est_sat_per_1000_weight(&self, confirmation_target: ConfirmationTarget) -> u32 {
59+
(**self).get_est_sat_per_1000_weight(confirmation_target)
60+
}
61+
}
62+
5363
/// Minimum relay fee as required by bitcoin network mempool policy.
5464
pub const MIN_RELAY_FEE_SAT_PER_1000_WEIGHT: u64 = 4000;
65+
/// Minimum feerate that takes a sane approach to bitcoind weight-to-vbytes rounding.
66+
/// See the following Core Lightning commit for an explanation:
67+
/// https://github.com/ElementsProject/lightning/commit/2e687b9b352c9092b5e8bd4a688916ac50b44af0
68+
pub const FEERATE_FLOOR_SATS_PER_KW: u32 = 253;
69+
70+
/// Wraps a `Deref` to a `FeeEstimator` so that any fee estimations provided by it
71+
/// are bounded below by `FEERATE_FLOOR_SATS_PER_KW` (253 sats/KW)
72+
pub(crate) struct LowerBoundedFeeEstimator<F: Deref>(pub F) where F::Target: FeeEstimator;
73+
74+
impl<F: Deref> LowerBoundedFeeEstimator<F> where F::Target: FeeEstimator {
75+
/// Creates a new `LowerBoundedFeeEstimator` which wraps the provided fee_estimator
76+
pub fn new(fee_estimator: F) -> Self {
77+
LowerBoundedFeeEstimator(fee_estimator)
78+
}
79+
}
80+
81+
impl<F: Deref> FeeEstimator for LowerBoundedFeeEstimator<F> where F::Target: FeeEstimator {
82+
fn get_est_sat_per_1000_weight(&self, confirmation_target: ConfirmationTarget) -> u32 {
83+
cmp::max(
84+
self.0.get_est_sat_per_1000_weight(confirmation_target),
85+
FEERATE_FLOOR_SATS_PER_KW,
86+
)
87+
}
88+
}
89+
90+
#[cfg(test)]
91+
mod tests {
92+
use super::{FEERATE_FLOOR_SATS_PER_KW, LowerBoundedFeeEstimator, ConfirmationTarget, FeeEstimator};
93+
94+
struct TestFeeEstimator {
95+
sat_per_kw: u32,
96+
}
97+
98+
impl FeeEstimator for TestFeeEstimator {
99+
fn get_est_sat_per_1000_weight(&self, _: ConfirmationTarget) -> u32 {
100+
self.sat_per_kw
101+
}
102+
}
103+
104+
#[test]
105+
fn test_fee_estimator_less_than_floor() {
106+
let sat_per_kw = FEERATE_FLOOR_SATS_PER_KW - 1;
107+
let test_fee_estimator = &TestFeeEstimator { sat_per_kw };
108+
let fee_estimator = LowerBoundedFeeEstimator::new(test_fee_estimator);
109+
110+
assert_eq!(fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background), FEERATE_FLOOR_SATS_PER_KW);
111+
}
112+
113+
#[test]
114+
fn test_fee_estimator_greater_than_floor() {
115+
let sat_per_kw = FEERATE_FLOOR_SATS_PER_KW + 1;
116+
let test_fee_estimator = &TestFeeEstimator { sat_per_kw };
117+
let fee_estimator = LowerBoundedFeeEstimator::new(test_fee_estimator);
118+
119+
assert_eq!(fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background), sat_per_kw);
120+
}
121+
}

lightning/src/chain/channelmonitor.rs

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ use ln::chan_utils::{CounterpartyCommitmentSecrets, HTLCOutputInCommitment, HTLC
4040
use ln::channelmanager::HTLCSource;
4141
use chain;
4242
use chain::{BestBlock, WatchedOutput};
43-
use chain::chaininterface::{BroadcasterInterface, FeeEstimator};
43+
use chain::chaininterface::{BroadcasterInterface, FeeEstimator, LowerBoundedFeeEstimator};
4444
use chain::transaction::{OutPoint, TransactionData};
4545
use chain::keysinterface::{SpendableOutputDescriptor, StaticPaymentOutputDescriptor, DelayedPaymentOutputDescriptor, Sign, KeysInterface};
4646
use chain::onchaintx::OnchainTxHandler;
@@ -1104,7 +1104,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
11041104
payment_hash: &PaymentHash,
11051105
payment_preimage: &PaymentPreimage,
11061106
broadcaster: &B,
1107-
fee_estimator: &F,
1107+
fee_estimator: &LowerBoundedFeeEstimator<F>,
11081108
logger: &L,
11091109
) where
11101110
B::Target: BroadcasterInterface,
@@ -1300,8 +1300,9 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
13001300
F::Target: FeeEstimator,
13011301
L::Target: Logger,
13021302
{
1303+
let bounded_fee_estimator = LowerBoundedFeeEstimator::new(fee_estimator);
13031304
self.inner.lock().unwrap().transactions_confirmed(
1304-
header, txdata, height, broadcaster, fee_estimator, logger)
1305+
header, txdata, height, broadcaster, &bounded_fee_estimator, logger)
13051306
}
13061307

13071308
/// Processes a transaction that was reorganized out of the chain.
@@ -1321,8 +1322,9 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
13211322
F::Target: FeeEstimator,
13221323
L::Target: Logger,
13231324
{
1325+
let bounded_fee_estimator = LowerBoundedFeeEstimator::new(fee_estimator);
13241326
self.inner.lock().unwrap().transaction_unconfirmed(
1325-
txid, broadcaster, fee_estimator, logger);
1327+
txid, broadcaster, &bounded_fee_estimator, logger);
13261328
}
13271329

13281330
/// Updates the monitor with the current best chain tip, returning new outputs to watch. See
@@ -1345,8 +1347,9 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
13451347
F::Target: FeeEstimator,
13461348
L::Target: Logger,
13471349
{
1350+
let bounded_fee_estimator = LowerBoundedFeeEstimator::new(fee_estimator);
13481351
self.inner.lock().unwrap().best_block_updated(
1349-
header, height, broadcaster, fee_estimator, logger)
1352+
header, height, broadcaster, &bounded_fee_estimator, logger)
13501353
}
13511354

13521355
/// Returns the set of txids that should be monitored for re-organization out of the chain.
@@ -1882,7 +1885,9 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
18821885

18831886
/// Provides a payment_hash->payment_preimage mapping. Will be automatically pruned when all
18841887
/// commitment_tx_infos which contain the payment hash have been revoked.
1885-
fn provide_payment_preimage<B: Deref, F: Deref, L: Deref>(&mut self, payment_hash: &PaymentHash, payment_preimage: &PaymentPreimage, broadcaster: &B, fee_estimator: &F, logger: &L)
1888+
fn provide_payment_preimage<B: Deref, F: Deref, L: Deref>(
1889+
&mut self, payment_hash: &PaymentHash, payment_preimage: &PaymentPreimage, broadcaster: &B,
1890+
fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L)
18861891
where B::Target: BroadcasterInterface,
18871892
F::Target: FeeEstimator,
18881893
L::Target: Logger,
@@ -1980,7 +1985,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
19801985
},
19811986
ChannelMonitorUpdateStep::PaymentPreimage { payment_preimage } => {
19821987
log_trace!(logger, "Updating ChannelMonitor with payment preimage");
1983-
self.provide_payment_preimage(&PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner()), &payment_preimage, broadcaster, fee_estimator, logger)
1988+
let bounded_fee_estimator = LowerBoundedFeeEstimator::new(fee_estimator);
1989+
self.provide_payment_preimage(&PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner()), &payment_preimage, broadcaster, &bounded_fee_estimator, logger)
19841990
},
19851991
ChannelMonitorUpdateStep::CommitmentSecret { idx, secret } => {
19861992
log_trace!(logger, "Updating ChannelMonitor with commitment secret");
@@ -2406,15 +2412,16 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
24062412
let block_hash = header.block_hash();
24072413
self.best_block = BestBlock::new(block_hash, height);
24082414

2409-
self.transactions_confirmed(header, txdata, height, broadcaster, fee_estimator, logger)
2415+
let bounded_fee_estimator = LowerBoundedFeeEstimator::new(fee_estimator);
2416+
self.transactions_confirmed(header, txdata, height, broadcaster, &bounded_fee_estimator, logger)
24102417
}
24112418

24122419
fn best_block_updated<B: Deref, F: Deref, L: Deref>(
24132420
&mut self,
24142421
header: &BlockHeader,
24152422
height: u32,
24162423
broadcaster: B,
2417-
fee_estimator: F,
2424+
fee_estimator: &LowerBoundedFeeEstimator<F>,
24182425
logger: L,
24192426
) -> Vec<TransactionOutputs>
24202427
where
@@ -2441,7 +2448,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
24412448
txdata: &TransactionData,
24422449
height: u32,
24432450
broadcaster: B,
2444-
fee_estimator: F,
2451+
fee_estimator: &LowerBoundedFeeEstimator<F>,
24452452
logger: L,
24462453
) -> Vec<TransactionOutputs>
24472454
where
@@ -2538,7 +2545,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
25382545
mut watch_outputs: Vec<TransactionOutputs>,
25392546
mut claimable_outpoints: Vec<PackageTemplate>,
25402547
broadcaster: &B,
2541-
fee_estimator: &F,
2548+
fee_estimator: &LowerBoundedFeeEstimator<F>,
25422549
logger: &L,
25432550
) -> Vec<TransactionOutputs>
25442551
where
@@ -2676,7 +2683,8 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
26762683
//- maturing spendable output has transaction paying us has been disconnected
26772684
self.onchain_events_awaiting_threshold_conf.retain(|ref entry| entry.height < height);
26782685

2679-
self.onchain_tx_handler.block_disconnected(height, broadcaster, fee_estimator, logger);
2686+
let bounded_fee_estimator = LowerBoundedFeeEstimator::new(fee_estimator);
2687+
self.onchain_tx_handler.block_disconnected(height, broadcaster, &bounded_fee_estimator, logger);
26802688

26812689
self.best_block = BestBlock::new(header.prev_blockhash, height - 1);
26822690
}
@@ -2685,7 +2693,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
26852693
&mut self,
26862694
txid: &Txid,
26872695
broadcaster: B,
2688-
fee_estimator: F,
2696+
fee_estimator: &LowerBoundedFeeEstimator<F>,
26892697
logger: L,
26902698
) where
26912699
B::Target: BroadcasterInterface,
@@ -3428,6 +3436,8 @@ mod tests {
34283436

34293437
use hex;
34303438

3439+
use crate::chain::chaininterface::LowerBoundedFeeEstimator;
3440+
34313441
use super::ChannelMonitorUpdateStep;
34323442
use ::{check_added_monitors, check_closed_broadcast, check_closed_event, check_spends, get_local_commitment_txn, get_monitor, get_route_and_payment_hash, unwrap_send_err};
34333443
use chain::{BestBlock, Confirm};
@@ -3549,7 +3559,7 @@ mod tests {
35493559
let secp_ctx = Secp256k1::new();
35503560
let logger = Arc::new(TestLogger::new());
35513561
let broadcaster = Arc::new(TestBroadcaster{txn_broadcasted: Mutex::new(Vec::new()), blocks: Arc::new(Mutex::new(Vec::new()))});
3552-
let fee_estimator = Arc::new(TestFeeEstimator { sat_per_kw: Mutex::new(253) });
3562+
let fee_estimator = TestFeeEstimator { sat_per_kw: Mutex::new(253) };
35533563

35543564
let dummy_key = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
35553565
let dummy_tx = Transaction { version: 0, lock_time: 0, input: Vec::new(), output: Vec::new() };
@@ -3648,7 +3658,8 @@ mod tests {
36483658
monitor.provide_latest_counterparty_commitment_tx(dummy_txid, preimages_slice_to_htlc_outputs!(preimages[17..20]), 281474976710653, dummy_key, &logger);
36493659
monitor.provide_latest_counterparty_commitment_tx(dummy_txid, preimages_slice_to_htlc_outputs!(preimages[18..20]), 281474976710652, dummy_key, &logger);
36503660
for &(ref preimage, ref hash) in preimages.iter() {
3651-
monitor.provide_payment_preimage(hash, preimage, &broadcaster, &fee_estimator, &logger);
3661+
let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&fee_estimator);
3662+
monitor.provide_payment_preimage(hash, preimage, &broadcaster, &bounded_fee_estimator, &logger);
36523663
}
36533664

36543665
// Now provide a secret, pruning preimages 10-15

lightning/src/chain/onchaintx.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use bitcoin::secp256k1;
2424
use ln::msgs::DecodeError;
2525
use ln::PaymentPreimage;
2626
use ln::chan_utils::{ChannelTransactionParameters, HolderCommitmentTransaction};
27-
use chain::chaininterface::{FeeEstimator, BroadcasterInterface};
27+
use chain::chaininterface::{FeeEstimator, BroadcasterInterface, LowerBoundedFeeEstimator};
2828
use chain::channelmonitor::{ANTI_REORG_DELAY, CLTV_SHARED_CLAIM_BUFFER};
2929
use chain::keysinterface::{Sign, KeysInterface};
3030
use chain::package::PackageTemplate;
@@ -377,7 +377,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
377377
/// (CSV or CLTV following cases). In case of high-fee spikes, claim tx may stuck in the mempool, so you need to bump its feerate quickly using Replace-By-Fee or Child-Pay-For-Parent.
378378
/// Panics if there are signing errors, because signing operations in reaction to on-chain events
379379
/// are not expected to fail, and if they do, we may lose funds.
380-
fn generate_claim_tx<F: Deref, L: Deref>(&mut self, cur_height: u32, cached_request: &PackageTemplate, fee_estimator: &F, logger: &L) -> Option<(Option<u32>, u64, Transaction)>
380+
fn generate_claim_tx<F: Deref, L: Deref>(&mut self, cur_height: u32, cached_request: &PackageTemplate, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L) -> Option<(Option<u32>, u64, Transaction)>
381381
where F::Target: FeeEstimator,
382382
L::Target: Logger,
383383
{
@@ -415,7 +415,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
415415
/// `conf_height` represents the height at which the transactions in `txn_matched` were
416416
/// confirmed. This does not need to equal the current blockchain tip height, which should be
417417
/// provided via `cur_height`, however it must never be higher than `cur_height`.
418-
pub(crate) fn update_claims_view<B: Deref, F: Deref, L: Deref>(&mut self, txn_matched: &[&Transaction], requests: Vec<PackageTemplate>, conf_height: u32, cur_height: u32, broadcaster: &B, fee_estimator: &F, logger: &L)
418+
pub(crate) fn update_claims_view<B: Deref, F: Deref, L: Deref>(&mut self, txn_matched: &[&Transaction], requests: Vec<PackageTemplate>, conf_height: u32, cur_height: u32, broadcaster: &B, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L)
419419
where B::Target: BroadcasterInterface,
420420
F::Target: FeeEstimator,
421421
L::Target: Logger,
@@ -617,7 +617,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
617617
&mut self,
618618
txid: &Txid,
619619
broadcaster: B,
620-
fee_estimator: F,
620+
fee_estimator: &LowerBoundedFeeEstimator<F>,
621621
logger: L,
622622
) where
623623
B::Target: BroadcasterInterface,
@@ -637,7 +637,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
637637
}
638638
}
639639

640-
pub(crate) fn block_disconnected<B: Deref, F: Deref, L: Deref>(&mut self, height: u32, broadcaster: B, fee_estimator: F, logger: L)
640+
pub(crate) fn block_disconnected<B: Deref, F: Deref, L: Deref>(&mut self, height: u32, broadcaster: B, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: L)
641641
where B::Target: BroadcasterInterface,
642642
F::Target: FeeEstimator,
643643
L::Target: Logger,
@@ -667,7 +667,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
667667
}
668668
}
669669
for (_, request) in bump_candidates.iter_mut() {
670-
if let Some((new_timer, new_feerate, bump_tx)) = self.generate_claim_tx(height, &request, &&*fee_estimator, &&*logger) {
670+
if let Some((new_timer, new_feerate, bump_tx)) = self.generate_claim_tx(height, &request, fee_estimator, &&*logger) {
671671
request.set_timer(new_timer);
672672
request.set_feerate(new_feerate);
673673
log_info!(logger, "Broadcasting onchain {}", log_tx!(bump_tx));

lightning/src/chain/package.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ use core::mem;
3838
use core::ops::Deref;
3939
use bitcoin::Witness;
4040

41+
use super::chaininterface::LowerBoundedFeeEstimator;
42+
4143
const MAX_ALLOC_SIZE: usize = 64*1024;
4244

4345

@@ -665,7 +667,7 @@ impl PackageTemplate {
665667
/// Returns value in satoshis to be included as package outgoing output amount and feerate
666668
/// which was used to generate the value. Will not return less than `dust_limit_sats` for the
667669
/// value.
668-
pub(crate) fn compute_package_output<F: Deref, L: Deref>(&self, predicted_weight: usize, dust_limit_sats: u64, fee_estimator: &F, logger: &L) -> Option<(u64, u64)>
670+
pub(crate) fn compute_package_output<F: Deref, L: Deref>(&self, predicted_weight: usize, dust_limit_sats: u64, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L) -> Option<(u64, u64)>
669671
where F::Target: FeeEstimator,
670672
L::Target: Logger,
671673
{
@@ -772,7 +774,7 @@ impl Readable for PackageTemplate {
772774
/// If the proposed fee is less than the available spent output's values, we return the proposed
773775
/// fee and the corresponding updated feerate. If the proposed fee is equal or more than the
774776
/// available spent output's values, we return nothing
775-
fn compute_fee_from_spent_amounts<F: Deref, L: Deref>(input_amounts: u64, predicted_weight: usize, fee_estimator: &F, logger: &L) -> Option<(u64, u64)>
777+
fn compute_fee_from_spent_amounts<F: Deref, L: Deref>(input_amounts: u64, predicted_weight: usize, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L) -> Option<(u64, u64)>
776778
where F::Target: FeeEstimator,
777779
L::Target: Logger,
778780
{
@@ -808,7 +810,7 @@ fn compute_fee_from_spent_amounts<F: Deref, L: Deref>(input_amounts: u64, predic
808810
/// attempt, use them. Otherwise, blindly bump the feerate by 25% of the previous feerate. We also
809811
/// verify that those bumping heuristics respect BIP125 rules 3) and 4) and if required adjust
810812
/// the new fee to meet the RBF policy requirement.
811-
fn feerate_bump<F: Deref, L: Deref>(predicted_weight: usize, input_amounts: u64, previous_feerate: u64, fee_estimator: &F, logger: &L) -> Option<(u64, u64)>
813+
fn feerate_bump<F: Deref, L: Deref>(predicted_weight: usize, input_amounts: u64, previous_feerate: u64, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L) -> Option<(u64, u64)>
812814
where F::Target: FeeEstimator,
813815
L::Target: Logger,
814816
{

0 commit comments

Comments
 (0)