Skip to content

Commit 39f67a6

Browse files
authored
feat(crypto): CRP-2609 Introduce master key ID variant for vetKD (#2108)
Adds a variant for vetKD in the `MasterPublicKeyId` in the 1. registry protobuf definitions, where it is used in the `KeyConfig` (which is used in the `ChainKeyConfig`, which is used in the `SubnetRecord`). 2. management canister types, where it is used in the `ComputeInitialIDkgDealingsArgs` (which will be generalized in a later step, e.g., to `ReshareChainKeyArgs`). 3. registry canister API (registry.did), where it is used in the `KeyConfig` (which is used in the `KeyConfigRequest`, which is used in the `InitialChainKeyConfig`, which is used in `CreateSubnetPayload` and `RecoverSubnetPayload`), and in the `UpdateSubnetPayload`'s `chain_key_signing_enable`/`chain_key_signing_disable`. This is the very first step for the vetKeys feature. As discussed with the Consensus team, various consensus tests related to pre-signatures are adapted so that the tests panic if the vetKD variant is used, because vetKD doesn't have pre-signatures. ### Registry API backwards-compatibility The changes in the registry canister API should be safe/backwards-compatible based on the following argumentation (see [Can I add a variant alternative?](https://mmapped.blog/posts/20-candid-for-engineers#faq-remove-alternative)): The `MasterPublicKeyId` variant in `registry.did` is extended with a new alternative as follows: ``` - type MasterPublicKeyId = variant { Schnorr : SchnorrKeyId; Ecdsa : EcdsaKeyId }; + type MasterPublicKeyId = variant { Schnorr : SchnorrKeyId; Ecdsa : EcdsaKeyId; VetKd : VetKdKeyId }; ``` This variant is used in two places: 1. ``` type KeyConfig = record { key_id : opt MasterPublicKeyId; [...] }; ``` Here, adding the alternative is safe, given that the variant field `key_id` is optional. 2. ``` type UpdateSubnetPayload = record { [...] chain_key_signing_enable : opt vec MasterPublicKeyId; chain_key_signing_disable : opt vec MasterPublicKeyId; [...] } ``` Although `chain_key_signing_enable` and `chain_key_signing_disable` are not (directly) optional variant fields (because they are contained in a `vec`), adding the alternative is safe, given that the `MasterPublicKeyId` variant is only ever used (as part of `UpdateSubnetPayload`) in method arguments but never as method result. This argumentation is also supported by the fact that the `//rs/registry/canister:registry-canister_did_git_test` test passes. ### Registry protobuf backwards-compatibility The changes in the registry protocol buffer definitions is backwards-compatible. On the one hand, adding a new field to a `oneof` is generally backward-compatible in Protocol Buffers (with some [nuances](https://protobuf.dev/programming-guides/proto3/#backward) that are not relevant here). On the other hand, the new field/variant in the `MasterPublicKeyId` is not yet written by any code, and this new variant won't be written for many weeks to come. In particular, it will only be written to the registry once subnets will actually hold master public keys for vetKD, which will only happen in 2025. ### Crypto Algorithm ID For the time being, we don't need a particular `AlgorithmId` for vetKD, so we use the `AlgorithmId::Placeholder`. In any case, the exact algorithm also doesn't matter for now because neither the intended Crypto APIs will use an algorithm ID nor will this algorithm be persisted anywhere (e.g., in the registry or in a key store).
1 parent 60ce9d3 commit 39f67a6

File tree

22 files changed

+406
-12
lines changed

22 files changed

+406
-12
lines changed

rs/consensus/src/idkg/payload_builder.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,6 +1082,7 @@ mod tests {
10821082
signature: vec![2; 32],
10831083
})
10841084
}
1085+
MasterPublicKeyId::VetKd(_) => panic!("not applicable to vetKD"),
10851086
},
10861087
);
10871088

