@@ -23,8 +23,10 @@ use std::thread::JoinHandle;
23
23
use std:: time:: { Duration , Instant } ;
24
24
use std:: { env, thread} ;
25
25
26
+ use clarity:: boot_util:: boot_code_addr;
26
27
use clarity:: vm:: ast:: ASTRules ;
27
28
use clarity:: vm:: costs:: ExecutionCost ;
29
+ use clarity:: vm:: representations:: ContractName ;
28
30
use clarity:: vm:: types:: { PrincipalData , QualifiedContractIdentifier } ;
29
31
use clarity:: vm:: { ClarityName , ClarityVersion , Value } ;
30
32
use http_types:: headers:: AUTHORIZATION ;
@@ -64,8 +66,8 @@ use stacks::chainstate::stacks::miner::{
64
66
use stacks:: chainstate:: stacks:: {
65
67
SinglesigHashMode , SinglesigSpendingCondition , StacksTransaction , TenureChangeCause ,
66
68
TenureChangePayload , TransactionAnchorMode , TransactionAuth , TransactionPayload ,
67
- TransactionPostConditionMode , TransactionPublicKeyEncoding , TransactionSpendingCondition ,
68
- TransactionVersion , MAX_BLOCK_LEN ,
69
+ TransactionPostConditionMode , TransactionPublicKeyEncoding , TransactionSmartContract ,
70
+ TransactionSpendingCondition , TransactionVersion , MAX_BLOCK_LEN ,
69
71
} ;
70
72
use stacks:: config:: { EventKeyType , InitialBalance } ;
71
73
use stacks:: core:: mempool:: { MemPoolWalkStrategy , MAXIMUM_MEMPOOL_TX_CHAINING } ;
@@ -266,14 +268,32 @@ impl TestSigningChannel {
266
268
/// Assert that the block events captured by the test observer
267
269
/// all match the miner heuristic of *exclusively* including the
268
270
/// tenure change transaction in tenure changing blocks.
269
- pub fn check_nakamoto_empty_block_heuristics ( ) {
271
+ pub fn check_nakamoto_empty_block_heuristics ( mainnet : bool ) {
270
272
let blocks = test_observer:: get_blocks ( ) ;
271
273
for block in blocks. iter ( ) {
272
274
// if its not a nakamoto block, don't check anything
273
275
if block. get ( "miner_signature" ) . is_none ( ) {
274
276
continue ;
275
277
}
278
+
276
279
let txs = test_observer:: parse_transactions ( block) ;
280
+ let has_sip_031_boot_contract_deploy = txs. iter ( ) . any ( |tx| match & tx. payload {
281
+ TransactionPayload :: SmartContract (
282
+ TransactionSmartContract {
283
+ name : contract_name,
284
+ ..
285
+ } ,
286
+ ..,
287
+ ) => {
288
+ contract_name == & ContractName :: try_from ( SIP_031_NAME . to_string ( ) ) . unwrap ( )
289
+ && tx. origin_address ( ) == boot_code_addr ( mainnet)
290
+ }
291
+ _ => false ,
292
+ } ) ;
293
+ // skip sip-031 boot contract
294
+ if has_sip_031_boot_contract_deploy {
295
+ continue ;
296
+ }
277
297
let has_tenure_change = txs. iter ( ) . any ( |tx| {
278
298
matches ! (
279
299
tx. payload,
@@ -749,6 +769,33 @@ pub fn next_block_and_process_new_stacks_block(
749
769
} )
750
770
}
751
771
772
+ /// Mine a bitcoin block, and wait until:
773
+ /// number_of_blocks has been processed by the coordinator
774
+ pub fn next_block_and_process_new_stacks_blocks (
775
+ btc_controller : & BitcoinRegtestController ,
776
+ number_of_blocks : u32 ,
777
+ timeout_secs : u64 ,
778
+ coord_channels : & Arc < Mutex < CoordinatorChannels > > ,
779
+ ) -> Result < ( ) , String > {
780
+ for _ in 0 ..number_of_blocks {
781
+ let blocks_processed_before = coord_channels
782
+ . lock ( )
783
+ . expect ( "Mutex poisoned" )
784
+ . get_stacks_blocks_processed ( ) ;
785
+ next_block_and ( btc_controller, timeout_secs, || {
786
+ let blocks_processed = coord_channels
787
+ . lock ( )
788
+ . expect ( "Mutex poisoned" )
789
+ . get_stacks_blocks_processed ( ) ;
790
+ if blocks_processed > blocks_processed_before {
791
+ return Ok ( true ) ;
792
+ }
793
+ Ok ( false )
794
+ } ) ?;
795
+ }
796
+ Ok ( ( ) )
797
+ }
798
+
752
799
/// Mine a bitcoin block, and wait until:
753
800
/// (1) a new block has been processed by the coordinator
754
801
/// (2) 2 block commits have been issued ** or ** more than 10 seconds have
@@ -1703,7 +1750,7 @@ fn simple_neon_integration() {
1703
1750
. expect ( "Prometheus metrics did not update" ) ;
1704
1751
}
1705
1752
1706
- check_nakamoto_empty_block_heuristics ( ) ;
1753
+ check_nakamoto_empty_block_heuristics ( naka_conf . is_mainnet ( ) ) ;
1707
1754
1708
1755
coord_channel
1709
1756
. lock ( )
@@ -1919,7 +1966,7 @@ fn restarting_miner() {
1919
1966
panic ! ( "Missing the following burn blocks: {missing_is_error:?}" ) ;
1920
1967
}
1921
1968
1922
- check_nakamoto_empty_block_heuristics ( ) ;
1969
+ check_nakamoto_empty_block_heuristics ( naka_conf . is_mainnet ( ) ) ;
1923
1970
1924
1971
assert ! ( tip. stacks_block_height >= block_height_pre_3_0 + 4 ) ;
1925
1972
}
@@ -2161,7 +2208,7 @@ fn flash_blocks_on_epoch_3_FLAKY() {
2161
2208
// Verify blocks before and after the gap
2162
2209
test_observer:: contains_burn_block_range ( 220 ..=( gap_start - 1 ) ) . unwrap ( ) ;
2163
2210
test_observer:: contains_burn_block_range ( ( gap_end + 1 ) ..=bhh) . unwrap ( ) ;
2164
- check_nakamoto_empty_block_heuristics ( ) ;
2211
+ check_nakamoto_empty_block_heuristics ( naka_conf . is_mainnet ( ) ) ;
2165
2212
2166
2213
info ! ( "Verified burn block ranges, including expected gap for flash blocks" ) ;
2167
2214
info ! ( "Confirmed that the gap includes the Epoch 3.0 activation height (Bitcoin block height): {epoch_3_start_height}" ) ;
@@ -2341,7 +2388,7 @@ fn mine_multiple_per_tenure_integration() {
2341
2388
"Should have mined (1 + interim_blocks_per_tenure) * tenure_count nakamoto blocks"
2342
2389
) ;
2343
2390
2344
- check_nakamoto_empty_block_heuristics ( ) ;
2391
+ check_nakamoto_empty_block_heuristics ( naka_conf . is_mainnet ( ) ) ;
2345
2392
2346
2393
coord_channel
2347
2394
. lock ( )
@@ -2593,7 +2640,7 @@ fn multiple_miners() {
2593
2640
"Should have mined (1 + interim_blocks_per_tenure) * tenure_count nakamoto blocks"
2594
2641
) ;
2595
2642
2596
- check_nakamoto_empty_block_heuristics ( ) ;
2643
+ check_nakamoto_empty_block_heuristics ( naka_conf . is_mainnet ( ) ) ;
2597
2644
2598
2645
coord_channel
2599
2646
. lock ( )
@@ -2934,7 +2981,7 @@ fn correct_burn_outs() {
2934
2981
assert_eq ! ( signer_weight, 1 , "The signer should have a weight of 1, indicating they stacked the minimum stacking amount" ) ;
2935
2982
}
2936
2983
2937
- check_nakamoto_empty_block_heuristics ( ) ;
2984
+ check_nakamoto_empty_block_heuristics ( naka_conf . is_mainnet ( ) ) ;
2938
2985
2939
2986
run_loop_thread. join ( ) . unwrap ( ) ;
2940
2987
}
@@ -9792,7 +9839,7 @@ fn skip_mining_long_tx() {
9792
9839
let bhh = u64:: from ( tip. burn_header_height ) ;
9793
9840
check_nakamoto_no_missing_blocks ( & naka_conf, 220 ..=bhh) ;
9794
9841
9795
- check_nakamoto_empty_block_heuristics ( ) ;
9842
+ check_nakamoto_empty_block_heuristics ( naka_conf . is_mainnet ( ) ) ;
9796
9843
9797
9844
coord_channel
9798
9845
. lock ( )
@@ -12845,6 +12892,10 @@ fn test_sip_031_activation() {
12845
12892
if burn_block_height
12846
12893
== naka_conf. burnchain . epochs . clone ( ) . unwrap ( ) [ StacksEpochId :: Epoch32 ] . start_height
12847
12894
{
12895
+ println ! (
12896
+ "\n \n OOPS {:?}\n \n " ,
12897
+ block. get( "transactions" ) . unwrap( ) . as_array( ) . unwrap( )
12898
+ ) ;
12848
12899
// the first transaction is the coinbase
12849
12900
coinbase_txid = Some (
12850
12901
block
@@ -13080,7 +13131,7 @@ fn test_sip_031_last_phase() {
13080
13131
) ;
13081
13132
13082
13133
// get current liquidity
13083
- let sip_031_current_liquid_ustx = chainstate
13134
+ let _sip_031_current_liquid_ustx = chainstate
13084
13135
. with_read_only_clarity_tx (
13085
13136
& sortdb
13086
13137
. index_handle_at_block ( & chainstate, & latest_stacks_block_id)
@@ -13093,16 +13144,76 @@ fn test_sip_031_last_phase() {
13093
13144
// 50 more tenures...
13094
13145
for _ in 0 ..50 {
13095
13146
let commits_before = commits_submitted. load ( Ordering :: SeqCst ) ;
13096
- next_block_and_process_new_stacks_block ( & mut btc_regtest_controller, 60 , & coord_channel)
13097
- . unwrap ( ) ;
13147
+ next_block_and_process_new_stacks_blocks (
13148
+ & mut btc_regtest_controller,
13149
+ 3 ,
13150
+ 60 ,
13151
+ & coord_channel,
13152
+ )
13153
+ . unwrap ( ) ;
13098
13154
wait_for ( 20 , || {
13099
13155
Ok ( commits_submitted. load ( Ordering :: SeqCst ) > commits_before)
13100
13156
} )
13101
13157
. unwrap ( ) ;
13158
+ }
13102
13159
13103
- let node_info = get_chain_info_opt ( & naka_conf) . unwrap ( ) ;
13160
+ let mut total_minted_and_transferred: u128 = 0 ;
13161
+
13162
+ for block in test_observer:: get_blocks ( ) {
13163
+ let burn_block_height = block. get ( "burn_block_height" ) . unwrap ( ) . as_u64 ( ) . unwrap ( ) ;
13164
+
13165
+ let sip_031_mint_and_transfer_amount =
13166
+ SIP031EmissionInterval :: get_sip_031_emission_at_height (
13167
+ burn_block_height,
13168
+ naka_conf. is_mainnet ( ) ,
13169
+ ) ;
13170
+
13171
+ let events = block. get ( "events" ) . unwrap ( ) . as_array ( ) . unwrap ( ) ;
13172
+ for event in events {
13173
+ if let Some ( mint_event) = event. get ( "stx_mint_event" ) {
13174
+ let minted_amount =
13175
+ u128:: try_from ( mint_event. get ( "amount" ) . unwrap ( ) . as_u64 ( ) . unwrap ( ) ) . unwrap ( ) ;
13176
+ assert_eq ! ( sip_031_mint_and_transfer_amount, minted_amount) ;
13177
+ total_minted_and_transferred += minted_amount;
13178
+ break ;
13179
+ }
13180
+ }
13181
+ total_minted_and_transferred += sip_031_mint_and_transfer_amount;
13104
13182
}
13105
13183
13184
+ // (100_000 + 200_000 + 300_000) * 5
13185
+ assert_eq ! ( total_minted_and_transferred, 3_000_000 ) ;
13186
+
13187
+ let latest_stacks_block_id = get_latest_block_proposal ( & naka_conf, & sortdb)
13188
+ . unwrap ( )
13189
+ . 0
13190
+ . block_id ( ) ;
13191
+
13192
+ // get sip-031 boot contract balance (will be checked for 200_000_000 STX + total_minted_and_transferred)
13193
+ let sip_031_boot_contract_balance = chainstate. with_read_only_clarity_tx (
13194
+ & sortdb
13195
+ . index_handle_at_block ( & chainstate, & latest_stacks_block_id)
13196
+ . unwrap ( ) ,
13197
+ & latest_stacks_block_id,
13198
+ |conn| {
13199
+ conn. with_clarity_db_readonly ( |db| {
13200
+ db. get_account_stx_balance ( & PrincipalData :: Contract ( boot_code_id (
13201
+ SIP_031_NAME ,
13202
+ naka_conf. is_mainnet ( ) ,
13203
+ ) ) )
13204
+ } )
13205
+ } ,
13206
+ ) ;
13207
+
13208
+ assert_eq ! (
13209
+ sip_031_boot_contract_balance,
13210
+ Some ( Ok ( STXBalance :: Unlocked {
13211
+ amount: SIP_031_INITIAL_MINT + total_minted_and_transferred
13212
+ } ) )
13213
+ ) ;
13214
+
13215
+ set_test_sip_031_emission_schedule ( None ) ;
13216
+
13106
13217
coord_channel
13107
13218
. lock ( )
13108
13219
. expect ( "Mutex poisoned" )
0 commit comments