Skip to content

Commit b4c8c6a

Browse files
committed
Merge #1826: deps(bdk_testenv)!: bump electrsd to 0.36.1
303cc70 docs(testenv): fix rustdocs for `corepc` types (valued mammal) 9393832 build(testenv): `mine_empty_blocks` requires `std` feature (valued mammal) cbad92e test(bdk_esplora,bdk_electrum): update to new `bdk_testenv` APIs (Leonardo Lima) b78a9de test(bdk_chain): update to new `bdk_testenv` APIs (Leonardo Lima) f393145 test(bdk_bitcoind_rpc): update it's tests to use `ClientExt` (valued mammal) c3f7257 deps(bdk_testenv): bump `electrsd` to `0.36.1` (Leonardo Lima) Pull request description: partially addresses #1949 ### Description Upgrades the `electrsd` version from `0.28.0` to `0.36.1`, migrating from old `bitcoind` to `corepc-node` and using the `corepc-node_28_2` feature. Updates the `bitcoind` client type for `TestEnv`, and its internal methods. Also, updates: bdk_bitcoind_rpc, bdk_esplora, bdk_electrum usage of `bdk_testenv` and `TestEnv`. ### Notes to the reviewers As we are upgrading to the latest `electrsd`, we can drop for now the pinning for `home` in the MSRV step. ### Changelog notice ``` ### Added - deps(bdk_testenv): introduces `bitcoin and it's `bitcoin/rand-std` feature under `bdk_testenv/std`. - test(bdk_bitcoind_rpc): introcuce `ClientExt` trait to use custom testing RPC client with current `bitcoincore-rpc` one. ### Changed - deps(bdk_testenv)!: bump `electrsd` to `0.36.1`. - deps(bdk_testenv): updates `electrsd` feature to `corepc-node_28_2`. - test(bdk_bitcoind_rpc): update all tests to use new `ClientExt` trait when building the `Emitter`. - test(bdk_chain): update all tests to use new `bdk_testenv`, `electrsd` and `corepc-node` APIs. - test(bdk_esplora, bdk_electrum): update all tests to use new `bdk_testenv`, `electrsd` and `corepc-node` APIs. - build(testenv): feature gate `mine_empty_blocks`, `reorg_empty_blocks` behind `std` feature. ``` ### Checklists #### All Submissions: * [x] I've signed all my commits * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md) * [x] I ran `cargo fmt` and `cargo clippy` before committing #### New Features: * [x] I've added tests for the new feature * [x] I've added docs for the new feature ACKs for top commit: ValuedMammal: ACK 303cc70 luisschwab: ACK 303cc70 Tree-SHA512: 721a328a09d8bf75e6e2903dd2e244fdd211895c3e1a1b9aa5c6ee256ea1b07be9ab25db9a7ffcff88d94e7b05cdd06580598fd09292f5a17471583eb1252435
2 parents 66f3f70 + 303cc70 commit b4c8c6a

File tree

15 files changed

+529
-471
lines changed

15 files changed

+529
-471
lines changed

ci/pin-msrv.sh

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,4 @@ set -euo pipefail
1010
# cargo clean
1111
# rustup override set 1.85.0
1212

13-
cargo update -p home --precise "0.5.11"
14-
cargo update -p time --precise "0.3.45"
15-
cargo update -p time-core --precise "0.1.7"
13+
# e.g cargo update -p home --precise "0.5.11"

