@@ -16,6 +16,7 @@ use ic_interfaces::{consensus_pool::ConsensusBlockChain, ecdsa::EcdsaPool};
16
16
use ic_interfaces_registry:: RegistryClient ;
17
17
use ic_interfaces_state_manager:: { StateManager , StateManagerError } ;
18
18
use ic_logger:: { debug, error, info, warn, ReplicaLogger } ;
19
+ use ic_registry_client_helpers:: ecdsa_keys:: EcdsaKeysRegistry ;
19
20
use ic_registry_client_helpers:: subnet:: SubnetRegistry ;
20
21
use ic_registry_subnet_features:: EcdsaConfig ;
21
22
use ic_replicated_state:: { metadata_state:: subnet_call_context_manager:: * , ReplicatedState } ;
@@ -207,7 +208,7 @@ pub fn make_bootstrap_summary(
207
208
Ok ( Some ( summary_payload) )
208
209
}
209
210
210
- /// Return EcdsaConfig if it is enabled for the given subnet.
211
+ /// Return [ EcdsaConfig] if it is enabled for the given subnet.
211
212
pub ( crate ) fn get_ecdsa_config_if_enabled (
212
213
subnet_id : SubnetId ,
213
214
registry_version : RegistryVersion ,
@@ -236,6 +237,28 @@ pub(crate) fn get_ecdsa_config_if_enabled(
236
237
Ok ( None )
237
238
}
238
239
240
+ /// Return ids of ECDSA keys of the given [EcdsaConfig] for which
241
+ /// signing is enabled on the given subnet.
242
+ pub ( crate ) fn get_enabled_signing_keys (
243
+ subnet_id : SubnetId ,
244
+ registry_version : RegistryVersion ,
245
+ registry_client : & dyn RegistryClient ,
246
+ ecdsa_config : & EcdsaConfig ,
247
+ ) -> Result < BTreeSet < EcdsaKeyId > , RegistryClientError > {
248
+ let signing_subnets = registry_client
249
+ . get_ecdsa_signing_subnets ( registry_version) ?
250
+ . unwrap_or_default ( ) ;
251
+ Ok ( ecdsa_config
252
+ . key_ids
253
+ . iter ( )
254
+ . cloned ( )
255
+ . filter ( |key_id| match signing_subnets. get ( key_id) {
256
+ Some ( subnets) => subnets. contains ( & subnet_id) ,
257
+ None => false ,
258
+ } )
259
+ . collect ( ) )
260
+ }
261
+
239
262
/// Creates a threshold ECDSA summary payload.
240
263
pub ( crate ) fn create_summary_payload (
241
264
subnet_id : SubnetId ,
@@ -644,16 +667,21 @@ pub(crate) fn create_data_payload_helper(
644
667
// For next interval: context.registry_version from the new summary block
645
668
let next_interval_registry_version = summary_block. context . registry_version ;
646
669
647
- let ecdsa_config = get_ecdsa_config_if_enabled (
670
+ let Some ( ecdsa_config) = get_ecdsa_config_if_enabled (
648
671
subnet_id,
649
672
curr_interval_registry_version,
650
673
registry_client,
651
674
& log,
652
- ) ?;
653
- if ecdsa_config. is_none ( ) {
675
+ ) ? else {
654
676
return Ok ( None ) ;
655
- }
656
- let ecdsa_config = ecdsa_config. unwrap ( ) ;
677
+ } ;
678
+ let enabled_signing_keys = get_enabled_signing_keys (
679
+ subnet_id,
680
+ curr_interval_registry_version,
681
+ registry_client,
682
+ & ecdsa_config,
683
+ ) ?;
684
+
657
685
let mut ecdsa_payload = if let Some ( prev_payload) = parent_block. payload . as_ref ( ) . as_ecdsa ( ) {
658
686
prev_payload. clone ( )
659
687
} else {
@@ -678,6 +706,7 @@ pub(crate) fn create_data_payload_helper(
678
706
height,
679
707
context. time ,
680
708
& ecdsa_config,
709
+ & enabled_signing_keys,
681
710
next_interval_registry_version,
682
711
& receivers,
683
712
all_signing_requests,
@@ -696,6 +725,7 @@ pub(crate) fn create_data_payload_helper_2(
696
725
height : Height ,
697
726
context_time : Time ,
698
727
ecdsa_config : & EcdsaConfig ,
728
+ enabled_signing_keys : & BTreeSet < EcdsaKeyId > ,
699
729
next_interval_registry_version : RegistryVersion ,
700
730
receivers : & [ NodeId ] ,
701
731
all_signing_requests : & BTreeMap < CallbackId , SignWithEcdsaContext > ,
@@ -721,7 +751,6 @@ pub(crate) fn create_data_payload_helper_2(
721
751
ecdsa_payload. uid_generator . update_height ( height) ?;
722
752
let current_key_transcript = ecdsa_payload. key_transcript . current . as_ref ( ) . cloned ( ) ;
723
753
724
- let valid_keys: BTreeSet < _ > = ecdsa_config. key_ids . iter ( ) . cloned ( ) . collect ( ) ;
725
754
let request_expiry_time = ecdsa_config. signature_request_timeout_ns . and_then ( |t| {
726
755
let timeout = Duration :: from_nanos ( t) ;
727
756
if context_time. as_nanos_since_unix_epoch ( ) >= t {
@@ -736,7 +765,7 @@ pub(crate) fn create_data_payload_helper_2(
736
765
request_expiry_time,
737
766
ecdsa_payload,
738
767
all_signing_requests,
739
- & valid_keys ,
768
+ enabled_signing_keys ,
740
769
ecdsa_payload_metrics,
741
770
) ;
742
771
update_ongoing_signatures (
@@ -981,7 +1010,10 @@ pub(crate) fn get_signing_requests<'a>(
981
1010
refund : context. request . payment ,
982
1011
response_payload : ic_types:: messages:: Payload :: Reject ( RejectContext {
983
1012
code : RejectCode :: CanisterReject ,
984
- message : format ! ( "Invalid key_id in signature request: {:?}" , context. key_id) ,
1013
+ message : format ! (
1014
+ "Invalid or disabled key_id in signature request: {:?}" ,
1015
+ context. key_id
1016
+ ) ,
985
1017
} ) ,
986
1018
} ;
987
1019
ecdsa_payload. signature_agreements . insert (
@@ -1752,7 +1784,11 @@ mod tests {
1752
1784
} ;
1753
1785
use ic_interfaces_registry:: RegistryValue ;
1754
1786
use ic_logger:: replica_logger:: no_op_logger;
1787
+ use ic_protobuf:: registry:: crypto:: v1:: EcdsaSigningSubnetList ;
1755
1788
use ic_protobuf:: types:: v1 as pb;
1789
+ use ic_registry_client_fake:: FakeRegistryClient ;
1790
+ use ic_registry_keys:: make_ecdsa_signing_subnet_list_key;
1791
+ use ic_registry_proto_data_provider:: ProtoRegistryDataProvider ;
1756
1792
use ic_registry_subnet_features:: DEFAULT_ECDSA_MAX_QUEUE_SIZE ;
1757
1793
use ic_test_artifact_pool:: consensus_pool:: TestConsensusPool ;
1758
1794
use ic_test_utilities:: consensus:: fake:: { Fake , FakeContentSigner } ;
@@ -1775,6 +1811,7 @@ mod tests {
1775
1811
idkg:: IDkgTranscriptId , ThresholdEcdsaCombinedSignature ,
1776
1812
} ;
1777
1813
use ic_types:: crypto:: { CryptoHash , CryptoHashOf } ;
1814
+ use ic_types:: subnet_id_into_protobuf;
1778
1815
use ic_types:: { messages:: CallbackId , Height , RegistryVersion } ;
1779
1816
use std:: collections:: BTreeSet ;
1780
1817
use std:: convert:: TryInto ;
@@ -1890,6 +1927,59 @@ mod tests {
1890
1927
block_proposal. content . as_ref ( ) . clone ( )
1891
1928
}
1892
1929
1930
+ #[ test]
1931
+ fn test_get_enabled_signing_keys ( ) {
1932
+ let key_id1 = EcdsaKeyId :: from_str ( "Secp256k1:some_key1" ) . unwrap ( ) ;
1933
+ let key_id2 = EcdsaKeyId :: from_str ( "Secp256k1:some_key2" ) . unwrap ( ) ;
1934
+ let key_id3 = EcdsaKeyId :: from_str ( "Secp256k1:some_key3" ) . unwrap ( ) ;
1935
+ let ecdsa_config = EcdsaConfig {
1936
+ key_ids : vec ! [ key_id1. clone( ) , key_id2. clone( ) ] ,
1937
+ ..EcdsaConfig :: default ( )
1938
+ } ;
1939
+ let registry_data = Arc :: new ( ProtoRegistryDataProvider :: new ( ) ) ;
1940
+ let registry = Arc :: new ( FakeRegistryClient :: new ( Arc :: clone ( & registry_data) as Arc < _ > ) ) ;
1941
+ let subnet_id = subnet_test_id ( 1 ) ;
1942
+
1943
+ let add_key = |version, key_id, subnets| {
1944
+ registry_data
1945
+ . add (
1946
+ & make_ecdsa_signing_subnet_list_key ( key_id) ,
1947
+ RegistryVersion :: from ( version) ,
1948
+ Some ( EcdsaSigningSubnetList { subnets } ) ,
1949
+ )
1950
+ . expect ( "failed to add subnets to registry" ) ;
1951
+ } ;
1952
+
1953
+ add_key ( 1 , & key_id1, vec ! [ subnet_id_into_protobuf( subnet_id) ] ) ;
1954
+ add_key ( 2 , & key_id2, vec ! [ subnet_id_into_protobuf( subnet_id) ] ) ;
1955
+ add_key ( 2 , & key_id3, vec ! [ subnet_id_into_protobuf( subnet_id) ] ) ;
1956
+ add_key ( 3 , & key_id1, vec ! [ ] ) ;
1957
+ registry. update_to_latest_version ( ) ;
1958
+
1959
+ let test_cases = vec ! [
1960
+ ( 0 , Ok ( BTreeSet :: new( ) ) ) ,
1961
+ ( 1 , Ok ( BTreeSet :: from_iter( vec![ key_id1. clone( ) ] ) ) ) ,
1962
+ ( 2 , Ok ( BTreeSet :: from_iter( vec![ key_id1, key_id2. clone( ) ] ) ) ) ,
1963
+ ( 3 , Ok ( BTreeSet :: from_iter( vec![ key_id2] ) ) ) ,
1964
+ (
1965
+ 4 ,
1966
+ Err ( RegistryClientError :: VersionNotAvailable {
1967
+ version: RegistryVersion :: from( 4 ) ,
1968
+ } ) ,
1969
+ ) ,
1970
+ ] ;
1971
+
1972
+ for ( version, expected) in test_cases {
1973
+ let result = get_enabled_signing_keys (
1974
+ subnet_id,
1975
+ RegistryVersion :: from ( version) ,
1976
+ registry. as_ref ( ) ,
1977
+ & ecdsa_config,
1978
+ ) ;
1979
+ assert_eq ! ( result, expected) ;
1980
+ }
1981
+ }
1982
+
1893
1983
#[ test]
1894
1984
fn test_ecdsa_make_new_quadruples_if_needed ( ) {
1895
1985
let subnet_id = subnet_test_id ( 1 ) ;
@@ -2869,6 +2959,7 @@ mod tests {
2869
2959
Height :: from ( 5 ) ,
2870
2960
mock_time ( ) ,
2871
2961
& EcdsaConfig :: default ( ) ,
2962
+ & valid_keys,
2872
2963
RegistryVersion :: from ( 9 ) ,
2873
2964
& [ node_test_id ( 0 ) ] ,
2874
2965
& sign_with_ecdsa_contexts,
@@ -2891,6 +2982,7 @@ mod tests {
2891
2982
Height :: from ( 5 ) ,
2892
2983
mock_time ( ) ,
2893
2984
& EcdsaConfig :: default ( ) ,
2985
+ & valid_keys,
2894
2986
RegistryVersion :: from ( 9 ) ,
2895
2987
& [ node_test_id ( 0 ) ] ,
2896
2988
& sign_with_ecdsa_contexts,
@@ -3865,8 +3957,9 @@ mod tests {
3865
3957
add_subnet_record ( & registry_data_provider, 11 , subnet_id, subnet_record) ;
3866
3958
registry. update_to_latest_version ( ) ;
3867
3959
let registry_version = registry. get_latest_version ( ) ;
3868
-
3960
+ let mut valid_keys = BTreeSet :: new ( ) ;
3869
3961
let key_id = EcdsaKeyId :: from_str ( "Secp256k1:some_key" ) . unwrap ( ) ;
3962
+ valid_keys. insert ( key_id. clone ( ) ) ;
3870
3963
let block_reader = TestEcdsaBlockReader :: new ( ) ;
3871
3964
let transcript_builder = TestEcdsaTranscriptBuilder :: new ( ) ;
3872
3965
let signature_builder = TestEcdsaSignatureBuilder :: new ( ) ;
@@ -3909,6 +4002,7 @@ mod tests {
3909
4002
Height :: from ( 2 ) ,
3910
4003
mock_time ( ) ,
3911
4004
& ecdsa_config,
4005
+ & valid_keys,
3912
4006
registry_version,
3913
4007
& node_ids,
3914
4008
& BTreeMap :: default ( ) ,
@@ -3999,8 +4093,9 @@ mod tests {
3999
4093
add_subnet_record ( & registry_data_provider, 511 , subnet_id, subnet_record) ;
4000
4094
registry. update_to_latest_version ( ) ;
4001
4095
let registry_version = registry. get_latest_version ( ) ;
4002
-
4096
+ let mut valid_keys = BTreeSet :: new ( ) ;
4003
4097
let key_id = EcdsaKeyId :: from_str ( "Secp256k1:some_key" ) . unwrap ( ) ;
4098
+ valid_keys. insert ( key_id. clone ( ) ) ;
4004
4099
let mut block_reader = TestEcdsaBlockReader :: new ( ) ;
4005
4100
let transcript_builder = TestEcdsaTranscriptBuilder :: new ( ) ;
4006
4101
let signature_builder = TestEcdsaSignatureBuilder :: new ( ) ;
@@ -4062,6 +4157,7 @@ mod tests {
4062
4157
Height :: from ( 2 ) ,
4063
4158
mock_time ( ) ,
4064
4159
& ecdsa_config,
4160
+ & valid_keys,
4065
4161
registry_version,
4066
4162
& node_ids,
4067
4163
& BTreeMap :: default ( ) ,
@@ -4089,6 +4185,7 @@ mod tests {
4089
4185
Height :: from ( 3 ) ,
4090
4186
mock_time ( ) ,
4091
4187
& ecdsa_config,
4188
+ & valid_keys,
4092
4189
registry_version,
4093
4190
& node_ids,
4094
4191
& BTreeMap :: default ( ) ,
@@ -4114,6 +4211,7 @@ mod tests {
4114
4211
Height :: from ( 3 ) ,
4115
4212
mock_time ( ) ,
4116
4213
& ecdsa_config,
4214
+ & valid_keys,
4117
4215
registry_version,
4118
4216
& node_ids,
4119
4217
& BTreeMap :: default ( ) ,
0 commit comments