@@ -37,6 +37,7 @@ use std::time::{Duration, Instant};
37
37
38
38
use clarity:: boot_util:: boot_code_id;
39
39
use clarity:: vm:: types:: PrincipalData ;
40
+ use libsigner:: v0:: messages:: { BlockResponse , RejectCode , SignerMessage } ;
40
41
use libsigner:: { SignerEntries , SignerEventTrait } ;
41
42
use stacks:: chainstate:: coordinator:: comm:: CoordinatorChannels ;
42
43
use stacks:: chainstate:: nakamoto:: signer_set:: NakamotoSigners ;
@@ -46,7 +47,9 @@ use stacks::core::StacksEpoch;
46
47
use stacks:: net:: api:: postblock_proposal:: {
47
48
BlockValidateOk , BlockValidateReject , BlockValidateResponse ,
48
49
} ;
49
- use stacks:: types:: chainstate:: StacksAddress ;
50
+ use stacks:: types:: chainstate:: { StacksAddress , StacksPublicKey } ;
51
+ use stacks:: types:: PublicKey ;
52
+ use stacks:: util:: hash:: MerkleHashFunc ;
50
53
use stacks:: util:: secp256k1:: { MessageSignature , Secp256k1PublicKey } ;
51
54
use stacks_common:: codec:: StacksMessageCodec ;
52
55
use stacks_common:: consts:: SIGNER_SLOTS_PER_USER ;
@@ -678,6 +681,76 @@ impl<S: Signer<T> + Send + 'static, T: SignerEventTrait + 'static> SignerTest<Sp
678
681
assert ! ( signer. stop( ) . is_none( ) ) ;
679
682
}
680
683
}
684
+
685
+ pub fn wait_for_block_acceptance (
686
+ & self ,
687
+ timeout_secs : u64 ,
688
+ signer_signature_hash : & Sha512Trunc256Sum ,
689
+ expected_signers : & [ StacksPublicKey ] ,
690
+ ) -> Result < ( ) , String > {
691
+ // Make sure that ALL signers accepted the block proposal
692
+ wait_for ( timeout_secs, || {
693
+ let signatures = test_observer:: get_stackerdb_chunks ( )
694
+ . into_iter ( )
695
+ . flat_map ( |chunk| chunk. modified_slots )
696
+ . filter_map ( |chunk| {
697
+ let message = SignerMessage :: consensus_deserialize ( & mut chunk. data . as_slice ( ) )
698
+ . expect ( "Failed to deserialize SignerMessage" ) ;
699
+ match message {
700
+ SignerMessage :: BlockResponse ( BlockResponse :: Accepted ( (
701
+ hash,
702
+ signature,
703
+ ) ) ) => {
704
+ if hash == * signer_signature_hash
705
+ && expected_signers. iter ( ) . any ( |pk| {
706
+ pk. verify ( hash. bits ( ) , & signature)
707
+ . expect ( "Failed to verify signature" )
708
+ } )
709
+ {
710
+ Some ( signature)
711
+ } else {
712
+ None
713
+ }
714
+ }
715
+ _ => None ,
716
+ }
717
+ } )
718
+ . collect :: < HashSet < _ > > ( ) ;
719
+ Ok ( signatures. len ( ) == expected_signers. len ( ) )
720
+ } )
721
+ }
722
+
723
+ pub fn wait_for_block_rejections (
724
+ & self ,
725
+ timeout_secs : u64 ,
726
+ expected_signers : & [ StacksPublicKey ] ,
727
+ ) -> Result < ( ) , String > {
728
+ wait_for ( timeout_secs, || {
729
+ let stackerdb_events = test_observer:: get_stackerdb_chunks ( ) ;
730
+ let block_rejections = stackerdb_events
731
+ . into_iter ( )
732
+ . flat_map ( |chunk| chunk. modified_slots )
733
+ . filter_map ( |chunk| {
734
+ let message = SignerMessage :: consensus_deserialize ( & mut chunk. data . as_slice ( ) )
735
+ . expect ( "Failed to deserialize SignerMessage" ) ;
736
+ match message {
737
+ SignerMessage :: BlockResponse ( BlockResponse :: Rejected ( rejection) ) => {
738
+ let rejected_pubkey = rejection
739
+ . recover_public_key ( )
740
+ . expect ( "Failed to recover public key from rejection" ) ;
741
+ if expected_signers. contains ( & rejected_pubkey) {
742
+ Some ( rejection)
743
+ } else {
744
+ None
745
+ }
746
+ }
747
+ _ => None ,
748
+ }
749
+ } )
750
+ . collect :: < Vec < _ > > ( ) ;
751
+ Ok ( block_rejections. len ( ) == expected_signers. len ( ) )
752
+ } )
753
+ }
681
754
}
682
755
683
756
fn setup_stx_btc_node < G : FnMut ( & mut NeonConfig ) -> ( ) > (
@@ -748,9 +821,22 @@ fn setup_stx_btc_node<G: FnMut(&mut NeonConfig) -> ()>(
748
821
info ! ( "Make new BitcoinRegtestController" ) ;
749
822
let mut btc_regtest_controller = BitcoinRegtestController :: new ( naka_conf. clone ( ) , None ) ;
750
823
751
- info ! ( "Bootstraping..." ) ;
752
- // Should be 201 for other tests?
753
- btc_regtest_controller. bootstrap_chain_to_pks ( 195 , btc_miner_pubkeys) ;
824
+ let epoch_2_5_start = usize:: try_from (
825
+ naka_conf
826
+ . burnchain
827
+ . epochs
828
+ . as_ref ( )
829
+ . unwrap ( )
830
+ . iter ( )
831
+ . find ( |epoch| epoch. epoch_id == StacksEpochId :: Epoch25 )
832
+ . unwrap ( )
833
+ . start_height ,
834
+ )
835
+ . expect ( "Failed to get epoch 2.5 start height" ) ;
836
+ let bootstrap_block = epoch_2_5_start - 6 ;
837
+
838
+ info ! ( "Bootstraping to block {bootstrap_block}..." ) ;
839
+ btc_regtest_controller. bootstrap_chain_to_pks ( bootstrap_block, btc_miner_pubkeys) ;
754
840
755
841
info ! ( "Chain bootstrapped..." ) ;
756
842
0 commit comments