@@ -5074,6 +5074,201 @@ fn miner_recovers_when_broadcast_block_delay_across_tenures_occurs() {
5074
5074
assert_ne ! ( block_n_2, block_n) ;
5075
5075
}
5076
5076
5077
+ /// Test a scenario where:
5078
+ /// We have one miner. During block A, there is a sortition and a TenureChange.
5079
+ /// Block B is mined, but it does not contain a TenureChange (ie because a
5080
+ /// new burn block was mined too quickly).
5081
+ /// Then block C occurs, which does not have a sortition.
5082
+ #[ test]
5083
+ #[ ignore]
5084
+ fn continue_after_fast_block_no_sortition ( ) {
5085
+ if env:: var ( "BITCOIND_TEST" ) != Ok ( "1" . into ( ) ) {
5086
+ return ;
5087
+ }
5088
+
5089
+ tracing_subscriber:: registry ( )
5090
+ . with ( fmt:: layer ( ) )
5091
+ . with ( EnvFilter :: from_default_env ( ) )
5092
+ . init ( ) ;
5093
+
5094
+ info ! ( "------------------------- Test Setup -------------------------" ) ;
5095
+ let num_signers = 5 ;
5096
+ let sender_sk = Secp256k1PrivateKey :: new ( ) ;
5097
+ let sender_addr = tests:: to_addr ( & sender_sk) ;
5098
+ let _recipient = PrincipalData :: from ( StacksAddress :: burn_address ( false ) ) ;
5099
+ let send_amt = 100 ;
5100
+ let send_fee = 180 ;
5101
+ let mut signer_test: SignerTest < SpawnedSigner > = SignerTest :: new (
5102
+ num_signers,
5103
+ vec ! [ ( sender_addr. clone( ) , ( send_amt + send_fee) * 5 ) ] ,
5104
+ ) ;
5105
+ let timeout = Duration :: from_secs ( 200 ) ;
5106
+ let _coord_channel = signer_test. running_nodes . coord_channel . clone ( ) ;
5107
+ let _http_origin = format ! ( "http://{}" , & signer_test. running_nodes. conf. node. rpc_bind) ;
5108
+
5109
+ signer_test. boot_to_epoch_3 ( ) ;
5110
+
5111
+ let burnchain = signer_test. running_nodes . conf . get_burnchain ( ) ;
5112
+ let sortdb = burnchain. open_sortition_db ( true ) . unwrap ( ) ;
5113
+
5114
+ let get_burn_height = || {
5115
+ SortitionDB :: get_canonical_burn_chain_tip ( & sortdb. conn ( ) )
5116
+ . unwrap ( )
5117
+ . block_height
5118
+ } ;
5119
+
5120
+ let all_signers = signer_test
5121
+ . signer_stacks_private_keys
5122
+ . iter ( )
5123
+ . map ( StacksPublicKey :: from_private)
5124
+ . collect :: < Vec < _ > > ( ) ;
5125
+
5126
+ let commits_before = signer_test
5127
+ . running_nodes
5128
+ . commits_submitted
5129
+ . load ( Ordering :: SeqCst ) ;
5130
+
5131
+ info ! ( "------------------------- Mine Normal Tenure -------------------------" ) ;
5132
+ signer_test. mine_and_verify_confirmed_naka_block ( timeout, num_signers) ;
5133
+
5134
+ let stacks_height_before = signer_test
5135
+ . stacks_client
5136
+ . get_peer_info ( )
5137
+ . expect ( "Failed to get peer info" )
5138
+ . stacks_tip_height ;
5139
+
5140
+ // Wait for a new block commit
5141
+ wait_for ( 20 , || {
5142
+ let commits = signer_test
5143
+ . running_nodes
5144
+ . commits_submitted
5145
+ . load ( Ordering :: SeqCst ) ;
5146
+ // 2 because we mined one block in the normal tenure
5147
+ Ok ( commits - commits_before >= 2 )
5148
+ } )
5149
+ . expect ( "Timed out waiting for a new block commit" ) ;
5150
+
5151
+ // Make all signers ignore block proposals
5152
+ let ignoring_signers: Vec < _ > = all_signers. iter ( ) . cloned ( ) . collect ( ) ;
5153
+ TEST_REJECT_ALL_BLOCK_PROPOSAL
5154
+ . lock ( )
5155
+ . unwrap ( )
5156
+ . replace ( ignoring_signers. clone ( ) ) ;
5157
+
5158
+ // Don't make future block commits
5159
+ signer_test
5160
+ . running_nodes
5161
+ . nakamoto_test_skip_commit_op
5162
+ . set ( true ) ;
5163
+
5164
+ let burn_height_before = get_burn_height ( ) ;
5165
+
5166
+ let rejections_before = signer_test
5167
+ . running_nodes
5168
+ . nakamoto_blocks_rejected
5169
+ . load ( Ordering :: SeqCst ) ;
5170
+
5171
+ // Mine a new burn block
5172
+ info ! ( "------------------------- Starting Tenure B -------------------------" ;
5173
+ "burn_height_before" => burn_height_before,
5174
+ "rejections_before" => rejections_before,
5175
+ ) ;
5176
+
5177
+ next_block_and (
5178
+ & mut signer_test. running_nodes . btc_regtest_controller ,
5179
+ 60 ,
5180
+ || Ok ( get_burn_height ( ) > burn_height_before) ,
5181
+ )
5182
+ . unwrap ( ) ;
5183
+
5184
+ // assure we have a sortition
5185
+ let tip = SortitionDB :: get_canonical_burn_chain_tip ( & sortdb. conn ( ) ) . unwrap ( ) ;
5186
+ assert ! ( tip. sortition) ;
5187
+
5188
+ let burn_height_before = signer_test
5189
+ . stacks_client
5190
+ . get_peer_info ( )
5191
+ . expect ( "Failed to get peer info" )
5192
+ . burn_block_height ;
5193
+
5194
+ info ! ( "----- Waiting for block rejections -----" ) ;
5195
+ let min_rejections = ( num_signers as u64 ) * 4 / 10 ;
5196
+ // Wait until we have some block rejections
5197
+ wait_for ( 30 , || {
5198
+ let rejections = signer_test
5199
+ . running_nodes
5200
+ . nakamoto_blocks_rejected
5201
+ . load ( Ordering :: SeqCst ) ;
5202
+ let rejections_diff = rejections - rejections_before;
5203
+ Ok ( rejections_diff >= min_rejections)
5204
+ } )
5205
+ . expect ( "Timed out waiting for block rejections" ) ;
5206
+
5207
+ // Miner another block and ensure there is _no_ sortition
5208
+ info ! ( "------------------------- Mine another block -------------------------" ) ;
5209
+ next_block_and (
5210
+ & mut signer_test. running_nodes . btc_regtest_controller ,
5211
+ 60 ,
5212
+ || {
5213
+ let burn_height = signer_test
5214
+ . stacks_client
5215
+ . get_peer_info ( )
5216
+ . expect ( "Failed to get peer info" )
5217
+ . burn_block_height ;
5218
+ Ok ( burn_height > burn_height_before)
5219
+ } ,
5220
+ )
5221
+ . unwrap ( ) ;
5222
+
5223
+ // Verify that no Stacks blocks have been mined (signers are ignoring)
5224
+ let stacks_height = signer_test
5225
+ . stacks_client
5226
+ . get_peer_info ( )
5227
+ . expect ( "Failed to get peer info" )
5228
+ . stacks_tip_height ;
5229
+ assert_eq ! ( stacks_height, stacks_height_before) ;
5230
+
5231
+ let stacks_height_before = stacks_height;
5232
+
5233
+ info ! ( "----- Enabling signers to approve proposals -----" ;
5234
+ "stacks_height" => stacks_height_before,
5235
+ ) ;
5236
+
5237
+ // Allow signers to respond to proposals again
5238
+ TEST_REJECT_ALL_BLOCK_PROPOSAL
5239
+ . lock ( )
5240
+ . unwrap ( )
5241
+ . replace ( Vec :: new ( ) ) ;
5242
+
5243
+ wait_for ( 30 , || {
5244
+ let stacks_height = signer_test
5245
+ . stacks_client
5246
+ . get_peer_info ( )
5247
+ . expect ( "Failed to get peer info" )
5248
+ . stacks_tip_height ;
5249
+ Ok ( stacks_height > stacks_height_before)
5250
+ } )
5251
+ . expect ( "Expected a new Stacks block to be mined" ) ;
5252
+
5253
+ let blocks = test_observer:: get_blocks ( ) ;
5254
+ // Debug the last 4 blocks
5255
+ let blocks = blocks. iter ( ) . rev ( ) . take ( 4 ) . rev ( ) . collect :: < Vec < _ > > ( ) ;
5256
+ for block in blocks {
5257
+ println ! ( "\n \n " ) ;
5258
+ info ! ( "Block: {}" , serde_json:: to_string_pretty( & block) . unwrap( ) ) ;
5259
+ let transactions = block. get ( "transactions" ) . unwrap ( ) . as_array ( ) . unwrap ( ) ;
5260
+ for tx in transactions. iter ( ) . rev ( ) {
5261
+ let raw_tx = tx. get ( "raw_tx" ) . unwrap ( ) . as_str ( ) . unwrap ( ) ;
5262
+ if raw_tx != "0x00" {
5263
+ let tx_bytes = hex_bytes ( & raw_tx[ 2 ..] ) . unwrap ( ) ;
5264
+ let parsed =
5265
+ StacksTransaction :: consensus_deserialize ( & mut tx_bytes. as_slice ( ) ) . unwrap ( ) ;
5266
+ info ! ( "Tx: {}" , serde_json:: to_string_pretty( & parsed) . unwrap( ) ) ;
5267
+ }
5268
+ }
5269
+ }
5270
+ }
5271
+
5077
5272
#[ test]
5078
5273
#[ ignore]
5079
5274
/// Test that we can mine a tenure extend and then continue mining afterwards.
0 commit comments