Skip to content

Commit cd2ffaf

Browse files
committed
Fix rounding bug when checking counterparty fees
Instead of calculating the fee for the entire weight contributed by the counterparty, each portion of the weight was calculated individually before summed. That caused a rounding error that is avoided by summing the weights first.
1 parent c18422d commit cd2ffaf

File tree

1 file changed

+20
-22
lines changed

1 file changed

+20
-22
lines changed

lightning/src/ln/interactivetxs.rs

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -915,20 +915,18 @@ impl NegotiationContext {
915915
fn check_counterparty_fees(
916916
&self, counterparty_fees_contributed: u64,
917917
) -> Result<(), AbortReason> {
918-
let counterparty_weight_contributed = self
918+
let mut counterparty_weight_contributed = self
919919
.remote_inputs_weight()
920920
.to_wu()
921921
.saturating_add(self.remote_outputs_weight().to_wu());
922-
let mut required_counterparty_contribution_fee =
923-
fee_for_weight(self.feerate_sat_per_kw, counterparty_weight_contributed);
924922
if !self.holder_is_initiator {
925923
// if is the non-initiator:
926924
// - the initiator's fees do not cover the common fields (version, segwit marker + flag,
927925
// input count, output count, locktime)
928-
let tx_common_fields_fee =
929-
fee_for_weight(self.feerate_sat_per_kw, TX_COMMON_FIELDS_WEIGHT);
930-
required_counterparty_contribution_fee += tx_common_fields_fee;
926+
counterparty_weight_contributed += TX_COMMON_FIELDS_WEIGHT;
931927
}
928+
let required_counterparty_contribution_fee =
929+
fee_for_weight(self.feerate_sat_per_kw, counterparty_weight_contributed);
932930
if counterparty_fees_contributed < required_counterparty_contribution_fee {
933931
return Err(AbortReason::InsufficientFees);
934932
}
@@ -2432,16 +2430,12 @@ mod tests {
24322430
outputs_b: vec![],
24332431
expect_error: Some((AbortReason::InsufficientFees, ErrorCulprit::NodeA)),
24342432
});
2435-
let p2wpkh_fee = fee_for_weight(TEST_FEERATE_SATS_PER_KW, P2WPKH_INPUT_WEIGHT_LOWER_BOUND);
2436-
let outputs_fee = fee_for_weight(
2437-
TEST_FEERATE_SATS_PER_KW,
2438-
get_output_weight(&generate_p2wsh_script_pubkey()).to_wu(),
2439-
);
2440-
let tx_common_fields_fee =
2441-
fee_for_weight(TEST_FEERATE_SATS_PER_KW, TX_COMMON_FIELDS_WEIGHT);
2442-
2443-
let amount_adjusted_with_p2wpkh_fee =
2444-
1_000_000 - p2wpkh_fee - outputs_fee - tx_common_fields_fee + 1;
2433+
let outputs_weight = get_output_weight(&generate_p2wsh_script_pubkey()).to_wu();
2434+
let amount_adjusted_with_p2wpkh_fee = 1_000_000
2435+
- fee_for_weight(
2436+
TEST_FEERATE_SATS_PER_KW,
2437+
P2WPKH_INPUT_WEIGHT_LOWER_BOUND + TX_COMMON_FIELDS_WEIGHT + outputs_weight,
2438+
);
24452439
do_test_interactive_tx_constructor(TestSession {
24462440
description: "Single contribution, with P2WPKH input, insufficient fees",
24472441
inputs_a: generate_inputs(&[TestOutput::P2WPKH(1_000_000)]),
@@ -2473,9 +2467,11 @@ mod tests {
24732467
outputs_b: vec![],
24742468
expect_error: None,
24752469
});
2476-
let p2wsh_fee = fee_for_weight(TEST_FEERATE_SATS_PER_KW, P2WSH_INPUT_WEIGHT_LOWER_BOUND);
2477-
let amount_adjusted_with_p2wsh_fee =
2478-
1_000_000 - p2wsh_fee - outputs_fee - tx_common_fields_fee + 1;
2470+
let amount_adjusted_with_p2wsh_fee = 1_000_000
2471+
- fee_for_weight(
2472+
TEST_FEERATE_SATS_PER_KW,
2473+
P2WSH_INPUT_WEIGHT_LOWER_BOUND + TX_COMMON_FIELDS_WEIGHT + outputs_weight,
2474+
);
24792475
do_test_interactive_tx_constructor(TestSession {
24802476
description: "Single contribution, with P2WSH input, insufficient fees",
24812477
inputs_a: generate_inputs(&[TestOutput::P2WSH(1_000_000)]),
@@ -2507,9 +2503,11 @@ mod tests {
25072503
outputs_b: vec![],
25082504
expect_error: None,
25092505
});
2510-
let p2tr_fee = fee_for_weight(TEST_FEERATE_SATS_PER_KW, P2TR_INPUT_WEIGHT_LOWER_BOUND);
2511-
let amount_adjusted_with_p2tr_fee =
2512-
1_000_000 - p2tr_fee - outputs_fee - tx_common_fields_fee;
2506+
let amount_adjusted_with_p2tr_fee = 1_000_000
2507+
- fee_for_weight(
2508+
TEST_FEERATE_SATS_PER_KW,
2509+
P2TR_INPUT_WEIGHT_LOWER_BOUND + TX_COMMON_FIELDS_WEIGHT + outputs_weight,
2510+
);
25132511
do_test_interactive_tx_constructor(TestSession {
25142512
description: "Single contribution, with P2TR input, insufficient fees",
25152513
inputs_a: generate_inputs(&[TestOutput::P2TR(1_000_000)]),

0 commit comments

Comments
 (0)