Skip to content

Commit 7e7e7a0

Browse files
authored
Merge pull request #2587 from wpaulino/anchors-fee-fixes
Anchor outputs fee fixes
2 parents a7e3575 + 9736c70 commit 7e7e7a0

File tree

2 files changed

+64
-29
lines changed

2 files changed

+64
-29
lines changed

lightning/src/chain/package.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -976,14 +976,23 @@ impl PackageTemplate {
976976
) -> u32 where F::Target: FeeEstimator {
977977
let feerate_estimate = fee_estimator.bounded_sat_per_1000_weight(conf_target);
978978
if self.feerate_previous != 0 {
979-
// If old feerate inferior to actual one given back by Fee Estimator, use it to compute new fee...
979+
// Use the new fee estimate if it's higher than the one previously used.
980980
if feerate_estimate as u64 > self.feerate_previous {
981981
feerate_estimate
982982
} else if !force_feerate_bump {
983983
self.feerate_previous.try_into().unwrap_or(u32::max_value())
984984
} else {
985-
// ...else just increase the previous feerate by 25% (because that's a nice number)
986-
(self.feerate_previous + (self.feerate_previous / 4)).try_into().unwrap_or(u32::max_value())
985+
// Our fee estimate has decreased, but our transaction remains unconfirmed after
986+
// using our previous fee estimate. This may point to an unreliable fee estimator,
987+
// so we choose to bump our previous feerate by 25%, making sure we don't use a
988+
// lower feerate or overpay by a large margin by limiting it to 5x the new fee
989+
// estimate.
990+
let previous_feerate = self.feerate_previous.try_into().unwrap_or(u32::max_value());
991+
let mut new_feerate = previous_feerate.saturating_add(previous_feerate / 4);
992+
if new_feerate > feerate_estimate * 5 {
993+
new_feerate = cmp::max(feerate_estimate * 5, previous_feerate);
994+
}
995+
new_feerate
987996
}
988997
} else {
989998
feerate_estimate

lightning/src/events/bump_transaction.rs

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
use alloc::collections::BTreeMap;
1515
use core::ops::Deref;
1616

17-
use crate::chain::chaininterface::{BroadcasterInterface, compute_feerate_sat_per_1000_weight, fee_for_weight, FEERATE_FLOOR_SATS_PER_KW};
17+
use crate::chain::chaininterface::{BroadcasterInterface, fee_for_weight};
1818
use crate::chain::ClaimId;
1919
use crate::io_extras::sink;
2020
use crate::ln::channel::ANCHOR_OUTPUT_VALUE_SATOSHI;
@@ -542,7 +542,7 @@ where
542542
fn select_confirmed_utxos_internal(
543543
&self, utxos: &[Utxo], claim_id: ClaimId, force_conflicting_utxo_spend: bool,
544544
tolerate_high_network_feerates: bool, target_feerate_sat_per_1000_weight: u32,
545-
preexisting_tx_weight: u64, target_amount_sat: u64,
545+
preexisting_tx_weight: u64, input_amount_sat: u64, target_amount_sat: u64,
546546
) -> Result<CoinSelection, ()> {
547547
let mut locked_utxos = self.locked_utxos.lock().unwrap();
548548
let mut eligible_utxos = utxos.iter().filter_map(|utxo| {
@@ -569,7 +569,7 @@ where
569569
}).collect::<Vec<_>>();
570570
eligible_utxos.sort_unstable_by_key(|(utxo, _)| utxo.output.value);
571571

572-
let mut selected_amount = 0;
572+
let mut selected_amount = input_amount_sat;
573573
let mut total_fees = fee_for_weight(target_feerate_sat_per_1000_weight, preexisting_tx_weight);
574574
let mut selected_utxos = Vec::new();
575575
for (utxo, fee_to_spend_utxo) in eligible_utxos {
@@ -632,13 +632,14 @@ where
632632

633633
let preexisting_tx_weight = 2 /* segwit marker & flag */ + total_input_weight +
634634
((BASE_TX_SIZE + total_output_size) * WITNESS_SCALE_FACTOR as u64);
635+
let input_amount_sat: u64 = must_spend.iter().map(|input| input.previous_utxo.value).sum();
635636
let target_amount_sat = must_pay_to.iter().map(|output| output.value).sum();
636637
let do_coin_selection = |force_conflicting_utxo_spend: bool, tolerate_high_network_feerates: bool| {
637638
log_debug!(self.logger, "Attempting coin selection targeting {} sat/kW (force_conflicting_utxo_spend = {}, tolerate_high_network_feerates = {})",
638639
target_feerate_sat_per_1000_weight, force_conflicting_utxo_spend, tolerate_high_network_feerates);
639640
self.select_confirmed_utxos_internal(
640641
&utxos, claim_id, force_conflicting_utxo_spend, tolerate_high_network_feerates,
641-
target_feerate_sat_per_1000_weight, preexisting_tx_weight, target_amount_sat,
642+
target_feerate_sat_per_1000_weight, preexisting_tx_weight, input_amount_sat, target_amount_sat,
642643
)
643644
};
644645
do_coin_selection(false, false)
@@ -724,27 +725,22 @@ where
724725
commitment_tx: &Transaction, commitment_tx_fee_sat: u64, anchor_descriptor: &AnchorDescriptor,
725726
) -> Result<(), ()> {
726727
// Our commitment transaction already has fees allocated to it, so we should take them into
727-
// account. We compute its feerate and subtract it from the package target, using the result
728-
// as the target feerate for our anchor transaction. Unfortunately, this results in users
729-
// overpaying by a small margin since we don't yet know the anchor transaction size, and
730-
// avoiding the small overpayment only makes our API even more complex.
731-
let commitment_tx_sat_per_1000_weight: u32 = compute_feerate_sat_per_1000_weight(
732-
commitment_tx_fee_sat, commitment_tx.weight() as u64,
733-
);
734-
let anchor_target_feerate_sat_per_1000_weight = core::cmp::max(
735-
package_target_feerate_sat_per_1000_weight - commitment_tx_sat_per_1000_weight,
736-
FEERATE_FLOOR_SATS_PER_KW,
737-
);
738-
739-
log_debug!(self.logger, "Peforming coin selection for anchor transaction targeting {} sat/kW",
740-
anchor_target_feerate_sat_per_1000_weight);
728+
// account. We do so by pretending the commitment tranasction's fee and weight are part of
729+
// the anchor input.
730+
let mut anchor_utxo = anchor_descriptor.previous_utxo();
731+
anchor_utxo.value += commitment_tx_fee_sat;
741732
let must_spend = vec![Input {
742733
outpoint: anchor_descriptor.outpoint,
743-
previous_utxo: anchor_descriptor.previous_utxo(),
734+
previous_utxo: anchor_utxo,
744735
satisfaction_weight: commitment_tx.weight() as u64 + ANCHOR_INPUT_WITNESS_WEIGHT + EMPTY_SCRIPT_SIG_WEIGHT,
745736
}];
737+
#[cfg(debug_assertions)]
738+
let must_spend_amount = must_spend.iter().map(|input| input.previous_utxo.value).sum::<u64>();
739+
740+
log_debug!(self.logger, "Peforming coin selection for commitment package (commitment and anchor transaction) targeting {} sat/kW",
741+
package_target_feerate_sat_per_1000_weight);
746742
let coin_selection = self.utxo_source.select_confirmed_utxos(
747-
claim_id, must_spend, &[], anchor_target_feerate_sat_per_1000_weight,
743+
claim_id, must_spend, &[], package_target_feerate_sat_per_1000_weight,
748744
)?;
749745

750746
let mut anchor_tx = Transaction {
@@ -753,10 +749,13 @@ where
753749
input: vec![anchor_descriptor.unsigned_tx_input()],
754750
output: vec![],
755751
};
752+
756753
#[cfg(debug_assertions)]
757-
let total_satisfaction_weight =
758-
coin_selection.confirmed_utxos.iter().map(|utxo| utxo.satisfaction_weight).sum::<u64>() +
759-
ANCHOR_INPUT_WITNESS_WEIGHT + EMPTY_SCRIPT_SIG_WEIGHT;
754+
let total_satisfaction_weight = ANCHOR_INPUT_WITNESS_WEIGHT + EMPTY_SCRIPT_SIG_WEIGHT +
755+
coin_selection.confirmed_utxos.iter().map(|utxo| utxo.satisfaction_weight).sum::<u64>();
756+
#[cfg(debug_assertions)]
757+
let total_input_amount = must_spend_amount +
758+
coin_selection.confirmed_utxos.iter().map(|utxo| utxo.output.value).sum::<u64>();
760759

761760
self.process_coin_selection(&mut anchor_tx, coin_selection);
762761
let anchor_txid = anchor_tx.txid();
@@ -779,6 +778,16 @@ where
779778
// never underestimate.
780779
assert!(expected_signed_tx_weight >= signed_tx_weight &&
781780
expected_signed_tx_weight - (expected_signed_tx_weight / 100) <= signed_tx_weight);
781+
782+
let expected_package_fee = fee_for_weight(package_target_feerate_sat_per_1000_weight,
783+
signed_tx_weight + commitment_tx.weight() as u64);
784+
let package_fee = total_input_amount -
785+
anchor_tx.output.iter().map(|output| output.value).sum::<u64>();
786+
// Our fee should be within a 5% error margin of the expected fee based on the
787+
// feerate and transaction weight and we should never pay less than required.
788+
let fee_error_margin = expected_package_fee * 5 / 100;
789+
assert!(package_fee >= expected_package_fee &&
790+
package_fee - fee_error_margin <= expected_package_fee);
782791
}
783792

784793
log_info!(self.logger, "Broadcasting anchor transaction {} to bump channel close with txid {}",
@@ -818,16 +827,24 @@ where
818827

819828
log_debug!(self.logger, "Peforming coin selection for HTLC transaction targeting {} sat/kW",
820829
target_feerate_sat_per_1000_weight);
830+
821831
#[cfg(debug_assertions)]
822832
let must_spend_satisfaction_weight =
823833
must_spend.iter().map(|input| input.satisfaction_weight).sum::<u64>();
834+
#[cfg(debug_assertions)]
835+
let must_spend_amount = must_spend.iter().map(|input| input.previous_utxo.value).sum::<u64>();
836+
824837
let coin_selection = self.utxo_source.select_confirmed_utxos(
825838
claim_id, must_spend, &htlc_tx.output, target_feerate_sat_per_1000_weight,
826839
)?;
840+
827841
#[cfg(debug_assertions)]
828-
let total_satisfaction_weight =
829-
coin_selection.confirmed_utxos.iter().map(|utxo| utxo.satisfaction_weight).sum::<u64>() +
830-
must_spend_satisfaction_weight;
842+
let total_satisfaction_weight = must_spend_satisfaction_weight +
843+
coin_selection.confirmed_utxos.iter().map(|utxo| utxo.satisfaction_weight).sum::<u64>();
844+
#[cfg(debug_assertions)]
845+
let total_input_amount = must_spend_amount +
846+
coin_selection.confirmed_utxos.iter().map(|utxo| utxo.output.value).sum::<u64>();
847+
831848
self.process_coin_selection(&mut htlc_tx, coin_selection);
832849

833850
#[cfg(debug_assertions)]
@@ -852,6 +869,15 @@ where
852869
// never underestimate.
853870
assert!(expected_signed_tx_weight >= signed_tx_weight &&
854871
expected_signed_tx_weight - (expected_signed_tx_weight / 100) <= signed_tx_weight);
872+
873+
let expected_signed_tx_fee = fee_for_weight(target_feerate_sat_per_1000_weight, signed_tx_weight);
874+
let signed_tx_fee = total_input_amount -
875+
htlc_tx.output.iter().map(|output| output.value).sum::<u64>();
876+
// Our fee should be within a 5% error margin of the expected fee based on the
877+
// feerate and transaction weight and we should never pay less than required.
878+
let fee_error_margin = expected_signed_tx_fee * 5 / 100;
879+
assert!(signed_tx_fee >= expected_signed_tx_fee &&
880+
signed_tx_fee - fee_error_margin <= expected_signed_tx_fee);
855881
}
856882

857883
log_info!(self.logger, "Broadcasting {}", log_tx!(htlc_tx));

0 commit comments

Comments
 (0)