@@ -9,32 +9,29 @@ use bdk_chain::{
9
9
local_chain:: CheckPoint ,
10
10
BlockId ,
11
11
} ;
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 ;
17
13
18
14
pub 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 ;
22
18
pub use electrsd:: electrum_client;
23
19
use electrsd:: electrum_client:: ElectrumApi ;
20
+ use serde:: { Deserialize , Serialize } ;
24
21
use std:: time:: Duration ;
25
22
26
23
/// Struct for running a regtest environment with a single `bitcoind` node with an `electrs`
27
24
/// instance connected to it.
28
25
pub struct TestEnv {
29
- pub bitcoind : electrsd:: bitcoind :: BitcoinD ,
26
+ pub bitcoind : electrsd:: corepc_node :: Node ,
30
27
pub electrsd : electrsd:: ElectrsD ,
31
28
}
32
29
33
30
/// Configuration parameters.
34
31
#[ derive( Debug ) ]
35
32
pub struct Config < ' a > {
36
33
/// [`bitcoind::Conf`]
37
- pub bitcoind : bitcoind :: Conf < ' a > ,
34
+ pub bitcoind : corepc_node :: Conf < ' a > ,
38
35
/// [`electrsd::Conf`]
39
36
pub electrsd : electrsd:: Conf < ' a > ,
40
37
}
@@ -44,7 +41,7 @@ impl Default for Config<'_> {
44
41
/// which is required for testing `bdk_esplora`.
45
42
fn default ( ) -> Self {
46
43
Self {
47
- bitcoind : bitcoind :: Conf :: default ( ) ,
44
+ bitcoind : corepc_node :: Conf :: default ( ) ,
48
45
electrsd : {
49
46
let mut conf = electrsd:: Conf :: default ( ) ;
50
47
conf. http_enabled = true ;
@@ -54,6 +51,22 @@ impl Default for Config<'_> {
54
51
}
55
52
}
56
53
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
+
57
70
impl TestEnv {
58
71
/// Construct a new [`TestEnv`] instance with the default configuration used by BDK.
59
72
pub fn new ( ) -> anyhow:: Result < Self > {
@@ -64,11 +77,11 @@ impl TestEnv {
64
77
pub fn new_with_config ( config : Config ) -> anyhow:: Result < Self > {
65
78
let bitcoind_exe = match std:: env:: var ( "BITCOIND_EXE" ) {
66
79
Ok ( path) => path,
67
- Err ( _) => bitcoind :: downloaded_exe_path ( ) . context (
80
+ Err ( _) => corepc_node :: downloaded_exe_path ( ) . context (
68
81
"you need to provide an env var BITCOIND_EXE or specify a bitcoind version feature" ,
69
82
) ?,
70
83
} ;
71
- let bitcoind = bitcoind :: BitcoinD :: with_conf ( bitcoind_exe, & config. bitcoind ) ?;
84
+ let bitcoind = corepc_node :: Node :: with_conf ( bitcoind_exe, & config. bitcoind ) ?;
72
85
73
86
let electrs_exe = match std:: env:: var ( "ELECTRS_EXE" ) {
74
87
Ok ( path) => path,
@@ -86,7 +99,7 @@ impl TestEnv {
86
99
}
87
100
88
101
/// Exposes the [`RpcApi`] calls from [`bitcoincore_rpc`].
89
- pub fn rpc_client ( & self ) -> & impl RpcApi {
102
+ pub fn rpc_client ( & self ) -> & corepc_node :: Client {
90
103
& self . bitcoind . client
91
104
}
92
105
@@ -117,26 +130,28 @@ impl TestEnv {
117
130
) -> anyhow:: Result < Vec < BlockHash > > {
118
131
let coinbase_address = match address {
119
132
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 ( ) ?,
125
134
} ;
126
135
let block_hashes = self
127
136
. bitcoind
128
137
. client
129
- . generate_to_address ( count as _ , & coinbase_address) ?;
138
+ . generate_to_address ( count as _ , & coinbase_address) ?
139
+ . into_model ( ) ?
140
+ . 0 ;
130
141
Ok ( block_hashes)
131
142
}
132
143
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
+
133
152
/// Mine a block that is guaranteed to be empty even with transactions in the mempool.
134
153
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 ( ) ?;
140
155
141
156
let txdata = vec ! [ Transaction {
142
157
version: transaction:: Version :: ONE ,
@@ -145,7 +160,7 @@ impl TestEnv {
145
160
previous_output: bdk_chain:: bitcoin:: OutPoint :: default ( ) ,
146
161
script_sig: ScriptBuf :: builder( )
147
162
. 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
149
164
. push_int( random( ) )
150
165
. into_script( ) ,
151
166
sequence: bdk_chain:: bitcoin:: Sequence :: default ( ) ,
@@ -157,11 +172,11 @@ impl TestEnv {
157
172
} ] ,
158
173
} ] ;
159
174
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" ) ;
165
180
166
181
let mut block = Block {
167
182
header : Header {
@@ -184,7 +199,15 @@ impl TestEnv {
184
199
}
185
200
}
186
201
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
+ } ?;
188
211
Ok ( ( bt. height as usize , block. block_hash ( ) ) )
189
212
}
190
213
@@ -235,18 +258,16 @@ impl TestEnv {
235
258
236
259
/// Invalidate a number of blocks of a given size `count`.
237
260
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 ( ) ? ;
239
262
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
+ // }
250
271
}
251
272
Ok ( ( ) )
252
273
}
@@ -287,7 +308,8 @@ impl TestEnv {
287
308
let txid = self
288
309
. bitcoind
289
310
. client
290
- . send_to_address ( address, amount, None , None , None , None , None , None ) ?;
311
+ . send_to_address ( address, amount) ?
312
+ . txid ( ) ?;
291
313
Ok ( txid)
292
314
}
293
315
@@ -298,14 +320,19 @@ impl TestEnv {
298
320
. client
299
321
. get_block_hash ( height as u64 )
300
322
. 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
+ } )
302
329
} ) )
303
330
. expect ( "must craft tip" )
304
331
}
305
332
306
333
/// Get the genesis hash of the blockchain.
307
334
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 ;
309
336
Ok ( hash)
310
337
}
311
338
}
@@ -314,7 +341,7 @@ impl TestEnv {
314
341
mod test {
315
342
use crate :: TestEnv ;
316
343
use core:: time:: Duration ;
317
- use electrsd:: bitcoind :: { anyhow:: Result , bitcoincore_rpc :: RpcApi } ;
344
+ use electrsd:: corepc_node :: anyhow:: Result ;
318
345
319
346
/// This checks that reorgs initiated by `bitcoind` is detected by our `electrsd` instance.
320
347
#[ test]
@@ -324,15 +351,15 @@ mod test {
324
351
// Mine some blocks.
325
352
env. mine_blocks ( 101 , None ) ?;
326
353
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 ;
328
355
let blocks = ( 0 ..=height)
329
356
. map ( |i| env. bitcoind . client . get_block_hash ( i) )
330
357
. collect :: < Result < Vec < _ > , _ > > ( ) ?;
331
358
332
359
// Perform reorg on six blocks.
333
360
env. reorg ( 6 ) ?;
334
361
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 ;
336
363
let reorged_blocks = ( 0 ..=height)
337
364
. map ( |i| env. bitcoind . client . get_block_hash ( i) )
338
365
. collect :: < Result < Vec < _ > , _ > > ( ) ?;
0 commit comments