@@ -35,6 +35,7 @@ use stacks::chainstate::stacks::db::{StacksBlockHeaderTypes, StacksChainState, S
35
35
use stacks:: codec:: StacksMessageCodec ;
36
36
use stacks:: core:: { StacksEpochId , CHAIN_ID_TESTNET } ;
37
37
use stacks:: libstackerdb:: StackerDBChunkData ;
38
+ use stacks:: net:: api:: getsigner:: GetSignerResponse ;
38
39
use stacks:: net:: api:: postblock_proposal:: { ValidateRejectCode , TEST_VALIDATE_STALL } ;
39
40
use stacks:: net:: relay:: fault_injection:: set_ignore_block;
40
41
use stacks:: types:: chainstate:: { StacksAddress , StacksBlockId , StacksPrivateKey , StacksPublicKey } ;
@@ -1991,35 +1992,29 @@ fn end_of_tenure() {
1991
1992
std:: thread:: sleep ( Duration :: from_millis ( 100 ) ) ;
1992
1993
}
1993
1994
1994
- while signer_test. get_current_reward_cycle ( ) != final_reward_cycle {
1995
- next_block_and (
1996
- & mut signer_test. running_nodes . btc_regtest_controller ,
1997
- 10 ,
1998
- || Ok ( true ) ,
1999
- )
2000
- . unwrap ( ) ;
2001
- assert ! (
2002
- start_time. elapsed( ) <= short_timeout,
2003
- "Timed out waiting to enter the next reward cycle"
2004
- ) ;
2005
- std:: thread:: sleep ( Duration :: from_millis ( 100 ) ) ;
2006
- }
1995
+ wait_for ( short_timeout. as_secs ( ) , || {
1996
+ let result = signer_test. get_current_reward_cycle ( ) == final_reward_cycle;
1997
+ if !result {
1998
+ signer_test
1999
+ . running_nodes
2000
+ . btc_regtest_controller
2001
+ . build_next_block ( 1 ) ;
2002
+ }
2003
+ Ok ( result)
2004
+ } )
2005
+ . expect ( "Timed out waiting to enter the next reward cycle" ) ;
2007
2006
2008
- while test_observer:: get_burn_blocks ( )
2009
- . last ( )
2010
- . unwrap ( )
2011
- . get ( "burn_block_height" )
2012
- . unwrap ( )
2013
- . as_u64 ( )
2014
- . unwrap ( )
2015
- < final_reward_cycle_height_boundary + 1
2016
- {
2017
- assert ! (
2018
- start_time. elapsed( ) <= short_timeout,
2019
- "Timed out waiting for burn block events"
2020
- ) ;
2021
- std:: thread:: sleep ( Duration :: from_millis ( 100 ) ) ;
2022
- }
2007
+ wait_for ( short_timeout. as_secs ( ) , || {
2008
+ let blocks = test_observer:: get_burn_blocks ( )
2009
+ . last ( )
2010
+ . unwrap ( )
2011
+ . get ( "burn_block_height" )
2012
+ . unwrap ( )
2013
+ . as_u64 ( )
2014
+ . unwrap ( ) ;
2015
+ Ok ( blocks > final_reward_cycle_height_boundary)
2016
+ } )
2017
+ . expect ( "Timed out waiting for burn block events" ) ;
2023
2018
2024
2019
signer_test. wait_for_cycle ( 30 , final_reward_cycle) ;
2025
2020
@@ -2077,21 +2072,11 @@ fn retry_on_rejection() {
2077
2072
let burnchain = signer_test. running_nodes . conf . get_burnchain ( ) ;
2078
2073
let sortdb = burnchain. open_sortition_db ( true ) . unwrap ( ) ;
2079
2074
2080
- loop {
2081
- next_block_and (
2082
- & mut signer_test. running_nodes . btc_regtest_controller ,
2083
- 60 ,
2084
- || Ok ( true ) ,
2085
- )
2086
- . unwrap ( ) ;
2087
-
2088
- sleep_ms ( 10_000 ) ;
2089
-
2075
+ wait_for ( 30 , || {
2090
2076
let tip = SortitionDB :: get_canonical_burn_chain_tip ( & sortdb. conn ( ) ) . unwrap ( ) ;
2091
- if tip. sortition {
2092
- break ;
2093
- }
2094
- }
2077
+ Ok ( tip. sortition )
2078
+ } )
2079
+ . expect ( "Timed out waiting for sortition" ) ;
2095
2080
2096
2081
// mine a nakamoto block
2097
2082
let mined_blocks = signer_test. running_nodes . nakamoto_blocks_mined . clone ( ) ;
@@ -2533,12 +2518,10 @@ fn mock_sign_epoch_25() {
2533
2518
{
2534
2519
let mut mock_block_mesage = None ;
2535
2520
let mock_poll_time = Instant :: now ( ) ;
2536
- next_block_and (
2537
- & mut signer_test. running_nodes . btc_regtest_controller ,
2538
- 60 ,
2539
- || Ok ( true ) ,
2540
- )
2541
- . unwrap ( ) ;
2521
+ signer_test
2522
+ . running_nodes
2523
+ . btc_regtest_controller
2524
+ . build_next_block ( 1 ) ;
2542
2525
let current_burn_block_height = signer_test
2543
2526
. running_nodes
2544
2527
. btc_regtest_controller
@@ -2746,12 +2729,10 @@ fn multiple_miners_mock_sign_epoch_25() {
2746
2729
{
2747
2730
let mut mock_block_mesage = None ;
2748
2731
let mock_poll_time = Instant :: now ( ) ;
2749
- next_block_and (
2750
- & mut signer_test. running_nodes . btc_regtest_controller ,
2751
- 60 ,
2752
- || Ok ( true ) ,
2753
- )
2754
- . unwrap ( ) ;
2732
+ signer_test
2733
+ . running_nodes
2734
+ . btc_regtest_controller
2735
+ . build_next_block ( 1 ) ;
2755
2736
let current_burn_block_height = signer_test
2756
2737
. running_nodes
2757
2738
. btc_regtest_controller
@@ -4546,21 +4527,11 @@ fn miner_recovers_when_broadcast_block_delay_across_tenures_occurs() {
4546
4527
let burnchain = signer_test. running_nodes . conf . get_burnchain ( ) ;
4547
4528
let sortdb = burnchain. open_sortition_db ( true ) . unwrap ( ) ;
4548
4529
4549
- loop {
4550
- next_block_and (
4551
- & mut signer_test. running_nodes . btc_regtest_controller ,
4552
- 60 ,
4553
- || Ok ( true ) ,
4554
- )
4555
- . unwrap ( ) ;
4556
-
4557
- sleep_ms ( 10_000 ) ;
4558
-
4530
+ wait_for ( 30 , || {
4559
4531
let tip = SortitionDB :: get_canonical_burn_chain_tip ( & sortdb. conn ( ) ) . unwrap ( ) ;
4560
- if tip. sortition {
4561
- break ;
4562
- }
4563
- }
4532
+ Ok ( tip. sortition )
4533
+ } )
4534
+ . expect ( "Timed out waiting for sortition" ) ;
4564
4535
4565
4536
// submit a tx so that the miner will mine a stacks block
4566
4537
let mut sender_nonce = 0 ;
@@ -4821,3 +4792,97 @@ fn miner_recovers_when_broadcast_block_delay_across_tenures_occurs() {
4821
4792
assert_eq ! ( info_after. stacks_tip. to_string( ) , block_n_2. block_hash) ;
4822
4793
assert_ne ! ( block_n_2, block_n) ;
4823
4794
}
4795
+
4796
+ #[ test]
4797
+ #[ ignore]
4798
+ /// Test that signers can successfully sign a block proposal in the 0th tenure of a reward cycle
4799
+ /// This ensures there is no race condition in the /v2/pox endpoint which could prevent it from updating
4800
+ /// on time, possibly triggering an "off by one" like behaviour in the 0th tenure.
4801
+ ///
4802
+ fn signing_in_0th_tenure_of_reward_cycle ( ) {
4803
+ if env:: var ( "BITCOIND_TEST" ) != Ok ( "1" . into ( ) ) {
4804
+ return ;
4805
+ }
4806
+
4807
+ tracing_subscriber:: registry ( )
4808
+ . with ( fmt:: layer ( ) )
4809
+ . with ( EnvFilter :: from_default_env ( ) )
4810
+ . init ( ) ;
4811
+
4812
+ info ! ( "------------------------- Test Setup -------------------------" ) ;
4813
+ let num_signers = 5 ;
4814
+ let mut signer_test: SignerTest < SpawnedSigner > = SignerTest :: new ( num_signers, vec ! [ ] ) ;
4815
+ let signer_public_keys = signer_test
4816
+ . signer_stacks_private_keys
4817
+ . iter ( )
4818
+ . map ( StacksPublicKey :: from_private)
4819
+ . collect :: < Vec < _ > > ( ) ;
4820
+ let long_timeout = Duration :: from_secs ( 200 ) ;
4821
+ signer_test. boot_to_epoch_3 ( ) ;
4822
+ let curr_reward_cycle = signer_test. get_current_reward_cycle ( ) ;
4823
+ let next_reward_cycle = curr_reward_cycle + 1 ;
4824
+ // Mine until the boundary of the first full Nakamoto reward cycles (epoch 3 starts in the middle of one)
4825
+ let next_reward_cycle_height_boundary = signer_test
4826
+ . running_nodes
4827
+ . btc_regtest_controller
4828
+ . get_burnchain ( )
4829
+ . reward_cycle_to_block_height ( next_reward_cycle)
4830
+ . saturating_sub ( 1 ) ;
4831
+
4832
+ info ! ( "------------------------- Advancing to {next_reward_cycle} Boundary at Block {next_reward_cycle_height_boundary} -------------------------" ) ;
4833
+ signer_test. run_until_burnchain_height_nakamoto (
4834
+ long_timeout,
4835
+ next_reward_cycle_height_boundary,
4836
+ num_signers,
4837
+ ) ;
4838
+
4839
+ let http_origin = format ! ( "http://{}" , & signer_test. running_nodes. conf. node. rpc_bind) ;
4840
+ let get_v3_signer = |pubkey : & Secp256k1PublicKey , reward_cycle : u64 | {
4841
+ let url = & format ! (
4842
+ "{http_origin}/v3/signer/{pk}/{reward_cycle}" ,
4843
+ pk = pubkey. to_hex( )
4844
+ ) ;
4845
+ info ! ( "Send request: GET {url}" ) ;
4846
+ reqwest:: blocking:: get ( url)
4847
+ . unwrap_or_else ( |e| panic ! ( "GET request failed: {e}" ) )
4848
+ . json :: < GetSignerResponse > ( )
4849
+ . unwrap ( )
4850
+ . blocks_signed
4851
+ } ;
4852
+
4853
+ assert_eq ! ( signer_test. get_current_reward_cycle( ) , curr_reward_cycle) ;
4854
+
4855
+ for signer in & signer_public_keys {
4856
+ let blocks_signed = get_v3_signer ( & signer, next_reward_cycle) ;
4857
+ assert_eq ! ( blocks_signed, 0 ) ;
4858
+ }
4859
+
4860
+ info ! ( "------------------------- Enter Reward Cycle {next_reward_cycle} -------------------------" ) ;
4861
+ for signer in & signer_public_keys {
4862
+ let blocks_signed = get_v3_signer ( & signer, next_reward_cycle) ;
4863
+ assert_eq ! ( blocks_signed, 0 ) ;
4864
+ }
4865
+ let blocks_before = signer_test
4866
+ . running_nodes
4867
+ . nakamoto_blocks_mined
4868
+ . load ( Ordering :: SeqCst ) ;
4869
+ signer_test
4870
+ . running_nodes
4871
+ . btc_regtest_controller
4872
+ . build_next_block ( 1 ) ;
4873
+
4874
+ wait_for ( 30 , || {
4875
+ Ok ( signer_test
4876
+ . running_nodes
4877
+ . nakamoto_blocks_mined
4878
+ . load ( Ordering :: SeqCst )
4879
+ > blocks_before)
4880
+ } )
4881
+ . unwrap ( ) ;
4882
+
4883
+ for signer in & signer_public_keys {
4884
+ let blocks_signed = get_v3_signer ( & signer, next_reward_cycle) ;
4885
+ assert_eq ! ( blocks_signed, 1 ) ;
4886
+ }
4887
+ assert_eq ! ( signer_test. get_current_reward_cycle( ) , next_reward_cycle) ;
4888
+ }
0 commit comments