@@ -1924,6 +1925,7 @@ mod tests {
19241925
&mut rng,
19251926
))
19261927
}
1928+
MasterPublicKeyId::VetKd(_) => panic!("not applicable to vetKD"),
19271929
};
19281930
payload_0.available_pre_signatures.insert(
19291931
payload_0.uid_generator.next_pre_signature_id(),

rs/consensus/src/idkg/payload_builder/pre_signatures.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,12 @@ fn make_new_pre_signatures_if_needed_helper(
359359
let Some(pre_signatures_to_create) = chain_key_config
360360
.key_configs
361361
.iter()
362+
.filter(|key_config| {
363+
matches!(
364+
&key_config.key_id,
365+
MasterPublicKeyId::Ecdsa(_) | MasterPublicKeyId::Schnorr(_)
366+
)
367+
})
362368
.find(|key_config| &key_config.key_id == key_id)
363369
.map(|key_config| key_config.pre_signatures_to_create_in_advance as usize)
364370
else {
@@ -370,7 +376,7 @@ fn make_new_pre_signatures_if_needed_helper(
370376
}
371377

372378
for _ in 0..(pre_signatures_to_create - unassigned_pre_signatures) {
373-
let pre_signature = match key_id {
379+
match key_id {
374380
MasterPublicKeyId::Ecdsa(ecdsa_key_id) => {
375381
let kappa_config = new_random_unmasked_config(
376382
key_id,
@@ -380,11 +386,12 @@ fn make_new_pre_signatures_if_needed_helper(
380386
);
381387
let lambda_config =
382388
new_random_config(key_id, subnet_nodes, registry_version, uid_generator);
383-
PreSignatureInCreation::Ecdsa(QuadrupleInCreation::new(
389+
let pre_signature = PreSignatureInCreation::Ecdsa(QuadrupleInCreation::new(
384390
ecdsa_key_id.clone(),
385391
kappa_config,
386392
lambda_config,
387-
))
393+
));
394+
new_pre_signatures.insert(uid_generator.next_pre_signature_id(), pre_signature);
388395
}
389396
MasterPublicKeyId::Schnorr(schnorr_key_id) => {
390397
let blinder_config = new_random_unmasked_config(
@@ -393,13 +400,16 @@ fn make_new_pre_signatures_if_needed_helper(
393400
registry_version,
394401
uid_generator,
395402
);
396-
PreSignatureInCreation::Schnorr(TranscriptInCreation::new(
403+
let pre_signature = PreSignatureInCreation::Schnorr(TranscriptInCreation::new(
397404
schnorr_key_id.clone(),
398405
blinder_config,
399-
))
406+
));
407+
new_pre_signatures.insert(uid_generator.next_pre_signature_id(), pre_signature);
408+
}
409+
MasterPublicKeyId::VetKd(_vetkd_key_id) => {
410+
// vetKD does not have pre-signatures
400411
}
401412
};
402-
new_pre_signatures.insert(uid_generator.next_pre_signature_id(), pre_signature);
403413
}
404414

405415
new_pre_signatures
@@ -495,6 +505,7 @@ pub(super) mod test_utils {
495505
blinder_config_ref,
496506
))
497507
}
508+
MasterPublicKeyId::VetKd(_) => panic!("not applicable to vetKD"),
498509
};
499510
let configs = pre_signature
500511
.iter_transcript_configs_in_creation()
@@ -709,6 +720,7 @@ pub(super) mod tests {
709720
let expected_transcript_ids = match key_id {
710721
MasterPublicKeyId::Ecdsa(_) => 2 * expected_pre_signatures_in_creation,
711722
MasterPublicKeyId::Schnorr(_) => expected_pre_signatures_in_creation,
723+
MasterPublicKeyId::VetKd(_) => panic!("not applicable to vetKD"),
712724
};
713725
assert_eq!(transcript_ids.len(), expected_transcript_ids);
714726
assert_eq!(

rs/consensus/src/idkg/payload_builder/signatures.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,7 @@ mod tests {
311311
signature: vec![i as u8; 32],
312312
})
313313
}
314+
MasterPublicKeyId::VetKd(_) => panic!("not applicable to vetKD"),
314315
},
315316
);
316317
}

