@@ -230,6 +230,32 @@ impl TestSigningChannel {
230
230
}
231
231
}
232
232
233
+ /// Assert that the block events captured by the test observer
234
+ /// all match the miner heuristic of *exclusively* including the
235
+ /// tenure change transaction in tenure changing blocks.
236
+ pub fn check_nakamoto_empty_block_heuristics ( ) {
237
+ let blocks = test_observer:: get_blocks ( ) ;
238
+ for block in blocks. iter ( ) {
239
+ // if its not a nakamoto block, don't check anything
240
+ if block. get ( "miner_signature" ) . is_none ( ) {
241
+ continue ;
242
+ }
243
+ let txs = test_observer:: parse_transactions ( block) ;
244
+ let has_tenure_change = txs
245
+ . iter ( )
246
+ . any ( |tx| matches ! ( tx. payload, TransactionPayload :: TenureChange ( _) ) ) ;
247
+ if has_tenure_change {
248
+ let only_coinbase_and_tenure_change = txs. iter ( ) . all ( |tx| {
249
+ matches ! (
250
+ tx. payload,
251
+ TransactionPayload :: TenureChange ( _) | TransactionPayload :: Coinbase ( ..)
252
+ )
253
+ } ) ;
254
+ assert ! ( only_coinbase_and_tenure_change, "Nakamoto blocks with a tenure change in them should only have coinbase or tenure changes" ) ;
255
+ }
256
+ }
257
+ }
258
+
233
259
pub fn get_stacker_set ( http_origin : & str , cycle : u64 ) -> GetStackersResponse {
234
260
let client = reqwest:: blocking:: Client :: new ( ) ;
235
261
let path = format ! ( "{http_origin}/v3/stacker_set/{cycle}" ) ;
@@ -1683,6 +1709,8 @@ fn simple_neon_integration() {
1683
1709
assert ! ( res. contains( & expected_result) ) ;
1684
1710
}
1685
1711
1712
+ check_nakamoto_empty_block_heuristics ( ) ;
1713
+
1686
1714
coord_channel
1687
1715
. lock ( )
1688
1716
. expect ( "Mutex poisoned" )
@@ -1960,6 +1988,7 @@ fn flash_blocks_on_epoch_3() {
1960
1988
// Verify blocks before and after the gap
1961
1989
test_observer:: contains_burn_block_range ( 220 ..=( gap_start - 1 ) ) . unwrap ( ) ;
1962
1990
test_observer:: contains_burn_block_range ( ( gap_end + 1 ) ..=bhh) . unwrap ( ) ;
1991
+ check_nakamoto_empty_block_heuristics ( ) ;
1963
1992
1964
1993
info ! ( "Verified burn block ranges, including expected gap for flash blocks" ) ;
1965
1994
info ! ( "Confirmed that the gap includes the Epoch 3.0 activation height (Bitcoin block height): {}" , epoch_3_start_height) ;
@@ -2141,6 +2170,8 @@ fn mine_multiple_per_tenure_integration() {
2141
2170
"Should have mined (1 + interim_blocks_per_tenure) * tenure_count nakamoto blocks"
2142
2171
) ;
2143
2172
2173
+ check_nakamoto_empty_block_heuristics ( ) ;
2174
+
2144
2175
coord_channel
2145
2176
. lock ( )
2146
2177
. expect ( "Mutex poisoned" )
@@ -2394,6 +2425,8 @@ fn multiple_miners() {
2394
2425
"Should have mined (1 + interim_blocks_per_tenure) * tenure_count nakamoto blocks"
2395
2426
) ;
2396
2427
2428
+ check_nakamoto_empty_block_heuristics ( ) ;
2429
+
2397
2430
coord_channel
2398
2431
. lock ( )
2399
2432
. expect ( "Mutex poisoned" )
@@ -2761,6 +2794,8 @@ fn correct_burn_outs() {
2761
2794
assert_eq ! ( signer_weight, 1 , "The signer should have a weight of 1, indicating they stacked the minimum stacking amount" ) ;
2762
2795
}
2763
2796
2797
+ check_nakamoto_empty_block_heuristics ( ) ;
2798
+
2764
2799
run_loop_thread. join ( ) . unwrap ( ) ;
2765
2800
}
2766
2801
0 commit comments