Skip to content

Commit 12403a1

Browse files
committed
feat: added electrsd support for TestEnv
Added `electrsd` support so that `TestEnv` can serve `esplora` and `electrum`.
1 parent 0be5338 commit 12403a1

File tree

3 files changed

+118
-64
lines changed

3 files changed

+118
-64
lines changed

crates/bitcoind_rpc/tests/test_emitter.rs

Lines changed: 66 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,23 @@ fn block_to_chain_update(block: &bitcoin::Block, height: u32) -> local_chain::Up
4343
pub fn test_sync_local_chain() -> anyhow::Result<()> {
4444
let env = TestEnv::new()?;
4545
let mut local_chain = LocalChain::default();
46-
let mut emitter = Emitter::from_height(&env.client, 0);
46+
let tip = env.rpc_client().get_block_count()?;
47+
let mut emitter = Emitter::from_height(env.rpc_client(), tip as u32);
4748

4849
// mine some blocks and returned the actual block hashes
4950
let exp_hashes = {
50-
let mut hashes = vec![env.client.get_block_hash(0)?]; // include genesis block
51-
hashes.extend(env.mine_blocks(101, None)?);
51+
let mut hashes = (0..=tip)
52+
.map(|height| env.rpc_client().get_block_hash(height))
53+
.collect::<Result<Vec<_>, _>>()?; // includes genesis block
54+
hashes.extend(env.mine_blocks(101 - tip as usize, None, &env.bitcoind)?);
5255
hashes
5356
};
5457

58+
(0..tip).for_each(|height| {
59+
let changeset = BTreeMap::from([(height as u32, Some(exp_hashes[height as usize]))]);
60+
local_chain.apply_changeset(&changeset);
61+
});
62+
5563
// see if the emitter outputs the right blocks
5664
println!("first sync:");
5765
while let Some((height, block)) = emitter.next_block()? {
@@ -141,13 +149,22 @@ fn test_into_tx_graph() -> anyhow::Result<()> {
141149
let env = TestEnv::new()?;
142150

143151
println!("getting new addresses!");
144-
let addr_0 = env.client.get_new_address(None, None)?.assume_checked();
145-
let addr_1 = env.client.get_new_address(None, None)?.assume_checked();
146-
let addr_2 = env.client.get_new_address(None, None)?.assume_checked();
152+
let addr_0 = env
153+
.rpc_client()
154+
.get_new_address(None, None)?
155+
.assume_checked();
156+
let addr_1 = env
157+
.rpc_client()
158+
.get_new_address(None, None)?
159+
.assume_checked();
160+
let addr_2 = env
161+
.rpc_client()
162+
.get_new_address(None, None)?
163+
.assume_checked();
147164
println!("got new addresses!");
148165

149166
println!("mining block!");
150-
env.mine_blocks(101, None)?;
167+
env.mine_blocks(101, None, &env.bitcoind)?;
151168
println!("mined blocks!");
152169

153170
let mut chain = LocalChain::default();
@@ -159,7 +176,7 @@ fn test_into_tx_graph() -> anyhow::Result<()> {
159176
index
160177
});
161178

162-
let emitter = &mut Emitter::from_height(&env.client, 0);
179+
let emitter = &mut Emitter::from_height(env.rpc_client(), 0);
163180

164181
while let Some((height, block)) = emitter.next_block()? {
165182
let _ = chain.apply_update(block_to_chain_update(&block, height))?;
@@ -171,7 +188,7 @@ fn test_into_tx_graph() -> anyhow::Result<()> {
171188
let exp_txids = {
172189
let mut txids = BTreeSet::new();
173190
for _ in 0..3 {
174-
txids.insert(env.client.send_to_address(
191+
txids.insert(env.rpc_client().send_to_address(
175192
&addr_0,
176193
Amount::from_sat(10_000),
177194
None,
@@ -206,8 +223,8 @@ fn test_into_tx_graph() -> anyhow::Result<()> {
206223
}
207224

208225
// mine a block that confirms the 3 txs
209-
let exp_block_hash = env.mine_blocks(1, None)?[0];
210-
let exp_block_height = env.client.get_block_info(&exp_block_hash)?.height as u32;
226+
let exp_block_hash = env.mine_blocks(1, None, &env.bitcoind)?[0];
227+
let exp_block_height = env.rpc_client().get_block_info(&exp_block_hash)?.height as u32;
211228
let exp_anchors = exp_txids
212229
.iter()
213230
.map({
@@ -247,9 +264,9 @@ fn ensure_block_emitted_after_reorg_is_at_reorg_height() -> anyhow::Result<()> {
247264
const CHAIN_TIP_HEIGHT: usize = 110;
248265

249266
let env = TestEnv::new()?;
250-
let mut emitter = Emitter::from_height(&env.client, EMITTER_START_HEIGHT as _);
267+
let mut emitter = Emitter::from_height(env.rpc_client(), EMITTER_START_HEIGHT as _);
251268

252-
env.mine_blocks(CHAIN_TIP_HEIGHT, None)?;
269+
env.mine_blocks(CHAIN_TIP_HEIGHT, None, &env.bitcoind)?;
253270
while emitter.next_header()?.is_some() {}
254271

255272
for reorg_count in 1..=10 {
@@ -315,10 +332,13 @@ fn tx_can_become_unconfirmed_after_reorg() -> anyhow::Result<()> {
315332
const SEND_AMOUNT: Amount = Amount::from_sat(10_000);
316333

317334
let env = TestEnv::new()?;
318-
let mut emitter = Emitter::from_height(&env.client, 0);
335+
let mut emitter = Emitter::from_height(env.rpc_client(), 0);
319336

320337
// setup addresses
321-
let addr_to_mine = env.client.get_new_address(None, None)?.assume_checked();
338+
let addr_to_mine = env
339+
.rpc_client()
340+
.get_new_address(None, None)?
341+
.assume_checked();
322342
let spk_to_track = ScriptBuf::new_v0_p2wsh(&WScriptHash::all_zeros());
323343
let addr_to_track = Address::from_script(&spk_to_track, bitcoin::Network::Regtest)?;
324344

@@ -331,15 +351,15 @@ fn tx_can_become_unconfirmed_after_reorg() -> anyhow::Result<()> {
331351
});
332352

333353
// mine and sync receiver up to tip
334-
env.mine_blocks(PREMINE_COUNT, Some(addr_to_mine))?;
354+
env.mine_blocks(PREMINE_COUNT, Some(addr_to_mine), &env.bitcoind)?;
335355

336356
// create transactions that are tracked by our receiver
337357
for _ in 0..ADDITIONAL_COUNT {
338358
let txid = env.send(&addr_to_track, SEND_AMOUNT)?;
339359

340360
// lock outputs that send to `addr_to_track`
341361
let outpoints_to_lock = env
342-
.client
362+
.rpc_client()
343363
.get_transaction(&txid, None)?
344364
.transaction()?
345365
.output
@@ -348,9 +368,9 @@ fn tx_can_become_unconfirmed_after_reorg() -> anyhow::Result<()> {
348368
.filter(|(_, txo)| txo.script_pubkey == spk_to_track)
349369
.map(|(vout, _)| OutPoint::new(txid, vout as _))
350370
.collect::<Vec<_>>();
351-
env.client.lock_unspent(&outpoints_to_lock)?;
371+
env.rpc_client().lock_unspent(&outpoints_to_lock)?;
352372

353-
let _ = env.mine_blocks(1, None)?;
373+
let _ = env.mine_blocks(1, None, &env.bitcoind)?;
354374
}
355375

356376
// get emitter up to tip
@@ -396,11 +416,14 @@ fn mempool_avoids_re_emission() -> anyhow::Result<()> {
396416
const MEMPOOL_TX_COUNT: usize = 2;
397417

398418
let env = TestEnv::new()?;
399-
let mut emitter = Emitter::from_height(&env.client, 0);
419+
let mut emitter = Emitter::from_height(env.rpc_client(), 0);
400420

401421
// mine blocks and sync up emitter
402-
let addr = env.client.get_new_address(None, None)?.assume_checked();
403-
env.mine_blocks(BLOCKS_TO_MINE, Some(addr.clone()))?;
422+
let addr = env
423+
.rpc_client()
424+
.get_new_address(None, None)?
425+
.assume_checked();
426+
env.mine_blocks(BLOCKS_TO_MINE, Some(addr.clone()), &env.bitcoind)?;
404427
while emitter.next_header()?.is_some() {}
405428

406429
// have some random txs in mempool
@@ -451,11 +474,14 @@ fn mempool_re_emits_if_tx_introduction_height_not_reached() -> anyhow::Result<()
451474
const MEMPOOL_TX_COUNT: usize = 21;
452475

453476
let env = TestEnv::new()?;
454-
let mut emitter = Emitter::from_height(&env.client, 0);
477+
let mut emitter = Emitter::from_height(env.rpc_client(), 0);
455478

456479
// mine blocks to get initial balance, sync emitter up to tip
457-
let addr = env.client.get_new_address(None, None)?.assume_checked();
458-
env.mine_blocks(PREMINE_COUNT, Some(addr.clone()))?;
480+
let addr = env
481+
.rpc_client()
482+
.get_new_address(None, None)?
483+
.assume_checked();
484+
env.mine_blocks(PREMINE_COUNT, Some(addr.clone()), &env.bitcoind)?;
459485
while emitter.next_header()?.is_some() {}
460486

461487
// mine blocks to introduce txs to mempool at different heights
@@ -528,11 +554,14 @@ fn mempool_during_reorg() -> anyhow::Result<()> {
528554
const PREMINE_COUNT: usize = 101;
529555

530556
let env = TestEnv::new()?;
531-
let mut emitter = Emitter::from_height(&env.client, 0);
557+
let mut emitter = Emitter::from_height(env.rpc_client(), 0);
532558

533559
// mine blocks to get initial balance
534-
let addr = env.client.get_new_address(None, None)?.assume_checked();
535-
env.mine_blocks(PREMINE_COUNT, Some(addr.clone()))?;
560+
let addr = env
561+
.rpc_client()
562+
.get_new_address(None, None)?
563+
.assume_checked();
564+
env.mine_blocks(PREMINE_COUNT, Some(addr.clone()), &env.bitcoind)?;
536565

537566
// introduce mempool tx at each block extension
538567
for _ in 0..TIP_DIFF {
@@ -549,7 +578,7 @@ fn mempool_during_reorg() -> anyhow::Result<()> {
549578
.into_iter()
550579
.map(|(tx, _)| tx.txid())
551580
.collect::<BTreeSet<_>>(),
552-
env.client
581+
env.rpc_client()
553582
.get_raw_mempool()?
554583
.into_iter()
555584
.collect::<BTreeSet<_>>(),
@@ -568,7 +597,7 @@ fn mempool_during_reorg() -> anyhow::Result<()> {
568597
// emission.
569598
// TODO: How can have have reorg logic in `TestEnv` NOT blacklast old blocks first?
570599
let tx_introductions = dbg!(env
571-
.client
600+
.rpc_client()
572601
.get_raw_mempool_verbose()?
573602
.into_iter()
574603
.map(|(txid, entry)| (txid, entry.height as usize))
@@ -643,10 +672,10 @@ fn no_agreement_point() -> anyhow::Result<()> {
643672
let env = TestEnv::new()?;
644673

645674
// start height is 99
646-
let mut emitter = Emitter::from_height(&env.client, (PREMINE_COUNT - 2) as u32);
675+
let mut emitter = Emitter::from_height(env.rpc_client(), (PREMINE_COUNT - 2) as u32);
647676

648677
// mine 101 blocks
649-
env.mine_blocks(PREMINE_COUNT, None)?;
678+
env.mine_blocks(PREMINE_COUNT, None, &env.bitcoind)?;
650679

651680
// emit block 99a
652681
let (_, block_header_99a) = emitter.next_header()?.expect("block 99a header");
@@ -658,15 +687,15 @@ fn no_agreement_point() -> anyhow::Result<()> {
658687
let block_hash_100a = block_header_100a.block_hash();
659688

660689
// get hash for block 101a
661-
let block_hash_101a = env.client.get_block_hash(101)?;
690+
let block_hash_101a = env.rpc_client().get_block_hash(101)?;
662691

663692
// invalidate blocks 99a, 100a, 101a
664-
env.client.invalidate_block(&block_hash_99a)?;
665-
env.client.invalidate_block(&block_hash_100a)?;
666-
env.client.invalidate_block(&block_hash_101a)?;
693+
env.rpc_client().invalidate_block(&block_hash_99a)?;
694+
env.rpc_client().invalidate_block(&block_hash_100a)?;
695+
env.rpc_client().invalidate_block(&block_hash_101a)?;
667696

668697
// mine new blocks 99b, 100b, 101b
669-
env.mine_blocks(3, None)?;
698+
env.mine_blocks(3, None, &env.bitcoind)?;
670699

671700
// emit block header 99b
672701
let (_, block_header_99b) = emitter.next_header()?.expect("block 99b header");

crates/testenv/Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ edition = "2021"
1010
bitcoin = { version = "0.30", default-features = false }
1111
bitcoincore-rpc = { version = "0.17" }
1212
bdk_chain = { path = "../chain", version = "0.6", default-features = false }
13-
bdk_bitcoind_rpc = { path = "../bitcoind_rpc", version = "0.1.0", default-features = false }
14-
bitcoind = { version = "0.33", features = ["25_0"] }
13+
electrsd = { version= "0.25.0", features = ["bitcoind_25_0", "esplora_a33e97e1", "legacy"] }
1514
anyhow = { version = "1" }
1615

1716
[features]

0 commit comments

Comments
 (0)