Skip to content

Commit 99888fa

Browse files
committed
test(electrum): test for checking that fee calculation is correct
1 parent 91d7d3c commit 99888fa

File tree

1 file changed

+113
-0
lines changed

1 file changed

+113
-0
lines changed

crates/electrum/tests/test_electrum.rs

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,3 +525,116 @@ fn tx_can_become_unconfirmed_after_reorg() -> anyhow::Result<()> {
525525

526526
Ok(())
527527
}
528+
529+
#[test]
530+
fn test_check_fee_calculation() -> anyhow::Result<()> {
531+
const SEND_AMOUNT: Amount = Amount::from_sat(10_000);
532+
let env = TestEnv::new()?;
533+
let electrum_client = electrum_client::Client::new(env.electrsd.electrum_url.as_str())?;
534+
let client = BdkElectrumClient::new(electrum_client);
535+
536+
let spk_to_track = ScriptBuf::new_p2wsh(&WScriptHash::all_zeros());
537+
let addr_to_track = Address::from_script(&spk_to_track, bdk_chain::bitcoin::Network::Regtest)?;
538+
539+
// Setup receiver.
540+
let (mut recv_chain, _) = LocalChain::from_genesis_hash(env.bitcoind.client.get_block_hash(0)?);
541+
let mut recv_graph = IndexedTxGraph::<ConfirmationBlockTime, _>::new({
542+
let mut recv_index = SpkTxOutIndex::default();
543+
recv_index.insert_spk((), spk_to_track.clone());
544+
recv_index
545+
});
546+
547+
// Mine some blocks.
548+
env.mine_blocks(101, None)?;
549+
550+
// Send a preliminary tx such that the new utxo in Core's wallet
551+
// becomes the input of the next tx
552+
let new_addr = env
553+
.rpc_client()
554+
.get_new_address(None, None)?
555+
.assume_checked();
556+
let prev_amt = SEND_AMOUNT + Amount::from_sat(1650);
557+
env.send(&new_addr, prev_amt)?;
558+
let prev_hash_block = env.mine_blocks(1, None)?.into_iter().nth(0);
559+
560+
let txid = env.send(&addr_to_track, SEND_AMOUNT)?;
561+
562+
// Mine a block to confirm sent tx.
563+
let hash_block = env.mine_blocks(1, None)?.into_iter().nth(0);
564+
565+
// Look at the tx we just sent, it should have 1 input and 1 output
566+
let tx = env
567+
.rpc_client()
568+
.get_raw_transaction_info(&txid, hash_block.as_ref())?;
569+
assert_eq!(tx.vin.len(), 1);
570+
assert_eq!(tx.vout.len(), 1);
571+
let vin = &tx.vin[0];
572+
let prev_txid = vin.txid.unwrap();
573+
let vout = vin.vout.unwrap();
574+
let outpoint = bdk_chain::bitcoin::OutPoint::new(prev_txid, vout);
575+
576+
// Get the txout of the previous tx
577+
let prev_tx = env
578+
.rpc_client()
579+
.get_raw_transaction_info(&prev_txid, prev_hash_block.as_ref())?;
580+
let txout = prev_tx
581+
.vout
582+
.iter()
583+
.find(|txout| txout.value == prev_amt)
584+
.unwrap();
585+
let script_pubkey = ScriptBuf::from_bytes(txout.script_pub_key.hex.to_vec());
586+
let txout = bdk_chain::bitcoin::TxOut {
587+
value: txout.value,
588+
script_pubkey,
589+
};
590+
591+
// Sync up to tip.
592+
env.wait_until_electrum_sees_block(Duration::from_secs(6))?;
593+
let _ = sync_with_electrum(
594+
&client,
595+
[spk_to_track.clone()],
596+
&mut recv_chain,
597+
&mut recv_graph,
598+
)?;
599+
600+
// Check the graph update contains the right floating txout
601+
let graph_txout = recv_graph
602+
.graph()
603+
.all_txouts()
604+
.find(|(_op, txout)| txout.value == prev_amt)
605+
.unwrap();
606+
assert_eq!(graph_txout, (outpoint, &txout));
607+
608+
// Check to see if tx is confirmed.
609+
assert_eq!(
610+
get_balance(&recv_chain, &recv_graph)?,
611+
Balance {
612+
confirmed: SEND_AMOUNT,
613+
..Balance::default()
614+
},
615+
);
616+
617+
for tx in recv_graph.graph().full_txs() {
618+
// Retrieve the calculated fee from `TxGraph`, which will panic if we do not have the
619+
// floating txouts available from the transaction's previous outputs.
620+
let fee = recv_graph
621+
.graph()
622+
.calculate_fee(&tx.tx)
623+
.expect("fee must exist");
624+
625+
// Retrieve the fee in the transaction data from `bitcoind`.
626+
let tx_fee = env
627+
.bitcoind
628+
.client
629+
.get_transaction(&tx.txid, None)
630+
.expect("Tx must exist")
631+
.fee
632+
.expect("Fee must exist")
633+
.abs()
634+
.to_sat() as u64;
635+
636+
// Check that the calculated fee matches the fee from the transaction data.
637+
assert_eq!(fee, Amount::from_sat(tx_fee)); // 1650sat
638+
}
639+
Ok(())
640+
}

0 commit comments

Comments
 (0)