Skip to content

Commit

Permalink
test(electrum): test for checking that fee calculation is correct
Browse files Browse the repository at this point in the history
  • Loading branch information
f3r10 committed Dec 9, 2024
1 parent ab08b8c commit fb7ca7e
Showing 1 changed file with 113 additions and 0 deletions.
113 changes: 113 additions & 0 deletions crates/electrum/tests/test_electrum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,3 +559,116 @@ fn test_sync_with_coinbase() -> anyhow::Result<()> {

Ok(())
}

#[test]
fn test_check_fee_calculation() -> anyhow::Result<()> {
const SEND_AMOUNT: Amount = Amount::from_sat(10_000);
let env = TestEnv::new()?;
let electrum_client = electrum_client::Client::new(env.electrsd.electrum_url.as_str())?;
let client = BdkElectrumClient::new(electrum_client);

let spk_to_track = ScriptBuf::new_p2wsh(&WScriptHash::all_zeros());
let addr_to_track = Address::from_script(&spk_to_track, bdk_chain::bitcoin::Network::Regtest)?;

// Setup receiver.
let (mut recv_chain, _) = LocalChain::from_genesis_hash(env.bitcoind.client.get_block_hash(0)?);
let mut recv_graph = IndexedTxGraph::<ConfirmationBlockTime, _>::new({
let mut recv_index = SpkTxOutIndex::default();
recv_index.insert_spk((), spk_to_track.clone());
recv_index
});

// Mine some blocks.
env.mine_blocks(101, None)?;

// Send a preliminary tx such that the new utxo in Core's wallet
// becomes the input of the next tx
let new_addr = env
.rpc_client()
.get_new_address(None, None)?
.assume_checked();
let prev_amt = SEND_AMOUNT + Amount::from_sat(1650);
env.send(&new_addr, prev_amt)?;
let prev_hash_block = env.mine_blocks(1, None)?.into_iter().next();

let txid = env.send(&addr_to_track, SEND_AMOUNT)?;

// Mine a block to confirm sent tx.
let hash_block = env.mine_blocks(1, None)?.into_iter().next();

// Look at the tx we just sent, it should have 1 input and 1 output
let tx = env
.rpc_client()
.get_raw_transaction_info(&txid, hash_block.as_ref())?;
assert_eq!(tx.vin.len(), 1);
assert_eq!(tx.vout.len(), 1);
let vin = &tx.vin[0];
let prev_txid = vin.txid.unwrap();
let vout = vin.vout.unwrap();
let outpoint = bdk_chain::bitcoin::OutPoint::new(prev_txid, vout);

// Get the txout of the previous tx
let prev_tx = env
.rpc_client()
.get_raw_transaction_info(&prev_txid, prev_hash_block.as_ref())?;
let txout = prev_tx
.vout
.iter()
.find(|txout| txout.value == prev_amt)
.unwrap();
let script_pubkey = ScriptBuf::from_bytes(txout.script_pub_key.hex.to_vec());
let txout = bdk_chain::bitcoin::TxOut {
value: txout.value,
script_pubkey,
};

// Sync up to tip.
env.wait_until_electrum_sees_block(Duration::from_secs(6))?;
let _ = sync_with_electrum(
&client,
[spk_to_track.clone()],
&mut recv_chain,
&mut recv_graph,
)?;

// Check the graph update contains the right floating txout
let graph_txout = recv_graph
.graph()
.all_txouts()
.find(|(_op, txout)| txout.value == prev_amt)
.unwrap();
assert_eq!(graph_txout, (outpoint, &txout));

// Check to see if tx is confirmed.
assert_eq!(
get_balance(&recv_chain, &recv_graph)?,
Balance {
confirmed: SEND_AMOUNT,
..Balance::default()
},
);

for tx in recv_graph.graph().full_txs() {
// Retrieve the calculated fee from `TxGraph`, which will panic if we do not have the
// floating txouts available from the transaction's previous outputs.
let fee = recv_graph
.graph()
.calculate_fee(&tx.tx)
.expect("fee must exist");

// Retrieve the fee in the transaction data from `bitcoind`.
let tx_fee = env
.bitcoind
.client
.get_transaction(&tx.txid, None)
.expect("Tx must exist")
.fee
.expect("Fee must exist")
.abs()
.to_sat() as u64;

// Check that the calculated fee matches the fee from the transaction data.
assert_eq!(fee, Amount::from_sat(tx_fee)); // 1650sat
}
Ok(())
}

0 comments on commit fb7ca7e

Please sign in to comment.