@@ -456,7 +456,6 @@ fn block_proposal_rejection() {
456
456
let proposal_conf = ProposalEvalConfig {
457
457
first_proposal_burn_block_timing : Duration :: from_secs ( 0 ) ,
458
458
block_proposal_timeout : Duration :: from_secs ( 100 ) ,
459
- block_proposal_validation_timeout : Duration :: from_secs ( 100 ) ,
460
459
} ;
461
460
let mut block = NakamotoBlock {
462
461
header : NakamotoBlockHeader :: empty ( ) ,
@@ -5608,3 +5607,152 @@ fn multiple_miners_with_custom_chain_id() {
5608
5607
run_loop_2_thread. join ( ) . unwrap ( ) ;
5609
5608
signer_test. shutdown ( ) ;
5610
5609
}
5610
+
5611
+ // Teimout a block validation response
5612
+ #[ test]
5613
+ #[ ignore]
5614
+ fn block_validation_response_timeout ( ) {
5615
+ if env:: var ( "BITCOIND_TEST" ) != Ok ( "1" . into ( ) ) {
5616
+ return ;
5617
+ }
5618
+
5619
+ tracing_subscriber:: registry ( )
5620
+ . with ( fmt:: layer ( ) )
5621
+ . with ( EnvFilter :: from_default_env ( ) )
5622
+ . init ( ) ;
5623
+
5624
+ info ! ( "------------------------- Test Setup -------------------------" ) ;
5625
+ let num_signers = 5 ;
5626
+ let timeout = Duration :: from_secs ( 60 ) ;
5627
+ let sender_sk = Secp256k1PrivateKey :: new ( ) ;
5628
+ let sender_addr = tests:: to_addr ( & sender_sk) ;
5629
+ let send_amt = 100 ;
5630
+ let send_fee = 180 ;
5631
+ let recipient = PrincipalData :: from ( StacksAddress :: burn_address ( false ) ) ;
5632
+
5633
+ let mut signer_test: SignerTest < SpawnedSigner > = SignerTest :: new_with_config_modifications (
5634
+ num_signers,
5635
+ vec ! [ ( sender_addr. clone( ) , send_amt + send_fee) ] ,
5636
+ |config| {
5637
+ config. block_proposal_validation_timeout = timeout;
5638
+ } ,
5639
+ |_| { } ,
5640
+ None ,
5641
+ None ,
5642
+ ) ;
5643
+ let http_origin = format ! ( "http://{}" , & signer_test. running_nodes. conf. node. rpc_bind) ;
5644
+ signer_test. boot_to_epoch_3 ( ) ;
5645
+
5646
+ info ! ( "------------------------- Test Mine and Verify Confirmed Nakamoto Block -------------------------" ) ;
5647
+ signer_test. mine_and_verify_confirmed_naka_block ( timeout, num_signers) ;
5648
+ info ! ( "------------------------- Test Block Validation Stalled -------------------------" ) ;
5649
+ TEST_VALIDATE_STALL . lock ( ) . unwrap ( ) . replace ( true ) ;
5650
+ let validation_stall_start = Instant :: now ( ) ;
5651
+
5652
+ let proposals_before = signer_test
5653
+ . running_nodes
5654
+ . nakamoto_blocks_proposed
5655
+ . load ( Ordering :: SeqCst ) ;
5656
+
5657
+ // submit a tx so that the miner will attempt to mine an extra block
5658
+ let sender_nonce = 0 ;
5659
+ let transfer_tx = make_stacks_transfer (
5660
+ & sender_sk,
5661
+ sender_nonce,
5662
+ send_fee,
5663
+ signer_test. running_nodes . conf . burnchain . chain_id ,
5664
+ & recipient,
5665
+ send_amt,
5666
+ ) ;
5667
+ submit_tx ( & http_origin, & transfer_tx) ;
5668
+
5669
+ info ! ( "Submitted transfer tx and waiting for block proposal" ) ;
5670
+ wait_for ( 30 , || {
5671
+ Ok ( signer_test
5672
+ . running_nodes
5673
+ . nakamoto_blocks_proposed
5674
+ . load ( Ordering :: SeqCst )
5675
+ > proposals_before)
5676
+ } )
5677
+ . expect ( "Timed out waiting for block proposal" ) ;
5678
+
5679
+ info ! ( "------------------------- Propose Another Block -------------------------" ) ;
5680
+ let proposal_conf = ProposalEvalConfig {
5681
+ first_proposal_burn_block_timing : Duration :: from_secs ( 0 ) ,
5682
+ block_proposal_timeout : Duration :: from_secs ( 100 ) ,
5683
+ } ;
5684
+ let mut block = NakamotoBlock {
5685
+ header : NakamotoBlockHeader :: empty ( ) ,
5686
+ txs : vec ! [ ] ,
5687
+ } ;
5688
+
5689
+ // Propose a block to the signers that passes initial checks but will not be submitted to the stacks node due to the submission stall
5690
+ let view = SortitionsView :: fetch_view ( proposal_conf, & signer_test. stacks_client ) . unwrap ( ) ;
5691
+ block. header . pox_treatment = BitVec :: ones ( 1 ) . unwrap ( ) ;
5692
+ block. header . consensus_hash = view. cur_sortition . consensus_hash ;
5693
+ block. header . chain_length = 1 ; // We have mined 1 block so far
5694
+
5695
+ let block_signer_signature_hash_1 = block. header . signer_signature_hash ( ) ;
5696
+ let info_before = get_chain_info ( & signer_test. running_nodes . conf ) ;
5697
+ signer_test. propose_block ( block, Duration :: from_secs ( 30 ) ) ;
5698
+
5699
+ info ! ( "------------------------- Waiting for Timeout -------------------------" ) ;
5700
+ // Sleep the necessary timeout to make sure the validation times out.
5701
+ let elapsed = validation_stall_start. elapsed ( ) ;
5702
+ std:: thread:: sleep ( timeout. saturating_sub ( elapsed) ) ;
5703
+
5704
+ info ! ( "------------------------- Wait for Block Rejection Due to Timeout -------------------------" ) ;
5705
+ // Verify the signers rejected the first block due to timeout
5706
+ let start = Instant :: now ( ) ;
5707
+ let mut rejected_signers = vec ! [ ] ;
5708
+ let mut saw_connectivity_complaint = false ;
5709
+ while rejected_signers. len ( ) < num_signers {
5710
+ std:: thread:: sleep ( Duration :: from_secs ( 1 ) ) ;
5711
+ let chunks = test_observer:: get_stackerdb_chunks ( ) ;
5712
+ for chunk in chunks. into_iter ( ) . flat_map ( |chunk| chunk. modified_slots ) {
5713
+ let Ok ( message) = SignerMessage :: consensus_deserialize ( & mut chunk. data . as_slice ( ) )
5714
+ else {
5715
+ continue ;
5716
+ } ;
5717
+ if let SignerMessage :: BlockResponse ( BlockResponse :: Rejected ( BlockRejection {
5718
+ reason : _reason,
5719
+ reason_code,
5720
+ signer_signature_hash,
5721
+ signature,
5722
+ ..
5723
+ } ) ) = message
5724
+ {
5725
+ if signer_signature_hash == block_signer_signature_hash_1 {
5726
+ rejected_signers. push ( signature) ;
5727
+ if matches ! ( reason_code, RejectCode :: ConnectivityIssues ) {
5728
+ saw_connectivity_complaint = true ;
5729
+ }
5730
+ }
5731
+ }
5732
+ }
5733
+ assert ! (
5734
+ start. elapsed( ) <= Duration :: from_secs( 10 ) ,
5735
+ "Timed out after waiting for response from signer"
5736
+ ) ;
5737
+ }
5738
+
5739
+ assert ! (
5740
+ saw_connectivity_complaint,
5741
+ "We did not see the expected connectity rejection reason"
5742
+ ) ;
5743
+ // Make sure our chain has still not advanced
5744
+ let info_after = get_chain_info ( & signer_test. running_nodes . conf ) ;
5745
+ assert_eq ! ( info_before, info_after) ;
5746
+
5747
+ info ! ( "Unpausing block validation" ) ;
5748
+ // Disable the stall and wait for the block to be processed
5749
+ TEST_VALIDATE_STALL . lock ( ) . unwrap ( ) . replace ( false ) ;
5750
+
5751
+ info ! ( "------------------------- Test Mine and Verify Confirmed Nakamoto Block -------------------------" ) ;
5752
+ signer_test. mine_and_verify_confirmed_naka_block ( timeout, num_signers) ;
5753
+
5754
+ assert_eq ! (
5755
+ get_chain_info( & signer_test. running_nodes. conf) . stacks_tip_height,
5756
+ info_before. stacks_tip_height + 1 ,
5757
+ ) ;
5758
+ }
0 commit comments