@@ -42,14 +42,16 @@ use libsigner::v0::messages::{
42
42
use libsigner:: { SignerEntries , SignerEventTrait } ;
43
43
use stacks:: chainstate:: coordinator:: comm:: CoordinatorChannels ;
44
44
use stacks:: chainstate:: nakamoto:: signer_set:: NakamotoSigners ;
45
+ use stacks:: chainstate:: nakamoto:: NakamotoBlock ;
45
46
use stacks:: chainstate:: stacks:: boot:: { NakamotoSignerEntry , SIGNERS_NAME } ;
46
47
use stacks:: chainstate:: stacks:: StacksPrivateKey ;
47
48
use stacks:: config:: { Config as NeonConfig , EventKeyType , EventObserverConfig , InitialBalance } ;
48
49
use stacks:: net:: api:: postblock_proposal:: {
49
50
BlockValidateOk , BlockValidateReject , BlockValidateResponse ,
50
51
} ;
51
52
use stacks:: types:: chainstate:: { StacksAddress , StacksPublicKey } ;
52
- use stacks:: types:: PublicKey ;
53
+ use stacks:: types:: { PrivateKey , PublicKey } ;
54
+ use stacks:: util:: get_epoch_time_secs;
53
55
use stacks:: util:: hash:: MerkleHashFunc ;
54
56
use stacks:: util:: secp256k1:: { MessageSignature , Secp256k1PublicKey } ;
55
57
use stacks_common:: codec:: StacksMessageCodec ;
@@ -262,6 +264,33 @@ impl<S: Signer<T> + Send + 'static, T: SignerEventTrait + 'static> SignerTest<Sp
262
264
} ) . expect ( "Timed out while waiting for the signers to be registered" ) ;
263
265
}
264
266
267
+ /// Send a status request to the signers to ensure they are registered for both reward cycles.
268
+ pub fn wait_for_registered_both_reward_cycles ( & mut self , timeout_secs : u64 ) {
269
+ let mut finished_signers = HashSet :: new ( ) ;
270
+ wait_for ( timeout_secs, || {
271
+ self . send_status_request ( & finished_signers) ;
272
+ thread:: sleep ( Duration :: from_secs ( 1 ) ) ;
273
+ let latest_states = self . get_states ( & finished_signers) ;
274
+ for ( ix, state) in latest_states. iter ( ) . enumerate ( ) {
275
+ let Some ( state) = state else {
276
+ continue ;
277
+ } ;
278
+ debug ! ( "Signer #{ix} state info: {state:?}" ) ;
279
+ if state. runloop_state == State :: RegisteredSigners && state. running_signers . len ( ) == 2 {
280
+ finished_signers. insert ( ix) ;
281
+ } else {
282
+ warn ! (
283
+ "Signer #{ix} returned state = {:?}, running signers = {:?}. Will try again" ,
284
+ state. runloop_state, state. running_signers
285
+ ) ;
286
+ }
287
+ }
288
+ debug ! ( "Number of finished signers: {:?}" , finished_signers. len( ) ) ;
289
+ Ok ( finished_signers. len ( ) == self . spawned_signers . len ( ) )
290
+ } )
291
+ . expect ( "Timed out while waiting for the signers to be registered for both reward cycles" ) ;
292
+ }
293
+
265
294
pub fn wait_for_cycle ( & mut self , timeout_secs : u64 , reward_cycle : u64 ) {
266
295
let mut finished_signers = HashSet :: new ( ) ;
267
296
wait_for ( timeout_secs, || {
@@ -517,6 +546,27 @@ impl<S: Signer<T> + Send + 'static, T: SignerEventTrait + 'static> SignerTest<Sp
517
546
. get_stackerdb_signer_slots ( & signer_stackerdb_contract_id, valid_signer_set)
518
547
}
519
548
549
+ fn get_signer_slot_id (
550
+ & self ,
551
+ reward_cycle : u64 ,
552
+ signer_address : & StacksAddress ,
553
+ ) -> Result < Option < SignerSlotID > , ClientError > {
554
+ let valid_signer_set =
555
+ u32:: try_from ( reward_cycle % 2 ) . expect ( "FATAL: reward_cycle % 2 exceeds u32::MAX" ) ;
556
+ let signer_stackerdb_contract_id = boot_code_id ( SIGNERS_NAME , false ) ;
557
+
558
+ let slots = self
559
+ . stacks_client
560
+ . get_stackerdb_signer_slots ( & signer_stackerdb_contract_id, valid_signer_set) ?;
561
+
562
+ Ok ( slots
563
+ . iter ( )
564
+ . position ( |( address, _) | address == signer_address)
565
+ . map ( |pos| {
566
+ SignerSlotID ( u32:: try_from ( pos) . expect ( "FATAL: number of signers exceeds u32::MAX" ) )
567
+ } ) )
568
+ }
569
+
520
570
fn get_signer_indices ( & self , reward_cycle : u64 ) -> Vec < SignerSlotID > {
521
571
self . get_signer_slots ( reward_cycle)
522
572
. expect ( "FATAL: failed to get signer slots from stackerdb" )
@@ -681,6 +731,61 @@ impl<S: Signer<T> + Send + 'static, T: SignerEventTrait + 'static> SignerTest<Sp
681
731
. get_peer_info ( )
682
732
. expect ( "Failed to get peer info" )
683
733
}
734
+
735
+ pub fn verify_no_block_response_found (
736
+ & self ,
737
+ stackerdb : & mut StackerDB < MessageSlotID > ,
738
+ reward_cycle : u64 ,
739
+ hash : Sha512Trunc256Sum ,
740
+ ) {
741
+ let slot_ids: Vec < _ > = self
742
+ . get_signer_indices ( reward_cycle)
743
+ . iter ( )
744
+ . map ( |id| id. 0 )
745
+ . collect ( ) ;
746
+
747
+ let latest_msgs = StackerDB :: get_messages :: < SignerMessage > (
748
+ stackerdb
749
+ . get_session_mut ( & MessageSlotID :: BlockResponse )
750
+ . expect ( "Failed to get BlockResponse stackerdb session" ) ,
751
+ & slot_ids,
752
+ )
753
+ . expect ( "Failed to get messages from stackerdb" ) ;
754
+ for msg in latest_msgs. iter ( ) {
755
+ if let SignerMessage :: BlockResponse ( response) = msg {
756
+ assert_ne ! ( response. get_signer_signature_hash( ) , hash) ;
757
+ }
758
+ }
759
+ }
760
+
761
+ pub fn inject_accept_signature (
762
+ & self ,
763
+ block : & NakamotoBlock ,
764
+ private_key : & StacksPrivateKey ,
765
+ reward_cycle : u64 ,
766
+ ) {
767
+ let mut stackerdb = StackerDB :: new (
768
+ & self . running_nodes . conf . node . rpc_bind ,
769
+ private_key. clone ( ) ,
770
+ false ,
771
+ reward_cycle,
772
+ self . get_signer_slot_id ( reward_cycle, & to_addr ( private_key) )
773
+ . expect ( "Failed to get signer slot id" )
774
+ . expect ( "Signer does not have a slot id" ) ,
775
+ ) ;
776
+
777
+ let signature = private_key
778
+ . sign ( block. header . signer_signature_hash ( ) . bits ( ) )
779
+ . expect ( "Failed to sign block" ) ;
780
+ let accepted = BlockResponse :: accepted (
781
+ block. header . signer_signature_hash ( ) ,
782
+ signature,
783
+ get_epoch_time_secs ( ) . wrapping_add ( u64:: MAX ) ,
784
+ ) ;
785
+ stackerdb
786
+ . send_message_with_retry :: < SignerMessage > ( accepted. into ( ) )
787
+ . expect ( "Failed to send accept signature" ) ;
788
+ }
684
789
}
685
790
686
791
fn setup_stx_btc_node < G : FnMut ( & mut NeonConfig ) > (
0 commit comments