Skip to content

Commit 49be34e

Browse files
committed
refactor(crypto): CRP-1447 make IDkgReceivers::position() private
1 parent 2640da7 commit 49be34e

File tree

11 files changed

+103
-33
lines changed

11 files changed

+103
-33
lines changed

rs/consensus/src/ecdsa/pre_signer.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -278,8 +278,7 @@ impl EcdsaPreSignerImpl {
278278
self.resolve_ref(transcript_params_ref, block_reader, "send_dealing_support")
279279
.and_then(|transcript_params| {
280280
transcript_params
281-
.receivers()
282-
.position(self.node_id)
281+
.receiver_index(self.node_id)
283282
.map(|_| (id, transcript_params, signed_dealing))
284283
})
285284
} else {
@@ -404,10 +403,9 @@ impl EcdsaPreSignerImpl {
404403
}
405404
};
406405

407-
if transcript_params
406+
if !transcript_params
408407
.receivers()
409-
.position(support.sig_share.signer)
410-
.is_none()
408+
.contains(support.sig_share.signer)
411409
{
412410
// The node is not in the receiver list for this transcript,
413411
// support share is not expected from it

rs/crypto/src/sign/canister_threshold_sig/ecdsa.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use ic_types::crypto::canister_threshold_sig::{
1717
use ic_types::crypto::AlgorithmId;
1818
use ic_types::{NodeId, NodeIndex};
1919
use serde::{Deserialize, Serialize};
20-
use std::collections::{BTreeMap, BTreeSet};
20+
use std::collections::BTreeMap;
2121
use std::convert::TryFrom;
2222

2323
#[cfg(test)]
@@ -43,7 +43,7 @@ pub fn sign_share<C: CspThresholdEcdsaSigner>(
4343
self_node_id: &NodeId,
4444
inputs: &ThresholdEcdsaSigInputs,
4545
) -> Result<ThresholdEcdsaSigShare, ThresholdEcdsaSignShareError> {
46-
ensure_self_was_receiver(self_node_id, inputs.receivers().get())?;
46+
ensure_self_was_receiver(self_node_id, inputs.receivers())?;
4747

4848
let internal_sig_share = csp_client.ecdsa_sign_share(inputs)?;
4949

@@ -166,7 +166,7 @@ pub fn combine_sig_shares<C: CspThresholdEcdsaSigVerifier>(
166166
let kappa_unmasked =
167167
IDkgTranscriptInternal::deserialize(kappa_transcript).map_err(conv_error)?;
168168

169-
let internal_shares = internal_sig_shares_by_index_from_sig_shares(shares, inputs.receivers())?;
169+
let internal_shares = internal_sig_shares_by_index_from_sig_shares(shares, inputs)?;
170170

171171
let key = IDkgTranscriptInternal::try_from(inputs.key_transcript()).map_err(conv_error)?;
172172

@@ -219,9 +219,9 @@ pub fn get_tecdsa_master_public_key(
219219

220220
fn ensure_self_was_receiver(
221221
self_node_id: &NodeId,
222-
receivers: &BTreeSet<NodeId>,
222+
receivers: &IDkgReceivers,
223223
) -> Result<(), ThresholdEcdsaSignShareError> {
224-
if receivers.contains(self_node_id) {
224+
if receivers.contains(*self_node_id) {
225225
Ok(())
226226
} else {
227227
Err(ThresholdEcdsaSignShareError::NotAReceiver)
@@ -248,14 +248,14 @@ fn ensure_sufficient_sig_shares_collected(
248248
/// and map them by signer index (rather than signer Id).
249249
fn internal_sig_shares_by_index_from_sig_shares(
250250
shares: &BTreeMap<NodeId, ThresholdEcdsaSigShare>,
251-
receivers: &IDkgReceivers,
251+
inputs: &ThresholdEcdsaSigInputs,
252252
) -> Result<BTreeMap<NodeIndex, ThresholdEcdsaSigShareInternal>, ThresholdEcdsaCombineSigSharesError>
253253
{
254254
shares
255255
.iter()
256256
.map(|(&id, share)| {
257-
let index = receivers
258-
.position(id)
257+
let index = inputs
258+
.index_for_signer_id(id)
259259
.ok_or(ThresholdEcdsaCombineSigSharesError::SignerNotAllowed { node_id: id })?;
260260
let internal_share = ThresholdEcdsaSigShareInternal::deserialize(&share.sig_share_raw)
261261
.map_err(

rs/crypto/src/sign/canister_threshold_sig/idkg/complaint.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ fn index_of_complainer(
4949
complainer_id: NodeId,
5050
transcript: &IDkgTranscript,
5151
) -> Result<NodeIndex, IDkgVerifyComplaintError> {
52-
transcript.receivers.position(complainer_id).ok_or(
52+
transcript.index_for_signer_id(complainer_id).ok_or(
5353
IDkgVerifyComplaintError::InvalidArgumentMissingComplainerInTranscript { complainer_id },
5454
)
5555
}

rs/crypto/src/sign/canister_threshold_sig/idkg/transcript.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ pub fn load_transcript<C: CspIDkgProtocol>(
148148
registry: &dyn RegistryClient,
149149
transcript: &IDkgTranscript,
150150
) -> Result<Vec<IDkgComplaint>, IDkgLoadTranscriptError> {
151-
let self_index = match transcript.receivers.position(*self_node_id) {
151+
let self_index = match transcript.index_for_signer_id(*self_node_id) {
152152
Some(index) => index,
153153
None => {
154154
return Ok(vec![]); // This is not a receiver: nothing to do.
@@ -180,7 +180,7 @@ pub fn load_transcript_with_openings<C: CspIDkgProtocol>(
180180
transcript: &IDkgTranscript,
181181
openings: &BTreeMap<IDkgComplaint, BTreeMap<NodeId, IDkgOpening>>,
182182
) -> Result<(), IDkgLoadTranscriptError> {
183-
let self_index = match transcript.receivers.position(*self_node_id) {
183+
let self_index = match transcript.index_for_signer_id(*self_node_id) {
184184
Some(index) => index,
185185
None => {
186186
return Ok(()); // This is not a receiver: nothing to do.
@@ -199,7 +199,7 @@ pub fn load_transcript_with_openings<C: CspIDkgProtocol>(
199199
for (complaint, openings_by_opener_id) in openings {
200200
let mut internal_openings_by_opener_index = BTreeMap::new();
201201
for (opener_id, opening) in openings_by_opener_id {
202-
let opener_index = transcript.receivers.position(*opener_id).ok_or_else(|| {
202+
let opener_index = transcript.index_for_signer_id(*opener_id).ok_or_else(|| {
203203
IDkgLoadTranscriptError::InvalidArguments {
204204
internal_error: format!(
205205
"invalid opener: node with ID {:?} is not a receiver",
@@ -266,7 +266,7 @@ pub fn open_transcript<C: CspIDkgProtocol>(
266266
let (dealer_index, signed_dealing) =
267267
index_and_batch_signed_dealing_of_dealer(complaint.dealer_id, transcript)?;
268268
let context_data = transcript.context_data();
269-
let opener_index = match transcript.receivers.position(*self_node_id) {
269+
let opener_index = match transcript.index_for_signer_id(*self_node_id) {
270270
None => {
271271
return Err(IDkgOpenTranscriptError::InternalError {
272272
internal_error: "This node is not a receiver of the given transcript".to_string(),
@@ -317,8 +317,7 @@ pub fn verify_opening<C: CspIDkgProtocol>(
317317
// Extract the accused dealing from the transcript
318318
let (_, internal_dealing) = index_and_dealing_of_dealer(complaint.dealer_id, transcript)?;
319319
let opener_index = transcript
320-
.receivers
321-
.position(opener_id)
320+
.index_for_signer_id(opener_id)
322321
.ok_or(IDkgVerifyOpeningError::MissingOpenerInReceivers { opener_id })?;
323322
let internal_opening = CommitmentOpening::try_from(opening).map_err(|e| {
324323
IDkgVerifyOpeningError::InternalError {
@@ -362,7 +361,7 @@ fn ensure_signers_allowed_by_params(
362361
) -> Result<(), IDkgCreateTranscriptError> {
363362
for dealing in dealings {
364363
for signer in dealing.signers() {
365-
if !params.receivers().get().contains(&signer) {
364+
if !params.receivers().contains(signer) {
366365
return Err(IDkgCreateTranscriptError::SignerNotAllowed { node_id: signer });
367366
}
368367
}

rs/crypto/test_utils/canister_threshold_sigs/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -751,15 +751,15 @@ pub mod node {
751751
) -> impl Iterator<Item = Node> + 'a {
752752
self.nodes
753753
.into_iter()
754-
.filter(move |node| idkg_receivers.as_ref().get().contains(&node.id))
754+
.filter(move |node| idkg_receivers.as_ref().contains(node.id))
755755
}
756756

757757
pub fn receivers<'a, T: AsRef<IDkgReceivers> + 'a>(
758758
&'a self,
759759
idkg_receivers: T,
760760
) -> impl Iterator<Item = &Node> + 'a {
761761
self.iter()
762-
.filter(move |node| idkg_receivers.as_ref().get().contains(&node.id))
762+
.filter(move |node| idkg_receivers.as_ref().contains(node.id))
763763
}
764764

765765
pub fn dealers<'a, T: AsRef<IDkgDealers> + 'a>(
@@ -1456,7 +1456,7 @@ pub fn corrupt_signed_idkg_dealing<R: CryptoRng + RngCore, T: BasicSigner<IDkgDe
14561456
let receiver =
14571457
random_receiver_id_excluding_set(transcript_params.receivers(), excluded_receivers, rng)
14581458
.ok_or(CorruptSignedIDkgDealingError::NoReceivers)?;
1459-
let node_index = transcript_params.receivers().position(*receiver).unwrap();
1459+
let node_index = transcript_params.receiver_index(*receiver).unwrap();
14601460

14611461
Ok(idkg_dealing
14621462
.into_builder()

rs/crypto/tests/canister_threshold_sigs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3737,7 +3737,7 @@ mod verify_opening {
37373737
let verifier = env.nodes.random_receiver(&transcript.receivers, rng);
37383738
let wrong_opener_id = node_id(123456789);
37393739
assert!(
3740-
!transcript.receivers.get().contains(&wrong_opener_id),
3740+
!transcript.receivers.contains(wrong_opener_id),
37413741
"Wrong opener_id unexpectedly in receivers"
37423742
);
37433743
let result =

rs/types/types/src/crypto/canister_threshold_sig.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ use crate::crypto::canister_threshold_sig::idkg::{
66
use crate::crypto::AlgorithmId;
77
use crate::{NumberOfNodes, Randomness};
88
use core::fmt;
9-
use ic_base_types::PrincipalId;
9+
use ic_base_types::{NodeId, PrincipalId};
10+
use ic_crypto_internal_types::NodeIndex;
1011
#[cfg(test)]
1112
use ic_exhaustive_derive::ExhaustiveSet;
1213
use serde::{Deserialize, Serialize};
@@ -481,6 +482,10 @@ impl ThresholdEcdsaSigInputs {
481482
),
482483
}
483484
}
485+
486+
pub fn index_for_signer_id(&self, node_id: NodeId) -> Option<NodeIndex> {
487+
self.key_transcript().index_for_signer_id(node_id)
488+
}
484489
}
485490

486491
/// A single threshold ECDSA signature share.

rs/types/types/src/crypto/canister_threshold_sig/idkg.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -163,13 +163,21 @@ impl IDkgReceivers {
163163

164164
/// Returns the position of the given `node_id` in the receivers. Returns
165165
/// `None` if the `node_id` is not a receiver.
166-
pub fn position(&self, node_id: NodeId) -> Option<NodeIndex> {
166+
///
167+
/// This method is intended to be PRIVATE. For public methods for obtaining
168+
/// a receiver's index, the methods of the objects like [`IDkgTranscript`],
169+
/// [`IDkgTranscriptParams`], or [`ThresholdEcdsaSigInputs`] should be used.
170+
fn position(&self, node_id: NodeId) -> Option<NodeIndex> {
167171
self.receivers
168172
.iter()
169173
.position(|receiver| node_id == *receiver)
170174
.map(|index| NodeIndex::try_from(index).expect("node index overflow"))
171175
}
172176

177+
pub fn contains(&self, node_id: NodeId) -> bool {
178+
self.receivers.contains(&node_id)
179+
}
180+
173181
pub fn get(&self) -> &BTreeSet<NodeId> {
174182
&self.receivers
175183
}
@@ -407,15 +415,15 @@ impl IDkgTranscriptParams {
407415
match &self.operation_type {
408416
IDkgTranscriptOperation::Random => Some(index),
409417
IDkgTranscriptOperation::ReshareOfMasked(transcript) => {
410-
transcript.receivers.position(node_id)
418+
transcript.index_for_signer_id(node_id)
411419
}
412420
IDkgTranscriptOperation::ReshareOfUnmasked(transcript) => {
413-
transcript.receivers.position(node_id)
421+
transcript.index_for_signer_id(node_id)
414422
}
415423
IDkgTranscriptOperation::UnmaskedTimesMasked(transcript_1, _transcript_2) => {
416424
// transcript_1.receivers == transcript_2.receivers already checked by
417425
// IDkgTranscriptParams::new
418-
transcript_1.receivers.position(node_id)
426+
transcript_1.index_for_signer_id(node_id)
419427
}
420428
}
421429
}
@@ -936,7 +944,7 @@ impl IDkgTranscript {
936944

937945
/// Checks if the specified `NodeId` is a receiver of the transcript.
938946
pub fn has_receiver(&self, receiver_id: NodeId) -> bool {
939-
self.receivers.position(receiver_id).is_some()
947+
self.receivers.contains(receiver_id)
940948
}
941949

942950
/// Returns a copy of the raw internal transcript.

rs/types/types/src/crypto/canister_threshold_sig/idkg/tests/receivers.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,30 @@ fn should_return_none_position_if_node_id_not_in_receivers() {
9191
assert!(receivers.position(not_a_receiver_node).is_none());
9292
}
9393

94+
#[test]
95+
fn should_return_contains_false_if_node_id_not_in_receivers() {
96+
let not_a_receiver_node = node_id(NODE_3);
97+
let mut receivers = BTreeSet::new();
98+
receivers.insert(node_id(NODE_1));
99+
receivers.insert(node_id(NODE_2));
100+
let receivers = IDkgReceivers::new(receivers).unwrap();
101+
102+
assert!(!receivers.contains(not_a_receiver_node));
103+
}
104+
105+
#[test]
106+
fn should_return_contains_true_if_node_id_in_receivers() {
107+
let receiver_node_1 = node_id(NODE_1);
108+
let receiver_node_2 = node_id(NODE_2);
109+
let mut receivers = BTreeSet::new();
110+
receivers.insert(receiver_node_1);
111+
receivers.insert(receiver_node_2);
112+
let receivers = IDkgReceivers::new(receivers).unwrap();
113+
114+
assert!(receivers.contains(receiver_node_1));
115+
assert!(receivers.contains(receiver_node_2));
116+
}
117+
94118
#[test]
95119
fn should_return_correct_reconstruction_threshold() {
96120
let mut receivers = BTreeSet::new();

rs/types/types/src/crypto/canister_threshold_sig/idkg/tests/verify_transcript_params.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ fn should_fail_on_ineligible_signer() {
211211
let rng = &mut reproducible_rng();
212212
let (mut transcript, params) = valid_transcript_and_params(rng);
213213
let non_receiver = node_id(99999);
214-
assert!(!params.receivers.get().contains(&non_receiver));
214+
assert!(!params.receivers.contains(non_receiver));
215215
let first_dealer_index = *transcript.verified_dealings.keys().next().unwrap();
216216
transcript
217217
.verified_dealings

rs/types/types/src/crypto/canister_threshold_sig/tests.rs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::crypto::canister_threshold_sig::error::{
55
use crate::crypto::canister_threshold_sig::idkg::IDkgTranscriptId;
66
use crate::{Height, NodeId, RegistryVersion, SubnetId};
77
use assert_matches::assert_matches;
8-
use ic_crypto_test_utils_canister_threshold_sigs::set_of_nodes;
8+
use ic_crypto_test_utils_canister_threshold_sigs::{node_id, set_of_nodes};
99
use ic_crypto_test_utils_reproducible_rng::reproducible_rng;
1010
use rand::{CryptoRng, Rng};
1111
use std::collections::{BTreeMap, BTreeSet};
@@ -486,6 +486,42 @@ fn serde_cbor_deserialization_of_extended_derivation_path_is_backward_compatible
486486
assert_eq!(computed_derivation_path, expected_derivation_path);
487487
}
488488

489+
#[test]
490+
fn should_return_correct_index_for_signer_id_from_threshold_ecdsa_sig_inputs() {
491+
let rng = &mut reproducible_rng();
492+
let common_receivers = set_of_nodes(&[42, 43, 45, 128]);
493+
let (kappa_unmasked, lambda_masked, kappa_times_lambda, key_times_lambda, key_transcript) =
494+
transcripts_for_ecdsa_inputs(common_receivers, rng);
495+
496+
let quadruple = PreSignatureQuadruple::new(
497+
kappa_unmasked,
498+
lambda_masked,
499+
kappa_times_lambda,
500+
key_times_lambda,
501+
);
502+
assert!(quadruple.is_ok());
503+
504+
let derivation_path = derivation_path();
505+
let hashed_message = hashed_message();
506+
let nonce = nonce();
507+
let quadruple = quadruple.unwrap();
508+
let inputs = ThresholdEcdsaSigInputs::new(
509+
&derivation_path,
510+
&hashed_message,
511+
nonce,
512+
quadruple.clone(),
513+
key_transcript.clone(),
514+
)
515+
.expect("failed to create ThresholdEcdsaSigInputs");
516+
517+
assert_eq!(inputs.index_for_signer_id(node_id(42)), Some(0));
518+
assert_eq!(inputs.index_for_signer_id(node_id(43)), Some(1));
519+
assert_eq!(inputs.index_for_signer_id(node_id(44)), None);
520+
assert_eq!(inputs.index_for_signer_id(node_id(45)), Some(2));
521+
assert_eq!(inputs.index_for_signer_id(node_id(46)), None);
522+
assert_eq!(inputs.index_for_signer_id(node_id(128)), Some(3));
523+
}
524+
489525
// A randomized way to get non-repeating IDs.
490526
pub fn random_transcript_id<R: Rng + CryptoRng>(rng: &mut R) -> IDkgTranscriptId {
491527
let id = rng.gen();

0 commit comments

Comments
 (0)