@@ -198,6 +198,98 @@ impl_error!(bitcoin::hashes::hex::Error, Hex, Error);
198
198
#[ cfg( test) ]
199
199
mod test {
200
200
use super :: * ;
201
+ use bitcoin:: Amount ;
202
+ use electrsd:: {
203
+ bitcoind, bitcoind:: bitcoincore_rpc:: bitcoincore_rpc_json:: AddressType ,
204
+ bitcoind:: bitcoincore_rpc:: RpcApi , bitcoind:: BitcoinD , ElectrsD ,
205
+ } ;
206
+ use electrum_client:: ElectrumApi ;
207
+ use lazy_static:: lazy_static;
208
+ use std:: sync:: { Mutex , Once } ;
209
+ use std:: time:: Duration ;
210
+
211
+ lazy_static ! {
212
+ static ref BITCOIND : BitcoinD = {
213
+ let bitcoind_exe =
214
+ bitcoind:: downloaded_exe_path( ) . expect( "bitcoind version feature must be enabled" ) ;
215
+ let conf = bitcoind:: Conf :: default ( ) ;
216
+ BitcoinD :: with_conf( bitcoind_exe, & conf) . unwrap( )
217
+ } ;
218
+ static ref ELECTRSD : ElectrsD = {
219
+ let electrs_exe =
220
+ electrsd:: downloaded_exe_path( ) . expect( "electrs version feature must be enabled" ) ;
221
+ let mut conf = electrsd:: Conf :: default ( ) ;
222
+ conf. http_enabled = true ;
223
+ ElectrsD :: with_conf( electrs_exe, & BITCOIND , & conf) . unwrap( )
224
+ } ;
225
+ static ref MINER : Mutex <( ) > = Mutex :: new( ( ) ) ;
226
+ }
227
+
228
+ static PREMINE : Once = Once :: new ( ) ;
229
+
230
+ fn setup_clients ( ) -> ( BlockingClient , AsyncClient ) {
231
+ PREMINE . call_once ( || {
232
+ let _miner = MINER . lock ( ) . unwrap ( ) ;
233
+ generate_blocks_and_wait ( 101 ) ;
234
+ } ) ;
235
+
236
+ let esplora_url = ELECTRSD . esplora_url . as_ref ( ) . unwrap ( ) ;
237
+
238
+ let builder = Builder :: new ( & format ! ( "http://{}" , esplora_url) ) ;
239
+ let blocking_client = builder. build_blocking ( ) . unwrap ( ) ;
240
+
241
+ let builder_async = Builder :: new ( & format ! ( "http://{}" , esplora_url) ) ;
242
+ let async_client = builder_async. build_async ( ) . unwrap ( ) ;
243
+
244
+ ( blocking_client, async_client)
245
+ }
246
+
247
+ fn generate_blocks_and_wait ( num : usize ) {
248
+ let cur_height = BITCOIND . client . get_block_count ( ) . unwrap ( ) ;
249
+ generate_blocks ( num) ;
250
+ wait_for_block ( cur_height as usize + num) ;
251
+ }
252
+
253
+ fn generate_blocks ( num : usize ) {
254
+ let address = BITCOIND
255
+ . client
256
+ . get_new_address ( Some ( "test" ) , Some ( AddressType :: Legacy ) )
257
+ . unwrap ( ) ;
258
+ let _block_hashes = BITCOIND
259
+ . client
260
+ . generate_to_address ( num as u64 , & address)
261
+ . unwrap ( ) ;
262
+ }
263
+
264
+ fn wait_for_block ( min_height : usize ) {
265
+ let mut header = ELECTRSD . client . block_headers_subscribe ( ) . unwrap ( ) ;
266
+ loop {
267
+ if header. height >= min_height {
268
+ break ;
269
+ }
270
+ header = exponential_backoff_poll ( || {
271
+ ELECTRSD . trigger ( ) . unwrap ( ) ;
272
+ ELECTRSD . client . ping ( ) . unwrap ( ) ;
273
+ ELECTRSD . client . block_headers_pop ( ) . unwrap ( )
274
+ } ) ;
275
+ }
276
+ }
277
+
278
+ fn exponential_backoff_poll < T , F > ( mut poll : F ) -> T
279
+ where
280
+ F : FnMut ( ) -> Option < T > ,
281
+ {
282
+ let mut delay = Duration :: from_millis ( 64 ) ;
283
+ loop {
284
+ match poll ( ) {
285
+ Some ( data) => break data,
286
+ None if delay. as_millis ( ) < 512 => delay = delay. mul_f32 ( 2.0 ) ,
287
+ None => { }
288
+ }
289
+
290
+ std:: thread:: sleep ( delay) ;
291
+ }
292
+ }
201
293
202
294
#[ test]
203
295
fn feerate_parsing ( ) {
@@ -242,4 +334,257 @@ mod test {
242
334
"should inherit from value for 25"
243
335
) ;
244
336
}
337
+
338
+ #[ tokio:: test]
339
+ async fn test_get_tx ( ) {
340
+ let ( blocking_client, async_client) = setup_clients ( ) ;
341
+
342
+ let address = BITCOIND
343
+ . client
344
+ . get_new_address ( Some ( "test" ) , Some ( AddressType :: Legacy ) )
345
+ . unwrap ( ) ;
346
+ let txid = BITCOIND
347
+ . client
348
+ . send_to_address (
349
+ & address,
350
+ Amount :: from_sat ( 1000 ) ,
351
+ None ,
352
+ None ,
353
+ None ,
354
+ None ,
355
+ None ,
356
+ None ,
357
+ )
358
+ . unwrap ( ) ;
359
+ let _miner = MINER . lock ( ) . unwrap ( ) ;
360
+ generate_blocks_and_wait ( 1 ) ;
361
+
362
+ let tx = blocking_client. get_tx ( & txid) . unwrap ( ) ;
363
+ let tx_async = async_client. get_tx ( & txid) . await . unwrap ( ) ;
364
+ assert_eq ! ( tx, tx_async) ;
365
+ }
366
+
367
+ #[ tokio:: test]
368
+ async fn test_get_tx_no_opt ( ) {
369
+ let ( blocking_client, async_client) = setup_clients ( ) ;
370
+
371
+ let address = BITCOIND
372
+ . client
373
+ . get_new_address ( Some ( "test" ) , Some ( AddressType :: Legacy ) )
374
+ . unwrap ( ) ;
375
+ let txid = BITCOIND
376
+ . client
377
+ . send_to_address (
378
+ & address,
379
+ Amount :: from_sat ( 1000 ) ,
380
+ None ,
381
+ None ,
382
+ None ,
383
+ None ,
384
+ None ,
385
+ None ,
386
+ )
387
+ . unwrap ( ) ;
388
+ let _miner = MINER . lock ( ) . unwrap ( ) ;
389
+ generate_blocks_and_wait ( 1 ) ;
390
+
391
+ let tx_no_opt = blocking_client. get_tx_no_opt ( & txid) . unwrap ( ) ;
392
+ let tx_no_opt_async = async_client. get_tx_no_opt ( & txid) . await . unwrap ( ) ;
393
+ assert_eq ! ( tx_no_opt, tx_no_opt_async) ;
394
+ }
395
+
396
+ #[ tokio:: test]
397
+ async fn test_get_tx_status ( ) {
398
+ let ( blocking_client, async_client) = setup_clients ( ) ;
399
+
400
+ let address = BITCOIND
401
+ . client
402
+ . get_new_address ( Some ( "test" ) , Some ( AddressType :: Legacy ) )
403
+ . unwrap ( ) ;
404
+ let txid = BITCOIND
405
+ . client
406
+ . send_to_address (
407
+ & address,
408
+ Amount :: from_sat ( 1000 ) ,
409
+ None ,
410
+ None ,
411
+ None ,
412
+ None ,
413
+ None ,
414
+ None ,
415
+ )
416
+ . unwrap ( ) ;
417
+ let _miner = MINER . lock ( ) . unwrap ( ) ;
418
+ generate_blocks_and_wait ( 1 ) ;
419
+
420
+ let tx_status = blocking_client. get_tx_status ( & txid) . unwrap ( ) . unwrap ( ) ;
421
+ let tx_status_async = async_client. get_tx_status ( & txid) . await . unwrap ( ) . unwrap ( ) ;
422
+ assert_eq ! ( tx_status, tx_status_async) ;
423
+ assert_eq ! ( tx_status. confirmed, true ) ;
424
+ }
425
+
426
+ #[ tokio:: test]
427
+ async fn test_get_header ( ) {
428
+ let ( blocking_client, async_client) = setup_clients ( ) ;
429
+ let block_header = blocking_client. get_header ( 53 ) . unwrap ( ) ;
430
+ let block_header_async = async_client. get_header ( 53 ) . await . unwrap ( ) ;
431
+ assert_eq ! ( block_header, block_header_async) ;
432
+ }
433
+
434
+ #[ tokio:: test]
435
+ async fn test_get_merkle_proof ( ) {
436
+ let ( blocking_client, async_client) = setup_clients ( ) ;
437
+
438
+ let address = BITCOIND
439
+ . client
440
+ . get_new_address ( Some ( "test" ) , Some ( AddressType :: Legacy ) )
441
+ . unwrap ( ) ;
442
+ let txid = BITCOIND
443
+ . client
444
+ . send_to_address (
445
+ & address,
446
+ Amount :: from_sat ( 1000 ) ,
447
+ None ,
448
+ None ,
449
+ None ,
450
+ None ,
451
+ None ,
452
+ None ,
453
+ )
454
+ . unwrap ( ) ;
455
+ let _miner = MINER . lock ( ) . unwrap ( ) ;
456
+ generate_blocks_and_wait ( 1 ) ;
457
+
458
+ let merkle_proof = blocking_client. get_merkle_proof ( & txid) . unwrap ( ) . unwrap ( ) ;
459
+ let merkle_proof_async = async_client. get_merkle_proof ( & txid) . await . unwrap ( ) . unwrap ( ) ;
460
+ assert_eq ! ( merkle_proof, merkle_proof_async) ;
461
+ assert ! ( merkle_proof. pos > 0 ) ;
462
+ }
463
+
464
+ #[ tokio:: test]
465
+ async fn test_get_output_status ( ) {
466
+ let ( blocking_client, async_client) = setup_clients ( ) ;
467
+
468
+ let address = BITCOIND
469
+ . client
470
+ . get_new_address ( Some ( "test" ) , Some ( AddressType :: Legacy ) )
471
+ . unwrap ( ) ;
472
+ let txid = BITCOIND
473
+ . client
474
+ . send_to_address (
475
+ & address,
476
+ Amount :: from_sat ( 1000 ) ,
477
+ None ,
478
+ None ,
479
+ None ,
480
+ None ,
481
+ None ,
482
+ None ,
483
+ )
484
+ . unwrap ( ) ;
485
+ let _miner = MINER . lock ( ) . unwrap ( ) ;
486
+ generate_blocks_and_wait ( 1 ) ;
487
+
488
+ let output_status = blocking_client
489
+ . get_output_status ( & txid, 1 )
490
+ . unwrap ( )
491
+ . unwrap ( ) ;
492
+ let output_status_async = async_client
493
+ . get_output_status ( & txid, 1 )
494
+ . await
495
+ . unwrap ( )
496
+ . unwrap ( ) ;
497
+
498
+ assert_eq ! ( output_status, output_status_async) ;
499
+ }
500
+
501
+ #[ tokio:: test]
502
+ async fn test_get_height ( ) {
503
+ let ( blocking_client, async_client) = setup_clients ( ) ;
504
+ let block_height = blocking_client. get_height ( ) . unwrap ( ) ;
505
+ let block_height_async = async_client. get_height ( ) . await . unwrap ( ) ;
506
+ assert ! ( block_height > 0 ) ;
507
+ assert_eq ! ( block_height, block_height_async) ;
508
+ }
509
+
510
+ #[ tokio:: test]
511
+ async fn test_get_tip_hash ( ) {
512
+ let ( blocking_client, async_client) = setup_clients ( ) ;
513
+ let tip_hash = blocking_client. get_tip_hash ( ) . unwrap ( ) ;
514
+ let tip_hash_async = async_client. get_tip_hash ( ) . await . unwrap ( ) ;
515
+ assert_eq ! ( tip_hash, tip_hash_async) ;
516
+ }
517
+
518
+ #[ tokio:: test]
519
+ async fn test_get_txid_at_block_index ( ) {
520
+ let ( blocking_client, async_client) = setup_clients ( ) ;
521
+
522
+ let block_hash = BITCOIND . client . get_block_hash ( 23 ) . unwrap ( ) ;
523
+
524
+ let txid_at_block_index = blocking_client
525
+ . get_txid_at_block_index ( & block_hash, 0 )
526
+ . unwrap ( )
527
+ . unwrap ( ) ;
528
+ let txid_at_block_index_async = async_client
529
+ . get_txid_at_block_index ( & block_hash, 0 )
530
+ . await
531
+ . unwrap ( )
532
+ . unwrap ( ) ;
533
+ assert_eq ! ( txid_at_block_index, txid_at_block_index_async) ;
534
+ }
535
+
536
+ #[ tokio:: test]
537
+ async fn test_get_fee_estimates ( ) {
538
+ let ( blocking_client, async_client) = setup_clients ( ) ;
539
+ let fee_estimates = blocking_client. get_fee_estimates ( ) . unwrap ( ) ;
540
+ let fee_estimates_async = async_client. get_fee_estimates ( ) . await . unwrap ( ) ;
541
+ assert_eq ! ( fee_estimates. len( ) , fee_estimates_async. len( ) ) ;
542
+ }
543
+
544
+ #[ tokio:: test]
545
+ async fn test_scripthash_txs ( ) {
546
+ let ( blocking_client, async_client) = setup_clients ( ) ;
547
+
548
+ let address = BITCOIND
549
+ . client
550
+ . get_new_address ( Some ( "test" ) , Some ( AddressType :: Legacy ) )
551
+ . unwrap ( ) ;
552
+ let txid = BITCOIND
553
+ . client
554
+ . send_to_address (
555
+ & address,
556
+ Amount :: from_sat ( 1000 ) ,
557
+ None ,
558
+ None ,
559
+ None ,
560
+ None ,
561
+ None ,
562
+ None ,
563
+ )
564
+ . unwrap ( ) ;
565
+ let _miner = MINER . lock ( ) . unwrap ( ) ;
566
+ generate_blocks_and_wait ( 1 ) ;
567
+
568
+ let expected_tx = BITCOIND
569
+ . client
570
+ . get_transaction ( & txid, None )
571
+ . unwrap ( )
572
+ . transaction ( )
573
+ . unwrap ( ) ;
574
+ let script = & expected_tx. output [ 0 ] . script_pubkey ;
575
+ let scripthash_txs_txids: Vec < Txid > = blocking_client
576
+ . scripthash_txs ( script, None )
577
+ . unwrap ( )
578
+ . iter ( )
579
+ . map ( |tx| tx. txid )
580
+ . collect ( ) ;
581
+ let scripthash_txs_txids_async: Vec < Txid > = async_client
582
+ . scripthash_txs ( script, None )
583
+ . await
584
+ . unwrap ( )
585
+ . iter ( )
586
+ . map ( |tx| tx. txid )
587
+ . collect ( ) ;
588
+ assert_eq ! ( scripthash_txs_txids, scripthash_txs_txids_async) ;
589
+ }
245
590
}
0 commit comments