Skip to content

Commit 3482610

Browse files
committed
fix(ecdsa): FOLLOW-1007 Reject signing requests for disabled keys
1 parent 9320948 commit 3482610

File tree

1 file changed

+109
-11
lines changed

1 file changed

+109
-11
lines changed

rs/consensus/src/ecdsa/payload_builder.rs

Lines changed: 109 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use ic_interfaces::{consensus_pool::ConsensusBlockChain, ecdsa::EcdsaPool};
1616
use ic_interfaces_registry::RegistryClient;
1717
use ic_interfaces_state_manager::{StateManager, StateManagerError};
1818
use ic_logger::{debug, error, info, warn, ReplicaLogger};
19+
use ic_registry_client_helpers::ecdsa_keys::EcdsaKeysRegistry;
1920
use ic_registry_client_helpers::subnet::SubnetRegistry;
2021
use ic_registry_subnet_features::EcdsaConfig;
2122
use ic_replicated_state::{metadata_state::subnet_call_context_manager::*, ReplicatedState};
@@ -207,7 +208,7 @@ pub fn make_bootstrap_summary(
207208
Ok(Some(summary_payload))
208209
}
209210

210-
/// Return EcdsaConfig if it is enabled for the given subnet.
211+
/// Return [EcdsaConfig] if it is enabled for the given subnet.
211212
pub(crate) fn get_ecdsa_config_if_enabled(
212213
subnet_id: SubnetId,
213214
registry_version: RegistryVersion,
@@ -236,6 +237,28 @@ pub(crate) fn get_ecdsa_config_if_enabled(
236237
Ok(None)
237238
}
238239

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+
239262
/// Creates a threshold ECDSA summary payload.
240263
pub(crate) fn create_summary_payload(
241264
subnet_id: SubnetId,
@@ -644,16 +667,21 @@ pub(crate) fn create_data_payload_helper(
644667
// For next interval: context.registry_version from the new summary block
645668
let next_interval_registry_version = summary_block.context.registry_version;
646669

647-
let ecdsa_config = get_ecdsa_config_if_enabled(
670+
let Some(ecdsa_config) = get_ecdsa_config_if_enabled(
648671
subnet_id,
649672
curr_interval_registry_version,
650673
registry_client,
651674
&log,
652-
)?;
653-
if ecdsa_config.is_none() {
675+
)? else {
654676
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+
657685
let mut ecdsa_payload = if let Some(prev_payload) = parent_block.payload.as_ref().as_ecdsa() {
658686
prev_payload.clone()
659687
} else {
@@ -678,6 +706,7 @@ pub(crate) fn create_data_payload_helper(
678706
height,
679707
context.time,
680708
&ecdsa_config,
709+
&enabled_signing_keys,
681710
next_interval_registry_version,
682711
&receivers,
683712
all_signing_requests,
@@ -696,6 +725,7 @@ pub(crate) fn create_data_payload_helper_2(
696725
height: Height,
697726
context_time: Time,
698727
ecdsa_config: &EcdsaConfig,
728+
enabled_signing_keys: &BTreeSet<EcdsaKeyId>,
699729
next_interval_registry_version: RegistryVersion,
700730
receivers: &[NodeId],
701731
all_signing_requests: &BTreeMap<CallbackId, SignWithEcdsaContext>,
@@ -721,7 +751,6 @@ pub(crate) fn create_data_payload_helper_2(
721751
ecdsa_payload.uid_generator.update_height(height)?;
722752
let current_key_transcript = ecdsa_payload.key_transcript.current.as_ref().cloned();
723753

724-
let valid_keys: BTreeSet<_> = ecdsa_config.key_ids.iter().cloned().collect();
725754
let request_expiry_time = ecdsa_config.signature_request_timeout_ns.and_then(|t| {
726755
let timeout = Duration::from_nanos(t);
727756
if context_time.as_nanos_since_unix_epoch() >= t {
@@ -736,7 +765,7 @@ pub(crate) fn create_data_payload_helper_2(
736765
request_expiry_time,
737766
ecdsa_payload,
738767
all_signing_requests,
739-
&valid_keys,
768+
enabled_signing_keys,
740769
ecdsa_payload_metrics,
741770
);
742771
update_ongoing_signatures(
@@ -981,7 +1010,10 @@ pub(crate) fn get_signing_requests<'a>(
9811010
refund: context.request.payment,
9821011
response_payload: ic_types::messages::Payload::Reject(RejectContext {
9831012
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+
),
9851017
}),
9861018
};
9871019
ecdsa_payload.signature_agreements.insert(
@@ -1752,7 +1784,11 @@ mod tests {
17521784
};
17531785
use ic_interfaces_registry::RegistryValue;
17541786
use ic_logger::replica_logger::no_op_logger;
1787+
use ic_protobuf::registry::crypto::v1::EcdsaSigningSubnetList;
17551788
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;
17561792
use ic_registry_subnet_features::DEFAULT_ECDSA_MAX_QUEUE_SIZE;
17571793
use ic_test_artifact_pool::consensus_pool::TestConsensusPool;
17581794
use ic_test_utilities::consensus::fake::{Fake, FakeContentSigner};
@@ -1775,6 +1811,7 @@ mod tests {
17751811
idkg::IDkgTranscriptId, ThresholdEcdsaCombinedSignature,
17761812
};
17771813
use ic_types::crypto::{CryptoHash, CryptoHashOf};
1814+
use ic_types::subnet_id_into_protobuf;
17781815
use ic_types::{messages::CallbackId, Height, RegistryVersion};
17791816
use std::collections::BTreeSet;
17801817
use std::convert::TryInto;
@@ -1890,6 +1927,59 @@ mod tests {
18901927
block_proposal.content.as_ref().clone()
18911928
}
18921929

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+
18931983
#[test]
18941984
fn test_ecdsa_make_new_quadruples_if_needed() {
18951985
let subnet_id = subnet_test_id(1);
@@ -2869,6 +2959,7 @@ mod tests {
28692959
Height::from(5),
28702960
mock_time(),
28712961
&EcdsaConfig::default(),
2962+
&valid_keys,
28722963
RegistryVersion::from(9),
28732964
&[node_test_id(0)],
28742965
&sign_with_ecdsa_contexts,
@@ -2891,6 +2982,7 @@ mod tests {
28912982
Height::from(5),
28922983
mock_time(),
28932984
&EcdsaConfig::default(),
2985+
&valid_keys,
28942986
RegistryVersion::from(9),
28952987
&[node_test_id(0)],
28962988
&sign_with_ecdsa_contexts,
@@ -3865,8 +3957,9 @@ mod tests {
38653957
add_subnet_record(&registry_data_provider, 11, subnet_id, subnet_record);
38663958
registry.update_to_latest_version();
38673959
let registry_version = registry.get_latest_version();
3868-
3960+
let mut valid_keys = BTreeSet::new();
38693961
let key_id = EcdsaKeyId::from_str("Secp256k1:some_key").unwrap();
3962+
valid_keys.insert(key_id.clone());
38703963
let block_reader = TestEcdsaBlockReader::new();
38713964
let transcript_builder = TestEcdsaTranscriptBuilder::new();
38723965
let signature_builder = TestEcdsaSignatureBuilder::new();
@@ -3909,6 +4002,7 @@ mod tests {
39094002
Height::from(2),
39104003
mock_time(),
39114004
&ecdsa_config,
4005+
&valid_keys,
39124006
registry_version,
39134007
&node_ids,
39144008
&BTreeMap::default(),
@@ -3999,8 +4093,9 @@ mod tests {
39994093
add_subnet_record(&registry_data_provider, 511, subnet_id, subnet_record);
40004094
registry.update_to_latest_version();
40014095
let registry_version = registry.get_latest_version();
4002-
4096+
let mut valid_keys = BTreeSet::new();
40034097
let key_id = EcdsaKeyId::from_str("Secp256k1:some_key").unwrap();
4098+
valid_keys.insert(key_id.clone());
40044099
let mut block_reader = TestEcdsaBlockReader::new();
40054100
let transcript_builder = TestEcdsaTranscriptBuilder::new();
40064101
let signature_builder = TestEcdsaSignatureBuilder::new();
@@ -4062,6 +4157,7 @@ mod tests {
40624157
Height::from(2),
40634158
mock_time(),
40644159
&ecdsa_config,
4160+
&valid_keys,
40654161
registry_version,
40664162
&node_ids,
40674163
&BTreeMap::default(),
@@ -4089,6 +4185,7 @@ mod tests {
40894185
Height::from(3),
40904186
mock_time(),
40914187
&ecdsa_config,
4188+
&valid_keys,
40924189
registry_version,
40934190
&node_ids,
40944191
&BTreeMap::default(),
@@ -4114,6 +4211,7 @@ mod tests {
41144211
Height::from(3),
41154212
mock_time(),
41164213
&ecdsa_config,
4214+
&valid_keys,
41174215
registry_version,
41184216
&node_ids,
41194217
&BTreeMap::default(),

0 commit comments

Comments
 (0)