@@ -38,6 +38,7 @@ use libsigner::v0::messages::{
38
38
use libsigner:: { SignerSession , StackerDBSession } ;
39
39
use rand:: { thread_rng, Rng } ;
40
40
use rusqlite:: { Connection , OptionalExtension } ;
41
+ use serial_test:: serial;
41
42
use stacks:: burnchains:: { MagicBytes , Txid } ;
42
43
use stacks:: chainstate:: burn:: db:: sortdb:: SortitionDB ;
43
44
use stacks:: chainstate:: burn:: operations:: {
@@ -12997,6 +12998,7 @@ fn test_sip_031_activation() {
12997
12998
/// - ensure liquidity is updated accordingly to SIP-031
12998
12999
#[ test]
12999
13000
#[ ignore]
13001
+ #[ serial]
13000
13002
fn test_sip_031_last_phase ( ) {
13001
13003
if env:: var ( "BITCOIND_TEST" ) != Ok ( "1" . into ( ) ) {
13002
13004
return ;
@@ -13297,3 +13299,172 @@ fn test_sip_031_last_phase() {
13297
13299
13298
13300
run_loop_thread. join ( ) . unwrap ( ) ;
13299
13301
}
13302
+
13303
+ /// Test SIP-031 last phase per-tenure-mint-and-transfer with out of epoch intervals
13304
+ ///
13305
+ /// - check epoch 3.2 is active
13306
+ /// - check SIP-031 boot contract has been deployed even if intervals are out of epoch
13307
+ #[ test]
13308
+ #[ ignore]
13309
+ #[ serial]
13310
+ fn test_sip_031_last_phase_out_of_epoch ( ) {
13311
+ if env:: var ( "BITCOIND_TEST" ) != Ok ( "1" . into ( ) ) {
13312
+ return ;
13313
+ }
13314
+
13315
+ let ( mut naka_conf, _miner_account) = naka_neon_integration_conf ( None ) ;
13316
+ naka_conf. node . pox_sync_sample_secs = 180 ;
13317
+ naka_conf. burnchain . max_rbf = 10_000_000 ;
13318
+
13319
+ let sender_sk = Secp256k1PrivateKey :: random ( ) ;
13320
+ let sender_signer_sk = Secp256k1PrivateKey :: random ( ) ;
13321
+ let sender_signer_addr = tests:: to_addr ( & sender_signer_sk) ;
13322
+ let mut signers = TestSigners :: new ( vec ! [ sender_signer_sk] ) ;
13323
+ // let's assume funds for 200 tenures
13324
+ let tenure_count = 200 ;
13325
+ let inter_blocks_per_tenure = 9 ;
13326
+ // setup sender + recipient for some test stx transfers
13327
+ // these are necessary for the interim blocks to get mined at all
13328
+ let sender_addr = tests:: to_addr ( & sender_sk) ;
13329
+ let send_amt = 100 ;
13330
+ let send_fee = 180 ;
13331
+ naka_conf. add_initial_balance (
13332
+ PrincipalData :: from ( sender_addr) . to_string ( ) ,
13333
+ ( send_amt + send_fee) * tenure_count * inter_blocks_per_tenure,
13334
+ ) ;
13335
+ naka_conf. add_initial_balance ( PrincipalData :: from ( sender_signer_addr) . to_string ( ) , 100000 ) ;
13336
+ let stacker_sk = setup_stacker ( & mut naka_conf) ;
13337
+
13338
+ let epoch32_start_height =
13339
+ naka_conf. burnchain . epochs . clone ( ) . unwrap ( ) [ StacksEpochId :: Epoch32 ] . start_height ;
13340
+
13341
+ set_test_sip_031_emission_schedule ( Some ( vec ! [
13342
+ SIP031EmissionInterval {
13343
+ amount: 0 ,
13344
+ start_height: 4 ,
13345
+ } ,
13346
+ SIP031EmissionInterval {
13347
+ amount: 300_000 ,
13348
+ start_height: 3 ,
13349
+ } ,
13350
+ SIP031EmissionInterval {
13351
+ amount: 200_000 ,
13352
+ start_height: 2 ,
13353
+ } ,
13354
+ SIP031EmissionInterval {
13355
+ amount: 100_000 ,
13356
+ start_height: 1 ,
13357
+ } ,
13358
+ ] ) ) ;
13359
+
13360
+ test_observer:: spawn ( ) ;
13361
+ test_observer:: register_any ( & mut naka_conf) ;
13362
+
13363
+ let mut btcd_controller = BitcoinCoreController :: new ( naka_conf. clone ( ) ) ;
13364
+ btcd_controller
13365
+ . start_bitcoind ( )
13366
+ . expect ( "Failed starting bitcoind" ) ;
13367
+ let mut btc_regtest_controller = BitcoinRegtestController :: new ( naka_conf. clone ( ) , None ) ;
13368
+ btc_regtest_controller. bootstrap_chain ( 201 ) ;
13369
+
13370
+ let mut run_loop = boot_nakamoto:: BootRunLoop :: new ( naka_conf. clone ( ) ) . unwrap ( ) ;
13371
+ let run_loop_stopper = run_loop. get_termination_switch ( ) ;
13372
+ let Counters {
13373
+ blocks_processed,
13374
+ naka_submitted_commits : commits_submitted,
13375
+ ..
13376
+ } = run_loop. counters ( ) ;
13377
+ let counters = run_loop. counters ( ) ;
13378
+
13379
+ let coord_channel = run_loop. coordinator_channels ( ) ;
13380
+
13381
+ let run_loop_thread = thread:: Builder :: new ( )
13382
+ . name ( "run_loop" . into ( ) )
13383
+ . spawn ( move || run_loop. start ( None , 0 ) )
13384
+ . unwrap ( ) ;
13385
+ wait_for_runloop ( & blocks_processed) ;
13386
+ boot_to_epoch_3 (
13387
+ & naka_conf,
13388
+ & blocks_processed,
13389
+ & [ stacker_sk] ,
13390
+ & [ sender_signer_sk] ,
13391
+ & mut Some ( & mut signers) ,
13392
+ & mut btc_regtest_controller,
13393
+ ) ;
13394
+
13395
+ info ! ( "Bootstrapped to Epoch-3.0 boundary, starting nakamoto miner" ) ;
13396
+
13397
+ let burnchain = naka_conf. get_burnchain ( ) ;
13398
+ let sortdb = burnchain. open_sortition_db ( true ) . unwrap ( ) ;
13399
+ let ( mut chainstate, _) = StacksChainState :: open (
13400
+ naka_conf. is_mainnet ( ) ,
13401
+ naka_conf. burnchain . chain_id ,
13402
+ & naka_conf. get_chainstate_path_str ( ) ,
13403
+ None ,
13404
+ )
13405
+ . unwrap ( ) ;
13406
+
13407
+ info ! ( "Nakamoto miner started..." ) ;
13408
+ blind_signer ( & naka_conf, & signers, & counters) ;
13409
+
13410
+ wait_for_first_naka_block_commit ( 60 , & commits_submitted) ;
13411
+
13412
+ // mine until epoch 3.2 height
13413
+ loop {
13414
+ let commits_before = commits_submitted. load ( Ordering :: SeqCst ) ;
13415
+ next_block_and_process_new_stacks_block ( & mut btc_regtest_controller, 60 , & coord_channel)
13416
+ . unwrap ( ) ;
13417
+ wait_for ( 20 , || {
13418
+ Ok ( commits_submitted. load ( Ordering :: SeqCst ) > commits_before)
13419
+ } )
13420
+ . unwrap ( ) ;
13421
+
13422
+ let node_info = get_chain_info_opt ( & naka_conf) . unwrap ( ) ;
13423
+ if node_info. burn_block_height >= epoch32_start_height {
13424
+ break ;
13425
+ }
13426
+ }
13427
+
13428
+ info ! (
13429
+ "Nakamoto miner has advanced to bitcoin height {}" ,
13430
+ get_chain_info_opt( & naka_conf) . unwrap( ) . burn_block_height
13431
+ ) ;
13432
+
13433
+ let latest_stacks_block_id = get_latest_block_proposal ( & naka_conf, & sortdb)
13434
+ . unwrap ( )
13435
+ . 0
13436
+ . block_id ( ) ;
13437
+
13438
+ // check if sip-031 boot contract has a balance of 200_000_000 STX
13439
+ let sip_031_boot_contract_balance = chainstate. with_read_only_clarity_tx (
13440
+ & sortdb
13441
+ . index_handle_at_block ( & chainstate, & latest_stacks_block_id)
13442
+ . unwrap ( ) ,
13443
+ & latest_stacks_block_id,
13444
+ |conn| {
13445
+ conn. with_clarity_db_readonly ( |db| {
13446
+ db. get_account_stx_balance ( & PrincipalData :: Contract ( boot_code_id (
13447
+ SIP_031_NAME ,
13448
+ naka_conf. is_mainnet ( ) ,
13449
+ ) ) )
13450
+ } )
13451
+ } ,
13452
+ ) ;
13453
+
13454
+ assert_eq ! (
13455
+ sip_031_boot_contract_balance,
13456
+ Some ( Ok ( STXBalance :: Unlocked {
13457
+ amount: SIP_031_INITIAL_MINT
13458
+ } ) )
13459
+ ) ;
13460
+
13461
+ set_test_sip_031_emission_schedule ( None ) ;
13462
+
13463
+ coord_channel
13464
+ . lock ( )
13465
+ . expect ( "Mutex poisoned" )
13466
+ . stop_chains_coordinator ( ) ;
13467
+ run_loop_stopper. store ( false , Ordering :: SeqCst ) ;
13468
+
13469
+ run_loop_thread. join ( ) . unwrap ( ) ;
13470
+ }
0 commit comments