@@ -9,32 +9,29 @@ use bdk_chain::{
99 local_chain:: CheckPoint ,
1010 BlockId ,
1111} ;
12- use bitcoincore_rpc:: {
13- bitcoincore_rpc_json:: { GetBlockTemplateModes , GetBlockTemplateRules } ,
14- RpcApi ,
15- } ;
16- use electrsd:: bitcoind:: anyhow:: Context ;
12+ use electrsd:: corepc_node:: anyhow:: Context ;
1713
1814pub use electrsd;
19- pub use electrsd:: bitcoind ;
20- pub use electrsd:: bitcoind :: anyhow ;
21- pub use electrsd:: bitcoind :: bitcoincore_rpc ;
15+ pub use electrsd:: corepc_client ;
16+ pub use electrsd:: corepc_node ;
17+ pub use electrsd:: corepc_node :: anyhow ;
2218pub use electrsd:: electrum_client;
2319use electrsd:: electrum_client:: ElectrumApi ;
20+ use serde:: { Deserialize , Serialize } ;
2421use std:: time:: Duration ;
2522
2623/// Struct for running a regtest environment with a single `bitcoind` node with an `electrs`
2724/// instance connected to it.
2825pub struct TestEnv {
29- pub bitcoind : electrsd:: bitcoind :: BitcoinD ,
26+ pub bitcoind : electrsd:: corepc_node :: Node ,
3027 pub electrsd : electrsd:: ElectrsD ,
3128}
3229
3330/// Configuration parameters.
3431#[ derive( Debug ) ]
3532pub struct Config < ' a > {
3633 /// [`bitcoind::Conf`]
37- pub bitcoind : bitcoind :: Conf < ' a > ,
34+ pub bitcoind : corepc_node :: Conf < ' a > ,
3835 /// [`electrsd::Conf`]
3936 pub electrsd : electrsd:: Conf < ' a > ,
4037}
@@ -44,7 +41,7 @@ impl Default for Config<'_> {
4441 /// which is required for testing `bdk_esplora`.
4542 fn default ( ) -> Self {
4643 Self {
47- bitcoind : bitcoind :: Conf :: default ( ) ,
44+ bitcoind : corepc_node :: Conf :: default ( ) ,
4845 electrsd : {
4946 let mut conf = electrsd:: Conf :: default ( ) ;
5047 conf. http_enabled = true ;
@@ -54,6 +51,22 @@ impl Default for Config<'_> {
5451 }
5552}
5653
54+ /// A minimal model of the result of "getblocktemplate", with only used fields
55+ #[ derive( Clone , PartialEq , Eq , Debug , Deserialize , Serialize ) ]
56+ pub struct GetBlockTemplateResult {
57+ /// The compressed difficulty in hexadecimal
58+ pub bits : String ,
59+ /// The previous block hash the current template is mining on
60+ #[ serde( rename = "hash" ) ]
61+ pub previous_block_hash : bdk_chain:: bitcoin:: BlockHash ,
62+ /// The height of the block we will be mining: `current height + 1`
63+ pub height : u64 ,
64+ /// The minimum timestamp appropriate for the next block time. Expressed as
65+ /// UNIX timestamp.
66+ #[ serde( rename = "mintime" ) ]
67+ pub min_time : u64 ,
68+ }
69+
5770impl TestEnv {
5871 /// Construct a new [`TestEnv`] instance with the default configuration used by BDK.
5972 pub fn new ( ) -> anyhow:: Result < Self > {
@@ -64,11 +77,11 @@ impl TestEnv {
6477 pub fn new_with_config ( config : Config ) -> anyhow:: Result < Self > {
6578 let bitcoind_exe = match std:: env:: var ( "BITCOIND_EXE" ) {
6679 Ok ( path) => path,
67- Err ( _) => bitcoind :: downloaded_exe_path ( ) . context (
80+ Err ( _) => corepc_node :: downloaded_exe_path ( ) . context (
6881 "you need to provide an env var BITCOIND_EXE or specify a bitcoind version feature" ,
6982 ) ?,
7083 } ;
71- let bitcoind = bitcoind :: BitcoinD :: with_conf ( bitcoind_exe, & config. bitcoind ) ?;
84+ let bitcoind = corepc_node :: Node :: with_conf ( bitcoind_exe, & config. bitcoind ) ?;
7285
7386 let electrs_exe = match std:: env:: var ( "ELECTRS_EXE" ) {
7487 Ok ( path) => path,
@@ -86,7 +99,7 @@ impl TestEnv {
8699 }
87100
88101 /// Exposes the [`RpcApi`] calls from [`bitcoincore_rpc`].
89- pub fn rpc_client ( & self ) -> & impl RpcApi {
102+ pub fn rpc_client ( & self ) -> & corepc_node :: Client {
90103 & self . bitcoind . client
91104 }
92105
@@ -117,26 +130,28 @@ impl TestEnv {
117130 ) -> anyhow:: Result < Vec < BlockHash > > {
118131 let coinbase_address = match address {
119132 Some ( address) => address,
120- None => self
121- . bitcoind
122- . client
123- . get_new_address ( None , None ) ?
124- . assume_checked ( ) ,
133+ None => self . bitcoind . client . new_address ( ) ?,
125134 } ;
126135 let block_hashes = self
127136 . bitcoind
128137 . client
129- . generate_to_address ( count as _ , & coinbase_address) ?;
138+ . generate_to_address ( count as _ , & coinbase_address) ?
139+ . into_model ( ) ?
140+ . 0 ;
130141 Ok ( block_hashes)
131142 }
132143
144+ fn get_block_template ( & self ) -> anyhow:: Result < GetBlockTemplateResult > {
145+ let argument = r#"{"mode": "template", "rules": "segwit", "capabilities": []}"# ;
146+ Ok ( self . bitcoind . client . call :: < GetBlockTemplateResult > (
147+ "getblocktemplate" ,
148+ & [ corepc_node:: serde_json:: to_value ( argument) ?] ,
149+ ) ?)
150+ }
151+
133152 /// Mine a block that is guaranteed to be empty even with transactions in the mempool.
134153 pub fn mine_empty_block ( & self ) -> anyhow:: Result < ( usize , BlockHash ) > {
135- let bt = self . bitcoind . client . get_block_template (
136- GetBlockTemplateModes :: Template ,
137- & [ GetBlockTemplateRules :: SegWit ] ,
138- & [ ] ,
139- ) ?;
154+ let bt = self . get_block_template ( ) ?;
140155
141156 let txdata = vec ! [ Transaction {
142157 version: transaction:: Version :: ONE ,
@@ -145,7 +160,7 @@ impl TestEnv {
145160 previous_output: bdk_chain:: bitcoin:: OutPoint :: default ( ) ,
146161 script_sig: ScriptBuf :: builder( )
147162 . push_int( bt. height as _)
148- // randomn number so that re-mining creates unique block
163+ // random number so that re-mining creates unique block
149164 . push_int( random( ) )
150165 . into_script( ) ,
151166 sequence: bdk_chain:: bitcoin:: Sequence :: default ( ) ,
@@ -157,11 +172,11 @@ impl TestEnv {
157172 } ] ,
158173 } ] ;
159174
160- let bits: [ u8 ; 4 ] = bt
161- . bits
162- . clone ( )
163- . try_into ( )
164- . expect ( "rpc provided us with invalid bits" ) ;
175+ let bits: [ u8 ; 4 ] =
176+ bdk_chain :: bitcoin :: consensus :: encode :: deserialize_hex :: < Vec < u8 > > ( & bt . bits ) ?
177+ . clone ( )
178+ . try_into ( )
179+ . expect ( "rpc provided us with invalid bits" ) ;
165180
166181 let mut block = Block {
167182 header : Header {
@@ -184,7 +199,15 @@ impl TestEnv {
184199 }
185200 }
186201
187- self . bitcoind . client . submit_block ( & block) ?;
202+ let block_hex: String = bdk_chain:: bitcoin:: consensus:: encode:: serialize_hex ( & block) ;
203+ match self . bitcoind . client . call (
204+ "submitblock" ,
205+ & [ corepc_node:: serde_json:: to_value ( block_hex) ?] ,
206+ ) {
207+ Ok ( corepc_node:: serde_json:: Value :: Null ) => Ok ( ( ) ) ,
208+ Ok ( res) => Err ( corepc_client:: client_sync:: Error :: Returned ( res. to_string ( ) ) ) ,
209+ Err ( err) => Err ( err. into ( ) ) ,
210+ } ?;
188211 Ok ( ( bt. height as usize , block. block_hash ( ) ) )
189212 }
190213
@@ -235,18 +258,16 @@ impl TestEnv {
235258
236259 /// Invalidate a number of blocks of a given size `count`.
237260 pub fn invalidate_blocks ( & self , count : usize ) -> anyhow:: Result < ( ) > {
238- let mut hash = self . bitcoind . client . get_best_block_hash ( ) ?;
261+ let mut hash = self . bitcoind . client . get_best_block_hash ( ) ?. block_hash ( ) ? ;
239262 for _ in 0 ..count {
240- let prev_hash = self
241- . bitcoind
242- . client
243- . get_block_info ( & hash) ?
244- . previousblockhash ;
245- self . bitcoind . client . invalidate_block ( & hash) ?;
246- match prev_hash {
247- Some ( prev_hash) => hash = prev_hash,
248- None => break ,
249- }
263+ let prev_hash = self . bitcoind . client . get_block ( hash) ?. header . prev_blockhash ;
264+ self . bitcoind . client . invalidate_block ( hash) ?;
265+ hash = prev_hash
266+ // TODO: (@leonardo) It requires a double check if there is any side-effect with this break removal.
267+ // match prev_hash {
268+ // Some(prev_hash) => hash = prev_hash,
269+ // None => break,
270+ // }
250271 }
251272 Ok ( ( ) )
252273 }
@@ -287,7 +308,8 @@ impl TestEnv {
287308 let txid = self
288309 . bitcoind
289310 . client
290- . send_to_address ( address, amount, None , None , None , None , None , None ) ?;
311+ . send_to_address ( address, amount) ?
312+ . txid ( ) ?;
291313 Ok ( txid)
292314 }
293315
@@ -298,14 +320,19 @@ impl TestEnv {
298320 . client
299321 . get_block_hash ( height as u64 )
300322 . ok ( )
301- . map ( |hash| BlockId { height, hash } )
323+ . map ( |get_block_hash| {
324+ let hash = get_block_hash
325+ . block_hash ( )
326+ . expect ( "should `successfully convert to `BlockHash` from `GetBlockHash`" ) ;
327+ BlockId { height, hash }
328+ } )
302329 } ) )
303330 . expect ( "must craft tip" )
304331 }
305332
306333 /// Get the genesis hash of the blockchain.
307334 pub fn genesis_hash ( & self ) -> anyhow:: Result < BlockHash > {
308- let hash = self . bitcoind . client . get_block_hash ( 0 ) ?;
335+ let hash = self . bitcoind . client . get_block_hash ( 0 ) ?. into_model ( ) ? . 0 ;
309336 Ok ( hash)
310337 }
311338}
@@ -314,7 +341,7 @@ impl TestEnv {
314341mod test {
315342 use crate :: TestEnv ;
316343 use core:: time:: Duration ;
317- use electrsd:: bitcoind :: { anyhow:: Result , bitcoincore_rpc :: RpcApi } ;
344+ use electrsd:: corepc_node :: anyhow:: Result ;
318345
319346 /// This checks that reorgs initiated by `bitcoind` is detected by our `electrsd` instance.
320347 #[ test]
@@ -324,15 +351,15 @@ mod test {
324351 // Mine some blocks.
325352 env. mine_blocks ( 101 , None ) ?;
326353 env. wait_until_electrum_sees_block ( Duration :: from_secs ( 6 ) ) ?;
327- let height = env. bitcoind . client . get_block_count ( ) ?;
354+ let height = env. bitcoind . client . get_block_count ( ) ?. into_model ( ) . 0 ;
328355 let blocks = ( 0 ..=height)
329356 . map ( |i| env. bitcoind . client . get_block_hash ( i) )
330357 . collect :: < Result < Vec < _ > , _ > > ( ) ?;
331358
332359 // Perform reorg on six blocks.
333360 env. reorg ( 6 ) ?;
334361 env. wait_until_electrum_sees_block ( Duration :: from_secs ( 6 ) ) ?;
335- let reorged_height = env. bitcoind . client . get_block_count ( ) ?;
362+ let reorged_height = env. bitcoind . client . get_block_count ( ) ?. into_model ( ) . 0 ;
336363 let reorged_blocks = ( 0 ..=height)
337364 . map ( |i| env. bitcoind . client . get_block_hash ( i) )
338365 . collect :: < Result < Vec < _ > , _ > > ( ) ?;
0 commit comments