crates/bitcoind_rpc/src/lib.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ impl BitcoindRpcErrorExt for bitcoincore_rpc::Error {
399399
#[cfg(test)]
400400
#[cfg_attr(coverage_nightly, coverage(off))]
401401
mod test {
402-
use crate::{bitcoincore_rpc::RpcApi, Emitter, NO_EXPECTED_MEMPOOL_TXS};
402+
use crate::{Emitter, NO_EXPECTED_MEMPOOL_TXS};
403403
use bdk_chain::local_chain::LocalChain;
404404
use bdk_testenv::{anyhow, TestEnv};
405405
use bitcoin::{hashes::Hash, Address, Amount, ScriptBuf, Txid, WScriptHash};
@@ -408,14 +408,15 @@ mod test {
408408
#[test]
409409
fn test_expected_mempool_txids_accumulate_and_remove() -> anyhow::Result<()> {
410410
let env = TestEnv::new()?;
411-
let chain = LocalChain::from_genesis(env.rpc_client().get_block_hash(0)?).0;
411+
let (chain, _) = LocalChain::from_genesis(env.genesis_hash()?);
412412
let chain_tip = chain.tip();
413-
let mut emitter = Emitter::new(
414-
env.rpc_client(),
415-
chain_tip.clone(),
416-
1,
417-
NO_EXPECTED_MEMPOOL_TXS,
418-
);
413+
414+
let rpc_client = bitcoincore_rpc::Client::new(
415+
&env.bitcoind.rpc_url(),
416+
bitcoincore_rpc::Auth::CookieFile(env.bitcoind.params.cookie_file.clone()),
417+
)?;
418+
419+
let mut emitter = Emitter::new(&rpc_client, chain_tip.clone(), 1, NO_EXPECTED_MEMPOOL_TXS);
419420

420421
env.mine_blocks(100, None)?;
421422
while emitter.next_block()?.is_some() {}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
use bdk_testenv::anyhow;
2+
use bdk_testenv::TestEnv;
3+
4+
/// This trait is used for testing. It allows creating a new [`bitcoincore_rpc::Client`] connected
5+
/// to the instance of bitcoind running in the test environment. This way the `TestEnv` and the
6+
/// `Emitter` aren't required to share the same client. In the future when we no longer depend on
7+
/// `bitcoincore-rpc`, this can be updated to return the production client that is used by BDK.
8+
pub trait ClientExt {
9+
/// Creates a new [`bitcoincore_rpc::Client`] connected to the current node instance.
10+
fn get_rpc_client(&self) -> anyhow::Result<bitcoincore_rpc::Client>;
11+
}
12+
13+
impl ClientExt for TestEnv {
14+
fn get_rpc_client(&self) -> anyhow::Result<bitcoincore_rpc::Client> {
15+
Ok(bitcoincore_rpc::Client::new(
16+
&self.bitcoind.rpc_url(),
17+
bitcoincore_rpc::Auth::CookieFile(self.bitcoind.params.cookie_file.clone()),
18+
)?)
19+
}
20+
}

crates/bitcoind_rpc/tests/test_emitter.rs

Lines changed: 82 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,16 @@ use bdk_chain::{
77
spk_txout::SpkTxOutIndex,
88
Balance, BlockId, CanonicalizationParams, IndexedTxGraph, Merge,
99
};
10-
use bdk_testenv::{anyhow, TestEnv};
11-
use bitcoin::{hashes::Hash, Block, Network, OutPoint, ScriptBuf, WScriptHash};
12-
use bitcoincore_rpc::RpcApi;
10+
use bdk_testenv::{
11+
anyhow,
12+
corepc_node::{Input, Output},
13+
TestEnv,
14+
};
15+
use bitcoin::{hashes::Hash, Block, Network, ScriptBuf, WScriptHash};
16+
17+
use crate::common::ClientExt;
18+
19+
mod common;
1320

1421
/// Ensure that blocks are emitted in order even after reorg.
1522
///
@@ -20,21 +27,18 @@ use bitcoincore_rpc::RpcApi;
2027
#[test]
2128
pub fn test_sync_local_chain() -> anyhow::Result<()> {
2229
let env = TestEnv::new()?;
23-
let network_tip = env.rpc_client().get_block_count()?;
24-
let (mut local_chain, _) = LocalChain::from_genesis(env.rpc_client().get_block_hash(0)?);
25-
let mut emitter = Emitter::new(
26-
env.rpc_client(),
27-
local_chain.tip(),
28-
0,
29-
NO_EXPECTED_MEMPOOL_TXS,
30-
);
30+
let network_tip = env.rpc_client().get_block_count()?.into_model().0;
31+
let (mut local_chain, _) = LocalChain::from_genesis(env.genesis_hash()?);
32+
33+
let client = ClientExt::get_rpc_client(&env)?;
34+
let mut emitter = Emitter::new(&client, local_chain.tip(), 0, NO_EXPECTED_MEMPOOL_TXS);
3135

3236
// Mine some blocks and return the actual block hashes.
3337
// Because initializing `ElectrsD` already mines some blocks, we must include those too when
3438
// returning block hashes.
3539
let exp_hashes = {
3640
let mut hashes = (0..=network_tip)
37-
.map(|height| env.rpc_client().get_block_hash(height))
41+
.map(|height| env.get_block_hash(height))
3842
.collect::<Result<Vec<_>, _>>()?;
3943
hashes.extend(env.mine_blocks(101 - network_tip as usize, None)?);
4044
hashes
@@ -140,19 +144,24 @@ fn test_into_tx_graph() -> anyhow::Result<()> {
140144
let addr_0 = env
141145
.rpc_client()
142146
.get_new_address(None, None)?
147+
.address()?
143148
.assume_checked();
149+
144150
let addr_1 = env
145151
.rpc_client()
146152
.get_new_address(None, None)?
153+
.address()?
147154
.assume_checked();
155+
148156
let addr_2 = env
149157
.rpc_client()
150158
.get_new_address(None, None)?
159+
.address()?
151160
.assume_checked();
152161

153162
env.mine_blocks(101, None)?;
154163

155-
let (mut chain, _) = LocalChain::from_genesis(env.rpc_client().get_block_hash(0)?);
164+
let (mut chain, _) = LocalChain::from_genesis(env.genesis_hash()?);
156165
let mut indexed_tx_graph = IndexedTxGraph::<BlockId, _>::new({
157166
let mut index = SpkTxOutIndex::<usize>::default();
158167
index.insert_spk(0, addr_0.script_pubkey());
@@ -161,7 +170,8 @@ fn test_into_tx_graph() -> anyhow::Result<()> {
161170
index
162171
});
163172

164-
let emitter = &mut Emitter::new(env.rpc_client(), chain.tip(), 0, NO_EXPECTED_MEMPOOL_TXS);
173+
let client = ClientExt::get_rpc_client(&env)?;
174+
let emitter = &mut Emitter::new(&client, chain.tip(), 0, NO_EXPECTED_MEMPOOL_TXS);
165175

166176
while let Some(emission) = emitter.next_block()? {
167177
let height = emission.block_height();
@@ -174,16 +184,11 @@ fn test_into_tx_graph() -> anyhow::Result<()> {
174184
let exp_txids = {
175185
let mut txids = BTreeSet::new();
176186
for _ in 0..3 {
177-
txids.insert(env.rpc_client().send_to_address(
178-
&addr_0,
179-
Amount::from_sat(10_000),
180-
None,
181-
None,
182-
None,
183-
None,
184-
None,
185-
None,
186-
)?);
187+
txids.insert(
188+
env.rpc_client()
189+
.send_to_address(&addr_0, Amount::from_sat(10_000))?
190+
.txid()?,
191+
);
187192
}
188193
txids
189194
};
@@ -210,7 +215,10 @@ fn test_into_tx_graph() -> anyhow::Result<()> {
210215

211216
// mine a block that confirms the 3 txs
212217
let exp_block_hash = env.mine_blocks(1, None)?[0];
213-
let exp_block_height = env.rpc_client().get_block_info(&exp_block_hash)?.height as u32;
218+
let exp_block_height = env
219+
.rpc_client()
220+
.get_block_verbose_one(exp_block_hash)?
221+
.height as u32;
214222
let exp_anchors = exp_txids
215223
.iter()
216224
.map({
@@ -250,9 +258,11 @@ fn ensure_block_emitted_after_reorg_is_at_reorg_height() -> anyhow::Result<()> {
250258
const CHAIN_TIP_HEIGHT: usize = 110;
251259

252260
let env = TestEnv::new()?;
261+
262+
let client = ClientExt::get_rpc_client(&env)?;
253263
let mut emitter = Emitter::new(
254-
env.rpc_client(),
255-
CheckPoint::new(0, env.rpc_client().get_block_hash(0)?),
264+
&client,
265+
CheckPoint::new(0, env.genesis_hash()?),
256266
EMITTER_START_HEIGHT as _,
257267
NO_EXPECTED_MEMPOOL_TXS,
258268
);
@@ -325,9 +335,11 @@ fn tx_can_become_unconfirmed_after_reorg() -> anyhow::Result<()> {
325335
const SEND_AMOUNT: Amount = Amount::from_sat(10_000);
326336

327337
let env = TestEnv::new()?;
338+
339+
let client = ClientExt::get_rpc_client(&env)?;
328340
let mut emitter = Emitter::new(
329-
env.rpc_client(),
330-
CheckPoint::new(0, env.rpc_client().get_block_hash(0)?),
341+
&client,
342+
CheckPoint::new(0, env.genesis_hash()?),
331343
0,
332344
NO_EXPECTED_MEMPOOL_TXS,
333345
);
@@ -336,12 +348,13 @@ fn tx_can_become_unconfirmed_after_reorg() -> anyhow::Result<()> {
336348
let addr_to_mine = env
337349
.rpc_client()
338350
.get_new_address(None, None)?
351+
.address()?
339352
.assume_checked();
340353
let spk_to_track = ScriptBuf::new_p2wsh(&WScriptHash::all_zeros());
341354
let addr_to_track = Address::from_script(&spk_to_track, Network::Regtest)?;
342355

343356
// setup receiver
344-
let (mut recv_chain, _) = LocalChain::from_genesis(env.rpc_client().get_block_hash(0)?);
357+
let (mut recv_chain, _) = LocalChain::from_genesis(env.genesis_hash()?);
345358
let mut recv_graph = IndexedTxGraph::<BlockId, _>::new({
346359
let mut recv_index = SpkTxOutIndex::default();
347360
recv_index.insert_spk((), spk_to_track.clone());
@@ -358,14 +371,16 @@ fn tx_can_become_unconfirmed_after_reorg() -> anyhow::Result<()> {
358371
// lock outputs that send to `addr_to_track`
359372
let outpoints_to_lock = env
360373
.rpc_client()
361-
.get_transaction(&txid, None)?
362-
.transaction()?
374+
.get_transaction(txid)?
375+
.into_model()?
376+
.tx
363377
.output
364378
.into_iter()
365379
.enumerate()
366380
.filter(|(_, txo)| txo.script_pubkey == spk_to_track)
367-
.map(|(vout, _)| OutPoint::new(txid, vout as _))
381+
.map(|(vout, _)| (txid, vout as u32))
368382
.collect::<Vec<_>>();
383+
369384
env.rpc_client().lock_unspent(&outpoints_to_lock)?;
370385

371386
let _ = env.mine_blocks(1, None)?;
@@ -413,9 +428,11 @@ fn mempool_avoids_re_emission() -> anyhow::Result<()> {
413428
const MEMPOOL_TX_COUNT: usize = 2;
414429

415430
let env = TestEnv::new()?;
431+
432+
let client = ClientExt::get_rpc_client(&env)?;
416433
let mut emitter = Emitter::new(
417-
env.rpc_client(),
418-
CheckPoint::new(0, env.rpc_client().get_block_hash(0)?),
434+
&client,
435+
CheckPoint::new(0, env.genesis_hash()?),
419436
0,
420437
NO_EXPECTED_MEMPOOL_TXS,
421438
);
@@ -424,6 +441,7 @@ fn mempool_avoids_re_emission() -> anyhow::Result<()> {
424441
let addr = env
425442
.rpc_client()
426443
.get_new_address(None, None)?
444+
.address()?
427445
.assume_checked();
428446
env.mine_blocks(BLOCKS_TO_MINE, Some(addr.clone()))?;
429447
while emitter.next_block()?.is_some() {}
@@ -482,10 +500,11 @@ fn no_agreement_point() -> anyhow::Result<()> {
482500

483501
let env = TestEnv::new()?;
484502

503+
let client = ClientExt::get_rpc_client(&env)?;
485504
// start height is 99
486505
let mut emitter = Emitter::new(
487-
env.rpc_client(),
488-
CheckPoint::new(0, env.rpc_client().get_block_hash(0)?),
506+
&client,
507+
CheckPoint::new(0, env.genesis_hash()?),
489508
(PREMINE_COUNT - 2) as u32,
490509
NO_EXPECTED_MEMPOOL_TXS,
491510
);
@@ -507,12 +526,12 @@ fn no_agreement_point() -> anyhow::Result<()> {
507526
let block_hash_100a = block_header_100a.block_hash();
508527

509528
// get hash for block 101a
510-
let block_hash_101a = env.rpc_client().get_block_hash(101)?;
529+
let block_hash_101a = env.rpc_client().get_block_hash(101)?.block_hash()?;
511530

512531
// invalidate blocks 99a, 100a, 101a
513-
env.rpc_client().invalidate_block(&block_hash_99a)?;
514-
env.rpc_client().invalidate_block(&block_hash_100a)?;
515-
env.rpc_client().invalidate_block(&block_hash_101a)?;
532+
env.rpc_client().invalidate_block(block_hash_99a)?;
533+
env.rpc_client().invalidate_block(block_hash_100a)?;
534+
env.rpc_client().invalidate_block(block_hash_101a)?;
516535

517536
// mine new blocks 99b, 100b, 101b
518537
env.mine_blocks(3, None)?;
@@ -542,13 +561,11 @@ fn no_agreement_point() -> anyhow::Result<()> {
542561
#[test]
543562
fn test_expect_tx_evicted() -> anyhow::Result<()> {
544563
use bdk_bitcoind_rpc::bitcoincore_rpc::bitcoin;
545-
use bdk_bitcoind_rpc::bitcoincore_rpc::bitcoincore_rpc_json::CreateRawTransactionInput;
546564
use bdk_chain::miniscript;
547565
use bdk_chain::spk_txout::SpkTxOutIndex;
548566
use bitcoin::constants::genesis_block;
549567
use bitcoin::secp256k1::Secp256k1;
550568
use bitcoin::Network;
551-
use std::collections::HashMap;
552569
let env = TestEnv::new()?;
553570

554571
let s = bdk_testenv::utils::DESCRIPTORS[0];
@@ -570,12 +587,10 @@ fn test_expect_tx_evicted() -> anyhow::Result<()> {
570587
&Address::from_script(&spk, Network::Regtest)?,
571588
Amount::ONE_BTC,
572589
)?;
573-
let tx_1 = env
574-
.rpc_client()
575-
.get_transaction(&txid_1, None)?
576-
.transaction()?;
590+
let tx_1 = env.rpc_client().get_transaction(txid_1)?.into_model()?.tx;
577591

578-
let mut emitter = Emitter::new(env.rpc_client(), chain.tip(), 1, core::iter::once(tx_1));
592+
let client = ClientExt::get_rpc_client(&env)?;
593+
let mut emitter = Emitter::new(&client, chain.tip(), 1, core::iter::once(tx_1));
579594
while let Some(emission) = emitter.next_block()? {
580595
let height = emission.block_height();
581596
chain.apply_header(&emission.block.header, height)?;
@@ -592,25 +607,28 @@ fn test_expect_tx_evicted() -> anyhow::Result<()> {
592607

593608
// Get `prevout` from core.
594609
let core = env.rpc_client();
595-
let tx1 = &core.get_raw_transaction(&txid_1, None)?;
610+
let tx1 = core.get_transaction(txid_1)?.into_model()?.tx;
596611
let txin = &tx1.input[0];
597612
let op = txin.previous_output;
598613

599614
// Create `tx1b` using the previous output from tx1.
600-
let utxo = CreateRawTransactionInput {
615+
let utxo = Input {
601616
txid: op.txid,
602-
vout: op.vout,
617+
vout: op.vout as u64,
603618
sequence: None,
604619
};
605-
let addr = core.get_new_address(None, None)?.assume_checked();
606-
let tx = core.create_raw_transaction(
607-
&[utxo],
608-
&HashMap::from([(addr.to_string(), Amount::from_btc(49.99)?)]),
609-
None,
610-
None,
611-
)?;
612-
let res = core.sign_raw_transaction_with_wallet(&tx, None, None)?;
613-
let tx1b = res.transaction()?;
620+
621+
let addr = core
622+
.get_new_address(None, None)?
623+
.address()?
624+
.assume_checked();
625+
626+
let outputs = [Output::new(addr, Amount::from_btc(49.99)?)];
627+
let tx = core
628+
.create_raw_transaction(&[utxo], &outputs)?
629+
.into_model()?
630+
.0;
631+
let tx1b = core.sign_raw_transaction_with_wallet(&tx)?.into_model()?.tx;
614632

615633
// Send the tx.
616634
let _txid_2 = core.send_raw_transaction(&tx1b)?;
@@ -651,11 +669,13 @@ fn detect_new_mempool_txs() -> anyhow::Result<()> {
651669
let addr = env
652670
.rpc_client()
653671
.get_new_address(None, None)?
672+
.address()?
654673
.require_network(Network::Regtest)?;
655674

675+
let client = ClientExt::get_rpc_client(&env)?;
656676
let mut emitter = Emitter::new(
657-
env.rpc_client(),
658-
CheckPoint::new(0, env.rpc_client().get_block_hash(0)?),
677+
&client,
678+
CheckPoint::new(0, env.genesis_hash()?),
659679
0,
660680
NO_EXPECTED_MEMPOOL_TXS,
661681
);

0 commit comments

Comments
 (0)