diff --git a/src/bitcoin/checkpoint.rs b/src/bitcoin/checkpoint.rs index 1bd986d1..fd1dd0fe 100644 --- a/src/bitcoin/checkpoint.rs +++ b/src/bitcoin/checkpoint.rs @@ -267,8 +267,12 @@ impl BitcoinTx { /// The estimated size of the transaction, including the worst-case sizes of /// all input witnesses once fully signed, in virtual bytes. - pub fn vsize(&self) -> Result { - Ok(self.to_bitcoin_tx()?.vsize().try_into()?) + pub fn est_vsize(&self) -> Result { + let base_vsize: u64 = self.to_bitcoin_tx()?.vsize().try_into()?; + let est_witness_vsize = self.input.iter()?.try_fold(0, |sum: u64, input| { + Ok::<_, Error>(sum + input?.est_witness_vsize) + })?; + Ok(base_vsize + est_witness_vsize) } /// The hash of the transaction. Note that this will change if any inputs or @@ -1303,7 +1307,7 @@ impl<'a> BuildingCheckpointMut<'a> { .get_mut(BatchType::IntermediateTx as u64)? .unwrap(); let mut intermediate_tx = intermediate_tx_batch.get_mut(0)?.unwrap(); - let fee = intermediate_tx.vsize()? * fee_rate; + let fee = intermediate_tx.est_vsize()? * fee_rate; intermediate_tx.deduct_fee(fee)?; fee }; @@ -1366,7 +1370,9 @@ impl<'a> BuildingCheckpointMut<'a> { // Deduct the final tx's miner fee from its outputs, // removing any outputs which are too small to pay their // share of the fee. - let tx_size = tx.vsize().map_err(|err| OrgaError::App(err.to_string()))?; + let tx_size = tx + .est_vsize() + .map_err(|err| OrgaError::App(err.to_string()))?; let fee = intermediate_tx_fee / intermediate_tx_len + tx_size * fee_rate; tx.deduct_fee(fee) .map_err(|err| OrgaError::App(err.to_string()))?; @@ -1479,7 +1485,7 @@ impl<'a> BuildingCheckpointMut<'a> { // and add our output there instead. // TODO: don't pop and repush, just get a mutable reference let mut curr_tx = final_txs.pop().unwrap(); - if curr_tx.vsize()? >= config.emergency_disbursal_max_tx_size { + if curr_tx.est_vsize()? >= config.emergency_disbursal_max_tx_size { self.link_intermediate_tx(&mut curr_tx, config.sigset_threshold)?; final_txs.push(curr_tx); curr_tx = BitcoinTx::with_lock_time(lock_time); diff --git a/src/bitcoin/recovery.rs b/src/bitcoin/recovery.rs index 0ff1678c..4ec74321 100644 --- a/src/bitcoin/recovery.rs +++ b/src/bitcoin/recovery.rs @@ -74,7 +74,7 @@ impl RecoveryTxs { tx.input.push_back(input)?; tx.output.push_back(Adapter::new(output))?; - tx.deduct_fee(args.fee_rate * tx.vsize()?)?; + tx.deduct_fee(args.fee_rate * tx.est_vsize()?)?; tx.populate_input_sig_message(0)?; diff --git a/tests/bitcoin.rs b/tests/bitcoin.rs index 5e585033..d303ddf1 100644 --- a/tests/bitcoin.rs +++ b/tests/bitcoin.rs @@ -541,7 +541,7 @@ async fn bitcoin_test() { } } } - assert_eq!(signatory_balance, 49994239); + assert_eq!(signatory_balance, 49993057); let funded_account_balances: Vec<_> = funded_accounts .iter() @@ -556,7 +556,7 @@ async fn bitcoin_test() { }) .collect(); - let expected_account_balances: Vec = vec![989980029, 0, 0, 0]; + let expected_account_balances: Vec = vec![989976483, 0, 0, 0]; assert_eq!(funded_account_balances, expected_account_balances); for (i, account) in funded_accounts[0..1].iter().enumerate() {