Skip to content

Commit b49769e

Browse files
committed
Account for existing input amounts throughout coin selection
We'd previously ignore the existing amount transactions were already attempting to spend when deciding whether we should add more inputs throughout coin selection. This would result in us attaching more inputs than necessary to satisfy our target amount. In the case of HTLC transactions, we'd burn the HTLC amount completely, since the pre-signed transaction has zero fee (input amount == output amount). Along the way, we also fix the slight overpayment in anchor transactions. We now properly account for the fees the transaction already paid for, simply by pretending the fees are part of the anchor input amount.
1 parent 3fd685a commit b49769e

File tree

1 file changed

+14
-20
lines changed

1 file changed

+14
-20
lines changed

lightning/src/events/bump_transaction.rs

Lines changed: 14 additions & 20 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,20 @@ 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+
738+
log_debug!(self.logger, "Peforming coin selection for commitment package (commitment and anchor transaction) targeting {} sat/kW",
739+
package_target_feerate_sat_per_1000_weight);
746740
let coin_selection = self.utxo_source.select_confirmed_utxos(
747-
claim_id, must_spend, &[], anchor_target_feerate_sat_per_1000_weight,
741+
claim_id, must_spend, &[], package_target_feerate_sat_per_1000_weight,
748742
)?;
749743

750744
let mut anchor_tx = Transaction {

0 commit comments

Comments
 (0)