Skip to content

Commit f1401ce

Browse files
committed
Use the rust-bitcoin fee calculator instead of hardcoded estimates
1 parent 7391636 commit f1401ce

File tree

1 file changed

+22
-37
lines changed

1 file changed

+22
-37
lines changed

payjoin/tests/integration.rs

+22-37
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ mod integration {
44
use std::env;
55
use std::str::FromStr;
66

7-
use bitcoin::psbt::Psbt;
87
use bitcoin::policy::DEFAULT_MIN_RELAY_TX_FEE;
8+
use bitcoin::psbt::Psbt;
99
use bitcoin::{Amount, FeeRate, OutPoint, Weight};
1010
use bitcoind::bitcoincore_rpc::json::{AddressType, WalletProcessPsbtResult};
1111
use bitcoind::bitcoincore_rpc::{self, RpcApi};
@@ -22,14 +22,6 @@ mod integration {
2222
static EXAMPLE_URL: Lazy<Url> =
2323
Lazy::new(|| Url::parse("https://example.com").expect("Invalid Url"));
2424

25-
// See https://jlopp.github.io/bitcoin-transaction-size-calculator/
26-
// Base weight of an empty transaction (no inputs, no outputs)
27-
static BASE_WEIGHT: Weight = Weight::from_vb_unchecked(11);
28-
// Per-input weight for P2WPKH inputs
29-
static INPUT_WEIGHT: Weight = Weight::from_vb_unchecked(68);
30-
// Per-output weight for P2WPKH inputs
31-
static OUTPUT_WEIGHT: Weight = Weight::from_vb_unchecked(31);
32-
3325
#[cfg(not(feature = "v2"))]
3426
mod v1 {
3527
use log::debug;
@@ -77,12 +69,9 @@ mod integration {
7769
sender.send_raw_transaction(&payjoin_tx)?;
7870

7971
// Check resulting transaction and balances
80-
let input_count = payjoin_tx.input.len() as u64;
81-
let output_count = payjoin_tx.output.len() as u64;
82-
let tx_weight = BASE_WEIGHT + input_count * INPUT_WEIGHT + output_count * OUTPUT_WEIGHT;
83-
let network_fees = tx_weight * FeeRate::BROADCAST_MIN;
84-
assert_eq!(input_count, 2);
85-
assert_eq!(output_count, 2);
72+
let network_fees = predicted_tx_weight(&payjoin_tx) * FeeRate::BROADCAST_MIN;
73+
assert_eq!(payjoin_tx.input.len(), 2);
74+
assert_eq!(payjoin_tx.output.len(), 2);
8675
assert_eq!(receiver.get_balances()?.mine.untrusted_pending, Amount::from_btc(51.0)?);
8776
assert_eq!(
8877
sender.get_balances()?.mine.untrusted_pending,
@@ -335,17 +324,13 @@ mod integration {
335324
log::info!("sent");
336325

337326
// Check resulting transaction and balances
338-
let input_count = payjoin_tx.input.len() as u64;
339-
let output_count = payjoin_tx.output.len() as u64;
340-
let tx_weight =
341-
BASE_WEIGHT + input_count * INPUT_WEIGHT + output_count * OUTPUT_WEIGHT;
342327
// NOTE: No one is contributing fees for the receiver input because the sender has
343-
// no change output and the receiver doesn't contribute fees
344-
let network_fees =
345-
(tx_weight - 1 * INPUT_WEIGHT) * FeeRate::from_sat_per_vb_unchecked(2);
328+
// no change output and the receiver doesn't contribute fees. Temporary workaround
329+
// is to ensure the sender overpays in the original psbt for the receiver's input.
330+
let network_fees = psbt.fee()?;
346331
// Sender sent the entire value of their utxo to receiver (minus fees)
347-
assert_eq!(input_count, 2);
348-
assert_eq!(output_count, 1);
332+
assert_eq!(payjoin_tx.input.len(), 2);
333+
assert_eq!(payjoin_tx.output.len(), 1);
349334
assert_eq!(
350335
receiver.get_balances()?.mine.untrusted_pending,
351336
Amount::from_btc(100.0)? - network_fees
@@ -394,12 +379,9 @@ mod integration {
394379
sender.send_raw_transaction(&payjoin_tx)?;
395380

396381
// Check resulting transaction and balances
397-
let input_count = payjoin_tx.input.len() as u64;
398-
let output_count = payjoin_tx.output.len() as u64;
399-
let tx_weight = BASE_WEIGHT + input_count * INPUT_WEIGHT + output_count * OUTPUT_WEIGHT;
400-
let network_fees = tx_weight * FeeRate::BROADCAST_MIN;
401-
assert_eq!(input_count, 2);
402-
assert_eq!(output_count, 2);
382+
let network_fees = predicted_tx_weight(&payjoin_tx) * FeeRate::BROADCAST_MIN;
383+
assert_eq!(payjoin_tx.input.len(), 2);
384+
assert_eq!(payjoin_tx.output.len(), 2);
403385
assert_eq!(receiver.get_balances()?.mine.untrusted_pending, Amount::from_btc(51.0)?);
404386
assert_eq!(
405387
sender.get_balances()?.mine.untrusted_pending,
@@ -532,13 +514,9 @@ mod integration {
532514
);
533515

534516
// Check resulting transaction and balances
535-
let input_count = payjoin_tx.input.len() as u64;
536-
let output_count = payjoin_tx.output.len() as u64;
537-
let tx_weight =
538-
BASE_WEIGHT + input_count * INPUT_WEIGHT + output_count * OUTPUT_WEIGHT;
539-
let network_fees = tx_weight * FeeRate::BROADCAST_MIN;
540-
assert_eq!(input_count, 2);
541-
assert_eq!(output_count, 2);
517+
let network_fees = predicted_tx_weight(&payjoin_tx) * FeeRate::BROADCAST_MIN;
518+
assert_eq!(payjoin_tx.input.len(), 2);
519+
assert_eq!(payjoin_tx.output.len(), 2);
542520
assert_eq!(
543521
receiver.get_balances()?.mine.untrusted_pending,
544522
Amount::from_btc(51.0)?
@@ -954,6 +932,13 @@ mod integration {
954932
Ok(payjoin_psbt.extract_tx()?)
955933
}
956934

935+
fn predicted_tx_weight(tx: &bitcoin::Transaction) -> Weight {
936+
bitcoin::transaction::predict_weight(
937+
vec![bitcoin::transaction::InputWeightPrediction::P2WPKH_MAX; tx.input.len()],
938+
tx.script_pubkey_lens(),
939+
)
940+
}
941+
957942
struct HeaderMock(HashMap<String, String>);
958943

959944
impl payjoin::receive::Headers for HeaderMock {

0 commit comments

Comments
 (0)