@@ -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 ( ) ;
@@ -2532,12 +2517,10 @@ fn mock_sign_epoch_25() {
2532
2517
{
2533
2518
let mut mock_block_mesage = None ;
2534
2519
let mock_poll_time = Instant :: now ( ) ;
2535
- next_block_and (
2536
- & mut signer_test. running_nodes . btc_regtest_controller ,
2537
- 60 ,
2538
- || Ok ( true ) ,
2539
- )
2540
- . unwrap ( ) ;
2520
+ signer_test
2521
+ . running_nodes
2522
+ . btc_regtest_controller
2523
+ . build_next_block ( 1 ) ;
2541
2524
let current_burn_block_height = signer_test
2542
2525
. running_nodes
2543
2526
. btc_regtest_controller
@@ -2744,12 +2727,10 @@ fn multiple_miners_mock_sign_epoch_25() {
2744
2727
{
2745
2728
let mut mock_block_mesage = None ;
2746
2729
let mock_poll_time = Instant :: now ( ) ;
2747
- next_block_and (
2748
- & mut signer_test. running_nodes . btc_regtest_controller ,
2749
- 60 ,
2750
- || Ok ( true ) ,
2751
- )
2752
- . unwrap ( ) ;
2730
+ signer_test
2731
+ . running_nodes
2732
+ . btc_regtest_controller
2733
+ . build_next_block ( 1 ) ;
2753
2734
let current_burn_block_height = signer_test
2754
2735
. running_nodes
2755
2736
. btc_regtest_controller
@@ -4536,21 +4517,11 @@ fn miner_recovers_when_broadcast_block_delay_across_tenures_occurs() {
4536
4517
let burnchain = signer_test. running_nodes . conf . get_burnchain ( ) ;
4537
4518
let sortdb = burnchain. open_sortition_db ( true ) . unwrap ( ) ;
4538
4519
4539
- loop {
4540
- next_block_and (
4541
- & mut signer_test. running_nodes . btc_regtest_controller ,
4542
- 60 ,
4543
- || Ok ( true ) ,
4544
- )
4545
- . unwrap ( ) ;
4546
-
4547
- sleep_ms ( 10_000 ) ;
4548
-
4520
+ wait_for ( 30 , || {
4549
4521
let tip = SortitionDB :: get_canonical_burn_chain_tip ( & sortdb. conn ( ) ) . unwrap ( ) ;
4550
- if tip. sortition {
4551
- break ;
4552
- }
4553
- }
4522
+ Ok ( tip. sortition )
4523
+ } )
4524
+ . expect ( "Timed out waiting for sortition" ) ;
4554
4525
4555
4526
// submit a tx so that the miner will mine a stacks block
4556
4527
let mut sender_nonce = 0 ;
@@ -4811,3 +4782,97 @@ fn miner_recovers_when_broadcast_block_delay_across_tenures_occurs() {
4811
4782
assert_eq ! ( info_after. stacks_tip. to_string( ) , block_n_2. block_hash) ;
4812
4783
assert_ne ! ( block_n_2, block_n) ;
4813
4784
}
4785
+
4786
+ #[ test]
4787
+ #[ ignore]
4788
+ /// Test that signers can successfully sign a block proposal in the 0th tenure of a reward cycle
4789
+ /// This ensures there is no race condition in the /v2/pox endpoint which could prevent it from updating
4790
+ /// on time, possibly triggering an "off by one" like behaviour in the 0th tenure.
4791
+ ///
4792
+ fn signing_in_0th_tenure_of_reward_cycle ( ) {
4793
+ if env:: var ( "BITCOIND_TEST" ) != Ok ( "1" . into ( ) ) {
4794
+ return ;
4795
+ }
4796
+
4797
+ tracing_subscriber:: registry ( )
4798
+ . with ( fmt:: layer ( ) )
4799
+ . with ( EnvFilter :: from_default_env ( ) )
4800
+ . init ( ) ;
4801
+
4802
+ info ! ( "------------------------- Test Setup -------------------------" ) ;
4803
+ let num_signers = 5 ;
4804
+ let mut signer_test: SignerTest < SpawnedSigner > = SignerTest :: new ( num_signers, vec ! [ ] ) ;
4805
+ let signer_public_keys = signer_test
4806
+ . signer_stacks_private_keys
4807
+ . iter ( )
4808
+ . map ( StacksPublicKey :: from_private)
4809
+ . collect :: < Vec < _ > > ( ) ;
4810
+ let long_timeout = Duration :: from_secs ( 200 ) ;
4811
+ signer_test. boot_to_epoch_3 ( ) ;
4812
+ let curr_reward_cycle = signer_test. get_current_reward_cycle ( ) ;
4813
+ let next_reward_cycle = curr_reward_cycle + 1 ;
4814
+ // Mine until the boundary of the first full Nakamoto reward cycles (epoch 3 starts in the middle of one)
4815
+ let next_reward_cycle_height_boundary = signer_test
4816
+ . running_nodes
4817
+ . btc_regtest_controller
4818
+ . get_burnchain ( )
4819
+ . reward_cycle_to_block_height ( next_reward_cycle)
4820
+ . saturating_sub ( 1 ) ;
4821
+
4822
+ info ! ( "------------------------- Advancing to {next_reward_cycle} Boundary at Block {next_reward_cycle_height_boundary} -------------------------" ) ;
4823
+ signer_test. run_until_burnchain_height_nakamoto (
4824
+ long_timeout,
4825
+ next_reward_cycle_height_boundary,
4826
+ num_signers,
4827
+ ) ;
4828
+
4829
+ let http_origin = format ! ( "http://{}" , & signer_test. running_nodes. conf. node. rpc_bind) ;
4830
+ let get_v3_signer = |pubkey : & Secp256k1PublicKey , reward_cycle : u64 | {
4831
+ let url = & format ! (
4832
+ "{http_origin}/v3/signer/{pk}/{reward_cycle}" ,
4833
+ pk = pubkey. to_hex( )
4834
+ ) ;
4835
+ info ! ( "Send request: GET {url}" ) ;
4836
+ reqwest:: blocking:: get ( url)
4837
+ . unwrap_or_else ( |e| panic ! ( "GET request failed: {e}" ) )
4838
+ . json :: < GetSignerResponse > ( )
4839
+ . unwrap ( )
4840
+ . blocks_signed
4841
+ } ;
4842
+
4843
+ assert_eq ! ( signer_test. get_current_reward_cycle( ) , curr_reward_cycle) ;
4844
+
4845
+ for signer in & signer_public_keys {
4846
+ let blocks_signed = get_v3_signer ( & signer, next_reward_cycle) ;
4847
+ assert_eq ! ( blocks_signed, 0 ) ;
4848
+ }
4849
+
4850
+ info ! ( "------------------------- Enter Reward Cycle {next_reward_cycle} -------------------------" ) ;
4851
+ for signer in & signer_public_keys {
4852
+ let blocks_signed = get_v3_signer ( & signer, next_reward_cycle) ;
4853
+ assert_eq ! ( blocks_signed, 0 ) ;
4854
+ }
4855
+ let blocks_before = signer_test
4856
+ . running_nodes
4857
+ . nakamoto_blocks_mined
4858
+ . load ( Ordering :: SeqCst ) ;
4859
+ signer_test
4860
+ . running_nodes
4861
+ . btc_regtest_controller
4862
+ . build_next_block ( 1 ) ;
4863
+
4864
+ wait_for ( 30 , || {
4865
+ Ok ( signer_test
4866
+ . running_nodes
4867
+ . nakamoto_blocks_mined
4868
+ . load ( Ordering :: SeqCst )
4869
+ > blocks_before)
4870
+ } )
4871
+ . unwrap ( ) ;
4872
+
4873
+ for signer in & signer_public_keys {
4874
+ let blocks_signed = get_v3_signer ( & signer, next_reward_cycle) ;
4875
+ assert_eq ! ( blocks_signed, 1 ) ;
4876
+ }
4877
+ assert_eq ! ( signer_test. get_current_reward_cycle( ) , next_reward_cycle) ;
4878
+ }
0 commit comments