@@ -7,93 +7,90 @@ use electrsd::bitcoind::bitcoincore_rpc::bitcoincore_rpc_json::AddressType;
7
7
use electrsd:: { bitcoind, bitcoind:: BitcoinD , ElectrsD } ;
8
8
use electrum_client:: ElectrumApi ;
9
9
10
- use once_cell:: sync:: OnceCell ;
11
-
12
10
use std:: env;
13
- use std:: sync:: Mutex ;
14
11
use std:: time:: Duration ;
15
12
16
- static BITCOIND : OnceCell < BitcoinD > = OnceCell :: new ( ) ;
17
- static ELECTRSD : OnceCell < ElectrsD > = OnceCell :: new ( ) ;
18
- static PREMINE : OnceCell < ( ) > = OnceCell :: new ( ) ;
19
- static MINER_LOCK : Mutex < ( ) > = Mutex :: new ( ( ) ) ;
20
-
21
- fn get_bitcoind ( ) -> & ' static BitcoinD {
22
- BITCOIND . get_or_init ( || {
23
- let bitcoind_exe =
24
- env:: var ( "BITCOIND_EXE" ) . ok ( ) . or_else ( || bitcoind:: downloaded_exe_path ( ) . ok ( ) ) . expect (
25
- "you need to provide an env var BITCOIND_EXE or specify a bitcoind version feature" ,
26
- ) ;
27
- let mut conf = bitcoind:: Conf :: default ( ) ;
28
- conf. network = "regtest" ;
29
- BitcoinD :: with_conf ( bitcoind_exe, & conf) . unwrap ( )
30
- } )
31
- }
32
-
33
- fn get_electrsd ( ) -> & ' static ElectrsD {
34
- ELECTRSD . get_or_init ( || {
35
- let bitcoind = get_bitcoind ( ) ;
36
- let electrs_exe =
37
- env:: var ( "ELECTRS_EXE" ) . ok ( ) . or_else ( electrsd:: downloaded_exe_path) . expect (
38
- "you need to provide env var ELECTRS_EXE or specify an electrsd version feature" ,
39
- ) ;
40
- let mut conf = electrsd:: Conf :: default ( ) ;
41
- conf. http_enabled = true ;
42
- conf. network = "regtest" ;
43
- ElectrsD :: with_conf ( electrs_exe, & bitcoind, & conf) . unwrap ( )
44
- } )
13
+ fn setup_bitcoind_and_electrsd ( ) -> ( BitcoinD , ElectrsD ) {
14
+ let bitcoind_exe =
15
+ env:: var ( "BITCOIND_EXE" ) . ok ( ) . or_else ( || bitcoind:: downloaded_exe_path ( ) . ok ( ) ) . expect (
16
+ "you need to provide an env var BITCOIND_EXE or specify a bitcoind version feature" ,
17
+ ) ;
18
+ let mut bitcoind_conf = bitcoind:: Conf :: default ( ) ;
19
+ bitcoind_conf. network = "regtest" ;
20
+ let bitcoind = BitcoinD :: with_conf ( bitcoind_exe, & bitcoind_conf) . unwrap ( ) ;
21
+
22
+ let electrs_exe = env:: var ( "ELECTRS_EXE" )
23
+ . ok ( )
24
+ . or_else ( electrsd:: downloaded_exe_path)
25
+ . expect ( "you need to provide env var ELECTRS_EXE or specify an electrsd version feature" ) ;
26
+ let mut electrsd_conf = electrsd:: Conf :: default ( ) ;
27
+ electrsd_conf. http_enabled = true ;
28
+ electrsd_conf. network = "regtest" ;
29
+ let electrsd = ElectrsD :: with_conf ( electrs_exe, & bitcoind, & electrsd_conf) . unwrap ( ) ;
30
+ ( bitcoind, electrsd)
45
31
}
46
32
47
- fn generate_blocks_and_wait ( num : usize ) {
48
- let _miner = MINER_LOCK . lock ( ) . unwrap ( ) ;
49
- let cur_height = get_bitcoind ( ) . client . get_block_count ( ) . unwrap ( ) ;
50
- let address =
51
- get_bitcoind ( ) . client . get_new_address ( Some ( "test" ) , Some ( AddressType :: Legacy ) ) . unwrap ( ) ;
52
- let _block_hashes = get_bitcoind ( ) . client . generate_to_address ( num as u64 , & address) . unwrap ( ) ;
53
- wait_for_block ( cur_height as usize + num) ;
33
+ fn generate_blocks_and_wait ( bitcoind : & BitcoinD , electrsd : & ElectrsD , num : usize ) {
34
+ let cur_height = bitcoind. client . get_block_count ( ) . expect ( "failed to get current block height" ) ;
35
+ let address = bitcoind
36
+ . client
37
+ . get_new_address ( Some ( "test" ) , Some ( AddressType :: Legacy ) )
38
+ . expect ( "failed to get new address" ) ;
39
+ // TODO: expect this Result once the WouldBlock issue is resolved upstream.
40
+ let _block_hashes_res = bitcoind. client . generate_to_address ( num as u64 , & address) ;
41
+ wait_for_block ( electrsd, cur_height as usize + num) ;
54
42
}
55
43
56
- fn wait_for_block ( min_height : usize ) {
57
- let mut header = get_electrsd ( ) . client . block_headers_subscribe ( ) . unwrap ( ) ;
44
+ fn wait_for_block ( electrsd : & ElectrsD , min_height : usize ) {
45
+ let mut header = match electrsd. client . block_headers_subscribe ( ) {
46
+ Ok ( header) => header,
47
+ Err ( _) => {
48
+ // While subscribing should succeed the first time around, we ran into some cases where
49
+ // it didn't. Since we can't proceed without subscribing, we try again after a delay
50
+ // and panic if it still fails.
51
+ std:: thread:: sleep ( Duration :: from_secs ( 1 ) ) ;
52
+ electrsd. client . block_headers_subscribe ( ) . expect ( "failed to subscribe to block headers" )
53
+ }
54
+ } ;
58
55
loop {
59
56
if header. height >= min_height {
60
57
break ;
61
58
}
62
59
header = exponential_backoff_poll ( || {
63
- get_electrsd ( ) . trigger ( ) . unwrap ( ) ;
64
- get_electrsd ( ) . client . ping ( ) . unwrap ( ) ;
65
- get_electrsd ( ) . client . block_headers_pop ( ) . unwrap ( )
60
+ electrsd . trigger ( ) . expect ( "failed to trigger electrsd" ) ;
61
+ electrsd . client . ping ( ) . expect ( "failed to ping electrsd" ) ;
62
+ electrsd . client . block_headers_pop ( ) . expect ( "failed to pop block header" )
66
63
} ) ;
67
64
}
68
65
}
69
66
70
- fn wait_for_tx ( txid : Txid ) {
71
- let mut tx_res = get_electrsd ( ) . client . transaction_get ( & txid) ;
67
+ fn wait_for_tx ( electrsd : & ElectrsD , txid : Txid ) {
68
+ let mut tx_res = electrsd . client . transaction_get ( & txid) ;
72
69
loop {
73
70
if tx_res. is_ok ( ) {
74
71
break ;
75
72
}
76
73
tx_res = exponential_backoff_poll ( || {
77
- get_electrsd ( ) . trigger ( ) . unwrap ( ) ;
78
- get_electrsd ( ) . client . ping ( ) . unwrap ( ) ;
79
- Some ( get_electrsd ( ) . client . transaction_get ( & txid) )
74
+ electrsd . trigger ( ) . unwrap ( ) ;
75
+ electrsd . client . ping ( ) . unwrap ( ) ;
76
+ Some ( electrsd . client . transaction_get ( & txid) )
80
77
} ) ;
81
78
}
82
79
}
83
80
84
- fn wait_for_outpoint_spend ( outpoint : OutPoint ) {
85
- let tx = get_electrsd ( ) . client . transaction_get ( & outpoint. txid ) . unwrap ( ) ;
81
+ fn wait_for_outpoint_spend ( electrsd : & ElectrsD , outpoint : OutPoint ) {
82
+ let tx = electrsd . client . transaction_get ( & outpoint. txid ) . unwrap ( ) ;
86
83
let txout_script = tx. output . get ( outpoint. vout as usize ) . unwrap ( ) . clone ( ) . script_pubkey ;
87
- let mut is_spent = !get_electrsd ( ) . client . script_get_history ( & txout_script) . unwrap ( ) . is_empty ( ) ;
84
+ let mut is_spent = !electrsd . client . script_get_history ( & txout_script) . unwrap ( ) . is_empty ( ) ;
88
85
loop {
89
86
if is_spent {
90
87
break ;
91
88
}
92
89
93
90
is_spent = exponential_backoff_poll ( || {
94
- get_electrsd ( ) . trigger ( ) . unwrap ( ) ;
95
- get_electrsd ( ) . client . ping ( ) . unwrap ( ) ;
96
- Some ( !get_electrsd ( ) . client . script_get_history ( & txout_script) . unwrap ( ) . is_empty ( ) )
91
+ electrsd . trigger ( ) . unwrap ( ) ;
92
+ electrsd . client . ping ( ) . unwrap ( ) ;
93
+ Some ( !electrsd . client . script_get_history ( & txout_script) . unwrap ( ) . is_empty ( ) )
97
94
} ) ;
98
95
}
99
96
}
@@ -119,26 +116,27 @@ where
119
116
}
120
117
}
121
118
122
- fn premine_and_distribute_funds ( addrs : Vec < Address > , amount : Amount ) {
123
- PREMINE . get_or_init ( || {
124
- generate_blocks_and_wait ( 101 ) ;
125
- } ) ;
119
+ fn premine_and_distribute_funds (
120
+ bitcoind : & BitcoinD , electrsd : & ElectrsD , addrs : Vec < Address > , amount : Amount ,
121
+ ) {
122
+ generate_blocks_and_wait ( bitcoind , electrsd , 101 ) ;
126
123
127
124
for addr in addrs {
128
- let txid = get_bitcoind ( )
125
+ let txid = bitcoind
129
126
. client
130
127
. send_to_address ( & addr, amount, None , None , None , None , None , None )
131
128
. unwrap ( ) ;
132
- wait_for_tx ( txid) ;
129
+ wait_for_tx ( electrsd , txid) ;
133
130
}
134
131
135
- generate_blocks_and_wait ( 1 ) ;
132
+ generate_blocks_and_wait ( bitcoind , electrsd , 1 ) ;
136
133
}
137
134
138
135
#[ test]
139
136
fn channel_full_cycle ( ) {
137
+ let ( bitcoind, electrsd) = setup_bitcoind_and_electrsd ( ) ;
140
138
println ! ( "== Node A ==" ) ;
141
- let esplora_url = get_electrsd ( ) . esplora_url . as_ref ( ) . unwrap ( ) ;
139
+ let esplora_url = electrsd . esplora_url . as_ref ( ) . unwrap ( ) ;
142
140
let config_a = random_config ( esplora_url) ;
143
141
let node_a = Builder :: from_config ( config_a) . build ( ) ;
144
142
node_a. start ( ) . unwrap ( ) ;
@@ -150,7 +148,12 @@ fn channel_full_cycle() {
150
148
node_b. start ( ) . unwrap ( ) ;
151
149
let addr_b = node_b. new_funding_address ( ) . unwrap ( ) ;
152
150
153
- premine_and_distribute_funds ( vec ! [ addr_a, addr_b] , Amount :: from_sat ( 100000 ) ) ;
151
+ premine_and_distribute_funds (
152
+ & bitcoind,
153
+ & electrsd,
154
+ vec ! [ addr_a, addr_b] ,
155
+ Amount :: from_sat ( 100000 ) ,
156
+ ) ;
154
157
node_a. sync_wallets ( ) . unwrap ( ) ;
155
158
node_b. sync_wallets ( ) . unwrap ( ) ;
156
159
assert_eq ! ( node_a. on_chain_balance( ) . unwrap( ) . get_spendable( ) , 100000 ) ;
@@ -170,10 +173,10 @@ fn channel_full_cycle() {
170
173
}
171
174
} ;
172
175
173
- wait_for_tx ( funding_txo. txid ) ;
176
+ wait_for_tx ( & electrsd , funding_txo. txid ) ;
174
177
175
178
println ! ( "\n .. generating blocks, syncing wallets .. " ) ;
176
- generate_blocks_and_wait ( 6 ) ;
179
+ generate_blocks_and_wait ( & bitcoind , & electrsd , 6 ) ;
177
180
node_a. sync_wallets ( ) . unwrap ( ) ;
178
181
node_b. sync_wallets ( ) . unwrap ( ) ;
179
182
@@ -276,9 +279,9 @@ fn channel_full_cycle() {
276
279
expect_event ! ( node_a, ChannelClosed ) ;
277
280
expect_event ! ( node_b, ChannelClosed ) ;
278
281
279
- wait_for_outpoint_spend ( funding_txo. into_bitcoin_outpoint ( ) ) ;
282
+ wait_for_outpoint_spend ( & electrsd , funding_txo. into_bitcoin_outpoint ( ) ) ;
280
283
281
- generate_blocks_and_wait ( 1 ) ;
284
+ generate_blocks_and_wait ( & bitcoind , & electrsd , 1 ) ;
282
285
node_a. sync_wallets ( ) . unwrap ( ) ;
283
286
node_b. sync_wallets ( ) . unwrap ( ) ;
284
287
@@ -293,8 +296,9 @@ fn channel_full_cycle() {
293
296
294
297
#[ test]
295
298
fn channel_open_fails_when_funds_insufficient ( ) {
299
+ let ( bitcoind, electrsd) = setup_bitcoind_and_electrsd ( ) ;
296
300
println ! ( "== Node A ==" ) ;
297
- let esplora_url = get_electrsd ( ) . esplora_url . as_ref ( ) . unwrap ( ) ;
301
+ let esplora_url = electrsd . esplora_url . as_ref ( ) . unwrap ( ) ;
298
302
let config_a = random_config ( & esplora_url) ;
299
303
let node_a = Builder :: from_config ( config_a) . build ( ) ;
300
304
node_a. start ( ) . unwrap ( ) ;
@@ -306,7 +310,12 @@ fn channel_open_fails_when_funds_insufficient() {
306
310
node_b. start ( ) . unwrap ( ) ;
307
311
let addr_b = node_b. new_funding_address ( ) . unwrap ( ) ;
308
312
309
- premine_and_distribute_funds ( vec ! [ addr_a, addr_b] , Amount :: from_sat ( 100000 ) ) ;
313
+ premine_and_distribute_funds (
314
+ & bitcoind,
315
+ & electrsd,
316
+ vec ! [ addr_a, addr_b] ,
317
+ Amount :: from_sat ( 100000 ) ,
318
+ ) ;
310
319
node_a. sync_wallets ( ) . unwrap ( ) ;
311
320
node_b. sync_wallets ( ) . unwrap ( ) ;
312
321
assert_eq ! ( node_a. on_chain_balance( ) . unwrap( ) . get_spendable( ) , 100000 ) ;
@@ -322,7 +331,8 @@ fn channel_open_fails_when_funds_insufficient() {
322
331
323
332
#[ test]
324
333
fn connect_to_public_testnet_esplora ( ) {
325
- let esplora_url = get_electrsd ( ) . esplora_url . as_ref ( ) . unwrap ( ) ;
334
+ let ( _bitcoind, electrsd) = setup_bitcoind_and_electrsd ( ) ;
335
+ let esplora_url = electrsd. esplora_url . as_ref ( ) . unwrap ( ) ;
326
336
let mut config = random_config ( & esplora_url) ;
327
337
config. esplora_server_url = "https://blockstream.info/testnet/api" . to_string ( ) ;
328
338
config. network = bitcoin:: Network :: Testnet ;
@@ -334,15 +344,16 @@ fn connect_to_public_testnet_esplora() {
334
344
335
345
#[ test]
336
346
fn start_stop_reinit ( ) {
337
- let esplora_url = get_electrsd ( ) . esplora_url . as_ref ( ) . unwrap ( ) ;
347
+ let ( bitcoind, electrsd) = setup_bitcoind_and_electrsd ( ) ;
348
+ let esplora_url = electrsd. esplora_url . as_ref ( ) . unwrap ( ) ;
338
349
let config = random_config ( & esplora_url) ;
339
350
let node = Builder :: from_config ( config. clone ( ) ) . build ( ) ;
340
351
let expected_node_id = node. node_id ( ) ;
341
352
342
353
let funding_address = node. new_funding_address ( ) . unwrap ( ) ;
343
354
let expected_amount = Amount :: from_sat ( 100000 ) ;
344
355
345
- premine_and_distribute_funds ( vec ! [ funding_address] , expected_amount) ;
356
+ premine_and_distribute_funds ( & bitcoind , & electrsd , vec ! [ funding_address] , expected_amount) ;
346
357
assert_eq ! ( node. on_chain_balance( ) . unwrap( ) . get_total( ) , 0 ) ;
347
358
348
359
node. start ( ) . unwrap ( ) ;
0 commit comments