Skip to content

Commit 25a4ceb

Browse files
ValuedMammalLagginTimes
authored andcommitted
test(rpc): add test_expect_tx_evicted
1 parent fcaabf5 commit 25a4ceb

1 file changed

Lines changed: 100 additions & 0 deletions

File tree

crates/bitcoind_rpc/tests/test_emitter.rs

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,3 +731,103 @@ fn no_agreement_point() -> anyhow::Result<()> {
731731

732732
Ok(())
733733
}
734+
735+
#[test]
736+
fn test_expect_tx_evicted() -> anyhow::Result<()> {
737+
use bdk_bitcoind_rpc::bitcoincore_rpc::bitcoin;
738+
use bdk_bitcoind_rpc::bitcoincore_rpc::bitcoincore_rpc_json::CreateRawTransactionInput;
739+
use bdk_chain::miniscript;
740+
use bdk_chain::spk_txout::SpkTxOutIndex;
741+
use bdk_chain::ConfirmationBlockTime;
742+
use bitcoin::constants::genesis_block;
743+
use bitcoin::secp256k1::Secp256k1;
744+
use bitcoin::Network;
745+
use std::collections::HashMap;
746+
let env = TestEnv::new()?;
747+
748+
let s = bdk_testenv::utils::DESCRIPTORS[0];
749+
let desc = miniscript::Descriptor::parse_descriptor(&Secp256k1::new(), s)
750+
.unwrap()
751+
.0;
752+
let spk = desc.at_derivation_index(0)?.script_pubkey();
753+
754+
let chain = LocalChain::from_genesis_hash(genesis_block(Network::Regtest).block_hash()).0;
755+
let chain_tip = chain.tip().block_id();
756+
757+
let mut index = SpkTxOutIndex::default();
758+
index.insert_spk(("external", 0u32), spk.clone());
759+
let mut graph = IndexedTxGraph::<ConfirmationBlockTime, _>::new(index);
760+
761+
// Receive tx1.
762+
let _ = env.mine_blocks(100, None)?;
763+
let txid_1 = env.send(
764+
&Address::from_script(&spk, Network::Regtest)?,
765+
Amount::ONE_BTC,
766+
)?;
767+
768+
let mut emitter = Emitter::new(env.rpc_client(), chain.tip(), 1);
769+
let changeset = graph.batch_insert_unconfirmed(emitter.mempool()?);
770+
assert!(changeset
771+
.tx_graph
772+
.txs
773+
.iter()
774+
.any(|tx| tx.compute_txid() == txid_1));
775+
let seen_at = graph
776+
.graph()
777+
.get_tx_node(txid_1)
778+
.unwrap()
779+
.last_seen_unconfirmed
780+
.unwrap();
781+
782+
// Double spend tx1.
783+
784+
// Get `prevout` from core.
785+
let core = env.rpc_client();
786+
let tx1 = &core.get_raw_transaction(&txid_1, None)?;
787+
let txin = &tx1.input[0];
788+
let op = txin.previous_output;
789+
790+
// Create `tx1b` using the previous output from tx1.
791+
let utxo = CreateRawTransactionInput {
792+
txid: op.txid,
793+
vout: op.vout,
794+
sequence: None,
795+
};
796+
let addr = core.get_new_address(None, None)?.assume_checked();
797+
let tx = core.create_raw_transaction(
798+
&[utxo],
799+
&HashMap::from([(addr.to_string(), Amount::from_btc(49.99)?)]),
800+
None,
801+
None,
802+
)?;
803+
let res = core.sign_raw_transaction_with_wallet(&tx, None, None)?;
804+
let tx1b = res.transaction()?;
805+
806+
// Send the tx.
807+
let txid_2 = core.send_raw_transaction(&tx1b)?;
808+
809+
// We evict the expected txs that are missing from mempool.
810+
let exp_txids = graph
811+
.iter_spks_with_expected_txids(&chain, ..)
812+
.collect::<Vec<_>>();
813+
assert_eq!(exp_txids, vec![(txid_1, spk)]);
814+
let mempool = emitter
815+
.mempool()?
816+
.into_iter()
817+
.map(|(tx, _)| tx.compute_txid())
818+
.collect::<Vec<_>>();
819+
assert!(mempool.contains(&txid_2));
820+
for (txid, _) in exp_txids {
821+
if !mempool.contains(&txid) {
822+
let _ = graph.insert_evicted_at(txid, seen_at + 1);
823+
}
824+
}
825+
826+
assert!(graph
827+
.graph()
828+
.list_canonical_txs(&chain, chain_tip)
829+
.next()
830+
.is_none());
831+
832+
Ok(())
833+
}

0 commit comments

Comments
 (0)