Skip to content

Commit

Permalink
Merge pull request #18 from bitfinity-network/fix/tx-size-estimation
Browse files Browse the repository at this point in the history
Fix: include number of inputs in the `total_estimated_tx_size`
  • Loading branch information
kobby-pentangeli authored Apr 4, 2024
2 parents 4917d94 + f97feea commit 663832e
Showing 1 changed file with 30 additions and 13 deletions.
43 changes: 30 additions & 13 deletions src/utils/fees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pub fn estimate_commit_fee(
estimate_transaction_fees(
script_type,
unsigned_commit_tx.vsize(),
unsigned_commit_tx.input.len(),
current_fee_rate,
multisig_config,
)
Expand Down Expand Up @@ -72,6 +73,7 @@ pub fn estimate_reveal_fee(
estimate_transaction_fees(
script_type,
unsigned_reveal_tx.vsize(),
unsigned_reveal_tx.input.len(),
current_fee_rate,
multisig_config,
)
Expand All @@ -80,11 +82,12 @@ pub fn estimate_reveal_fee(
fn estimate_transaction_fees(
script_type: ScriptType,
unsigned_tx_size: usize,
number_of_inputs: usize,
current_fee_rate: FeeRate,
multisig_config: &Option<MultisigConfig>,
) -> Amount {
let estimated_sig_size = estimate_signature_size(script_type, multisig_config);
let total_estimated_tx_size = unsigned_tx_size + estimated_sig_size;
let total_estimated_tx_size = unsigned_tx_size + (number_of_inputs * estimated_sig_size);

current_fee_rate
.fee_vb(total_estimated_tx_size as u64)
Expand Down Expand Up @@ -115,24 +118,27 @@ mod tests {
fn estimate_transaction_fees_p2wsh_single_signature() {
let script_type = ScriptType::P2WSH;
let unsigned_tx_size = 100; // in vbytes
let number_of_inputs = 5_usize;
let current_fee_rate = FeeRate::from_sat_per_vb(5_u64).unwrap();
let multisig_config: Option<MultisigConfig> = None; // No multisig config for single signature

let fee = estimate_transaction_fees(
script_type,
unsigned_tx_size,
number_of_inputs,
current_fee_rate,
&multisig_config,
);

// Expected fee calculation: (100 + 73) * 5 = 865 satoshis
assert_eq!(fee, Amount::from_sat(865));
// Expected fee calculation: (100 + (5 * 73)) * 5 = 2325 satoshis
assert_eq!(fee, Amount::from_sat(2325));
}

#[test]
fn estimate_transaction_fees_p2wsh_multisig() {
let script_type = ScriptType::P2WSH;
let unsigned_tx_size = 200; // in vbytes
let number_of_inputs = 10_usize;
let current_fee_rate = FeeRate::from_sat_per_vb(10_u64).unwrap();
let multisig_config = Some(MultisigConfig {
required: 2,
Expand All @@ -142,43 +148,48 @@ mod tests {
let fee = estimate_transaction_fees(
script_type,
unsigned_tx_size,
number_of_inputs,
current_fee_rate,
&multisig_config,
);

// Expected fee calculation: (200 + (73 * 2)) * 10 = 3460 satoshis
assert_eq!(fee, Amount::from_sat(3460));
// Expected fee calculation: (200 + (10 * 73 * 2)) * 10 = 16600 satoshis
assert_eq!(fee, Amount::from_sat(16600));
}

#[test]
fn estimate_transaction_fees_p2tr() {
let script_type = ScriptType::P2TR;
let unsigned_tx_size = 150; // in vbytes
let number_of_inputs = 5_usize;
let current_fee_rate = FeeRate::from_sat_per_vb(1_u64).unwrap();
let multisig_config = None;

let fee = estimate_transaction_fees(
script_type,
unsigned_tx_size,
number_of_inputs,
current_fee_rate,
&multisig_config,
);

// Expected fee calculation: (150 + 65) * 1 = 215 satoshis
assert_eq!(fee, Amount::from_sat(215));
// Expected fee calculation: (150 + (5 * 65)) * 1 = 475 satoshis
assert_eq!(fee, Amount::from_sat(475));
}

#[test]
#[should_panic]
fn estimate_transaction_fees_overflow() {
let script_type = ScriptType::P2TR;
let unsigned_tx_size = usize::MAX;
let number_of_inputs = 5_usize;
let current_fee_rate = FeeRate::from_sat_per_vb(1_u64).unwrap();
let multisig_config = None;

let _fee = estimate_transaction_fees(
script_type,
unsigned_tx_size,
number_of_inputs,
current_fee_rate,
&multisig_config,
);
Expand All @@ -188,6 +199,7 @@ mod tests {
fn estimate_transaction_fees_low_fee_rate() {
let script_type = ScriptType::P2WSH;
let unsigned_tx_size = 250; // in vbytes
let number_of_inputs = 15_usize;
let current_fee_rate = FeeRate::from_sat_per_vb(1_u64).unwrap(); // Low fee rate
let multisig_config = Some(MultisigConfig {
required: 3,
Expand All @@ -197,37 +209,41 @@ mod tests {
let fee = estimate_transaction_fees(
script_type,
unsigned_tx_size,
number_of_inputs,
current_fee_rate,
&multisig_config,
);

// Expected fee calculation: (250 + (73 * 3)) * 1 = 469 satoshis
assert_eq!(fee, Amount::from_sat(469));
// Expected fee calculation: (250 + (15 * 73 * 3)) * 1 = 3535 satoshis
assert_eq!(fee, Amount::from_sat(3535));
}

#[test]
fn estimate_transaction_fees_high_fee_rate() {
let script_type = ScriptType::P2TR;
let unsigned_tx_size = 180; // in vbytes
let number_of_inputs = 9_usize;
let current_fee_rate = FeeRate::from_sat_per_vb(50_u64).unwrap(); // High fee rate
let multisig_config = None;

let fee = estimate_transaction_fees(
script_type,
unsigned_tx_size,
number_of_inputs,
current_fee_rate,
&multisig_config,
);

// Expected fee calculation: (180 + 65) * 50 = 12250 satoshis
assert_eq!(fee, Amount::from_sat(12250));
// Expected fee calculation: (180 + (9 * 65)) * 50 = 38250 satoshis
assert_eq!(fee, Amount::from_sat(38250));
}

#[test]
fn estimate_transaction_fees_varying_fee_rate() {
let script_type = ScriptType::P2WSH;
let unsigned_tx_size = 300; // in vbytes
// Simulating a fee rate that might be seen during network congestion
let number_of_inputs = 10_usize;
// Simulating a fee rate that might be seen during network congestion
let fee_rates: Vec<u64> = vec![5, 10, 20, 30, 40];

for fee_rate in fee_rates {
Expand All @@ -240,12 +256,13 @@ mod tests {
let fee = estimate_transaction_fees(
script_type,
unsigned_tx_size,
number_of_inputs,
current_fee_rate,
&multisig_config,
);

// Expected fee calculation changes with the fee_rate
let expected_fee = (300 + (73 * 2)) as u64 * fee_rate;
let expected_fee = (300 + (10 * 73 * 2)) as u64 * fee_rate;
assert_eq!(
fee,
Amount::from_sat(expected_fee),
Expand Down

0 comments on commit 663832e

Please sign in to comment.