Skip to content

Commit f429973

Browse files
committed
test(electrum): test for checking that fee calculation is correct
1 parent 1afa439 commit f429973

File tree

1 file changed

+117
-0
lines changed

1 file changed

+117
-0
lines changed

crates/electrum/tests/test_electrum.rs

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,3 +559,120 @@ fn test_sync_with_coinbase() -> anyhow::Result<()> {
559559

560560
Ok(())
561561
}
562+
563+
#[test]
564+
fn test_check_fee_calculation() -> anyhow::Result<()> {
565+
const SEND_AMOUNT: Amount = Amount::from_sat(10_000);
566+
const FEE_AMOUNT: Amount = Amount::from_sat(1650);
567+
let env = TestEnv::new()?;
568+
let electrum_client = electrum_client::Client::new(env.electrsd.electrum_url.as_str())?;
569+
let client = BdkElectrumClient::new(electrum_client);
570+
571+
let spk_to_track = ScriptBuf::new_p2wsh(&WScriptHash::all_zeros());
572+
let addr_to_track = Address::from_script(&spk_to_track, bdk_chain::bitcoin::Network::Regtest)?;
573+
574+
// Setup receiver.
575+
let (mut recv_chain, _) = LocalChain::from_genesis_hash(env.bitcoind.client.get_block_hash(0)?);
576+
let mut recv_graph = IndexedTxGraph::<ConfirmationBlockTime, _>::new({
577+
let mut recv_index = SpkTxOutIndex::default();
578+
recv_index.insert_spk((), spk_to_track.clone());
579+
recv_index
580+
});
581+
582+
// Mine some blocks.
583+
env.mine_blocks(101, None)?;
584+
585+
// Send a preliminary tx such that the new utxo in Core's wallet
586+
// becomes the input of the next tx
587+
let new_addr = env
588+
.rpc_client()
589+
.get_new_address(None, None)?
590+
.assume_checked();
591+
let prev_amt = SEND_AMOUNT + FEE_AMOUNT;
592+
env.send(&new_addr, prev_amt)?;
593+
let prev_block_hash = env.mine_blocks(1, None)?.into_iter().next();
594+
595+
let txid = env.send(&addr_to_track, SEND_AMOUNT)?;
596+
597+
// Mine a block to confirm sent tx.
598+
let block_hash = env.mine_blocks(1, None)?.into_iter().next();
599+
600+
// Look at the tx we just sent, it should have 1 input and 1 output
601+
let tx = env
602+
.rpc_client()
603+
.get_raw_transaction_info(&txid, block_hash.as_ref())?;
604+
assert_eq!(tx.vin.len(), 1);
605+
assert_eq!(tx.vout.len(), 1);
606+
let vin = &tx.vin[0];
607+
let prev_txid = vin.txid.unwrap();
608+
let vout = vin.vout.unwrap();
609+
let outpoint = bdk_chain::bitcoin::OutPoint::new(prev_txid, vout);
610+
611+
// Get the txout of the previous tx
612+
let prev_tx = env
613+
.rpc_client()
614+
.get_raw_transaction_info(&prev_txid, prev_block_hash.as_ref())?;
615+
let txout = prev_tx
616+
.vout
617+
.iter()
618+
.find(|txout| txout.value == prev_amt)
619+
.unwrap();
620+
let script_pubkey = ScriptBuf::from_bytes(txout.script_pub_key.hex.to_vec());
621+
let txout = bdk_chain::bitcoin::TxOut {
622+
value: txout.value,
623+
script_pubkey,
624+
};
625+
626+
// Sync up to tip.
627+
env.wait_until_electrum_sees_block(Duration::from_secs(6))?;
628+
let _ = sync_with_electrum(
629+
&client,
630+
[spk_to_track.clone()],
631+
&mut recv_chain,
632+
&mut recv_graph,
633+
)?;
634+
635+
// Check the graph update contains the right floating txout
636+
let graph_txout = recv_graph
637+
.graph()
638+
.all_txouts()
639+
.find(|(_op, txout)| txout.value == prev_amt)
640+
.unwrap();
641+
assert_eq!(graph_txout, (outpoint, &txout));
642+
643+
// Check to see if tx is confirmed.
644+
assert_eq!(
645+
get_balance(&recv_chain, &recv_graph)?,
646+
Balance {
647+
confirmed: SEND_AMOUNT,
648+
..Balance::default()
649+
},
650+
);
651+
652+
for tx in recv_graph.graph().full_txs() {
653+
// Retrieve the calculated fee from `TxGraph`, which will panic if we do not have the
654+
// floating txouts available from the transaction's previous outputs.
655+
let fee = recv_graph
656+
.graph()
657+
.calculate_fee(&tx.tx)
658+
.expect("fee must exist");
659+
660+
// Check the fee calculated fee matches the initial fee amount
661+
assert_eq!(fee, FEE_AMOUNT);
662+
663+
// Retrieve the fee in the transaction data from `bitcoind`.
664+
let tx_fee = env
665+
.bitcoind
666+
.client
667+
.get_transaction(&tx.txid, None)
668+
.expect("Tx must exist")
669+
.fee
670+
.expect("Fee must exist")
671+
.abs()
672+
.to_sat() as u64;
673+
674+
// Check that the calculated fee matches the fee from the transaction data.
675+
assert_eq!(fee, Amount::from_sat(tx_fee)); // 1650sat
676+
}
677+
Ok(())
678+
}

0 commit comments

Comments
 (0)