@@ -7,93 +7,90 @@ use electrsd::bitcoind::bitcoincore_rpc::bitcoincore_rpc_json::AddressType;
77use electrsd:: { bitcoind, bitcoind:: BitcoinD , ElectrsD } ;
88use electrum_client:: ElectrumApi ;
99
10- use once_cell:: sync:: OnceCell ;
11-
1210use std:: env;
13- use std:: sync:: Mutex ;
1411use std:: time:: Duration ;
1512
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)
4531}
4632
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) ;
5442}
5543
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+ } ;
5855 loop {
5956 if header. height >= min_height {
6057 break ;
6158 }
6259 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" )
6663 } ) ;
6764 }
6865}
6966
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) ;
7269 loop {
7370 if tx_res. is_ok ( ) {
7471 break ;
7572 }
7673 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) )
8077 } ) ;
8178 }
8279}
8380
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 ( ) ;
8683 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 ( ) ;
8885 loop {
8986 if is_spent {
9087 break ;
9188 }
9289
9390 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 ( ) )
9794 } ) ;
9895 }
9996}
@@ -119,26 +116,27 @@ where
119116 }
120117}
121118
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 ) ;
126123
127124 for addr in addrs {
128- let txid = get_bitcoind ( )
125+ let txid = bitcoind
129126 . client
130127 . send_to_address ( & addr, amount, None , None , None , None , None , None )
131128 . unwrap ( ) ;
132- wait_for_tx ( txid) ;
129+ wait_for_tx ( electrsd , txid) ;
133130 }
134131
135- generate_blocks_and_wait ( 1 ) ;
132+ generate_blocks_and_wait ( bitcoind , electrsd , 1 ) ;
136133}
137134
138135#[ test]
139136fn channel_full_cycle ( ) {
137+ let ( bitcoind, electrsd) = setup_bitcoind_and_electrsd ( ) ;
140138 println ! ( "== Node A ==" ) ;
141- let esplora_url = get_electrsd ( ) . esplora_url . as_ref ( ) . unwrap ( ) ;
139+ let esplora_url = electrsd . esplora_url . as_ref ( ) . unwrap ( ) ;
142140 let config_a = random_config ( esplora_url) ;
143141 let node_a = Builder :: from_config ( config_a) . build ( ) ;
144142 node_a. start ( ) . unwrap ( ) ;
@@ -150,7 +148,12 @@ fn channel_full_cycle() {
150148 node_b. start ( ) . unwrap ( ) ;
151149 let addr_b = node_b. new_funding_address ( ) . unwrap ( ) ;
152150
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+ ) ;
154157 node_a. sync_wallets ( ) . unwrap ( ) ;
155158 node_b. sync_wallets ( ) . unwrap ( ) ;
156159 assert_eq ! ( node_a. on_chain_balance( ) . unwrap( ) . get_spendable( ) , 100000 ) ;
@@ -170,10 +173,10 @@ fn channel_full_cycle() {
170173 }
171174 } ;
172175
173- wait_for_tx ( funding_txo. txid ) ;
176+ wait_for_tx ( & electrsd , funding_txo. txid ) ;
174177
175178 println ! ( "\n .. generating blocks, syncing wallets .. " ) ;
176- generate_blocks_and_wait ( 6 ) ;
179+ generate_blocks_and_wait ( & bitcoind , & electrsd , 6 ) ;
177180 node_a. sync_wallets ( ) . unwrap ( ) ;
178181 node_b. sync_wallets ( ) . unwrap ( ) ;
179182
@@ -276,9 +279,9 @@ fn channel_full_cycle() {
276279 expect_event ! ( node_a, ChannelClosed ) ;
277280 expect_event ! ( node_b, ChannelClosed ) ;
278281
279- wait_for_outpoint_spend ( funding_txo. into_bitcoin_outpoint ( ) ) ;
282+ wait_for_outpoint_spend ( & electrsd , funding_txo. into_bitcoin_outpoint ( ) ) ;
280283
281- generate_blocks_and_wait ( 1 ) ;
284+ generate_blocks_and_wait ( & bitcoind , & electrsd , 1 ) ;
282285 node_a. sync_wallets ( ) . unwrap ( ) ;
283286 node_b. sync_wallets ( ) . unwrap ( ) ;
284287
@@ -293,8 +296,9 @@ fn channel_full_cycle() {
293296
294297#[ test]
295298fn channel_open_fails_when_funds_insufficient ( ) {
299+ let ( bitcoind, electrsd) = setup_bitcoind_and_electrsd ( ) ;
296300 println ! ( "== Node A ==" ) ;
297- let esplora_url = get_electrsd ( ) . esplora_url . as_ref ( ) . unwrap ( ) ;
301+ let esplora_url = electrsd . esplora_url . as_ref ( ) . unwrap ( ) ;
298302 let config_a = random_config ( & esplora_url) ;
299303 let node_a = Builder :: from_config ( config_a) . build ( ) ;
300304 node_a. start ( ) . unwrap ( ) ;
@@ -306,7 +310,12 @@ fn channel_open_fails_when_funds_insufficient() {
306310 node_b. start ( ) . unwrap ( ) ;
307311 let addr_b = node_b. new_funding_address ( ) . unwrap ( ) ;
308312
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+ ) ;
310319 node_a. sync_wallets ( ) . unwrap ( ) ;
311320 node_b. sync_wallets ( ) . unwrap ( ) ;
312321 assert_eq ! ( node_a. on_chain_balance( ) . unwrap( ) . get_spendable( ) , 100000 ) ;
@@ -322,7 +331,8 @@ fn channel_open_fails_when_funds_insufficient() {
322331
323332#[ test]
324333fn 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 ( ) ;
326336 let mut config = random_config ( & esplora_url) ;
327337 config. esplora_server_url = "https://blockstream.info/testnet/api" . to_string ( ) ;
328338 config. network = bitcoin:: Network :: Testnet ;
@@ -334,15 +344,16 @@ fn connect_to_public_testnet_esplora() {
334344
335345#[ test]
336346fn 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 ( ) ;
338349 let config = random_config ( & esplora_url) ;
339350 let node = Builder :: from_config ( config. clone ( ) ) . build ( ) ;
340351 let expected_node_id = node. node_id ( ) ;
341352
342353 let funding_address = node. new_funding_address ( ) . unwrap ( ) ;
343354 let expected_amount = Amount :: from_sat ( 100000 ) ;
344355
345- premine_and_distribute_funds ( vec ! [ funding_address] , expected_amount) ;
356+ premine_and_distribute_funds ( & bitcoind , & electrsd , vec ! [ funding_address] , expected_amount) ;
346357 assert_eq ! ( node. on_chain_balance( ) . unwrap( ) . get_total( ) , 0 ) ;
347358
348359 node. start ( ) . unwrap ( ) ;
0 commit comments