rs/consensus/src/idkg/payload_verifier.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,6 +1043,7 @@ mod test {
10431043
MasterPublicKeyId::Schnorr(_) => {
10441044
SignWithSchnorrReply { signature: vec![] }.encode()
10451045
}
1046+
MasterPublicKeyId::VetKd(_) => panic!("not applicable to vetKD"),
10461047
}),
10471048
));
10481049

@@ -1076,6 +1077,7 @@ mod test {
10761077
fake_schnorr_master_public_key_id(SchnorrAlgorithm::Ed25519)
10771078
}
10781079
MasterPublicKeyId::Schnorr(_) => fake_ecdsa_master_public_key_id(),
1080+
MasterPublicKeyId::VetKd(_) => panic!("not applicable to vetKD"),
10791081
};
10801082
// Add a pre-signature for the "wrong_key_id"
10811083
insert_test_sig_inputs(

rs/consensus/src/idkg/signer.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,6 +1101,7 @@ mod tests {
11011101
fake_schnorr_master_public_key_id(SchnorrAlgorithm::Ed25519)
11021102
}
11031103
MasterPublicKeyId::Schnorr(_) => fake_ecdsa_master_public_key_id(),
1104+
MasterPublicKeyId::VetKd(_) => panic!("not applicable to vetKD"),
11041105
};
11051106

11061107
// Set up the signature requests
@@ -1288,6 +1289,7 @@ mod tests {
12881289
let expected_complaints_count = match key_id {
12891290
MasterPublicKeyId::Ecdsa(_) => requested_signatures_count * 5,
12901291
MasterPublicKeyId::Schnorr(_) => requested_signatures_count * 2,
1292+
MasterPublicKeyId::VetKd(_) => panic!("not applicable to vetKD"),
12911293
};
12921294
let complaints = transcript_loader.returned_complaints();
12931295
assert_eq!(change_set.len(), complaints.len());
@@ -1368,6 +1370,7 @@ mod tests {
13681370
ThresholdSigInputs::Schnorr(inputs),
13691371
)
13701372
}
1373+
MasterPublicKeyId::VetKd(_) => panic!("not applicable to vetKD"),
13711374
};
13721375
let crypto = env
13731376
.nodes
@@ -1548,6 +1551,7 @@ mod tests {
15481551
fake_schnorr_master_public_key_id(SchnorrAlgorithm::Ed25519)
15491552
}
15501553
MasterPublicKeyId::Schnorr(_) => fake_ecdsa_master_public_key_id(),
1554+
MasterPublicKeyId::VetKd(_) => panic!("not applicable to vetKD"),
15511555
};
15521556
let message = create_signature_share(&key_id_wrong_scheme, NODE_2, id_2.clone());
15531557
let msg_id_2 = message.message_id();

rs/consensus/src/idkg/test_utils.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ fn fake_signature_request_args(key_id: MasterPublicKeyId) -> ThresholdArguments
9797
key_id,
9898
message: Arc::new(vec![1; 48]),
9999
}),
100+
MasterPublicKeyId::VetKd(_) => panic!("not applicable to vetKD"),
100101
}
101102
}
102103

@@ -1152,6 +1153,7 @@ pub(crate) fn create_sig_inputs_with_args(
11521153
MasterPublicKeyId::Schnorr(key_id) => {
11531154
create_schnorr_sig_inputs_with_args(caller, receivers, key_unmasked, height, key_id)
11541155
}
1156+
MasterPublicKeyId::VetKd(_) => panic!("not applicable to vetKD"),
11551157
}
11561158
}
11571159

@@ -1356,6 +1358,7 @@ pub(crate) fn create_signature_share_with_nonce(
13561358
sig_share_raw: vec![nonce],
13571359
},
13581360
}),
1361+
MasterPublicKeyId::VetKd(_) => panic!("not applicable to vetKD"),
13591362
}
13601363
}
13611364

