@@ -1731,7 +1731,12 @@ where
17311731 S : Stream < Item = Signed < SignerMessage > > ,
17321732 Coordinator : WstsCoordinator ,
17331733 {
1734- let signer_set = self . context . config ( ) . signer . bootstrap_signing_set . clone ( ) ;
1734+ // We only allow the coordinator to send us certain kinds of
1735+ // messages. So later, we need to check whether the sender is the
1736+ // coordinator, and for that we need to use the "coordinator signer
1737+ // set", which may differ from the set of signers sending us
1738+ // messages right now.
1739+ let signer_set = self . context . coordinator_signer_set ( ) ;
17351740 tokio:: pin!( signal_stream) ;
17361741
17371742 // Let's get the next message from the network or the
@@ -1860,15 +1865,15 @@ where
18601865 /// Determine if this signer is the signer set's coordinator for the
18611866 /// specified bitcoin block hash.
18621867 ///
1863- /// The coordinator is decided using the hash of the bitcoin chain tip.
1864- /// We don't use the chain tip directly because it typically starts
1865- /// with a lot of leading zeros.
1868+ /// The coordinator is decided using the hash of the bitcoin chain tip
1869+ /// and signer set info from the registry if present. We don't use the
1870+ /// chain tip directly because it typically starts with a lot of
1871+ /// leading zeros.
18661872 pub fn is_coordinator ( & self , bitcoin_chain_tip : & model:: BitcoinBlockHash ) -> bool {
1867- given_key_is_coordinator (
1868- self . signer_public_key ( ) ,
1869- bitcoin_chain_tip,
1870- & self . context . config ( ) . signer . bootstrap_signing_set ,
1871- )
1873+ let signer_public_keys = self . context . coordinator_signer_set ( ) ;
1874+
1875+ let signer_public_key = self . signer_public_key ( ) ;
1876+ given_key_is_coordinator ( signer_public_key, bitcoin_chain_tip, & signer_public_keys)
18721877 }
18731878
18741879 /// Constructs a new [`utxo::SignerBtcState`] based on the current market
@@ -2858,6 +2863,66 @@ mod tests {
28582863 . unwrap ( ) ;
28592864 }
28602865
2866+ /// Check that is_coordinator uses the registry for figuring out who
2867+ /// the cooridnator is and falls back to the config if the registry has
2868+ /// no signer set info.
2869+ #[ tokio:: test]
2870+ async fn is_coordinator_uses_registry_for_coordinator ( ) {
2871+ let mut rng = testing:: get_rng ( ) ;
2872+ let ctx = TestContext :: builder ( )
2873+ . with_in_memory_storage ( )
2874+ . with_mocked_clients ( )
2875+ . modify_settings ( |settings| {
2876+ settings. signer . bootstrap_signatures_required = 1 ;
2877+ settings. signer . bootstrap_signing_set =
2878+ std:: iter:: once ( settings. signer . public_key ( ) ) . collect ( ) ;
2879+ } )
2880+ . build ( ) ;
2881+
2882+ let network = WanNetwork :: default ( ) ;
2883+ let net = network. connect ( & ctx) ;
2884+
2885+ let ev = TxCoordinatorEventLoop {
2886+ network : net. spawn ( ) ,
2887+ context : ctx. clone ( ) ,
2888+ context_window : 10000 ,
2889+ private_key : ctx. config ( ) . signer . private_key ,
2890+ signing_round_max_duration : Duration :: from_secs ( 10 ) ,
2891+ bitcoin_presign_request_max_duration : Duration :: from_secs ( 10 ) ,
2892+ dkg_max_duration : Duration :: from_secs ( 10 ) ,
2893+ is_epoch3 : true ,
2894+ } ;
2895+
2896+ // We should always be the coordinator since the registry is unset
2897+ // and we're the only signer in the bootstrap signing set.
2898+ assert ! ( ev. context. state( ) . registry_signer_set_info( ) . is_none( ) ) ;
2899+
2900+ for _ in 0 ..100 {
2901+ let chain_tip1: BitcoinBlockRef = fake:: Faker . fake_with_rng ( & mut rng) ;
2902+ assert ! ( ev. is_coordinator( & chain_tip1. block_hash) ) ;
2903+ }
2904+
2905+ // Now let's set the signer set in the registry to some random
2906+ // signer set without our key. Now we should never be the
2907+ // coordinator.
2908+ let signer_set_info = crate :: stacks:: api:: SignerSetInfo {
2909+ aggregate_key : Faker . fake_with_rng ( & mut rng) ,
2910+ signer_set : std:: iter:: repeat_with ( || Faker . fake_with_rng ( & mut rng) )
2911+ . take ( 2 )
2912+ . collect ( ) ,
2913+ signatures_required : 2 ,
2914+ } ;
2915+
2916+ ctx. state ( ) . update_registry_signer_set_info ( signer_set_info) ;
2917+
2918+ // If we were part of the signing set, there is a 2^(-128) chance
2919+ // that this check would pass.
2920+ for _ in 0 ..128 {
2921+ let chain_tip1: BitcoinBlockRef = fake:: Faker . fake_with_rng ( & mut rng) ;
2922+ assert ! ( !ev. is_coordinator( & chain_tip1. block_hash) ) ;
2923+ }
2924+ }
2925+
28612926 #[ tokio:: test]
28622927 async fn should_get_signer_utxo_simple ( ) {
28632928 test_environment ( ) . assert_get_signer_utxo_simple ( ) . await ;
0 commit comments