diff --git a/lightning/src/ln/chan_utils.rs b/lightning/src/ln/chan_utils.rs index 0183d2ff2eb..66f677d2453 100644 --- a/lightning/src/ln/chan_utils.rs +++ b/lightning/src/ln/chan_utils.rs @@ -1893,7 +1893,7 @@ pub fn get_commitment_transaction_number_obscure_factor( mod tests { use super::{CounterpartyCommitmentSecrets, ChannelPublicKeys}; use crate::chain; - use crate::ln::chan_utils::{get_htlc_redeemscript, get_to_countersignatory_with_anchors_redeemscript, CommitmentTransaction, TxCreationKeys, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, HTLCOutputInCommitment}; + use crate::ln::chan_utils::{get_htlc_redeemscript, get_to_countersignatory_with_anchors_redeemscript, CommitmentTransaction, TxCreationKeys, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, HTLCOutputInCommitment, commit_tx_fee_sat, htlc_success_tx_weight, per_outbound_htlc_counterparty_commit_tx_fee_msat}; use bitcoin::secp256k1::{PublicKey, SecretKey, Secp256k1}; use crate::util::test_utils; use crate::sign::{ChannelSigner, SignerProvider}; @@ -2430,4 +2430,35 @@ mod tests { assert!(monitor.provide_secret(281474976710648, secrets.last().unwrap().clone()).is_err()); } } + + #[test] + fn test_commit_tx_fee_sat_num_htlcs_slope_per_outbound_htlc_counterparty_commit_tx_fee_msat() { + // Test that the slope (commit_tx_fee_sat/num_htlcs) is consistent with per_outbound_htlc_counterparty_commit_tx_fee_msat. + // `got`: floor(feerate * commit_tx_base_weight) + floor(num_htlcs * feerate * htlc_output_weight + num_htlcs * feerate * htlc_tx_weight) + // `want`: floor(feerate * commit_tx_base_weight + num_htlcs * feerate * htlc_output_weight) + floor(num_htlcs * feerate * htlc_tx_weight) + // At most, the difference between the two calculations is 1 satoshi, depending on how the num_htlcs * feerate * htlc_output_weight term + // adds with the two others. + // + // In the case of anchor channels, set `htlc_tx_weight` above to zero; the fees are exogenous. + + let num_htlcs = 966; // BOLT #2 maximum number of htlcs on a commit tx + + let features = ChannelTypeFeatures::only_static_remote_key(); + // Tests the range 1sat/vb - 250sat/vb + for feerate in 253..62500 { + let got = commit_tx_fee_sat(feerate, 0, &features) + num_htlcs * per_outbound_htlc_counterparty_commit_tx_fee_msat(feerate, &features) / 1000; + let want = commit_tx_fee_sat(feerate, num_htlcs as usize, &features) + num_htlcs * feerate as u64 * htlc_success_tx_weight(&features) / 1000; + let diff = u64::abs_diff(got, want); + assert!(diff <= 1, "assert failed for feerate: {}, absolute difference was: {}", feerate, diff); + } + + let features = ChannelTypeFeatures::anchors_zero_htlc_fee_and_dependencies(); + // Tests the range 1sat/vb - 250sat/vb + for feerate in 253..62500 { + let got = commit_tx_fee_sat(feerate, 0, &features) + num_htlcs * per_outbound_htlc_counterparty_commit_tx_fee_msat(feerate, &features) / 1000; + let want = commit_tx_fee_sat(feerate, num_htlcs as usize, &features); + let diff = u64::checked_sub(want, got).expect("got should not be greater than want"); + assert!(diff <= 1, "assert failed for feerate: {}, checked difference was: {}", feerate, diff); + } + } }