From 9736c709c0c7d02c27e4280e5f2dd4085bdf1169 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Mon, 18 Sep 2023 14:07:57 -0700 Subject: [PATCH] Sanity check fees on transactions produced by the bump event handler We add a few debug assertions to ensure we don't overpay fees by 5% more than expected. --- lightning/src/events/bump_transaction.rs | 44 ++++++++++++++++++++---- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/lightning/src/events/bump_transaction.rs b/lightning/src/events/bump_transaction.rs index ec16a16a..35e9da60 100644 --- a/lightning/src/events/bump_transaction.rs +++ b/lightning/src/events/bump_transaction.rs @@ -734,6 +734,8 @@ where previous_utxo: anchor_utxo, satisfaction_weight: commitment_tx.weight() as u64 + ANCHOR_INPUT_WITNESS_WEIGHT + EMPTY_SCRIPT_SIG_WEIGHT, }]; + #[cfg(debug_assertions)] + let must_spend_amount = must_spend.iter().map(|input| input.previous_utxo.value).sum::(); log_debug!(self.logger, "Peforming coin selection for commitment package (commitment and anchor transaction) targeting {} sat/kW", package_target_feerate_sat_per_1000_weight); @@ -747,10 +749,13 @@ where input: vec![anchor_descriptor.unsigned_tx_input()], output: vec![], }; + + #[cfg(debug_assertions)] + let total_satisfaction_weight = ANCHOR_INPUT_WITNESS_WEIGHT + EMPTY_SCRIPT_SIG_WEIGHT + + coin_selection.confirmed_utxos.iter().map(|utxo| utxo.satisfaction_weight).sum::(); #[cfg(debug_assertions)] - let total_satisfaction_weight = - coin_selection.confirmed_utxos.iter().map(|utxo| utxo.satisfaction_weight).sum::() + - ANCHOR_INPUT_WITNESS_WEIGHT + EMPTY_SCRIPT_SIG_WEIGHT; + let total_input_amount = must_spend_amount + + coin_selection.confirmed_utxos.iter().map(|utxo| utxo.output.value).sum::(); self.process_coin_selection(&mut anchor_tx, coin_selection); let anchor_txid = anchor_tx.txid(); @@ -773,6 +778,16 @@ where // never underestimate. assert!(expected_signed_tx_weight >= signed_tx_weight && expected_signed_tx_weight - (expected_signed_tx_weight / 100) <= signed_tx_weight); + + let expected_package_fee = fee_for_weight(package_target_feerate_sat_per_1000_weight, + signed_tx_weight + commitment_tx.weight() as u64); + let package_fee = total_input_amount - + anchor_tx.output.iter().map(|output| output.value).sum::(); + // Our fee should be within a 5% error margin of the expected fee based on the + // feerate and transaction weight and we should never pay less than required. + let fee_error_margin = expected_package_fee * 5 / 100; + assert!(package_fee >= expected_package_fee && + package_fee - fee_error_margin <= expected_package_fee); } log_info!(self.logger, "Broadcasting anchor transaction {} to bump channel close with txid {}", @@ -812,16 +827,24 @@ where log_debug!(self.logger, "Peforming coin selection for HTLC transaction targeting {} sat/kW", target_feerate_sat_per_1000_weight); + #[cfg(debug_assertions)] let must_spend_satisfaction_weight = must_spend.iter().map(|input| input.satisfaction_weight).sum::(); + #[cfg(debug_assertions)] + let must_spend_amount = must_spend.iter().map(|input| input.previous_utxo.value).sum::(); + let coin_selection = self.utxo_source.select_confirmed_utxos( claim_id, must_spend, &htlc_tx.output, target_feerate_sat_per_1000_weight, )?; + + #[cfg(debug_assertions)] + let total_satisfaction_weight = must_spend_satisfaction_weight + + coin_selection.confirmed_utxos.iter().map(|utxo| utxo.satisfaction_weight).sum::(); #[cfg(debug_assertions)] - let total_satisfaction_weight = - coin_selection.confirmed_utxos.iter().map(|utxo| utxo.satisfaction_weight).sum::() + - must_spend_satisfaction_weight; + let total_input_amount = must_spend_amount + + coin_selection.confirmed_utxos.iter().map(|utxo| utxo.output.value).sum::(); + self.process_coin_selection(&mut htlc_tx, coin_selection); #[cfg(debug_assertions)] @@ -846,6 +869,15 @@ where // never underestimate. assert!(expected_signed_tx_weight >= signed_tx_weight && expected_signed_tx_weight - (expected_signed_tx_weight / 100) <= signed_tx_weight); + + let expected_signed_tx_fee = fee_for_weight(target_feerate_sat_per_1000_weight, signed_tx_weight); + let signed_tx_fee = total_input_amount - + htlc_tx.output.iter().map(|output| output.value).sum::(); + // Our fee should be within a 5% error margin of the expected fee based on the + // feerate and transaction weight and we should never pay less than required. + let fee_error_margin = expected_signed_tx_fee * 5 / 100; + assert!(signed_tx_fee >= expected_signed_tx_fee && + signed_tx_fee - fee_error_margin <= expected_signed_tx_fee); } log_info!(self.logger, "Broadcasting {}", log_tx!(htlc_tx)); -- 2.30.2