@@ -11402,3 +11402,158 @@ fn rbf_on_config_change() {
11402
11402
11403
11403
run_loop_thread. join ( ) . unwrap ( ) ;
11404
11404
}
11405
+
11406
+ /// Test `/v3/transactions/txid` API endpoint
11407
+ ///
11408
+ /// This endpoint returns a JSON with index_block_hash,
11409
+ /// the transaction body as hex and the transaction result.
11410
+ #[ test]
11411
+ #[ ignore]
11412
+ fn v3_transactions_api_endpoint ( ) {
11413
+ if env:: var ( "BITCOIND_TEST" ) != Ok ( "1" . into ( ) ) {
11414
+ return ;
11415
+ }
11416
+
11417
+ let ( mut conf, _miner_account) = naka_neon_integration_conf ( None ) ;
11418
+ conf. node . txindex = true ;
11419
+
11420
+ let password = "12345" . to_string ( ) ;
11421
+ conf. connection_options . auth_token = Some ( password. clone ( ) ) ;
11422
+ conf. miner . wait_on_interim_blocks = Duration :: from_secs ( 1 ) ;
11423
+ let stacker_sk = setup_stacker ( & mut conf) ;
11424
+ let signer_sk = Secp256k1PrivateKey :: random ( ) ;
11425
+ let signer_addr = tests:: to_addr ( & signer_sk) ;
11426
+ let sender_sk = Secp256k1PrivateKey :: random ( ) ;
11427
+ // setup sender + recipient for some test stx transfers
11428
+ // these are necessary for the interim blocks to get mined at all
11429
+ let sender_addr = tests:: to_addr ( & sender_sk) ;
11430
+ let send_amt = 100 ;
11431
+ let send_fee = 180 ;
11432
+ conf. add_initial_balance (
11433
+ PrincipalData :: from ( sender_addr) . to_string ( ) ,
11434
+ send_amt + send_fee,
11435
+ ) ;
11436
+ conf. add_initial_balance ( PrincipalData :: from ( signer_addr) . to_string ( ) , 100000 ) ;
11437
+
11438
+ // only subscribe to the block proposal events
11439
+ test_observer:: spawn ( ) ;
11440
+ test_observer:: register ( & mut conf, & [ EventKeyType :: MinedBlocks ] ) ;
11441
+
11442
+ let mut btcd_controller = BitcoinCoreController :: new ( conf. clone ( ) ) ;
11443
+ btcd_controller
11444
+ . start_bitcoind ( )
11445
+ . expect ( "Failed starting bitcoind" ) ;
11446
+ let mut btc_regtest_controller = BitcoinRegtestController :: new ( conf. clone ( ) , None ) ;
11447
+ btc_regtest_controller. bootstrap_chain ( 201 ) ;
11448
+
11449
+ let mut run_loop = boot_nakamoto:: BootRunLoop :: new ( conf. clone ( ) ) . unwrap ( ) ;
11450
+ let run_loop_stopper = run_loop. get_termination_switch ( ) ;
11451
+ let counters = run_loop. counters ( ) ;
11452
+ let Counters {
11453
+ blocks_processed,
11454
+ naka_submitted_commits : commits_submitted,
11455
+ ..
11456
+ } = run_loop. counters ( ) ;
11457
+
11458
+ let coord_channel = run_loop. coordinator_channels ( ) ;
11459
+
11460
+ let run_loop_thread = thread:: spawn ( move || run_loop. start ( None , 0 ) ) ;
11461
+ let mut signers = TestSigners :: new ( vec ! [ signer_sk] ) ;
11462
+ wait_for_runloop ( & blocks_processed) ;
11463
+ boot_to_epoch_3 (
11464
+ & conf,
11465
+ & blocks_processed,
11466
+ & [ stacker_sk] ,
11467
+ & [ signer_sk] ,
11468
+ & mut Some ( & mut signers) ,
11469
+ & mut btc_regtest_controller,
11470
+ ) ;
11471
+
11472
+ info ! ( "------------------------- Reached Epoch 3.0 -------------------------" ) ;
11473
+
11474
+ blind_signer ( & conf, & signers, & counters) ;
11475
+
11476
+ wait_for_first_naka_block_commit ( 60 , & commits_submitted) ;
11477
+
11478
+ // Mine 1 nakamoto tenure
11479
+ next_block_and_mine_commit ( & mut btc_regtest_controller, 60 , & conf, & counters) . unwrap ( ) ;
11480
+
11481
+ let burnchain = conf. get_burnchain ( ) ;
11482
+ let _sortdb = burnchain. open_sortition_db ( true ) . unwrap ( ) ;
11483
+ let ( _chainstate, _) = StacksChainState :: open (
11484
+ conf. is_mainnet ( ) ,
11485
+ conf. burnchain . chain_id ,
11486
+ & conf. get_chainstate_path_str ( ) ,
11487
+ None ,
11488
+ )
11489
+ . unwrap ( ) ;
11490
+
11491
+ info ! ( "------------------------- Setup finished, run test -------------------------" ) ;
11492
+
11493
+ let http_origin = format ! ( "http://{}" , & conf. node. rpc_bind) ;
11494
+
11495
+ let get_v3_transactions = |txid : Txid | {
11496
+ let url = & format ! ( "{http_origin}/v3/transactions/{txid}" ) ;
11497
+ info ! ( "Send request: GET {url}" ) ;
11498
+ reqwest:: blocking:: get ( url)
11499
+ . unwrap_or_else ( |e| panic ! ( "GET request failed: {e}" ) )
11500
+ . json :: < serde_json:: Value > ( )
11501
+ . unwrap ( )
11502
+ } ;
11503
+
11504
+ let get_transaction_from_block = |index_block_hash : String , txid : String | {
11505
+ for block_json in test_observer:: get_blocks ( ) {
11506
+ if block_json[ "index_block_hash" ] . as_str ( ) . unwrap ( ) == format ! ( "0x{}" , index_block_hash)
11507
+ {
11508
+ for transaction_json in block_json[ "transactions" ] . as_array ( ) . unwrap ( ) {
11509
+ if transaction_json[ "txid" ] . as_str ( ) . unwrap ( ) == format ! ( "0x{}" , txid) {
11510
+ return Some ( transaction_json[ "raw_tx" ] . as_str ( ) . unwrap ( ) . to_string ( ) ) ;
11511
+ }
11512
+ }
11513
+ }
11514
+ }
11515
+ None
11516
+ } ;
11517
+
11518
+ let block_events = test_observer:: get_mined_nakamoto_blocks ( ) ;
11519
+
11520
+ let last_block_event = block_events. last ( ) . unwrap ( ) ;
11521
+
11522
+ let first_transaction = match last_block_event. tx_events . first ( ) . unwrap ( ) {
11523
+ TransactionEvent :: Success ( first_transaction) => Some ( first_transaction. txid ) ,
11524
+ _ => None ,
11525
+ }
11526
+ . unwrap ( ) ;
11527
+
11528
+ let response_json = get_v3_transactions ( first_transaction) ;
11529
+
11530
+ assert_eq ! (
11531
+ response_json
11532
+ . get( "index_block_hash" )
11533
+ . unwrap( )
11534
+ . as_str( )
11535
+ . unwrap( ) ,
11536
+ last_block_event. block_id
11537
+ ) ;
11538
+
11539
+ let raw_tx = get_transaction_from_block (
11540
+ last_block_event. block_id . clone ( ) ,
11541
+ first_transaction. to_hex ( ) ,
11542
+ )
11543
+ . unwrap ( ) ;
11544
+
11545
+ assert_eq ! (
11546
+ format!( "0x{}" , response_json. get( "tx" ) . unwrap( ) . as_str( ) . unwrap( ) ) ,
11547
+ raw_tx
11548
+ ) ;
11549
+
11550
+ info ! ( "------------------------- Test finished, clean up -------------------------" ) ;
11551
+
11552
+ coord_channel
11553
+ . lock ( )
11554
+ . expect ( "Mutex poisoned" )
11555
+ . stop_chains_coordinator ( ) ;
11556
+ run_loop_stopper. store ( false , Ordering :: SeqCst ) ;
11557
+
11558
+ run_loop_thread. join ( ) . unwrap ( ) ;
11559
+ }
0 commit comments