-
Notifications
You must be signed in to change notification settings - Fork 317
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(crypto): CRP-2597 Extend NiDkgTag with HighThresholdForKey variant #2445
base: master
Are you sure you want to change the base?
feat(crypto): CRP-2597 Extend NiDkgTag with HighThresholdForKey variant #2445
Conversation
…try/crypto to types
NiDkgTag::HighThresholdForKey(master_public_key_id) => { | ||
error!( | ||
log, | ||
"Implementation error: NiDkgTag::HighThresholdForKey({master_public_key_id}) used in SetupInitialDKG for callback ID {callback_id}", | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the idea here is to reuse the transcripts_for_remote_subnets
field also for xnet reshares of VetKD keys. So then we would generalize this function such that it can generate the correct ConsensusResponse
, depending on whether the callback ID is for a SetupInitialDKG context or a VetKD reshare context.
For now, logging an error and linking the ticket to generalize this function (CON-1416) should be fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a TODO linking to the mentioned ticket.
//////////////////////////////////////////////////////////////////////////////// | ||
// TODO: how to behave here? The code below is copied+adapted from the HighThreshold case. However, | ||
// this code currently won't be executed because we iterate over TAGS, which is a const that does not | ||
// and cannot contain an NiDkgTag::HighThresholdForKey entry | ||
/////////////////////////////////////////////////////////////////////////////// | ||
NiDkgTag::HighThresholdForKey(master_public_key_id) => { | ||
let resharing_transcript = reshared_transcripts | ||
.get(&NiDkgTag::HighThresholdForKey(master_public_key_id.clone())); | ||
( | ||
resharing_transcript | ||
.map(|transcript| transcript.committee.get().clone()) | ||
.unwrap_or_else(|| node_ids.clone()), | ||
resharing_transcript.cloned(), | ||
) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the behavior is correct (maybe it could even be combined with the NiDkgTag::HighThreshold
branch). We can link ticket CON-1413 above, reminding us to iterate over all vetKD keys that were requested by registry in addition to the tags in TAGS
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a TODO linking to the mentioned ticket.
Also, I combined the NiDkgTag::HighThreshold | NiDkgTag::HighThresholdForKey(_)
.
PTAL
///////////////////////////////////////// | ||
// TODO: check with Consensus team | ||
NiDkgTag::HighThresholdForKey(_) => panic!("not applicable"), | ||
///////////////////////////////////////// |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can link CON-1417 to extend this test once we have support for vet key transcripts in registry CUPs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
///////////////////////////////////////// | ||
// TODO: check with Consensus team | ||
NiDkgTag::HighThresholdForKey(_) => panic!("not applicable"), | ||
///////////////////////////////////////// | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can link CON-1413 to extend this test once we can create local transcript configs for vetKeys that were requested by registry
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @fspreiss, LGTM!
@@ -115,20 +125,21 @@ impl ThresholdSigDataStoreImpl { | |||
/// | |||
/// # Panics | |||
/// If `max_num_of_dkg_ids_per_tag` is smaller than 1. | |||
fn new_with_max_size(max_num_of_dkg_ids_per_tag: usize) -> Self { | |||
fn new_with_max_size(max_num_of_dkg_ids_per_tag_or_key: usize) -> Self { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
off-topic: Seems new
is the only caller of new_with_max_size
. I'm wondering if we want to eventually simplify this by inlining new_with_max_size
and adding a static assert on CAPACITY_FOR_TAG
to avoid having the runtime panic. But this is not a concern for this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, sure, sounds good. Did you mean to use static_assertions for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Either that or just
const _: () = assert!(...);
@@ -294,6 +294,9 @@ fn registry_with_ni_dkg_transcript( | |||
cup_contents.initial_ni_dkg_transcript_low_threshold = | |||
Some(InitialNiDkgTranscriptRecord::from(transcript())); | |||
} | |||
NiDkgTag::HighThresholdForKey(_master_public_key_id) => { | |||
unimplemented!("not supported currently") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this not supported? Is this is only testing NIDKG for consensus by definition, if yes it would be better to make it explicit in the error message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do I understand correctly, these transcripts should go into the ChainKeyInitialization
introduced with #2337? Then this should already be possible, now that the PR is merged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TL;DR: The tests in which the registry_with_ni_dkg_transcript
helper is used will never be extended so that a NiDkgTag::HighThresholdForKey
is needed, which is why this is unimplemented
.
Background
This helper function, registry_with_ni_dkg_transcript
, is used in two tests:
should_correctly_retrieve_initial_low_threshold_ni_dkg_transcript_from_registry
should_correctly_retrieve_initial_high_threshold_ni_dkg_transcript_from_registry
Both these tests test CryptoRegistry::get_initial_dkg_transcripts
, which returns a
struct DkgTranscripts {
low_threshold: NiDkgTranscript,
high_threshold: NiDkgTranscript,
}
(I'm not sure why these tests actually live in ic-crypto-test-utils-ni-dkg
. I'd say the correct place would be ic-registry-client-helpers
; we should probably move the tests).
These are the two initial NiDkgTranscripts that a subnet needs to operate (low-threshold for random beacon/tape, high-threshold for state certification). They are required by the ICP protocol itself.
The NIDKG-transcript that is created for vetKeys by means of a key re-sharing request (as part of subnet creation or subnet recovery) is not needed by a subnet to operate. Because of this, such transcripts won't be returned by CryptoRegistry::get_initial_dkg_transcripts
, but whoever needs them will likely fetch the CUP and then get the transcript out of that.
Because of this, I didn't see a reason
@@ -31,18 +32,22 @@ mod tests; | |||
|
|||
/// Allows to distinguish protocol executions in high and low threshold |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be worth adding what the new variant means, i.e., what is the Key
and what is its relation to an NIDKG tag.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM for management_canister_types
1 => Ok(NiDkgTag::LowThreshold), | ||
2 => Ok(NiDkgTag::HighThreshold), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we return an error if the tag is LowThreshold
or HighThreshold
, but ni_dkg_id_proto.key_id
isn't None
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
1 => Ok(NiDkgTag::LowThreshold), | ||
2 => Ok(NiDkgTag::HighThreshold), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
///////////////////////////////////////////////////// | ||
// TODO(CON-1417): extend this test once we have support for vetKD transcripts in registry CUPs | ||
///////////////////////////////////////////////////// | ||
NiDkgTag::HighThresholdForKey(_) => panic!("not applicable"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe instead of panicking with the not very informative "not applicable"
, we use unimplemented("CON-1417")
. I mean, if we were to ever hit this case (which I don't believe we will), we would know much faster whats going on
1 => Ok(NiDkgTag::LowThreshold), | ||
2 => Ok(NiDkgTag::HighThreshold), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
@@ -294,6 +294,9 @@ fn registry_with_ni_dkg_transcript( | |||
cup_contents.initial_ni_dkg_transcript_low_threshold = | |||
Some(InitialNiDkgTranscriptRecord::from(transcript())); | |||
} | |||
NiDkgTag::HighThresholdForKey(_master_public_key_id) => { | |||
unimplemented!("not supported currently") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do I understand correctly, these transcripts should go into the ChainKeyInitialization
introduced with #2337? Then this should already be possible, now that the PR is merged.
pub enum NiDkgTag { | ||
LowThreshold = 1, | ||
HighThreshold = 2, | ||
HighThresholdForKey(MasterPublicKeyId) = 3, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@altkdf, @randombit: @Sawchord suggested to use a new type NiDkgMasterPublicKeyId
here instead (i.e., using HighThresholdForKey(NiDkgMasterPublicKeyId) = 3,
), similar to the IDkgMasterPublicKeyId
that he introduced in #2445, so as to be explicit via the type system on which types of keys can be used with NiDkg (and which cannot) and at the same time be future proof.
This type could be a struct or an enum (or somewhat both): there is a discussion around it here: https://github.com/dfinity/ic/pull/2388/files#r1839804072
I think his suggestion makes sense, so I'll start working on integrating that. Please let me know if you'd prefer to keep it as is, or if you have other comments regarding this.
Extends the
NiDkgTag
with a new variantNiDkgTag::HighThresholdForKey
that holds aMasterPublicKeyId
.Notes:
Makes the representation for
NiDkgTag
explicit with#[repr(isize)]
because a#[repr(inttype)]
must be provided on an enum if it has a non-unit variant with a discriminant (E0732). The representation should be the same as it was before, given thatisize
is the default representation for enums.Note that casting
NiDkgTag
withas
, e.g., toi32
or evenisize
is no longer possible because "anas
expression can be used to convert enum types to numeric types only if the enum type is unit-only or field-less" (see Enumeration casting and E0605).The conversion
impl TryFrom<i32> for NiDkgTag
had to be removed, because it is no longer possible, because ani32
itself is no longer sufficient for instantiating anNiDkgTag
.This conversion was used in two places: (1)
impl TryFrom<NiDkgIdProto> for NiDkgId
and (2)build_tagged_transcripts_map
. There, the conversion is now implemented directly.No longer Implements
EnumIter
forNiDkgTag
because this would require aDefault
implementation forMasterPublicKeyId
, which does not make sense, at least in production. Instead implementsEnumCount
.