diff --git a/Cargo.lock b/Cargo.lock index 4f38790454e..bbda1d3771f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7094,6 +7094,8 @@ dependencies = [ "ic-types", "rand 0.8.5", "rand_chacha 0.3.1", + "strum 0.25.0", + "strum_macros 0.25.3", ] [[package]] diff --git a/rs/consensus/src/ecdsa/pre_signer.rs b/rs/consensus/src/ecdsa/pre_signer.rs index 7e5e3ff4838..1e3205e737f 100644 --- a/rs/consensus/src/ecdsa/pre_signer.rs +++ b/rs/consensus/src/ecdsa/pre_signer.rs @@ -1339,7 +1339,7 @@ mod tests { use crate::ecdsa::test_utils::*; use assert_matches::assert_matches; use ic_crypto_test_utils_canister_threshold_sigs::{ - CanisterThresholdSigTestEnvironment, IDkgParticipants, + setup_masked_random_params, CanisterThresholdSigTestEnvironment, IDkgParticipants, }; use ic_crypto_test_utils_reproducible_rng::reproducible_rng; use ic_interfaces::p2p::consensus::{MutablePool, UnvalidatedArtifact}; @@ -2567,10 +2567,11 @@ mod tests { &IDkgParticipants::AllNodesAsDealersAndReceivers, &mut rng, ); - let params = env.params_for_random_sharing( + let params = setup_masked_random_params( + &env, + AlgorithmId::ThresholdEcdsaSecp256k1, &dealers, &receivers, - AlgorithmId::ThresholdEcdsaSecp256k1, &mut rng, ); let tid = params.transcript_id(); diff --git a/rs/consensus/src/ecdsa/test_utils.rs b/rs/consensus/src/ecdsa/test_utils.rs index 30f4c0236fc..36b62ed8ced 100644 --- a/rs/consensus/src/ecdsa/test_utils.rs +++ b/rs/consensus/src/ecdsa/test_utils.rs @@ -10,7 +10,8 @@ use ic_consensus_utils::crypto::ConsensusCrypto; use ic_crypto_temp_crypto::TempCryptoComponent; use ic_crypto_test_utils_canister_threshold_sigs::dummy_values::dummy_idkg_dealing_for_tests; use ic_crypto_test_utils_canister_threshold_sigs::{ - generate_key_transcript, CanisterThresholdSigTestEnvironment, IDkgParticipants, IntoBuilder, + generate_key_transcript, setup_masked_random_params, CanisterThresholdSigTestEnvironment, + IDkgParticipants, IntoBuilder, }; use ic_crypto_test_utils_reproducible_rng::ReproducibleRng; use ic_ic00_types::EcdsaKeyId; @@ -742,10 +743,11 @@ pub(crate) fn create_valid_transcript( ) -> (NodeId, IDkgTranscriptParams, IDkgTranscript) { let (dealers, receivers) = env.choose_dealers_and_receivers(&IDkgParticipants::AllNodesAsDealersAndReceivers, rng); - let params = env.params_for_random_sharing( + let params = setup_masked_random_params( + env, + AlgorithmId::ThresholdEcdsaSecp256k1, &dealers, &receivers, - AlgorithmId::ThresholdEcdsaSecp256k1, rng, ); let dealings = env.nodes.create_and_verify_signed_dealings(¶ms); @@ -829,10 +831,11 @@ pub(crate) fn create_dealing_with_payload( let env = CanisterThresholdSigTestEnvironment::new(2, rng); let (dealers, receivers) = env.choose_dealers_and_receivers(&IDkgParticipants::AllNodesAsDealersAndReceivers, rng); - let params = env.params_for_random_sharing( + let params = setup_masked_random_params( + &env, + AlgorithmId::ThresholdEcdsaSecp256k1, &dealers, &receivers, - AlgorithmId::ThresholdEcdsaSecp256k1, rng, ); let dealer = env.nodes.dealers(¶ms).next().unwrap(); diff --git a/rs/crypto/benches/idkg.rs b/rs/crypto/benches/idkg.rs index 432cd9b0256..86dd76ca903 100644 --- a/rs/crypto/benches/idkg.rs +++ b/rs/crypto/benches/idkg.rs @@ -3,25 +3,26 @@ use criterion::BatchSize::SmallInput; use criterion::{criterion_group, criterion_main, BenchmarkGroup, Criterion, SamplingMode}; use ic_crypto_test_utils_canister_threshold_sigs::node::{Node, Nodes}; use ic_crypto_test_utils_canister_threshold_sigs::{ - build_params_from_previous, corrupt_single_dealing_and_generate_complaint, - generate_and_verify_openings_for_complaint, random_transcript_id, - CanisterThresholdSigTestEnvironment, IDkgParticipants, + build_params_from_previous, create_transcript_or_panic, + generate_and_verify_openings_for_complaint, load_previous_transcripts_for_all_dealers, + load_transcript_or_panic, random_transcript_id, run_idkg_without_complaint, + setup_masked_random_params, CanisterThresholdSigTestEnvironment, IDkgMode, IDkgModeTestContext, + IDkgParticipants, IDkgTestContextForComplaint, }; use ic_crypto_test_utils_reproducible_rng::ReproducibleRng; use ic_interfaces::crypto::IDkgProtocol; use ic_types::crypto::canister_threshold_sig::idkg::{ - BatchSignedIDkgDealings, IDkgComplaint, IDkgDealers, IDkgReceivers, IDkgTranscript, - IDkgTranscriptOperation, IDkgTranscriptParams, InitialIDkgDealings, SignedIDkgDealing, + IDkgDealers, IDkgReceivers, IDkgTranscript, IDkgTranscriptOperation, IDkgTranscriptParams, + InitialIDkgDealings, SignedIDkgDealing, }; use ic_types::crypto::canister_threshold_sig::PreSignatureQuadruple; use ic_types::crypto::AlgorithmId; use rand::{CryptoRng, RngCore}; use std::collections::HashSet; -use std::fmt::{Display, Formatter}; use strum::IntoEnumIterator; use strum_macros::EnumIter; -#[derive(strum_macros::EnumIter, PartialEq, Copy, Clone, Default)] +#[derive(EnumIter, PartialEq, Copy, Clone, Default)] enum VaultType { Local, #[default] @@ -41,9 +42,8 @@ criterion_main!(benches); criterion_group!(benches, crypto_idkg_benchmarks); fn crypto_idkg_benchmarks(criterion: &mut Criterion) { - let number_of_nodes = [1, 4, 13, 28, 40]; - - let test_cases = generate_test_cases(&number_of_nodes); + let nums_of_nodes = [1, 4, 13, 28, 40]; + let test_cases = generate_test_cases(&nums_of_nodes); let rng = &mut ReproducibleRng::new(); for test_case in test_cases { @@ -54,19 +54,15 @@ fn crypto_idkg_benchmarks(criterion: &mut Criterion) { .sample_size(test_case.sample_size) .sampling_mode(test_case.sampling_mode); - IDkgMode::iter() - .for_each(|mode| bench_create_dealing(group, &test_case, &mode, vault_type, rng)); - - IDkgMode::iter().for_each(|mode| { - bench_verify_dealing_private(group, &test_case, &mode, vault_type, rng) - }); - - IDkgMode::iter() - .for_each(|mode| bench_load_transcript(group, &test_case, &mode, vault_type, rng)); + for mode in IDkgMode::iter() { + bench_create_dealing(group, &test_case, mode, vault_type, rng); + bench_verify_dealing_private(group, &test_case, mode, vault_type, rng); + bench_load_transcript(group, &test_case, mode, vault_type, rng); + } bench_retain_active_transcripts(group, &test_case, 1, vault_type, rng); - if test_case.num_of_nodes > 1 { + if test_case.num_of_nodes >= IDkgMode::Random.min_subnet_size_for_complaint() { bench_open_transcript(group, &test_case, vault_type, rng); bench_load_transcript_with_openings(group, &test_case, vault_type, rng); } @@ -74,21 +70,16 @@ fn crypto_idkg_benchmarks(criterion: &mut Criterion) { // The following benchmarks are not affected by the choice of the // vault, we benchmark them only once with the default vault type. if vault_type == VaultType::default() { - IDkgMode::iter().for_each(|mode| { - bench_verify_dealing_public(group, &test_case, &mode, vault_type, rng) - }); + for mode in IDkgMode::iter() { + bench_verify_dealing_public(group, &test_case, mode, vault_type, rng); + bench_create_transcript(group, &test_case, mode, vault_type, rng); + bench_verify_transcript(group, &test_case, mode, vault_type, rng); + } bench_verify_initial_dealings(group, &test_case, vault_type, rng); - IDkgMode::iter().for_each(|mode| { - bench_create_transcript(group, &test_case, &mode, vault_type, rng) - }); - IDkgMode::iter().for_each(|mode| { - bench_verify_transcript(group, &test_case, &mode, vault_type, rng) - }); - bench_verify_complaint(group, &test_case, vault_type, rng); - - if test_case.num_of_nodes > 1 { + if test_case.num_of_nodes >= IDkgMode::Random.min_subnet_size_for_complaint() { + bench_verify_complaint(group, &test_case, vault_type, rng); bench_verify_opening(group, &test_case, vault_type, rng); } } @@ -99,14 +90,13 @@ fn crypto_idkg_benchmarks(criterion: &mut Criterion) { fn bench_create_dealing( group: &mut BenchmarkGroup<'_, M>, test_case: &TestCase, - mode: &IDkgMode, + mode: IDkgMode, vault_type: VaultType, rng: &mut R, ) { let env = test_case.new_test_environment(vault_type, rng); - let (dealers, receivers) = - env.choose_dealers_and_receivers(&IDkgParticipants::AllNodesAsDealersAndReceivers, rng); - let params = mode.setup_params(&env, test_case.alg(), &dealers, &receivers, rng); + let context = IDkgModeTestContext::new(mode, &env, rng); + let params = context.setup_params(&env, test_case.alg(), rng); group.bench_function(format!("create_dealing_{mode}"), |bench| { bench.iter_batched( @@ -120,14 +110,13 @@ fn bench_create_dealing( fn bench_verify_dealing_public( group: &mut BenchmarkGroup<'_, M>, test_case: &TestCase, - mode: &IDkgMode, + mode: IDkgMode, vault_type: VaultType, rng: &mut R, ) { let env = test_case.new_test_environment(vault_type, rng); - let (dealers, receivers) = - env.choose_dealers_and_receivers(&IDkgParticipants::AllNodesAsDealersAndReceivers, rng); - let params = mode.setup_params(&env, test_case.alg(), &dealers, &receivers, rng); + let context = IDkgModeTestContext::new(mode, &env, rng); + let params = context.setup_params(&env, test_case.alg(), rng); group.bench_function(format!("verify_dealing_public_{mode}"), |bench| { bench.iter_batched_ref( @@ -146,14 +135,13 @@ fn bench_verify_dealing_public( fn bench_verify_dealing_private( group: &mut BenchmarkGroup<'_, M>, test_case: &TestCase, - mode: &IDkgMode, + mode: IDkgMode, vault_type: VaultType, rng: &mut R, ) { let env = test_case.new_test_environment(vault_type, rng); - let (dealers, receivers) = - env.choose_dealers_and_receivers(&IDkgParticipants::AllNodesAsDealersAndReceivers, rng); - let params = mode.setup_params(&env, test_case.alg(), &dealers, &receivers, rng); + let context = IDkgModeTestContext::new(mode, &env, rng); + let params = context.setup_params(&env, test_case.alg(), rng); group.bench_function(format!("verify_dealing_private_{mode}"), |bench| { bench.iter_batched_ref( @@ -193,10 +181,11 @@ fn bench_verify_initial_dealings( group.bench_function("verify_initial_dealings", |bench| { bench.iter_batched_ref( || { - let initial_params = dealers_env.params_for_random_sharing( + let initial_params = setup_masked_random_params( + &dealers_env, + test_case.alg(), &src_dealers, &src_receivers, - test_case.alg(), rng, ); let initial_transcript = @@ -246,14 +235,13 @@ fn bench_verify_initial_dealings( fn bench_create_transcript( group: &mut BenchmarkGroup<'_, M>, test_case: &TestCase, - mode: &IDkgMode, + mode: IDkgMode, vault_type: VaultType, rng: &mut R, ) { let env = test_case.new_test_environment(vault_type, rng); - let (dealers, receivers) = - env.choose_dealers_and_receivers(&IDkgParticipants::AllNodesAsDealersAndReceivers, rng); - let params = mode.setup_params(&env, test_case.alg(), &dealers, &receivers, rng); + let context = IDkgModeTestContext::new(mode, &env, rng); + let params = context.setup_params(&env, test_case.alg(), rng); group.bench_function(format!("create_transcript_{mode}"), |bench| { bench.iter_batched_ref( @@ -265,7 +253,7 @@ fn bench_create_transcript( .support_dealings_from_all_receivers(dealings, ¶ms); (receiver, dealings_with_receivers_support) }, - |(receiver, dealings)| create_transcript(receiver, ¶ms, dealings), + |(receiver, dealings)| create_transcript_or_panic(receiver, ¶ms, dealings), SmallInput, ) }); @@ -274,14 +262,13 @@ fn bench_create_transcript( fn bench_verify_transcript( group: &mut BenchmarkGroup<'_, M>, test_case: &TestCase, - mode: &IDkgMode, + mode: IDkgMode, vault_type: VaultType, rng: &mut R, ) { let env = test_case.new_test_environment(vault_type, rng); - let (dealers, receivers) = - env.choose_dealers_and_receivers(&IDkgParticipants::AllNodesAsDealersAndReceivers, rng); - let params = mode.setup_params(&env, test_case.alg(), &dealers, &receivers, rng); + let context = IDkgModeTestContext::new(mode, &env, rng); + let params = context.setup_params(&env, test_case.alg(), rng); group.bench_function(format!("verify_transcript_{mode}"), |bench| { bench.iter_batched_ref( @@ -292,7 +279,7 @@ fn bench_verify_transcript( .support_dealings_from_all_receivers(dealings, ¶ms); let receiver = env.nodes.random_receiver(params.receivers(), rng); let transcript = - create_transcript(receiver, ¶ms, &dealings_with_receivers_support); + create_transcript_or_panic(receiver, ¶ms, &dealings_with_receivers_support); let other_receiver = other_receiver_or_same_if_only_one( params.receivers(), receiver, @@ -301,7 +288,7 @@ fn bench_verify_transcript( ); (other_receiver, transcript) }, - |(receiver, transcript)| verify_transcript(receiver, ¶ms, transcript), + |(receiver, transcript)| verify_transcript_or_panic(receiver, ¶ms, transcript), SmallInput, ) }); @@ -310,14 +297,13 @@ fn bench_verify_transcript( fn bench_load_transcript( group: &mut BenchmarkGroup<'_, M>, test_case: &TestCase, - mode: &IDkgMode, + mode: IDkgMode, vault_type: VaultType, rng: &mut R, ) { let env = test_case.new_test_environment(vault_type, rng); - let (dealers, receivers) = - env.choose_dealers_and_receivers(&IDkgParticipants::AllNodesAsDealersAndReceivers, rng); - let params = mode.setup_params(&env, test_case.alg(), &dealers, &receivers, rng); + let context = IDkgModeTestContext::new(mode, &env, rng); + let params = context.setup_params(&env, test_case.alg(), rng); group.bench_function(format!("load_transcript_{mode}"), |bench| { bench.iter_batched_ref( @@ -328,7 +314,7 @@ fn bench_load_transcript( .support_dealings_from_all_receivers(dealings, ¶ms); let receiver = env.nodes.random_receiver(params.receivers(), rng); let transcript = - create_transcript(receiver, ¶ms, &dealings_with_receivers_support); + create_transcript_or_panic(receiver, ¶ms, &dealings_with_receivers_support); let other_receiver = other_receiver_or_same_if_only_one( params.receivers(), receiver, @@ -337,7 +323,7 @@ fn bench_load_transcript( ); (other_receiver, transcript) }, - |(receiver, transcript)| load_transcript(receiver, transcript), + |(receiver, transcript)| load_transcript_or_panic(receiver, transcript), SmallInput, ) }); @@ -359,7 +345,7 @@ fn bench_retain_active_transcripts( // This is the case because all nodes in CanisterThresholdSigTestEnvironment act as receivers // and all involved IDkgTranscriptParams include all nodes from CanisterThresholdSigTestEnvironment. let receiver = env.nodes.random_receiver(&key_transcript.receivers, rng); - load_transcript(receiver, &key_transcript); + load_transcript_or_panic(receiver, &key_transcript); let num_transcripts_to_delete = num_pre_sig_quadruples * 4; group.bench_function( @@ -396,28 +382,20 @@ fn bench_verify_complaint( rng: &mut R, ) { let env = test_case.new_test_environment(vault_type, rng); - let (dealers, receivers) = - env.choose_dealers_and_receivers(&IDkgParticipants::AllNodesAsDealersAndReceivers, rng); - let params = env.params_for_random_sharing(&dealers, &receivers, test_case.alg, rng); + let context = IDkgModeTestContext::new_for_complaint(IDkgMode::Random, &env, rng); group.bench_function("verify_complaint_random", |bench| { bench.iter_batched_ref( - || { - let mut transcript = env - .nodes - .run_idkg_and_create_and_verify_transcript(¶ms, rng); - let (complainer, complaint) = corrupt_single_dealing_and_generate_complaint( - &mut transcript, - ¶ms, - &env, - rng, - ); - let receiver = env.nodes.random_receiver(params.receivers(), rng); - (receiver, transcript, complainer.id(), complaint) - }, - |(receiver, transcript, complainer_id, complaint)| { - receiver - .verify_complaint(transcript, *complainer_id, complaint) + || context.setup_outputs_for_complaint(&env, test_case.alg, rng), + |complaint_context| { + let IDkgTestContextForComplaint { + transcript, + complaint, + complainer, + verifier, + } = complaint_context; + verifier + .verify_complaint(transcript, complainer.id(), complaint) .expect("failed to verify complaint") }, SmallInput, @@ -432,30 +410,31 @@ fn bench_open_transcript( rng: &mut R, ) { let env = test_case.new_test_environment(vault_type, rng); - let (dealers, receivers) = - env.choose_dealers_and_receivers(&IDkgParticipants::AllNodesAsDealersAndReceivers, rng); - let params = env.params_for_random_sharing(&dealers, &receivers, test_case.alg, rng); + let context = IDkgModeTestContext::new_for_complaint(IDkgMode::Random, &env, rng); group.bench_function("open_transcript_random", |bench| { bench.iter_batched_ref( || { - let mut transcript = env - .nodes - .run_idkg_and_create_and_verify_transcript(¶ms, rng); - let (complainer, complaint) = corrupt_single_dealing_and_generate_complaint( - &mut transcript, - ¶ms, - &env, - rng, - ); - let opener = - env.nodes - .random_receiver_excluding(complainer, params.receivers(), rng); - (opener, transcript, complainer.id(), complaint) + let complaint_context = + context.setup_outputs_for_complaint(&env, test_case.alg, rng); + let opener = { + env.nodes.random_receiver_excluding( + complaint_context.complainer, + complaint_context.transcript.receivers.clone(), + rng, + ) + }; + (complaint_context, opener) }, - |(opener, transcript, complainer_id, complaint)| { + |(complaint_context, opener)| { + let IDkgTestContextForComplaint { + transcript, + complaint, + complainer, + .. + } = complaint_context; opener - .open_transcript(transcript, *complainer_id, complaint) + .open_transcript(transcript, complainer.id(), complaint) .expect("failed to open transcript") }, SmallInput, @@ -470,31 +449,28 @@ fn bench_verify_opening( rng: &mut R, ) { let env = test_case.new_test_environment(vault_type, rng); - let (dealers, receivers) = - env.choose_dealers_and_receivers(&IDkgParticipants::AllNodesAsDealersAndReceivers, rng); - let params = env.params_for_random_sharing(&dealers, &receivers, test_case.alg, rng); + let context = IDkgModeTestContext::new_for_complaint(IDkgMode::Random, &env, rng); group.bench_function("verify_opening_random", |bench| { bench.iter_batched_ref( || { - let mut transcript = env - .nodes - .run_idkg_and_create_and_verify_transcript(¶ms, rng); - let (complainer, complaint) = corrupt_single_dealing_and_generate_complaint( - &mut transcript, - ¶ms, - &env, + let complaint_context = + context.setup_outputs_for_complaint(&env, test_case.alg, rng); + let IDkgTestContextForComplaint { + transcript, + complaint, + verifier, + complainer, + } = complaint_context; + let opener = env.nodes.random_receiver_excluding( + complainer, + transcript.receivers.clone(), rng, ); - let opener = - env.nodes - .random_receiver_excluding(complainer, &transcript.receivers, rng); let opening = opener .open_transcript(&transcript, complainer.id(), &complaint) .expect("Unexpected failure of open_transcript"); - let opener_id = opener.id(); - let verifier = env.nodes.random_receiver(params.receivers(), rng); - (verifier, transcript, opener_id, complaint, opening) + (verifier, transcript, opener.id(), complaint, opening) }, |(verifier, transcript, opener_id, complaint, opening)| { verifier @@ -513,38 +489,35 @@ fn bench_load_transcript_with_openings( rng: &mut R, ) { let env = test_case.new_test_environment(vault_type, rng); - let (dealers, receivers) = - env.choose_dealers_and_receivers(&IDkgParticipants::AllNodesAsDealersAndReceivers, rng); - let params = env.params_for_random_sharing(&dealers, &receivers, test_case.alg, rng); + let context = IDkgModeTestContext::new_for_complaint(IDkgMode::Random, &env, rng); group.bench_function("load_transcript_with_openings_random", |bench| { bench.iter_batched_ref( || { - let mut transcript = env - .nodes - .run_idkg_and_create_and_verify_transcript(¶ms, rng); - let reconstruction_threshold = - usize::try_from(transcript.reconstruction_threshold().get()) - .expect("invalid number"); + let complaint_context = + context.setup_outputs_for_complaint(&env, test_case.alg, rng); + let reconstruction_threshold = usize::try_from( + complaint_context + .transcript + .reconstruction_threshold() + .get(), + ) + .expect("invalid number"); let number_of_openings = reconstruction_threshold; - - let (complainer, complaint) = corrupt_single_dealing_and_generate_complaint( - &mut transcript, - ¶ms, - &env, - rng, - ); let complaint_with_openings = generate_and_verify_openings_for_complaint( number_of_openings, - &transcript, + &complaint_context.transcript, &env, - complainer, - complaint, + complaint_context.complainer, + complaint_context.complaint.clone(), ); - (complainer, transcript, complaint_with_openings) + (complaint_context, complaint_with_openings) }, - |(complainer, transcript, complaint_with_openings)| { - complainer.load_transcript_with_openings(transcript, complaint_with_openings) + |(complaint_context, complaint_with_openings)| { + complaint_context.complainer.load_transcript_with_openings( + &complaint_context.transcript, + complaint_with_openings, + ) }, SmallInput, ) @@ -616,64 +589,11 @@ fn verify_initial_dealings( }) } -fn create_transcript( +fn verify_transcript_or_panic( receiver: &Node, params: &IDkgTranscriptParams, - dealings: &BatchSignedIDkgDealings, -) -> IDkgTranscript { - receiver - .create_transcript(params, dealings) - .unwrap_or_else(|error| { - panic!( - "failed to create IDKG transcript by receiver {:?} with parameters {:?}: {:?}", - receiver.id(), - params, - error - ) - }) -} - -fn run_idkg_without_complaint( - params: &IDkgTranscriptParams, - nodes: &Nodes, - rng: &mut R, -) -> IDkgTranscript { - load_previous_transcripts_for_all_dealers(params, nodes); - let receiver = nodes.random_receiver(params.receivers(), rng); - let dealings = nodes.create_dealings(params); - let dealings_with_receivers_support = - nodes.support_dealings_from_all_receivers(dealings, params); - create_transcript(receiver, params, &dealings_with_receivers_support) -} - -fn load_previous_transcripts_for_all_dealers(params: &IDkgTranscriptParams, nodes: &Nodes) { - let mut transcripts_to_load = Vec::with_capacity(2); - match params.operation_type() { - IDkgTranscriptOperation::Random => {} - IDkgTranscriptOperation::ReshareOfMasked(transcript) => { - transcripts_to_load.push(transcript) - } - IDkgTranscriptOperation::ReshareOfUnmasked(transcript) => { - transcripts_to_load.push(transcript) - } - IDkgTranscriptOperation::UnmaskedTimesMasked(transcript1, transcript2) => { - transcripts_to_load.push(transcript1); - transcripts_to_load.push(transcript2) - } - } - - nodes.dealers(params).for_each(|dealer| { - transcripts_to_load.iter().for_each(|transcript| { - assert_eq!( - load_transcript(dealer, transcript), - vec![], - "did not expect any complaint" - ) - }); - }); -} - -fn verify_transcript(receiver: &Node, params: &IDkgTranscriptParams, transcript: &IDkgTranscript) { + transcript: &IDkgTranscript, +) { receiver .verify_transcript(params, transcript) .unwrap_or_else(|error| { @@ -686,30 +606,21 @@ fn verify_transcript(receiver: &Node, params: &IDkgTranscriptParams, transcript: }) } -fn load_transcript(receiver: &Node, transcript: &IDkgTranscript) -> Vec { - receiver - .load_transcript(transcript) - .unwrap_or_else(|error| { - panic!( - "failed to load IDKG transcript by receiver {:?}: {:?}", - receiver.id(), - error - ) - }) -} - fn load_pre_signature_quadruple(receiver: &Node, quadruple: &PreSignatureQuadruple) { assert_eq!( - load_transcript(receiver, quadruple.kappa_unmasked()), + load_transcript_or_panic(receiver, quadruple.kappa_unmasked()), vec![] ); - assert_eq!(load_transcript(receiver, quadruple.lambda_masked()), vec![]); assert_eq!( - load_transcript(receiver, quadruple.kappa_times_lambda()), + load_transcript_or_panic(receiver, quadruple.lambda_masked()), vec![] ); assert_eq!( - load_transcript(receiver, quadruple.key_times_lambda()), + load_transcript_or_panic(receiver, quadruple.kappa_times_lambda()), + vec![] + ); + assert_eq!( + load_transcript_or_panic(receiver, quadruple.key_times_lambda()), vec![] ); } @@ -733,7 +644,7 @@ fn generate_key_transcript( receivers: &IDkgReceivers, rng: &mut R, ) -> IDkgTranscript { - let masked_key_params = env.params_for_random_sharing(dealers, receivers, alg, rng); + let masked_key_params = setup_masked_random_params(env, alg, dealers, receivers, rng); let masked_key_transcript = run_idkg_without_complaint(&masked_key_params, &env.nodes, rng); let unmasked_key_params = build_params_from_previous( @@ -753,11 +664,11 @@ fn generate_pre_sig_quadruple( key_transcript: IDkgTranscript, rng: &mut R, ) -> PreSignatureQuadruple { - let lambda_params = env.params_for_random_sharing(dealers, receivers, alg, rng); + let lambda_params = setup_masked_random_params(env, alg, dealers, receivers, rng); let lambda_transcript = run_idkg_without_complaint(&lambda_params, &env.nodes, rng); let kappa_transcript = { - let masked_kappa_params = env.params_for_random_sharing(dealers, receivers, alg, rng); + let masked_kappa_params = setup_masked_random_params(env, alg, dealers, receivers, rng); let masked_kappa_transcript = run_idkg_without_complaint(&masked_kappa_params, &env.nodes, rng); @@ -814,76 +725,6 @@ fn other_receiver_or_same_if_only_one<'a, R: RngCore + CryptoRng>( } } -fn setup_reshare_of_masked_params( - env: &CanisterThresholdSigTestEnvironment, - alg: AlgorithmId, - dealers: &IDkgDealers, - receivers: &IDkgReceivers, - rng: &mut R, -) -> IDkgTranscriptParams { - let params = env.params_for_random_sharing(dealers, receivers, alg, rng); - let masked_transcript = run_idkg_without_complaint(¶ms, &env.nodes, rng); - let reshare_params = build_params_from_previous( - params, - IDkgTranscriptOperation::ReshareOfMasked(masked_transcript), - rng, - ); - load_previous_transcripts_for_all_dealers(&reshare_params, &env.nodes); - reshare_params -} - -fn setup_reshare_of_unmasked_params( - env: &CanisterThresholdSigTestEnvironment, - alg: AlgorithmId, - dealers: &IDkgDealers, - receivers: &IDkgReceivers, - rng: &mut R, -) -> IDkgTranscriptParams { - let params = env.params_for_random_sharing(dealers, receivers, alg, rng); - let masked_transcript = run_idkg_without_complaint(¶ms, &env.nodes, rng); - let unmasked_params = build_params_from_previous( - params, - IDkgTranscriptOperation::ReshareOfMasked(masked_transcript), - rng, - ); - load_previous_transcripts_for_all_dealers(&unmasked_params, &env.nodes); - let unmasked_transcript = run_idkg_without_complaint(&unmasked_params, &env.nodes, rng); - let unmasked_reshare_params = build_params_from_previous( - unmasked_params, - IDkgTranscriptOperation::ReshareOfUnmasked(unmasked_transcript), - rng, - ); - load_previous_transcripts_for_all_dealers(&unmasked_reshare_params, &env.nodes); - unmasked_reshare_params -} - -fn setup_unmasked_times_masked_params( - env: &CanisterThresholdSigTestEnvironment, - alg: AlgorithmId, - dealers: &IDkgDealers, - receivers: &IDkgReceivers, - rng: &mut R, -) -> IDkgTranscriptParams { - let masked_params = env.params_for_random_sharing(dealers, receivers, alg, rng); - let masked_random_transcript = run_idkg_without_complaint(&masked_params, &env.nodes, rng); - - let unmasked_params = build_params_from_previous( - masked_params, - IDkgTranscriptOperation::ReshareOfMasked(masked_random_transcript.clone()), - rng, - ); - load_previous_transcripts_for_all_dealers(&unmasked_params, &env.nodes); - let unmasked_transcript = run_idkg_without_complaint(&unmasked_params, &env.nodes, rng); - - let product_params = build_params_from_previous( - unmasked_params, - IDkgTranscriptOperation::UnmaskedTimesMasked(unmasked_transcript, masked_random_transcript), - rng, - ); - load_previous_transcripts_for_all_dealers(&product_params, &env.nodes); - product_params -} - struct TestCase { sample_size: usize, sampling_mode: SamplingMode, @@ -953,50 +794,3 @@ fn generate_test_cases(node_counts: &[usize]) -> Vec { test_cases } - -#[derive(Clone, Debug, PartialEq, Eq, Hash, EnumIter)] -enum IDkgMode { - Random, - ReshareOfMasked, - ReshareOfUnmasked, - UnmaskedTimesMasked, -} - -impl IDkgMode { - fn setup_params( - &self, - env: &CanisterThresholdSigTestEnvironment, - alg: AlgorithmId, - dealers: &IDkgDealers, - receivers: &IDkgReceivers, - rng: &mut R, - ) -> IDkgTranscriptParams { - match self { - IDkgMode::Random => env.params_for_random_sharing(dealers, receivers, alg, rng), - IDkgMode::ReshareOfMasked => { - setup_reshare_of_masked_params(env, alg, dealers, receivers, rng) - } - IDkgMode::ReshareOfUnmasked => { - setup_reshare_of_unmasked_params(env, alg, dealers, receivers, rng) - } - IDkgMode::UnmaskedTimesMasked => { - setup_unmasked_times_masked_params(env, alg, dealers, receivers, rng) - } - } - } -} - -impl Display for IDkgMode { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!( - f, - "{}", - match self { - IDkgMode::Random => "random", - IDkgMode::ReshareOfMasked => "reshare_of_masked", - IDkgMode::ReshareOfUnmasked => "reshare_of_unmasked", - IDkgMode::UnmaskedTimesMasked => "product", - } - ) - } -} diff --git a/rs/crypto/test_utils/canister_threshold_sigs/BUILD.bazel b/rs/crypto/test_utils/canister_threshold_sigs/BUILD.bazel index 0e2f652fcec..32aa19cb8c8 100644 --- a/rs/crypto/test_utils/canister_threshold_sigs/BUILD.bazel +++ b/rs/crypto/test_utils/canister_threshold_sigs/BUILD.bazel @@ -6,6 +6,9 @@ rust_library( name = "canister_threshold_sigs", srcs = glob(["src/**"]), crate_name = "ic_crypto_test_utils_canister_threshold_sigs", + proc_macro_deps = [ + "@crate_index//:strum_macros", + ], version = "0.9.0", deps = [ "//rs/crypto/internal/crypto_lib/threshold_sig/tecdsa", @@ -20,6 +23,7 @@ rust_library( "//rs/types/types", "@crate_index//:rand", "@crate_index//:rand_chacha", + "@crate_index//:strum", ], ) diff --git a/rs/crypto/test_utils/canister_threshold_sigs/Cargo.toml b/rs/crypto/test_utils/canister_threshold_sigs/Cargo.toml index 14e4a94599c..a3531eb57d3 100644 --- a/rs/crypto/test_utils/canister_threshold_sigs/Cargo.toml +++ b/rs/crypto/test_utils/canister_threshold_sigs/Cargo.toml @@ -19,3 +19,5 @@ ic-test-utilities-in-memory-logger = { path = "../../../test_utilities/in_memory ic-types = { path = "../../../types/types" } rand = "0.8" rand_chacha = "0.3" +strum = { workspace = true } +strum_macros = { workspace = true } \ No newline at end of file diff --git a/rs/crypto/test_utils/canister_threshold_sigs/src/lib.rs b/rs/crypto/test_utils/canister_threshold_sigs/src/lib.rs index 50cd141256e..63249576192 100644 --- a/rs/crypto/test_utils/canister_threshold_sigs/src/lib.rs +++ b/rs/crypto/test_utils/canister_threshold_sigs/src/lib.rs @@ -6,17 +6,17 @@ use ic_crypto_internal_threshold_sig_ecdsa::{ IDkgComplaintInternal, IDkgDealingInternal, NodeIndex, Seed, }; use ic_crypto_temp_crypto::{TempCryptoComponent, TempCryptoComponentGeneric}; -use ic_interfaces::crypto::IDkgProtocol; use ic_interfaces::crypto::{ - BasicSigner, KeyManager, ThresholdEcdsaSigVerifier, ThresholdEcdsaSigner, + BasicSigner, IDkgProtocol, KeyManager, ThresholdEcdsaSigVerifier, ThresholdEcdsaSigner, }; use ic_registry_client_fake::FakeRegistryClient; use ic_registry_keys::make_crypto_node_key; use ic_registry_proto_data_provider::ProtoRegistryDataProvider; use ic_types::crypto::canister_threshold_sig::idkg::{ - BatchSignedIDkgDealing, IDkgComplaint, IDkgDealers, IDkgDealing, IDkgMaskedTranscriptOrigin, - IDkgOpening, IDkgReceivers, IDkgTranscript, IDkgTranscriptId, IDkgTranscriptOperation, - IDkgTranscriptParams, IDkgTranscriptType, IDkgUnmaskedTranscriptOrigin, SignedIDkgDealing, + BatchSignedIDkgDealing, BatchSignedIDkgDealings, IDkgComplaint, IDkgDealers, IDkgDealing, + IDkgMaskedTranscriptOrigin, IDkgOpening, IDkgReceivers, IDkgTranscript, IDkgTranscriptId, + IDkgTranscriptOperation, IDkgTranscriptParams, IDkgTranscriptType, + IDkgUnmaskedTranscriptOrigin, SignedIDkgDealing, }; use ic_types::crypto::canister_threshold_sig::{ ExtendedDerivationPath, PreSignatureQuadruple, ThresholdEcdsaSigShare, @@ -32,6 +32,7 @@ use rand::prelude::*; use rand_chacha::ChaCha20Rng; use std::collections::{BTreeMap, BTreeSet}; use std::sync::Arc; +use strum_macros::EnumIter; pub mod dummy_values; @@ -193,10 +194,10 @@ pub fn generate_key_transcript( env: &CanisterThresholdSigTestEnvironment, dealers: &IDkgDealers, receivers: &IDkgReceivers, - algorithm_id: AlgorithmId, + alg: AlgorithmId, rng: &mut R, ) -> IDkgTranscript { - let masked_key_params = env.params_for_random_sharing(dealers, receivers, algorithm_id, rng); + let masked_key_params = setup_masked_random_params(env, alg, dealers, receivers, rng); let masked_key_transcript = env .nodes @@ -216,18 +217,17 @@ pub fn generate_presig_quadruple( env: &CanisterThresholdSigTestEnvironment, dealers: &IDkgDealers, receivers: &IDkgReceivers, - algorithm_id: AlgorithmId, + alg: AlgorithmId, key_transcript: &IDkgTranscript, rng: &mut R, ) -> PreSignatureQuadruple { - let lambda_params = env.params_for_random_sharing(dealers, receivers, algorithm_id, rng); + let lambda_params = setup_masked_random_params(env, alg, dealers, receivers, rng); let lambda_transcript = env .nodes .run_idkg_and_create_and_verify_transcript(&lambda_params, rng); let kappa_transcript = { - let masked_kappa_params = - env.params_for_random_sharing(dealers, receivers, algorithm_id, rng); + let masked_kappa_params = setup_masked_random_params(env, alg, dealers, receivers, rng); let masked_kappa_transcript = env .nodes @@ -785,6 +785,20 @@ pub mod node { self.iter().choose_multiple(rng, subset_size).into_iter() } + pub fn random_subset<'a, R: RngCore + CryptoRng>( + &'a self, + size: usize, + rng: &'a mut R, + ) -> impl Iterator + 'a { + assert!( + size <= self.len(), + "Requested a random subset with {} elements but there are only {} elements", + size, + self.len() + ); + self.iter().choose_multiple(rng, size).into_iter() + } + pub fn into_random_receiver( self, idkg_receivers: &IDkgReceivers, @@ -805,10 +819,10 @@ pub mod node { .expect("empty receivers") } - pub fn random_receiver_excluding<'a, R: Rng>( + pub fn random_receiver_excluding<'a, T: AsRef + 'a, R: Rng>( &'a self, exclusion: &Node, - idkg_receivers: &'a IDkgReceivers, + idkg_receivers: T, rng: &mut R, ) -> &Node { self.receivers(idkg_receivers) @@ -1213,26 +1227,6 @@ impl CanisterThresholdSigTestEnvironment { env } - /// Returns an `IDkgTranscriptParams` appropriate for creating a random - /// sharing in this environment. - pub fn params_for_random_sharing( - &self, - dealers: &IDkgDealers, - receivers: &IDkgReceivers, - algorithm_id: AlgorithmId, - rng: &mut R, - ) -> IDkgTranscriptParams { - IDkgTranscriptParams::new( - random_transcript_id(rng), - dealers.get().clone(), - receivers.get().clone(), - self.newest_registry_version, - algorithm_id, - IDkgTranscriptOperation::Random, - ) - .expect("failed to create random IDkgTranscriptParams") - } - pub fn choose_dealers_and_receivers( &self, strategy: &IDkgParticipants, @@ -1440,6 +1434,364 @@ pub fn random_crypto_component_not_in_receivers( .build() } +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, EnumIter)] +pub enum IDkgMode { + Random, + ReshareOfMasked, + ReshareOfUnmasked, + UnmaskedTimesMasked, +} + +impl IDkgMode { + /// Generates a random subnet size that can be used to generate a complaint. + /// The reason to have this function is that `IDkgMode::ReshareOfUnmasked` + /// does not produce transcripts that are loaded into canister secret key + /// store for subnets of size <4. Thus, not all subnet sizes can be used to + /// benchmark loading transcripts or generating complaints. + pub fn subnet_size_for_complaint(&self, max: usize, rng: &mut R) -> usize { + let min = self.min_subnet_size_for_complaint(); + assert!( + min < max, + "min ({min}) should not be larger than max ({max}) subnet size" + ); + rng.gen_range(min..=max) + } + + /// Returns the minimum subnet size for `&self` that can be used to generate + /// complaint. See [`Self::subnet_size_for_complaint`] for more + /// details. + pub fn min_subnet_size_for_complaint(&self) -> usize { + match *self { + // In `IDkgMode::ReshareOfUnmasked` with subnet size <4 it is not + // possible to create a complaint. The reason is that the complaint + // creation happens on transcript loading, which effectively is skipped + // for `IDkgMode::ReshareOfUnmasked` with subnet size <4 because the + // secret (commitment opening) is already in the canister secret store. + // The reason for the latter is that with a subnet of size <4, the + // commitment polynomial is of degree zero, i.e., it is not random and + // thus the commitment remains the same after resharing. + Self::ReshareOfUnmasked => 4, + Self::Random | Self::ReshareOfMasked | Self::UnmaskedTimesMasked => 2, + } + } +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub enum IDkgModeTestContext { + Random { + dealers: IDkgDealers, + receivers: IDkgReceivers, + }, + ReshareOfMasked { + dealers: IDkgDealers, + receivers: IDkgReceivers, + }, + ReshareOfUnmasked { + dealers: IDkgDealers, + receivers: IDkgReceivers, + }, + UnmaskedTimesMasked { + dealers: IDkgDealers, + receivers: IDkgReceivers, + }, +} + +impl IDkgModeTestContext { + /// Generates dealers and receivers from `env` for the IDKG mode chosen in `mode`. + pub fn new( + mode: IDkgMode, + env: &CanisterThresholdSigTestEnvironment, + rng: &mut R, + ) -> Self { + match mode { + IDkgMode::Random => { + let (dealers, receivers) = + env.choose_dealers_and_receivers(&IDkgParticipants::Random, rng); + Self::Random { dealers, receivers } + } + IDkgMode::ReshareOfUnmasked => { + let (dealers, receivers) = env.choose_dealers_and_receivers( + &IDkgParticipants::AllNodesAsDealersAndReceivers, + rng, + ); + Self::UnmaskedTimesMasked { dealers, receivers } + } + IDkgMode::ReshareOfMasked => { + let (dealers, receivers) = env.choose_dealers_and_receivers( + &IDkgParticipants::AllNodesAsDealersAndReceivers, + rng, + ); + Self::ReshareOfMasked { dealers, receivers } + } + IDkgMode::UnmaskedTimesMasked => { + let (dealers, receivers) = env.choose_dealers_and_receivers( + &IDkgParticipants::AllNodesAsDealersAndReceivers, + rng, + ); + Self::UnmaskedTimesMasked { dealers, receivers } + } + } + } + + /// Generates dealers and receivers from `env` for the IDKG mode chosen in + /// `mode`. Since `Self::new` can return a setting with only 1 node, this + /// function modifies that setting to always return at least two receivers + /// s.t. complaints always work. + pub fn new_for_complaint( + mode: IDkgMode, + env: &CanisterThresholdSigTestEnvironment, + rng: &mut R, + ) -> Self { + match mode { + IDkgMode::Random => { + // If we want to generate and verify a complaint, we need at least 2 receivers. + let (dealers, receivers) = env.choose_dealers_and_receivers( + &IDkgParticipants::RandomWithAtLeast { + min_num_dealers: 1, + min_num_receivers: 2, + }, + rng, + ); + Self::Random { dealers, receivers } + } + _ => Self::new(mode, env, rng), + } + } + + /// Generates IDKG input parameters for the chosen IDKG mode. + pub fn setup_params( + &self, + env: &CanisterThresholdSigTestEnvironment, + alg: AlgorithmId, + rng: &mut R, + ) -> IDkgTranscriptParams { + match self { + IDkgModeTestContext::Random { dealers, receivers } => { + setup_masked_random_params(env, alg, dealers, receivers, rng) + } + IDkgModeTestContext::ReshareOfMasked { dealers, receivers } => { + setup_reshare_of_masked_params(env, alg, dealers, receivers, rng) + } + IDkgModeTestContext::ReshareOfUnmasked { dealers, receivers } => { + setup_reshare_of_unmasked_params(env, alg, dealers, receivers, rng) + } + IDkgModeTestContext::UnmaskedTimesMasked { dealers, receivers } => { + setup_unmasked_times_masked_params(env, alg, dealers, receivers, rng) + } + } + } + + /// Generates IDKG output parameters for the chosen IDKG mode, corrupts the + /// dealing for a random receiver and generates a complaint. + pub fn setup_outputs_for_complaint<'a, R: RngCore + CryptoRng>( + &self, + env: &'a CanisterThresholdSigTestEnvironment, + alg: AlgorithmId, + rng: &mut R, + ) -> IDkgTestContextForComplaint<'a> { + let params = self.setup_params(env, alg, rng); + let mut transcript = env + .nodes + .run_idkg_and_create_and_verify_transcript(¶ms, rng); + + let (complainer, complaint): (&'a Node, _) = + corrupt_random_dealing_and_generate_complaint(&mut transcript, ¶ms, env, rng); + let verifier: &Node = env.nodes.random_receiver(self.receivers().clone(), rng); + IDkgTestContextForComplaint { + transcript, + complaint, + complainer, + verifier, + } + } + + fn receivers(&self) -> &IDkgReceivers { + match self { + IDkgModeTestContext::Random { receivers, .. } + | IDkgModeTestContext::ReshareOfMasked { receivers, .. } + | IDkgModeTestContext::ReshareOfUnmasked { receivers, .. } + | IDkgModeTestContext::UnmaskedTimesMasked { receivers, .. } => receivers, + } + } +} + +impl std::fmt::Display for IDkgMode { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}", + match self { + Self::Random => "random", + Self::ReshareOfMasked => "reshare_of_masked", + Self::ReshareOfUnmasked => "reshare_of_unmasked", + Self::UnmaskedTimesMasked => "product", + } + ) + } +} + +/// Returns an `IDkgTranscriptParams` appropriate for creating a random +/// sharing in this environment. +pub fn setup_masked_random_params( + env: &CanisterThresholdSigTestEnvironment, + algorithm_id: AlgorithmId, + dealers: &IDkgDealers, + receivers: &IDkgReceivers, + rng: &mut R, +) -> IDkgTranscriptParams { + IDkgTranscriptParams::new( + random_transcript_id(rng), + dealers.get().clone(), + receivers.get().clone(), + env.newest_registry_version, + algorithm_id, + IDkgTranscriptOperation::Random, + ) + .expect("failed to create random IDkgTranscriptParams") +} + +pub fn setup_reshare_of_masked_params( + env: &CanisterThresholdSigTestEnvironment, + alg: AlgorithmId, + dealers: &IDkgDealers, + receivers: &IDkgReceivers, + rng: &mut R, +) -> IDkgTranscriptParams { + let params = setup_masked_random_params(env, alg, dealers, receivers, rng); + let masked_transcript = run_idkg_without_complaint(¶ms, &env.nodes, rng); + let reshare_params = build_params_from_previous( + params, + IDkgTranscriptOperation::ReshareOfMasked(masked_transcript), + rng, + ); + load_previous_transcripts_for_all_dealers(&reshare_params, &env.nodes); + reshare_params +} + +pub fn setup_reshare_of_unmasked_params( + env: &CanisterThresholdSigTestEnvironment, + alg: AlgorithmId, + dealers: &IDkgDealers, + receivers: &IDkgReceivers, + rng: &mut R, +) -> IDkgTranscriptParams { + let unmasked_params = setup_reshare_of_masked_params(env, alg, dealers, receivers, rng); + let unmasked_transcript = run_idkg_without_complaint(&unmasked_params, &env.nodes, rng); + let reshare_params = build_params_from_previous( + unmasked_params, + IDkgTranscriptOperation::ReshareOfMasked(unmasked_transcript), + rng, + ); + load_previous_transcripts_for_all_dealers(&reshare_params, &env.nodes); + reshare_params +} + +pub fn setup_unmasked_times_masked_params( + env: &CanisterThresholdSigTestEnvironment, + alg: AlgorithmId, + dealers: &IDkgDealers, + receivers: &IDkgReceivers, + rng: &mut R, +) -> IDkgTranscriptParams { + let masked_params = setup_masked_random_params(env, alg, dealers, receivers, rng); + let masked_random_transcript = run_idkg_without_complaint(&masked_params, &env.nodes, rng); + + let unmasked_params = build_params_from_previous( + masked_params, + IDkgTranscriptOperation::ReshareOfMasked(masked_random_transcript.clone()), + rng, + ); + load_previous_transcripts_for_all_dealers(&unmasked_params, &env.nodes); + let unmasked_transcript = run_idkg_without_complaint(&unmasked_params, &env.nodes, rng); + + let product_params = build_params_from_previous( + unmasked_params, + IDkgTranscriptOperation::UnmaskedTimesMasked(unmasked_transcript, masked_random_transcript), + rng, + ); + load_previous_transcripts_for_all_dealers(&product_params, &env.nodes); + product_params +} + +pub struct IDkgTestContextForComplaint<'a> { + pub transcript: IDkgTranscript, + pub complaint: IDkgComplaint, + pub complainer: &'a Node, + pub verifier: &'a Node, +} + +pub fn load_previous_transcripts_for_all_dealers(params: &IDkgTranscriptParams, nodes: &Nodes) { + let mut transcripts_to_load = Vec::with_capacity(2); + match params.operation_type() { + IDkgTranscriptOperation::Random => {} + IDkgTranscriptOperation::ReshareOfMasked(transcript) => { + transcripts_to_load.push(transcript) + } + IDkgTranscriptOperation::ReshareOfUnmasked(transcript) => { + transcripts_to_load.push(transcript) + } + IDkgTranscriptOperation::UnmaskedTimesMasked(transcript1, transcript2) => { + transcripts_to_load.push(transcript1); + transcripts_to_load.push(transcript2) + } + } + + nodes.dealers(params).for_each(|dealer| { + transcripts_to_load.iter().for_each(|transcript| { + assert_eq!( + load_transcript_or_panic(dealer, transcript), + vec![], + "did not expect any complaint" + ) + }); + }); +} + +pub fn create_transcript_or_panic( + receiver: &Node, + params: &IDkgTranscriptParams, + dealings: &BatchSignedIDkgDealings, +) -> IDkgTranscript { + receiver + .create_transcript(params, dealings) + .unwrap_or_else(|error| { + panic!( + "failed to create IDKG transcript by receiver {:?} with parameters {:?}: {:?}", + receiver.id(), + params, + error + ) + }) +} + +pub fn load_transcript_or_panic( + receiver: &Node, + transcript: &IDkgTranscript, +) -> Vec { + receiver + .load_transcript(transcript) + .unwrap_or_else(|error| { + panic!( + "failed to load IDKG transcript by receiver {:?}: {:?}", + receiver.id(), + error + ) + }) +} + +pub fn run_idkg_without_complaint( + params: &IDkgTranscriptParams, + nodes: &Nodes, + rng: &mut R, +) -> IDkgTranscript { + load_previous_transcripts_for_all_dealers(params, nodes); + let receiver = nodes.random_receiver(params.receivers(), rng); + let dealings = nodes.create_dealings(params); + let dealings_with_receivers_support = + nodes.support_dealings_from_all_receivers(dealings, params); + create_transcript_or_panic(receiver, params, &dealings_with_receivers_support) +} + /// Corrupts the dealing for a single randomly picked receiver. /// node_id is the self Node Id. The shares for the receivers specified /// in excluded_receivers won't be corrupted. @@ -2074,27 +2426,64 @@ pub fn to_corrupt_complaint( } } -pub fn corrupt_single_dealing_and_generate_complaint<'a, R: RngCore + CryptoRng>( +pub fn corrupt_single_dealing_and_generate_complaint( + params: &IDkgTranscriptParams, + transcript: &mut IDkgTranscript, + complainer: &Node, + rng: &mut R, +) -> IDkgComplaint { + let (_, complaints) = + corrupt_dealings_and_generate_complaints(params, transcript, 1, complainer, rng); + complaints + .into_iter() + .next() + .expect("empty complaints result") +} + +pub fn corrupt_random_dealing_and_generate_complaint<'a, R: RngCore + CryptoRng>( transcript: &mut IDkgTranscript, - params: &'a IDkgTranscriptParams, + params: &IDkgTranscriptParams, env: &'a CanisterThresholdSigTestEnvironment, rng: &mut R, ) -> (&'a Node, IDkgComplaint) { let (complainer, _, mut complaints) = - corrupt_dealings_and_generate_complaints(transcript, 1, params, env, rng); + corrupt_dealings_and_generate_complaints_for_random_complainer( + transcript, 1, params, env, rng, + ); ( complainer, complaints.pop().expect("expected one complaint"), ) } -pub fn corrupt_dealings_and_generate_complaints<'a, R: RngCore + CryptoRng>( +pub fn corrupt_dealings_and_generate_complaints_for_random_complainer< + 'a, + R: RngCore + CryptoRng, +>( transcript: &mut IDkgTranscript, number_of_complaints: usize, - params: &'a IDkgTranscriptParams, + params: &IDkgTranscriptParams, env: &'a CanisterThresholdSigTestEnvironment, rng: &mut R, ) -> (&'a Node, Vec, Vec) { + let complainer = env.nodes.random_receiver(params.receivers().clone(), rng); + let (dealing_indices_to_corrupt, complaints) = corrupt_dealings_and_generate_complaints( + params, + transcript, + number_of_complaints, + complainer, + rng, + ); + (complainer, dealing_indices_to_corrupt, complaints) +} + +pub fn corrupt_dealings_and_generate_complaints( + params: &IDkgTranscriptParams, + transcript: &mut IDkgTranscript, + number_of_complaints: usize, + complainer: &Node, + rng: &mut R, +) -> (Vec, Vec) { assert!( number_of_complaints > 0, "should generate at least one complaint" @@ -2113,7 +2502,6 @@ pub fn corrupt_dealings_and_generate_complaints<'a, R: RngCore + CryptoRng>( .choose_multiple(rng, number_of_complaints); assert_eq!(dealing_indices_to_corrupt.len(), number_of_complaints); - let complainer = env.nodes.random_receiver(params.receivers(), rng); let complainer_index = params .receiver_index(complainer.id()) .unwrap_or_else(|| panic!("Missing receiver {:?}", complainer)); @@ -2136,7 +2524,7 @@ pub fn corrupt_dealings_and_generate_complaints<'a, R: RngCore + CryptoRng>( complaints }; - (complainer, dealing_indices_to_corrupt, complaints) + (dealing_indices_to_corrupt, complaints) } pub fn generate_and_verify_openings_for_complaint( diff --git a/rs/crypto/tests/canister_threshold_sigs.rs b/rs/crypto/tests/canister_threshold_sigs.rs index 9c6f630d9d6..c2b86bfe047 100644 --- a/rs/crypto/tests/canister_threshold_sigs.rs +++ b/rs/crypto/tests/canister_threshold_sigs.rs @@ -7,16 +7,17 @@ use ic_crypto_temp_crypto::TempCryptoComponent; use ic_crypto_test_utils_canister_threshold_sigs::dummy_values::dummy_idkg_transcript_id_for_tests; use ic_crypto_test_utils_canister_threshold_sigs::node::Node; use ic_crypto_test_utils_canister_threshold_sigs::node::Nodes; -use ic_crypto_test_utils_canister_threshold_sigs::IDkgParticipants; use ic_crypto_test_utils_canister_threshold_sigs::{ build_params_from_previous, copy_dealing_in_transcript, - corrupt_single_dealing_and_generate_complaint, generate_key_transcript, + corrupt_dealings_and_generate_complaints_for_random_complainer, + corrupt_random_dealing_and_generate_complaint, generate_key_transcript, generate_presig_quadruple, node_id, random_crypto_component_not_in_receivers, random_dealer_id, random_dealer_id_excluding, random_node_id_excluding, random_receiver_for_inputs, random_receiver_id, random_receiver_id_excluding, run_tecdsa_protocol, sig_share_from_each_receiver, swap_two_dealings_in_transcript, CanisterThresholdSigTestEnvironment, IntoBuilder, }; +use ic_crypto_test_utils_canister_threshold_sigs::{setup_masked_random_params, IDkgParticipants}; use ic_crypto_test_utils_reproducible_rng::{reproducible_rng, ReproducibleRng}; use ic_interfaces::crypto::{IDkgProtocol, ThresholdEcdsaSigVerifier, ThresholdEcdsaSigner}; use ic_types::crypto::canister_threshold_sig::error::{ @@ -52,7 +53,7 @@ mod create_dealing { let env = CanisterThresholdSigTestEnvironment::new(subnet_size, rng); let (dealers, receivers) = env.choose_dealers_and_receivers(&IDkgParticipants::Random, rng); - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let dealer = env.nodes.random_dealer(¶ms, rng); let dealing = dealer @@ -91,7 +92,7 @@ mod create_dealing { (random_dealers, receivers_with_new_node_id) }; let params = - env.params_for_random_sharing(&dealers, &receivers_with_new_node_id, alg, rng); + setup_masked_random_params(&env, alg, &dealers, &receivers_with_new_node_id, rng); let dealer = env.nodes.random_dealer(¶ms, rng); let result = dealer.create_dealing(¶ms); @@ -108,7 +109,7 @@ mod create_dealing { let env = CanisterThresholdSigTestEnvironment::new(subnet_size, rng); let (dealers, receivers) = env.choose_dealers_and_receivers(&IDkgParticipants::Random, rng); - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let bad_dealer_id = random_node_id_excluding(params.dealers().get(), rng); let bad_dealer = Node::new(bad_dealer_id, Arc::clone(&env.registry), rng); @@ -128,7 +129,7 @@ mod create_dealing { let (dealers, receivers) = env .choose_dealers_and_receivers(&IDkgParticipants::RandomForThresholdSignature, rng); - let initial_params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let initial_params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let initial_transcript = env .nodes .run_idkg_and_create_and_verify_transcript(&initial_params, rng); @@ -163,7 +164,8 @@ mod create_dealing { let (dealers, receivers) = env .choose_dealers_and_receivers(&IDkgParticipants::RandomForThresholdSignature, rng); - let masked_key_params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let masked_key_params = + setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let masked_key_transcript = env .nodes @@ -252,7 +254,8 @@ mod create_dealing { let (dealers, receivers) = env .choose_dealers_and_receivers(&IDkgParticipants::RandomForThresholdSignature, rng); - let masked_key_params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let masked_key_params = + setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let masked_key_transcript = env .nodes @@ -301,7 +304,9 @@ mod create_dealing { mod create_transcript { use super::*; - use ic_crypto_test_utils_canister_threshold_sigs::CorruptBytesCollection; + use ic_crypto_test_utils_canister_threshold_sigs::{ + setup_masked_random_params, CorruptBytesCollection, + }; #[test] fn should_create_transcript() { @@ -312,7 +317,7 @@ mod create_transcript { let env = CanisterThresholdSigTestEnvironment::new(subnet_size, rng); let (dealers, receivers) = env.choose_dealers_and_receivers(&IDkgParticipants::Random, rng); - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let signed_dealings = env.nodes.create_and_verify_signed_dealings(¶ms); let batch_signed_dealings = env .nodes @@ -335,7 +340,7 @@ mod create_transcript { let (dealers, receivers) = env.choose_dealers_and_receivers(&IDkgParticipants::Random, rng); - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let dealings: BTreeMap = env .nodes @@ -378,7 +383,7 @@ mod create_transcript { }, rng, ); - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let signed_dealings = env.nodes.create_and_verify_signed_dealings(¶ms); let batch_signed_dealings = env .nodes @@ -425,7 +430,7 @@ mod create_transcript { rng, ); - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let signed_dealings = env.nodes.create_and_verify_signed_dealings(¶ms); let batch_signed_dealings = env @@ -480,7 +485,7 @@ mod create_transcript { rng, ); - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let signed_dealings = env.nodes.create_and_verify_signed_dealings(¶ms); let insufficient_supporters: Nodes = env @@ -511,7 +516,7 @@ mod create_transcript { let (dealers, receivers) = env.choose_dealers_and_receivers(&IDkgParticipants::Random, rng); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let creator = env.nodes.random_receiver(params.receivers(), rng); let batch_signed_dealings = env.nodes.create_batch_signed_dealings(¶ms); let corrupted_dealings = batch_signed_dealings @@ -541,7 +546,7 @@ mod create_transcript { let (dealers, receivers) = env.choose_dealers_and_receivers(&IDkgParticipants::Random, rng); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let creator = env.nodes.random_receiver(params.receivers(), rng); let mut batch_signed_dealings = env.nodes.create_batch_signed_dealings(¶ms); batch_signed_dealings.insert_or_update({ @@ -573,7 +578,7 @@ mod create_transcript { let (dealers, receivers) = env.choose_dealers_and_receivers(&IDkgParticipants::Random, rng); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let creator = env.nodes.random_receiver(params.receivers(), rng); let mut batch_signed_dealings = env.nodes.create_batch_signed_dealings(¶ms); batch_signed_dealings.insert_or_update({ @@ -600,7 +605,7 @@ mod create_transcript { mod load_transcript { use super::*; - use ic_crypto_test_utils_canister_threshold_sigs::node::Node; + use ic_crypto_test_utils_canister_threshold_sigs::{node::Node, setup_masked_random_params}; #[test] fn should_return_ok_from_load_transcript_if_not_a_receiver() { @@ -610,7 +615,7 @@ mod load_transcript { let (dealers, receivers) = env.choose_dealers_and_receivers(&IDkgParticipants::Random, rng); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let transcript = env .nodes .run_idkg_and_create_and_verify_transcript(¶ms, rng); @@ -636,7 +641,7 @@ mod load_transcript { let (dealers, receivers) = env.choose_dealers_and_receivers(&IDkgParticipants::Random, rng); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let transcript = env .nodes .run_idkg_and_create_and_verify_transcript(¶ms, rng); @@ -655,7 +660,7 @@ mod load_transcript { let (dealers, receivers) = env.choose_dealers_and_receivers(&IDkgParticipants::Random, rng); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let transcript = env .nodes .run_idkg_and_create_and_verify_transcript(¶ms, rng); @@ -669,32 +674,33 @@ mod load_transcript { } mod verify_complaint { - use ic_crypto_test_utils_canister_threshold_sigs::corrupt_dealings_and_generate_complaints; - use super::*; - use ic_crypto_test_utils_canister_threshold_sigs::to_corrupt_complaint; + use ic_crypto_test_utils_canister_threshold_sigs::{ + setup_masked_random_params, to_corrupt_complaint, IDkgMode, IDkgModeTestContext, + IDkgTestContextForComplaint, + }; + use strum::IntoEnumIterator; #[test] fn should_verify_complaint() { let rng = &mut reproducible_rng(); - let subnet_size = rng.gen_range(2..6); - let env = CanisterThresholdSigTestEnvironment::new(subnet_size, rng); - let (dealers, receivers) = env.choose_dealers_and_receivers(&IDkgParticipants::Random, rng); - - for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); - let mut transcript = env - .nodes - .run_idkg_and_create_and_verify_transcript(¶ms, rng); - let (complainer, complaint) = - corrupt_single_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); - - let result = env - .nodes - .random_receiver(params.receivers(), rng) - .verify_complaint(&transcript, complainer.id(), &complaint); - - assert_eq!(result, Ok(())); + for mode in IDkgMode::iter() { + println!("IDKG mode is {mode:?}"); + let subnet_size = mode.subnet_size_for_complaint(6, rng); + let env = CanisterThresholdSigTestEnvironment::new(subnet_size, rng); + for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { + let context = IDkgModeTestContext::new_for_complaint(mode, &env, rng); + let IDkgTestContextForComplaint { + transcript, + complaint, + complainer, + verifier, + } = context.setup_outputs_for_complaint(&env, alg, rng); + + let result = verifier.verify_complaint(&transcript, complainer.id(), &complaint); + + assert_eq!(result, Ok(())); + } } } @@ -706,14 +712,14 @@ mod verify_complaint { let (dealers, receivers) = env.choose_dealers_and_receivers(&IDkgParticipants::Random, rng); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let mut transcript = env .nodes .run_idkg_and_create_and_verify_transcript(¶ms, rng); let num_of_complaints = rng.gen_range(1..=transcript.verified_dealings.len()); let (complainer, corrupted_dealing_indices, complaints) = - corrupt_dealings_and_generate_complaints( + corrupt_dealings_and_generate_complaints_for_random_complainer( &mut transcript, num_of_complaints, ¶ms, @@ -758,12 +764,12 @@ mod verify_complaint { ); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let mut transcript = env .nodes .run_idkg_and_create_and_verify_transcript(¶ms, rng); let (complainer, complaint) = - corrupt_single_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); + corrupt_random_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); let wrong_complainer_id = random_receiver_id_excluding(params.receivers(), complainer.id(), rng); @@ -785,16 +791,15 @@ mod verify_complaint { let (dealers, receivers) = env.choose_dealers_and_receivers(&IDkgParticipants::Random, rng); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let mut transcript = env .nodes .run_idkg_and_create_and_verify_transcript(¶ms, rng); let (complainer, complaint) = - corrupt_single_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); + corrupt_random_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); - let other_transcript_id = env - .params_for_random_sharing(&dealers, &receivers, alg, rng) - .transcript_id(); + let other_transcript_id = + setup_masked_random_params(&env, alg, &dealers, &receivers, rng).transcript_id(); assert_ne!(other_transcript_id, params.transcript_id()); let complaint = complaint .into_builder() @@ -835,20 +840,21 @@ mod verify_complaint { ); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let mut transcript = env .nodes .run_idkg_and_create_and_verify_transcript(¶ms, rng); assert!(params.collection_threshold().get() >= 2); let num_of_dealings_to_corrupt = 2; - let (complainer, _, complaints) = corrupt_dealings_and_generate_complaints( - &mut transcript, - num_of_dealings_to_corrupt, - ¶ms, - &env, - rng, - ); + let (complainer, _, complaints) = + corrupt_dealings_and_generate_complaints_for_random_complainer( + &mut transcript, + num_of_dealings_to_corrupt, + ¶ms, + &env, + rng, + ); let complainer_id = complainer.id(); let mut complaint_1 = complaints.first().unwrap().clone(); @@ -889,19 +895,20 @@ mod verify_complaint { ); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); assert!(params.collection_threshold().get() as usize >= num_of_dealings_to_corrupt); let mut transcript = env .nodes .run_idkg_and_create_and_verify_transcript(¶ms, rng); - let (complainer, _, complaints) = corrupt_dealings_and_generate_complaints( - &mut transcript, - num_of_dealings_to_corrupt, - ¶ms, - &env, - rng, - ); + let (complainer, _, complaints) = + corrupt_dealings_and_generate_complaints_for_random_complainer( + &mut transcript, + num_of_dealings_to_corrupt, + ¶ms, + &env, + rng, + ); let complainer_id = complainer.id(); let mut complaint_1 = complaints.first().unwrap().clone(); @@ -938,12 +945,12 @@ mod verify_complaint { ); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let mut transcript = env .nodes .run_idkg_and_create_and_verify_transcript(¶ms, rng); let (complainer, complaint) = - corrupt_single_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); + corrupt_random_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); for complaint_corrupter in ComplaintCorrupter::iter() { let corrupt_complaint = to_corrupt_complaint(&complaint, &complaint_corrupter); assert_matches!( @@ -960,7 +967,7 @@ mod verify_complaint { mod verify_transcript { use super::*; - use ic_crypto_test_utils_canister_threshold_sigs::IntoBuilder; + use ic_crypto_test_utils_canister_threshold_sigs::{setup_masked_random_params, IntoBuilder}; #[test] fn should_run_idkg_successfully_for_random_dealing() { @@ -971,7 +978,7 @@ mod verify_transcript { let (dealers, receivers) = env.choose_dealers_and_receivers(&IDkgParticipants::Random, rng); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let transcript = env .nodes .run_idkg_and_create_and_verify_transcript(¶ms, rng); @@ -990,7 +997,7 @@ mod verify_transcript { env.choose_dealers_and_receivers(&IDkgParticipants::RandomForThresholdSignature, rng); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let initial_params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let initial_params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let initial_transcript = env .nodes .run_idkg_and_create_and_verify_transcript(&initial_params, rng); @@ -1021,7 +1028,7 @@ mod verify_transcript { env.choose_dealers_and_receivers(&IDkgParticipants::RandomForThresholdSignature, rng); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let initial_params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let initial_params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let initial_transcript = env .nodes .run_idkg_and_create_and_verify_transcript(&initial_params, rng); @@ -1060,7 +1067,7 @@ mod verify_transcript { env.choose_dealers_and_receivers(&IDkgParticipants::RandomForThresholdSignature, rng); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let masked_params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let masked_params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let masked_transcript = env .nodes .run_idkg_and_create_and_verify_transcript(&masked_params, rng); @@ -1070,7 +1077,7 @@ mod verify_transcript { let unmasked_transcript = { let masked_random_params = - env.params_for_random_sharing(&dealers, &receivers, alg, rng); + setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let masked_random_transcript = env .nodes .run_idkg_and_create_and_verify_transcript(&masked_random_params, rng); @@ -1116,7 +1123,7 @@ mod verify_transcript { env.choose_dealers_and_receivers(&IDkgParticipants::RandomForThresholdSignature, rng); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let random_params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let random_params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let random_transcript = env .nodes .run_idkg_and_create_and_verify_transcript(&random_params, rng); @@ -1210,7 +1217,7 @@ mod verify_transcript { ); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let transcript = env .nodes @@ -1244,7 +1251,8 @@ mod verify_transcript { env.choose_dealers_and_receivers(&IDkgParticipants::RandomForThresholdSignature, rng); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let masked_key_params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let masked_key_params = + setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let masked_key_transcript = env .nodes @@ -1293,7 +1301,7 @@ mod verify_transcript { ); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let mut transcript = env .nodes @@ -1354,7 +1362,7 @@ mod verify_transcript { ); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let transcript = env .nodes @@ -1402,7 +1410,7 @@ mod verify_transcript { rng, ); - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let transcript = env .nodes @@ -1425,20 +1433,20 @@ mod verify_transcript { #[test] fn should_verify_transcript_reject_transcript_with_corrupted_internal_data() { - let mut rng = reproducible_rng(); + let rng = &mut reproducible_rng(); let subnet_size = rng.gen_range(4..10); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let (env, params, transcript) = setup_for_verify_transcript(alg, &mut rng, subnet_size); + let (env, params, transcript) = setup_for_verify_transcript(alg, rng, subnet_size); let transcript = transcript .into_builder() - .corrupt_internal_transcript_raw(&mut rng) + .corrupt_internal_transcript_raw(rng) .build(); let r = env .nodes - .random_node(&mut rng) + .random_node(rng) .verify_transcript(¶ms, &transcript); // Since the corruption is randomized, we might corrupt the CBOR or the commitments @@ -1457,17 +1465,17 @@ mod verify_transcript { #[test] fn should_verify_transcript_reject_transcript_with_wrong_transcript_id() { - let mut rng = reproducible_rng(); + let rng = &mut reproducible_rng(); let subnet_size = rng.gen_range(4..10); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let (env, params, transcript) = setup_for_verify_transcript(alg, &mut rng, subnet_size); + let (env, params, transcript) = setup_for_verify_transcript(alg, rng, subnet_size); let transcript = transcript.into_builder().corrupt_transcript_id().build(); let r = env .nodes - .random_node(&mut rng) + .random_node(rng) .verify_transcript(¶ms, &transcript); assert_matches!(r, @@ -1478,17 +1486,17 @@ mod verify_transcript { #[test] fn should_verify_transcript_reject_transcript_with_wrong_registry_version() { - let mut rng = reproducible_rng(); + let rng = &mut reproducible_rng(); let subnet_size = rng.gen_range(4..10); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let (env, params, transcript) = setup_for_verify_transcript(alg, &mut rng, subnet_size); + let (env, params, transcript) = setup_for_verify_transcript(alg, rng, subnet_size); let transcript = transcript.into_builder().corrupt_registry_version().build(); let r = env .nodes - .random_node(&mut rng) + .random_node(rng) .verify_transcript(¶ms, &transcript); assert_matches!(r, @@ -1499,17 +1507,17 @@ mod verify_transcript { #[test] fn should_verify_transcript_reject_transcript_with_wrong_algorithm_id() { - let mut rng = reproducible_rng(); + let rng = &mut reproducible_rng(); let subnet_size = rng.gen_range(4..10); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let (env, params, transcript) = setup_for_verify_transcript(alg, &mut rng, subnet_size); + let (env, params, transcript) = setup_for_verify_transcript(alg, rng, subnet_size); let transcript = transcript.into_builder().corrupt_algorithm_id().build(); let r = env .nodes - .random_node(&mut rng) + .random_node(rng) .verify_transcript(¶ms, &transcript); assert_matches!(r, @@ -1520,17 +1528,17 @@ mod verify_transcript { #[test] fn should_verify_transcript_reject_transcript_with_an_extra_receiver() { - let mut rng = reproducible_rng(); + let rng = &mut reproducible_rng(); let subnet_size = rng.gen_range(4..10); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let (env, params, transcript) = setup_for_verify_transcript(alg, &mut rng, subnet_size); + let (env, params, transcript) = setup_for_verify_transcript(alg, rng, subnet_size); let transcript = transcript.into_builder().add_a_new_receiver().build(); let r = env .nodes - .random_node(&mut rng) + .random_node(rng) .verify_transcript(¶ms, &transcript); assert_matches!(r, @@ -1541,18 +1549,18 @@ mod verify_transcript { #[test] fn should_verify_transcript_reject_transcript_with_a_missing_receiver() { - let mut rng = reproducible_rng(); + let rng = &mut reproducible_rng(); let subnet_size = rng.gen_range(6..10); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { let (env, params, transcript) = - setup_for_verify_transcript_with_min_num_receivers(alg, &mut rng, subnet_size, 2); + setup_for_verify_transcript_with_min_num_receivers(alg, rng, subnet_size, 2); let transcript = transcript.into_builder().remove_a_receiver().build(); let r = env .nodes - .random_node(&mut rng) + .random_node(rng) .verify_transcript(¶ms, &transcript); assert_matches!(r, @@ -1563,17 +1571,17 @@ mod verify_transcript { #[test] fn should_verify_transcript_reject_transcript_with_wrong_transcript_type() { - let mut rng = reproducible_rng(); + let rng = &mut reproducible_rng(); let subnet_size = rng.gen_range(4..10); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let (env, params, transcript) = setup_for_verify_transcript(alg, &mut rng, subnet_size); + let (env, params, transcript) = setup_for_verify_transcript(alg, rng, subnet_size); let transcript = transcript.into_builder().corrupt_transcript_type().build(); let r = env .nodes - .random_node(&mut rng) + .random_node(rng) .verify_transcript(¶ms, &transcript); assert_matches!(r, @@ -1631,25 +1639,17 @@ mod sign_share { #[test] fn should_fail_create_signature_if_not_receiver() { - let mut rng = reproducible_rng(); + let rng = &mut reproducible_rng(); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { let subnet_size = rng.gen_range(1..10); - let env = CanisterThresholdSigTestEnvironment::new(subnet_size, &mut rng); - let (dealers, receivers) = env.choose_dealers_and_receivers( - &IDkgParticipants::RandomForThresholdSignature, - &mut rng, - ); + let env = CanisterThresholdSigTestEnvironment::new(subnet_size, rng); + let (dealers, receivers) = env + .choose_dealers_and_receivers(&IDkgParticipants::RandomForThresholdSignature, rng); - let key_transcript = generate_key_transcript(&env, &dealers, &receivers, alg, &mut rng); - let quadruple = generate_presig_quadruple( - &env, - &dealers, - &receivers, - alg, - &key_transcript, - &mut rng, - ); + let key_transcript = generate_key_transcript(&env, &dealers, &receivers, alg, rng); + let quadruple = + generate_presig_quadruple(&env, &dealers, &receivers, alg, &key_transcript, rng); let inputs = { let derivation_path = ExtendedDerivationPath { @@ -1670,7 +1670,7 @@ mod sign_share { .expect("failed to create signature inputs") }; - let bad_signer_id = random_node_id_excluding(inputs.receivers().get(), &mut rng); + let bad_signer_id = random_node_id_excluding(inputs.receivers().get(), rng); let bad_crypto_component = TempCryptoComponent::builder() .with_registry(Arc::clone(&env.registry) as Arc<_>) .with_node_id(bad_signer_id) @@ -2155,7 +2155,7 @@ mod retain_active_transcripts { let (dealers, receivers) = env.choose_dealers_and_receivers(&IDkgParticipants::Random, rng); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let transcript = env .nodes .run_idkg_and_create_and_verify_transcript(¶ms, rng); @@ -2184,7 +2184,7 @@ mod load_transcript_with_openings { let (dealers, receivers) = env.choose_dealers_and_receivers(&IDkgParticipants::Random, rng); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let transcript = env .nodes .run_idkg_and_create_and_verify_transcript(¶ms, rng); @@ -2211,7 +2211,7 @@ mod load_transcript_with_openings { rng, ); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let mut transcript = env .nodes .run_idkg_and_create_and_verify_transcript(¶ms, rng); @@ -2221,7 +2221,7 @@ mod load_transcript_with_openings { let number_of_openings = reconstruction_threshold; let (complainer, complaint) = - corrupt_single_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); + corrupt_random_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); let complaint_with_openings = generate_and_verify_openings_for_complaint( number_of_openings, &transcript, @@ -2250,7 +2250,7 @@ mod load_transcript_with_openings { env.choose_dealers_and_receivers(&IDkgParticipants::RandomForThresholdSignature, rng); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { let random_sharing_params = - env.params_for_random_sharing(&dealers, &receivers, alg, rng); + setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let random_sharing_transcript = env .nodes .run_idkg_and_create_and_verify_transcript(&random_sharing_params, rng); @@ -2267,7 +2267,7 @@ mod load_transcript_with_openings { .expect("invalid number"); let number_of_openings = reconstruction_threshold; - let (complainer, complaint) = corrupt_single_dealing_and_generate_complaint( + let (complainer, complaint) = corrupt_random_dealing_and_generate_complaint( &mut key_transcript, &unmasked_key_params, &env, @@ -2332,7 +2332,7 @@ mod load_transcript_with_openings { rng, ); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let mut transcript = env .nodes .run_idkg_and_create_and_verify_transcript(¶ms, rng); @@ -2342,7 +2342,7 @@ mod load_transcript_with_openings { let number_of_openings = reconstruction_threshold - 1; let (complainer, complaint) = - corrupt_single_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); + corrupt_random_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); let complaint_with_openings = generate_and_verify_openings_for_complaint( number_of_openings, &transcript, @@ -2758,7 +2758,7 @@ mod verify_dealing_private { use super::*; use ic_crypto::CryptoComponentImpl; use ic_crypto_internal_logmon::metrics::CryptoMetrics; - use ic_crypto_test_utils_canister_threshold_sigs::IntoBuilder; + use ic_crypto_test_utils_canister_threshold_sigs::{setup_masked_random_params, IntoBuilder}; use ic_crypto_test_utils_csp::MockAllCryptoServiceProvider; use ic_crypto_test_utils_keys::public_keys::valid_idkg_dealing_encryption_public_key; use ic_interfaces_registry_mocks::MockRegistryClient; @@ -2778,7 +2778,7 @@ mod verify_dealing_private { let (dealers, receivers) = env.choose_dealers_and_receivers(&IDkgParticipants::Random, rng); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let dealer = env.nodes.random_dealer(¶ms, rng); let signed_dealing = dealer.create_dealing_or_panic(¶ms); let receiver = env.nodes.random_receiver(params.receivers(), rng); @@ -2797,7 +2797,7 @@ mod verify_dealing_private { let (dealers, receivers) = env.choose_dealers_and_receivers(&IDkgParticipants::Random, rng); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let dealer = env.nodes.random_dealer(¶ms, rng); let signed_dealing_with_corrupted_signature = dealer .create_dealing_or_panic(¶ms) @@ -2842,10 +2842,11 @@ mod verify_dealing_private { }; for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing( + let params = setup_masked_random_params( + &env, + alg, &dealers_with_at_least_one_common_node, &receivers_with_at_least_one_common_node, - alg, rng, ); let signed_dealing = dealer_and_receiver.create_dealing_or_panic(¶ms); @@ -2864,7 +2865,7 @@ mod verify_dealing_private { let (dealers, receivers) = env.choose_dealers_and_receivers(&IDkgParticipants::Random, rng); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let dealer = env.nodes.random_dealer(¶ms, rng); let signed_dealing = dealer.create_dealing_or_panic(¶ms); let receiver = env.nodes.random_receiver(params.receivers(), rng); @@ -2889,7 +2890,7 @@ mod verify_dealing_private { let (dealers, receivers) = env.choose_dealers_and_receivers(&IDkgParticipants::Random, rng); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let dealer = env.nodes.random_dealer(¶ms, rng); let signed_dealing = dealer.create_dealing_or_panic(¶ms); let receiver = env.nodes.random_receiver(params.receivers(), rng); @@ -3013,7 +3014,7 @@ mod verify_dealing_private { let env = CanisterThresholdSigTestEnvironment::new(subnet_size, rng); let (dealers, receivers) = env.choose_dealers_and_receivers(&IDkgParticipants::Random, rng); - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let dealer = env.nodes.random_dealer(¶ms, rng); let signed_dealing = dealer.create_dealing_or_panic(¶ms); let node_id = *receivers @@ -3076,19 +3077,18 @@ mod verify_dealing_public { #[test] fn should_successfully_verify_random_sharing_dealing_with_valid_input() { - let mut rng = reproducible_rng(); + let rng = &mut reproducible_rng(); let subnet_size = rng.gen_range(1..10); - let env = CanisterThresholdSigTestEnvironment::new(subnet_size, &mut rng); - let (dealers, receivers) = - env.choose_dealers_and_receivers(&IDkgParticipants::Random, &mut rng); + let env = CanisterThresholdSigTestEnvironment::new(subnet_size, rng); + let (dealers, receivers) = env.choose_dealers_and_receivers(&IDkgParticipants::Random, rng); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, &mut rng); - let dealer = env.nodes.random_dealer(¶ms, &mut rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); + let dealer = env.nodes.random_dealer(¶ms, rng); let signed_dealing = dealer.create_dealing_or_panic(¶ms); - let verifier_id = random_node_id_excluding(&env.nodes.ids(), &mut rng); + let verifier_id = random_node_id_excluding(&env.nodes.ids(), rng); let verifier = TempCryptoComponent::builder() .with_registry(Arc::clone(&env.registry) as Arc<_>) .with_node_id(verifier_id) @@ -3102,22 +3102,21 @@ mod verify_dealing_public { #[test] fn should_fail_verify_dealing_public_with_invalid_signature() { - let mut rng = reproducible_rng(); + let rng = &mut reproducible_rng(); let subnet_size = rng.gen_range(1..10); - let env = CanisterThresholdSigTestEnvironment::new(subnet_size, &mut rng); - let (dealers, receivers) = - env.choose_dealers_and_receivers(&IDkgParticipants::Random, &mut rng); + let env = CanisterThresholdSigTestEnvironment::new(subnet_size, rng); + let (dealers, receivers) = env.choose_dealers_and_receivers(&IDkgParticipants::Random, rng); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, &mut rng); - let dealer = env.nodes.random_dealer(¶ms, &mut rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); + let dealer = env.nodes.random_dealer(¶ms, rng); let signed_dealing = dealer .create_dealing_or_panic(¶ms) .into_builder() .corrupt_signature() .build(); - let verifier_id = random_node_id_excluding(&env.nodes.ids(), &mut rng); + let verifier_id = random_node_id_excluding(&env.nodes.ids(), rng); let verifier = TempCryptoComponent::builder() .with_registry(Arc::clone(&env.registry) as Arc<_>) .with_node_id(verifier_id) @@ -3135,22 +3134,21 @@ mod verify_dealing_public { #[test] fn should_fail_verify_dealing_public_with_wrong_transcript_id() { - let mut rng = reproducible_rng(); + let rng = &mut reproducible_rng(); let subnet_size = rng.gen_range(1..10); - let env = CanisterThresholdSigTestEnvironment::new(subnet_size, &mut rng); - let (dealers, receivers) = - env.choose_dealers_and_receivers(&IDkgParticipants::Random, &mut rng); + let env = CanisterThresholdSigTestEnvironment::new(subnet_size, rng); + let (dealers, receivers) = env.choose_dealers_and_receivers(&IDkgParticipants::Random, rng); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, &mut rng); - let dealer = env.nodes.random_dealer(¶ms, &mut rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); + let dealer = env.nodes.random_dealer(¶ms, rng); let signed_dealing = dealer .create_dealing_or_panic(¶ms) .into_builder() .corrupt_transcript_id() .build_with_signature(¶ms, dealer, dealer.id()); - let verifier_id = random_node_id_excluding(&env.nodes.ids(), &mut rng); + let verifier_id = random_node_id_excluding(&env.nodes.ids(), rng); let verifier = TempCryptoComponent::builder() .with_registry(Arc::clone(&env.registry) as Arc<_>) .with_node_id(verifier_id) @@ -3169,20 +3167,20 @@ mod verify_dealing_public { #[test] fn should_fail_verify_dealing_public_with_wrong_dealer_id() { const MIN_NUM_NODES: usize = 2; - let mut rng = reproducible_rng(); + let rng = &mut reproducible_rng(); let subnet_size = rng.gen_range(MIN_NUM_NODES..10); //need at least 2 nodes to have a dealer and another node - let env = CanisterThresholdSigTestEnvironment::new(subnet_size, &mut rng); + let env = CanisterThresholdSigTestEnvironment::new(subnet_size, rng); let (dealers, receivers) = env.choose_dealers_and_receivers( &IDkgParticipants::RandomWithAtLeast { min_num_dealers: MIN_NUM_NODES, min_num_receivers: 1, }, - &mut rng, + rng, ); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, &mut rng); - let dealer = env.nodes.random_dealer(¶ms, &mut rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); + let dealer = env.nodes.random_dealer(¶ms, rng); let other_dealer = env .nodes .dealers(¶ms) @@ -3194,7 +3192,7 @@ mod verify_dealing_public { .with_dealer_id(other_dealer.id()) .build_with_signature(¶ms, other_dealer, other_dealer.id()); - let verifier_id = random_node_id_excluding(&env.nodes.ids(), &mut rng); + let verifier_id = random_node_id_excluding(&env.nodes.ids(), rng); let verifier = TempCryptoComponent::builder() .with_registry(Arc::clone(&env.registry) as Arc<_>) .with_node_id(verifier_id) @@ -3212,20 +3210,19 @@ mod verify_dealing_public { #[test] fn should_fail_verify_dealing_public_with_wrong_dealer_index() { - let mut rng = reproducible_rng(); + let rng = &mut reproducible_rng(); let subnet_size = rng.gen_range(1..10); - let env = CanisterThresholdSigTestEnvironment::new(subnet_size, &mut rng); - let (dealers, receivers) = - env.choose_dealers_and_receivers(&IDkgParticipants::Random, &mut rng); + let env = CanisterThresholdSigTestEnvironment::new(subnet_size, rng); + let (dealers, receivers) = env.choose_dealers_and_receivers(&IDkgParticipants::Random, rng); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, &mut rng); - let dealer = env.nodes.random_dealer(¶ms, &mut rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); + let dealer = env.nodes.random_dealer(¶ms, rng); // We need the signature verification to succeed, so the public key of the valid dealer in // the registry needs to be copied to a non-dealer. The subsequent dealer index check will // fail (which is what we are testing), since the `NodeId` of the non-dealer is not // included in the list of dealers in params. - let not_a_dealer_node_id = random_node_id_excluding(&env.nodes.ids(), &mut rng); + let not_a_dealer_node_id = random_node_id_excluding(&env.nodes.ids(), rng); copy_node_signing_key_in_registry_from_one_node_to_another( &env, dealer.id(), @@ -3239,7 +3236,7 @@ mod verify_dealing_public { .with_dealer_id(not_a_dealer_node_id) .build(); - let verifier_id = random_node_id_excluding(&env.nodes.ids(), &mut rng); + let verifier_id = random_node_id_excluding(&env.nodes.ids(), rng); let verifier = TempCryptoComponent::builder() .with_registry(Arc::clone(&env.registry) as Arc<_>) .with_node_id(verifier_id) @@ -3257,21 +3254,20 @@ mod verify_dealing_public { #[test] fn should_fail_verify_dealing_public_with_wrong_internal_dealing_raw() { - let mut rng = reproducible_rng(); + let rng = &mut reproducible_rng(); let subnet_size = rng.gen_range(1..10); - let env = CanisterThresholdSigTestEnvironment::new(subnet_size, &mut rng); - let (dealers, receivers) = - env.choose_dealers_and_receivers(&IDkgParticipants::Random, &mut rng); + let env = CanisterThresholdSigTestEnvironment::new(subnet_size, rng); + let (dealers, receivers) = env.choose_dealers_and_receivers(&IDkgParticipants::Random, rng); for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { - let params = env.params_for_random_sharing(&dealers, &receivers, alg, &mut rng); - let dealer = env.nodes.random_dealer(¶ms, &mut rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); + let dealer = env.nodes.random_dealer(¶ms, rng); let signed_dealing = dealer .create_dealing_or_panic(¶ms) .into_builder() .corrupt_internal_dealing_raw_by_flipping_bit() .build_with_signature(¶ms, dealer, dealer.id()); - let verifier_id = random_node_id_excluding(&env.nodes.ids(), &mut rng); + let verifier_id = random_node_id_excluding(&env.nodes.ids(), rng); let verifier = TempCryptoComponent::builder() .with_registry(Arc::clone(&env.registry) as Arc<_>) .with_node_id(verifier_id) @@ -3518,7 +3514,7 @@ mod open_transcript { for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { let (env, params, mut transcript) = environment_and_transcript_for_complaint(alg, rng); let (complainer, complaint) = - corrupt_single_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); + corrupt_random_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); let opener = env.nodes .random_receiver_excluding(complainer, &transcript.receivers, rng); @@ -3534,7 +3530,7 @@ mod open_transcript { for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { let (env, params, mut transcript) = environment_and_transcript_for_complaint(alg, rng); let (complainer, complaint) = - corrupt_single_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); + corrupt_random_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); let opener = complainer; // opener's share is invalid let result = opener.open_transcript(&transcript, opener.id(), &complaint); assert_matches!(result, Err(IDkgOpenTranscriptError::InternalError { internal_error }) @@ -3548,7 +3544,7 @@ mod open_transcript { for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { let (env, params, mut transcript) = environment_and_transcript_for_complaint(alg, rng); let (complainer, complaint) = - corrupt_single_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); + corrupt_random_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); // Remove the corrupted dealing from the transcript. transcript.verified_dealings.remove( &transcript @@ -3571,7 +3567,7 @@ mod open_transcript { for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { let (env, params, mut transcript) = environment_and_transcript_for_complaint(alg, rng); let (complainer, mut complaint) = - corrupt_single_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); + corrupt_random_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); // Set "wrong" dealer_id in the complaint complaint.dealer_id = random_dealer_id_excluding(&transcript, complaint.dealer_id, rng); @@ -3591,13 +3587,13 @@ mod open_transcript { for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { let (env, params, mut transcript) = environment_and_transcript_for_complaint(alg, rng); let (complainer, complaint) = - corrupt_single_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); + corrupt_random_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); // Create another environment of the same size, and generate a transcript for it. let env_2 = CanisterThresholdSigTestEnvironment::new(env.nodes.len(), rng); let (dealers_2, receivers_2) = env_2.choose_dealers_and_receivers(&IDkgParticipants::Random, rng); - let params_2 = env_2.params_for_random_sharing(&dealers_2, &receivers_2, alg, rng); + let params_2 = setup_masked_random_params(&env_2, alg, &dealers_2, &receivers_2, rng); let transcript_2 = &env_2 .nodes .run_idkg_and_create_and_verify_transcript(¶ms_2, rng); @@ -3623,7 +3619,7 @@ mod verify_opening { for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { let (env, params, mut transcript) = environment_and_transcript_for_complaint(alg, rng); let (complainer, complaint) = - corrupt_single_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); + corrupt_random_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); let opener = env.nodes .random_receiver_excluding(complainer, &transcript.receivers, rng); @@ -3643,7 +3639,7 @@ mod verify_opening { for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { let (env, params, mut transcript) = environment_and_transcript_for_complaint(alg, rng); let (complainer, complaint) = - corrupt_single_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); + corrupt_random_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); let opener = env.nodes .random_receiver_excluding(complainer, &transcript.receivers, rng); @@ -3670,7 +3666,7 @@ mod verify_opening { for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { let (env, params, mut transcript) = environment_and_transcript_for_complaint(alg, rng); let (complainer, mut complaint) = - corrupt_single_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); + corrupt_random_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); let opener = env.nodes .random_receiver_excluding(complainer, &transcript.receivers, rng); @@ -3698,7 +3694,7 @@ mod verify_opening { for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { let (env, params, mut transcript) = environment_and_transcript_for_complaint(alg, rng); let (complainer, complaint) = - corrupt_single_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); + corrupt_random_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); let opener = env.nodes .random_receiver_excluding(complainer, &transcript.receivers, rng); @@ -3721,7 +3717,7 @@ mod verify_opening { for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { let (env, params, mut transcript) = environment_and_transcript_for_complaint(alg, rng); let (complainer, complaint) = - corrupt_single_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); + corrupt_random_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); let opener = env.nodes .random_receiver_excluding(complainer, &transcript.receivers, rng); @@ -3751,7 +3747,7 @@ mod verify_opening { for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { let (env, params, mut transcript) = environment_and_transcript_for_complaint(alg, rng); let (complainer, complaint) = - corrupt_single_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); + corrupt_random_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); let opener = env.nodes .random_receiver_excluding(complainer, &transcript.receivers, rng); @@ -3776,7 +3772,7 @@ mod verify_opening { for alg in AlgorithmId::all_threshold_ecdsa_algorithms() { let (env, params, mut transcript) = environment_and_transcript_for_complaint(alg, rng); let (complainer, complaint) = - corrupt_single_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); + corrupt_random_dealing_and_generate_complaint(&mut transcript, ¶ms, &env, rng); let opener = env.nodes .random_receiver_excluding(complainer, &transcript.receivers, rng); @@ -4128,7 +4124,7 @@ fn environment_and_transcript_for_complaint( rng, ); - let params = env.params_for_random_sharing(&dealers, &receivers, alg, rng); + let params = setup_masked_random_params(&env, alg, &dealers, &receivers, rng); let transcript = env .nodes .run_idkg_and_create_and_verify_transcript(¶ms, rng); diff --git a/rs/types/types/src/crypto/canister_threshold_sig/idkg.rs b/rs/types/types/src/crypto/canister_threshold_sig/idkg.rs index 2d6036a28c7..0b04dc1342d 100644 --- a/rs/types/types/src/crypto/canister_threshold_sig/idkg.rs +++ b/rs/types/types/src/crypto/canister_threshold_sig/idkg.rs @@ -740,14 +740,15 @@ pub enum IDkgTranscriptOperation { /// Starts from a `masked` transcript and returns an `unmasked` transcript. /// - /// Useful to reveal `g^a_0` (where `a_0` is the shared secret and g is a group's generator) to + /// Takes in a secret share `x` and outputs `g^x` (g is a group's generator) to /// all parties. + /// + /// Useful to compute the public key from a masked transcript. ReshareOfMasked(IDkgTranscript), /// Starts from an `unmasked` transcript and returns an `unmasked` transcript. /// - /// Useful to reshare the public key if there was for example a change in the subnet's - /// topology. + /// Reshares the public key. Needed, e.g., after subnet topology changes. ReshareOfUnmasked(IDkgTranscript), /// Starts from a pair of transcripts (the first being `unmasked` while the second is `masked`)