@@ -1617,6 +1620,7 @@ pub(crate) fn key_id_with_name(key_id: &MasterPublicKeyId, name: &str) -> Master
16171620
match key_id {
16181621
MasterPublicKeyId::Ecdsa(ref mut key_id) => key_id.name = name.into(),
16191622
MasterPublicKeyId::Schnorr(ref mut key_id) => key_id.name = name.into(),
1623+
MasterPublicKeyId::VetKd(ref mut key_id) => key_id.name = name.into(),
16201624
}
16211625
key_id
16221626
}

rs/consensus/src/idkg/utils.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use ic_interfaces::consensus_pool::ConsensusBlockChain;
88
use ic_interfaces::idkg::{IDkgChangeAction, IDkgChangeSet, IDkgPool};
99
use ic_interfaces_registry::RegistryClient;
1010
use ic_logger::{warn, ReplicaLogger};
11-
use ic_management_canister_types::{EcdsaCurve, MasterPublicKeyId, SchnorrAlgorithm};
11+
use ic_management_canister_types::{EcdsaCurve, MasterPublicKeyId, SchnorrAlgorithm, VetKdCurve};
1212
use ic_protobuf::registry::subnet::v1 as pb;
1313
use ic_registry_client_helpers::subnet::SubnetRegistry;
1414
use ic_registry_subnet_features::ChainKeyConfig;
@@ -443,6 +443,9 @@ pub(crate) fn algorithm_for_key_id(key_id: &MasterPublicKeyId) -> AlgorithmId {
443443
SchnorrAlgorithm::Bip340Secp256k1 => AlgorithmId::ThresholdSchnorrBip340,
444444
SchnorrAlgorithm::Ed25519 => AlgorithmId::ThresholdEd25519,
445445
},
446+
MasterPublicKeyId::VetKd(vetkd_key_id) => match vetkd_key_id.curve {
447+
VetKdCurve::Bls12_381_G2 => AlgorithmId::Placeholder,
448+
},
446449
}
447450
}
448451

rs/consensus/utils/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -860,6 +860,7 @@ mod tests {
860860
MasterPublicKeyId::Schnorr(key_id) => {
861861
PreSignatureRef::Schnorr(fake_schnorr_transcript(id, key_id.clone()))
862862
}
863+
MasterPublicKeyId::VetKd(_) => panic!("not applicable to vetKD"),
863864
}
864865
}
865866

@@ -880,6 +881,7 @@ mod tests {
880881
key_id: key_id.clone(),
881882
})
882883
}
884+
MasterPublicKeyId::VetKd(_) => panic!("not applicable to vetKD"),
883885
},
884886
derivation_path: vec![],
885887
pseudo_random_id: [0; 32],

rs/execution_environment/src/scheduler/threshold_signatures.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ mod tests {
140140
key_id: key_id.clone(),
141141
message: Arc::new(vec![1; 64]),
142142
}),
143+
MasterPublicKeyId::VetKd(_) => panic!("vetKD does not have pre-signatures"),
143144
};
144145
let context = SignWithThresholdContext {
145146
request: RequestBuilder::new().build(),

rs/protobuf/def/registry/crypto/v1/crypto.proto

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,20 @@ message SchnorrKeyId {
8080
string name = 2;
8181
}
8282

83+
enum VetKdCurve {
84+
VET_KD_CURVE_UNSPECIFIED = 0;
85+
VET_KD_CURVE_BLS12_381_G2 = 1;
86+
}
87+
88+
message VetKdKeyId {
89+
VetKdCurve curve = 1;
90+
string name = 2;
91+
}
92+
8393
message MasterPublicKeyId {
8494
oneof key_id {
8595
EcdsaKeyId ecdsa = 1;
8696
SchnorrKeyId schnorr = 2;
97+
VetKdKeyId vetkd = 3;
8798
}
8899
}

0 commit comments

Comments
 (0)