diff --git a/book/src/tutorial/dkg.md b/book/src/tutorial/dkg.md index d2b0d18..ce467b5 100644 --- a/book/src/tutorial/dkg.md +++ b/book/src/tutorial/dkg.md @@ -58,7 +58,7 @@ calls [`dkg::part2()`](https://docs.rs/frost-ristretto255/latest/frost_ristretto255/keys/dkg/fn.part2.html) passing their own previously created `round1::SecretPackage` and the list of received `round1::Packages`. It returns a `round2::SecretPackage` and a -`HashMap` mapping other participants's `Identifier`s to `round2::Package`s: +`BTreeMap` mapping other participants's `Identifier`s to `round2::Package`s: ```rust,no_run,noplayground {{#include ../../../frost-ristretto255/dkg.md:dkg_part2}} diff --git a/book/src/tutorial/trusted-dealer.md b/book/src/tutorial/trusted-dealer.md index a779116..999485d 100644 --- a/book/src/tutorial/trusted-dealer.md +++ b/book/src/tutorial/trusted-dealer.md @@ -8,7 +8,7 @@ channel](https://frost.zfnd.org/terminology.html#peer-to-peer-channel). To generate the key shares, the dealer calls [`generate_with_dealer()`](https://docs.rs/frost-ristretto255/latest/frost_ristretto255/keys/fn.generate_with_dealer.html). -It returns a `HashMap` mapping the (automatically generated) `Identifier`s to +It returns a `BTreeMap` mapping the (automatically generated) `Identifier`s to their respective `SecretShare`s, and a `PublicKeyPackage` which contains the `VerifyingShare` for each participant and the group public key (`VerifyingKey`). diff --git a/frost-core/src/benches.rs b/frost-core/src/benches.rs index a0b28db..fc1496b 100644 --- a/frost-core/src/benches.rs +++ b/frost-core/src/benches.rs @@ -1,7 +1,7 @@ //! Ciphersuite-generic benchmark functions. #![allow(clippy::unwrap_used)] -use std::collections::{BTreeMap, HashMap}; +use std::collections::BTreeMap; use criterion::{BenchmarkId, Criterion, Throughput}; use rand_core::{CryptoRng, RngCore}; @@ -113,8 +113,8 @@ pub fn bench_sign( .unwrap(); // Verifies the secret shares from the dealer - let mut key_packages: HashMap, frost::keys::KeyPackage> = - HashMap::new(); + let mut key_packages: BTreeMap, frost::keys::KeyPackage> = + BTreeMap::new(); for (k, v) in shares { key_packages.insert(k, frost::keys::KeyPackage::try_from(v).unwrap()); @@ -137,7 +137,7 @@ pub fn bench_sign( }, ); - let mut nonces: HashMap<_, _> = HashMap::new(); + let mut nonces: BTreeMap<_, _> = BTreeMap::new(); let mut commitments: BTreeMap<_, _> = BTreeMap::new(); for participant_index in 1..=min_signers { @@ -173,7 +173,7 @@ pub fn bench_sign( }, ); - let mut signature_shares = HashMap::new(); + let mut signature_shares = BTreeMap::new(); for participant_identifier in nonces.keys() { let key_package = key_packages.get(participant_identifier).unwrap(); let nonces_to_use = &nonces.get(participant_identifier).unwrap(); diff --git a/frost-core/src/frost.rs b/frost-core/src/frost.rs index aaa5727..0e3d391 100644 --- a/frost-core/src/frost.rs +++ b/frost-core/src/frost.rs @@ -9,7 +9,7 @@ //! generation and the FROST rounds. use std::{ - collections::{BTreeMap, BTreeSet, HashMap}, + collections::{BTreeMap, BTreeSet}, fmt::{self, Debug}, }; @@ -408,7 +408,7 @@ where /// service attack due to publishing an invalid signature. pub fn aggregate( signing_package: &SigningPackage, - signature_shares: &HashMap, round2::SignatureShare>, + signature_shares: &BTreeMap, round2::SignatureShare>, pubkeys: &keys::PublicKeyPackage, ) -> Result, Error> where diff --git a/frost-core/src/frost/keys.rs b/frost-core/src/frost/keys.rs index e315ecd..b975e61 100644 --- a/frost-core/src/frost/keys.rs +++ b/frost-core/src/frost/keys.rs @@ -2,7 +2,7 @@ #![allow(clippy::type_complexity)] use std::{ - collections::{BTreeSet, HashMap, HashSet}, + collections::{BTreeMap, BTreeSet, HashSet}, convert::TryFrom, default::Default, fmt::{self, Debug}, @@ -458,7 +458,7 @@ pub fn generate_with_dealer( min_signers: u16, identifiers: IdentifierList, rng: &mut R, -) -> Result<(HashMap, SecretShare>, PublicKeyPackage), Error> { +) -> Result<(BTreeMap, SecretShare>, PublicKeyPackage), Error> { let mut bytes = [0; 64]; rng.fill_bytes(&mut bytes); @@ -479,7 +479,7 @@ pub fn split( min_signers: u16, identifiers: IdentifierList, rng: &mut R, -) -> Result<(HashMap, SecretShare>, PublicKeyPackage), Error> { +) -> Result<(BTreeMap, SecretShare>, PublicKeyPackage), Error> { validate_num_of_signers(min_signers, max_signers)?; if let IdentifierList::Custom(identifiers) = &identifiers { @@ -501,11 +501,9 @@ pub fn split( generate_secret_shares(key, max_signers, min_signers, coefficients, identifiers)? } }; - let mut verifying_shares: HashMap, VerifyingShare> = - HashMap::with_capacity(max_signers as usize); + let mut verifying_shares: BTreeMap, VerifyingShare> = BTreeMap::new(); - let mut secret_shares_by_id: HashMap, SecretShare> = - HashMap::with_capacity(max_signers as usize); + let mut secret_shares_by_id: BTreeMap, SecretShare> = BTreeMap::new(); for secret_share in secret_shares { let signer_public = secret_share.signing_share.into(); @@ -673,7 +671,7 @@ pub struct PublicKeyPackage { pub(crate) header: Header, /// The verifying shares for all participants. Used to validate signature /// shares they generate. - pub(crate) verifying_shares: HashMap, VerifyingShare>, + pub(crate) verifying_shares: BTreeMap, VerifyingShare>, /// The joint public key for the entire group. pub(crate) verifying_key: VerifyingKey, } @@ -684,7 +682,7 @@ where { /// Create a new [`PublicKeyPackage`] instance. pub fn new( - verifying_shares: HashMap, VerifyingShare>, + verifying_shares: BTreeMap, VerifyingShare>, verifying_key: VerifyingKey, ) -> Self { Self { diff --git a/frost-core/src/frost/keys/dkg.rs b/frost-core/src/frost/keys/dkg.rs index b99f0d4..85a74fa 100644 --- a/frost-core/src/frost/keys/dkg.rs +++ b/frost-core/src/frost/keys/dkg.rs @@ -30,7 +30,7 @@ //! [Feldman's VSS]: https://www.cs.umd.edu/~gasarch/TOPICS/secretsharing/feldmanVSS.pdf //! [secure broadcast channel]: https://frost.zfnd.org/terminology.html#broadcast-channel -use std::{collections::HashMap, iter}; +use std::{collections::BTreeMap, iter}; use rand_core::{CryptoRng, RngCore}; @@ -346,11 +346,11 @@ where /// must be sent to each participant who has the given identifier in the map key. pub fn part2( secret_package: round1::SecretPackage, - round1_packages: &HashMap, round1::Package>, + round1_packages: &BTreeMap, round1::Package>, ) -> Result< ( round2::SecretPackage, - HashMap, round2::Package>, + BTreeMap, round2::Package>, ), Error, > { @@ -358,7 +358,7 @@ pub fn part2( return Err(Error::IncorrectNumberOfPackages); } - let mut round2_packages = HashMap::new(); + let mut round2_packages = BTreeMap::new(); for (sender_identifier, round1_package) in round1_packages { let ell = *sender_identifier; @@ -407,14 +407,14 @@ pub fn part2( /// Computes the verifying shares of the other participants for the third step /// of the DKG protocol. fn compute_verifying_shares( - round1_packages: &HashMap, round1::Package>, + round1_packages: &BTreeMap, round1::Package>, round2_secret_package: &round2::SecretPackage, -) -> Result, VerifyingShare>, Error> { +) -> Result, VerifyingShare>, Error> { // Round 2, Step 4 // // > Any participant can compute the public verification share of any other participant // > by calculating Y_i = ∏_{j=1}^n ∏_{k=0}^{t−1} φ_{jk}^{i^k mod q}. - let mut others_verifying_shares = HashMap::new(); + let mut others_verifying_shares = BTreeMap::new(); // Note that in this loop, "i" refers to the other participant whose public verification share // we are computing, and not the current participant. @@ -464,8 +464,8 @@ fn compute_verifying_shares( /// signatures. pub fn part3( round2_secret_package: &round2::SecretPackage, - round1_packages: &HashMap, round1::Package>, - round2_packages: &HashMap, round2::Package>, + round1_packages: &BTreeMap, round1::Package>, + round2_packages: &BTreeMap, round2::Package>, ) -> Result<(KeyPackage, PublicKeyPackage), Error> { if round1_packages.len() != (round2_secret_package.max_signers - 1) as usize { return Err(Error::IncorrectNumberOfPackages); diff --git a/frost-core/src/frost/keys/repairable.rs b/frost-core/src/frost/keys/repairable.rs index 7c56bfb..fb07de9 100644 --- a/frost-core/src/frost/keys/repairable.rs +++ b/frost-core/src/frost/keys/repairable.rs @@ -4,7 +4,7 @@ //! The RTS is used to help a signer (participant) repair their lost share. This is achieved //! using a subset of the other signers know here as `helpers`. -use std::collections::{BTreeSet, HashMap}; +use std::collections::{BTreeMap, BTreeSet}; use crate::{ frost::{compute_lagrange_coefficient, Identifier}, @@ -19,13 +19,13 @@ use super::{generate_coefficients, SecretShare, SigningShare, VerifiableSecretSh /// where `helpers` contains the identifiers of all the helpers (including `helper_i`), and `share_i` /// is the share of `helper_i`. /// -/// Returns a HashMap mapping which value should be sent to which participant. +/// Returns a BTreeMap mapping which value should be sent to which participant. pub fn repair_share_step_1( helpers: &[Identifier], share_i: &SecretShare, rng: &mut R, participant: Identifier, -) -> Result, Scalar>, Error> { +) -> Result, Scalar>, Error> { if helpers.len() < 2 { return Err(Error::InvalidMinSigners); } @@ -46,19 +46,19 @@ pub fn repair_share_step_1( /// Compute the last delta value given the (generated uniformly at random) remaining ones /// since they all must add up to `zeta_i * share_i`. /// -/// Returns a HashMap mapping which value should be sent to which participant. +/// Returns a BTreeMap mapping which value should be sent to which participant. fn compute_last_random_value( helpers: &BTreeSet>, share_i: &SecretShare, random_values: &Vec>, participant: Identifier, -) -> Result, Scalar>, Error> { +) -> Result, Scalar>, Error> { // Calculate Lagrange Coefficient for helper_i let zeta_i = compute_lagrange_coefficient(helpers, Some(participant), share_i.identifier)?; let lhs = zeta_i * share_i.signing_share.0; - let mut out: HashMap, Scalar> = helpers + let mut out: BTreeMap, Scalar> = helpers .iter() .copied() .zip(random_values.iter().copied()) diff --git a/frost-core/src/tests/ciphersuite_generic.rs b/frost-core/src/tests/ciphersuite_generic.rs index 2d140a1..98ef8c7 100644 --- a/frost-core/src/tests/ciphersuite_generic.rs +++ b/frost-core/src/tests/ciphersuite_generic.rs @@ -1,10 +1,7 @@ //! Ciphersuite-generic test functions. #![allow(clippy::type_complexity)] -use std::{ - collections::{BTreeMap, HashMap}, - convert::TryFrom, -}; +use std::{collections::BTreeMap, convert::TryFrom}; use crate::{ frost::{self, Identifier}, @@ -119,8 +116,8 @@ pub fn check_sign_with_dealer( .unwrap(); // Verifies the secret shares from the dealer - let mut key_packages: HashMap, frost::keys::KeyPackage> = - HashMap::new(); + let mut key_packages: BTreeMap, frost::keys::KeyPackage> = + BTreeMap::new(); for (k, v) in shares { let key_package = frost::keys::KeyPackage::try_from(v).unwrap(); @@ -192,12 +189,12 @@ pub fn check_dkg_part1_fails_with_invalid_signers( min_signers: u16, - key_packages: HashMap, frost::keys::KeyPackage>, + key_packages: BTreeMap, frost::keys::KeyPackage>, mut rng: R, pubkey_package: frost::keys::PublicKeyPackage, ) -> Result<(Vec, Signature, VerifyingKey), Error> { - let mut nonces_map: HashMap, frost::round1::SigningNonces> = - HashMap::new(); + let mut nonces_map: BTreeMap, frost::round1::SigningNonces> = + BTreeMap::new(); let mut commitments_map: BTreeMap, frost::round1::SigningCommitments> = BTreeMap::new(); @@ -222,7 +219,7 @@ pub fn check_sign( // This is what the signature aggregator / coordinator needs to do: // - decide what message to sign // - take one (unused) commitment per signing participant - let mut signature_shares = HashMap::new(); + let mut signature_shares = BTreeMap::new(); let message = "message to sign".as_bytes(); let signing_package = frost::SigningPackage::new(commitments_map, message); @@ -305,7 +302,7 @@ fn check_sign_errors( fn check_aggregate_errors( signing_package: frost::SigningPackage, - signature_shares: HashMap, frost::round2::SignatureShare>, + signature_shares: BTreeMap, frost::round2::SignatureShare>, pubkey_package: frost::keys::PublicKeyPackage, ) { check_aggregate_corrupted_share( @@ -322,7 +319,7 @@ fn check_aggregate_errors( fn check_aggregate_corrupted_share( signing_package: frost::SigningPackage, - mut signature_shares: HashMap, frost::round2::SignatureShare>, + mut signature_shares: BTreeMap, frost::round2::SignatureShare>, pubkey_package: frost::keys::PublicKeyPackage, ) { let one = <::Group as Group>::Field::one(); @@ -340,7 +337,7 @@ fn check_aggregate_corrupted_share( /// part can't either since it's caught before by the PublicKeyPackage part. fn check_aggregate_invalid_share_identifier_for_verifying_shares( signing_package: frost::SigningPackage, - mut signature_shares: HashMap, frost::round2::SignatureShare>, + mut signature_shares: BTreeMap, frost::round2::SignatureShare>, pubkey_package: frost::keys::PublicKeyPackage, ) { let invalid_identifier = Identifier::derive("invalid identifier".as_bytes()).unwrap(); @@ -371,18 +368,18 @@ where // Keep track of each participant's round 1 secret package. // In practice each participant will keep its copy; no one // will have all the participant's packages. - let mut round1_secret_packages: HashMap< + let mut round1_secret_packages: BTreeMap< frost::Identifier, frost::keys::dkg::round1::SecretPackage, - > = HashMap::new(); + > = BTreeMap::new(); // Keep track of all round 1 packages sent to the given participant. // This is used to simulate the broadcast; in practice the packages // will be sent through some communication channel. - let mut received_round1_packages: HashMap< + let mut received_round1_packages: BTreeMap< frost::Identifier, - HashMap, frost::keys::dkg::round1::Package>, - > = HashMap::new(); + BTreeMap, frost::keys::dkg::round1::Package>, + > = BTreeMap::new(); // For each participant, perform the first part of the DKG protocol. // In practice, each participant will perform this on their own environments. @@ -397,7 +394,7 @@ where round1_secret_packages.insert(participant_identifier, round1_secret_package); // "Send" the round 1 package to all other participants. In this - // test this is simulated using a HashMap; in practice this will be + // test this is simulated using a BTreeMap; in practice this will be // sent through some communication channel. for receiver_participant_index in 1..=max_signers { if receiver_participant_index == participant_index { @@ -408,7 +405,7 @@ where .expect("should be nonzero"); received_round1_packages .entry(receiver_participant_identifier) - .or_insert_with(HashMap::new) + .or_insert_with(BTreeMap::new) .insert(participant_identifier, round1_package.clone()); } } @@ -420,12 +417,12 @@ where // Keep track of each participant's round 2 secret package. // In practice each participant will keep its copy; no one // will have all the participant's packages. - let mut round2_secret_packages = HashMap::new(); + let mut round2_secret_packages = BTreeMap::new(); // Keep track of all round 2 packages sent to the given participant. // This is used to simulate the broadcast; in practice the packages // will be sent through some communication channel. - let mut received_round2_packages = HashMap::new(); + let mut received_round2_packages = BTreeMap::new(); // For each participant, perform the second part of the DKG protocol. // In practice, each participant will perform this on their own environments. @@ -444,14 +441,14 @@ where round2_secret_packages.insert(participant_identifier, round2_secret_package); // "Send" the round 2 package to all other participants. In this - // test this is simulated using a HashMap; in practice this will be + // test this is simulated using a BTreeMap; in practice this will be // sent through some communication channel. // Note that, in contrast to the previous part, here each other participant // gets its own specific package. for (receiver_identifier, round2_package) in round2_packages { received_round2_packages .entry(receiver_identifier) - .or_insert_with(HashMap::new) + .or_insert_with(BTreeMap::new) .insert(participant_identifier, round2_package); } } @@ -463,11 +460,11 @@ where // Keep track of each participant's long-lived key package. // In practice each participant will keep its copy; no one // will have all the participant's packages. - let mut key_packages = HashMap::new(); + let mut key_packages = BTreeMap::new(); // Map of the verifying key of each participant. // Used by the signing test that follows. - let mut verifying_keys = HashMap::new(); + let mut verifying_keys = BTreeMap::new(); // The group public key, used by the signing test that follows. let mut verifying_key = None; // For each participant, store the set of verifying keys they have computed. @@ -476,7 +473,7 @@ where // If there is not, then all candidates must store their own sets. // The verifying keys are used to verify the signature shares produced // for each signature before being aggregated. - let mut pubkey_packages_by_participant = HashMap::new(); + let mut pubkey_packages_by_participant = BTreeMap::new(); check_part3_different_participants( max_signers, @@ -520,14 +517,14 @@ where /// Check that calling dkg::part3() with distinct sets of participants fail. fn check_part3_different_participants( max_signers: u16, - round2_secret_packages: HashMap, frost::keys::dkg::round2::SecretPackage>, - received_round1_packages: HashMap< + round2_secret_packages: BTreeMap, frost::keys::dkg::round2::SecretPackage>, + received_round1_packages: BTreeMap< Identifier, - HashMap, frost::keys::dkg::round1::Package>, + BTreeMap, frost::keys::dkg::round1::Package>, >, - received_round2_packages: HashMap< + received_round2_packages: BTreeMap< Identifier, - HashMap, frost::keys::dkg::round2::Package>, + BTreeMap, frost::keys::dkg::round2::Package>, >, ) { // For each participant, perform the third part of the DKG protocol. @@ -618,8 +615,8 @@ pub fn check_sign_with_dealer_and_identifiers, frost::keys::KeyPackage> = - HashMap::new(); + let mut key_packages: BTreeMap, frost::keys::KeyPackage> = + BTreeMap::new(); for (k, v) in shares { let key_package = frost::keys::KeyPackage::try_from(v).unwrap(); key_packages.insert(k, key_package); @@ -629,7 +626,7 @@ pub fn check_sign_with_dealer_and_identifiers( round1_secret_package: frost::keys::dkg::round1::SecretPackage, - mut round1_packages: HashMap, frost::keys::dkg::round1::Package>, + mut round1_packages: BTreeMap, frost::keys::dkg::round1::Package>, ) { let one = <::Group as Group>::Field::one(); // Corrupt a PoK @@ -686,16 +683,16 @@ pub fn check_sign_with_missing_identifier, frost::keys::KeyPackage> = - HashMap::new(); + let mut key_packages: BTreeMap, frost::keys::KeyPackage> = + BTreeMap::new(); for (k, v) in shares { let key_package = frost::keys::KeyPackage::try_from(v).unwrap(); key_packages.insert(k, key_package); } - let mut nonces_map: HashMap, frost::round1::SigningNonces> = - HashMap::new(); + let mut nonces_map: BTreeMap, frost::round1::SigningNonces> = + BTreeMap::new(); let mut commitments_map: BTreeMap, frost::round1::SigningCommitments> = BTreeMap::new(); @@ -767,8 +764,8 @@ pub fn check_sign_with_incorrect_commitments, frost::keys::KeyPackage> = - HashMap::new(); + let mut key_packages: BTreeMap, frost::keys::KeyPackage> = + BTreeMap::new(); for (k, v) in shares { let key_package = frost::keys::KeyPackage::try_from(v).unwrap(); diff --git a/frost-core/src/tests/repairable.rs b/frost-core/src/tests/repairable.rs index 1b3837e..a53bb6d 100644 --- a/frost-core/src/tests/repairable.rs +++ b/frost-core/src/tests/repairable.rs @@ -1,6 +1,6 @@ //! Test for Repairable Threshold Scheme -use std::collections::HashMap; +use std::collections::BTreeMap; use debugless_unwrap::DebuglessUnwrap; use rand_core::{CryptoRng, RngCore}; @@ -28,7 +28,7 @@ pub fn check_rts(mut rng: R) { let max_signers = 5; let min_signers = 3; - let (shares, _pubkeys): (HashMap, SecretShare>, PublicKeyPackage) = + let (shares, _pubkeys): (BTreeMap, SecretShare>, PublicKeyPackage) = frost::keys::generate_with_dealer( max_signers, min_signers, @@ -106,7 +106,7 @@ pub fn check_repair_share_step_1(mut rng let max_signers = 5; let min_signers = 3; - let (shares, _pubkeys): (HashMap, SecretShare>, PublicKeyPackage) = + let (shares, _pubkeys): (BTreeMap, SecretShare>, PublicKeyPackage) = frost::keys::generate_with_dealer( max_signers, min_signers, @@ -176,7 +176,7 @@ pub fn check_repair_share_step_3( // Generate shares let max_signers = 5; let min_signers = 3; - let (shares, _pubkeys): (HashMap, SecretShare>, PublicKeyPackage) = + let (shares, _pubkeys): (BTreeMap, SecretShare>, PublicKeyPackage) = frost::keys::generate_with_dealer( max_signers, min_signers, @@ -221,7 +221,7 @@ pub fn check_repair_share_step_1_fails_with_invalid_min_signers< // Generate shares let max_signers = 3; let min_signers = 2; // This is to make sure this test fails at the right point - let (shares, _pubkeys): (HashMap, SecretShare>, PublicKeyPackage) = + let (shares, _pubkeys): (BTreeMap, SecretShare>, PublicKeyPackage) = frost::keys::generate_with_dealer( max_signers, min_signers, diff --git a/frost-core/src/tests/vectors.rs b/frost-core/src/tests/vectors.rs index 4a4f5e2..5c1787a 100644 --- a/frost-core/src/tests/vectors.rs +++ b/frost-core/src/tests/vectors.rs @@ -1,5 +1,5 @@ //! Helper function for testing with test vectors. -use std::collections::{BTreeMap, HashMap}; +use std::collections::BTreeMap; use debugless_unwrap::DebuglessUnwrap; use hex::{self, FromHex}; @@ -14,16 +14,16 @@ use crate::{ pub struct TestVectors { secret_key: SigningKey, verifying_key: VerifyingKey, - key_packages: HashMap, KeyPackage>, + key_packages: BTreeMap, KeyPackage>, message_bytes: Vec, share_polynomial_coefficients: Vec>, - hiding_nonces_randomness: HashMap, Vec>, - binding_nonces_randomness: HashMap, Vec>, - signer_nonces: HashMap, SigningNonces>, + hiding_nonces_randomness: BTreeMap, Vec>, + binding_nonces_randomness: BTreeMap, Vec>, + signer_nonces: BTreeMap, SigningNonces>, signer_commitments: BTreeMap, SigningCommitments>, - binding_factor_inputs: HashMap, Vec>, - binding_factors: HashMap, BindingFactor>, - signature_shares: HashMap, SignatureShare>, + binding_factor_inputs: BTreeMap, Vec>, + binding_factors: BTreeMap, BindingFactor>, + signature_shares: BTreeMap, SignatureShare>, signature_bytes: Vec, } @@ -50,7 +50,7 @@ pub fn parse_test_vectors(json_vectors: &Value) -> TestVectors, KeyPackage> = HashMap::new(); + let mut key_packages: BTreeMap, KeyPackage> = BTreeMap::new(); let possible_participants = json_vectors["inputs"].as_object().unwrap()["participant_shares"] .as_array() @@ -83,12 +83,12 @@ pub fn parse_test_vectors(json_vectors: &Value) -> TestVectors, Vec> = HashMap::new(); - let mut binding_nonces_randomness: HashMap, Vec> = HashMap::new(); - let mut signer_nonces: HashMap, SigningNonces> = HashMap::new(); + let mut hiding_nonces_randomness: BTreeMap, Vec> = BTreeMap::new(); + let mut binding_nonces_randomness: BTreeMap, Vec> = BTreeMap::new(); + let mut signer_nonces: BTreeMap, SigningNonces> = BTreeMap::new(); let mut signer_commitments: BTreeMap, SigningCommitments> = BTreeMap::new(); - let mut binding_factor_inputs: HashMap, Vec> = HashMap::new(); - let mut binding_factors: HashMap, BindingFactor> = HashMap::new(); + let mut binding_factor_inputs: BTreeMap, Vec> = BTreeMap::new(); + let mut binding_factors: BTreeMap, BindingFactor> = BTreeMap::new(); for signer in round_one_outputs["outputs"].as_array().unwrap().iter() { let i = signer["identifier"].as_u64().unwrap() as u16; @@ -132,7 +132,7 @@ pub fn parse_test_vectors(json_vectors: &Value) -> TestVectors, SignatureShare> = HashMap::new(); + let mut signature_shares: BTreeMap, SignatureShare> = BTreeMap::new(); for signer in round_two_outputs["outputs"].as_array().unwrap().iter() { let i = signer["identifier"].as_u64().unwrap() as u16; @@ -201,7 +201,7 @@ pub fn check_sign_with_test_vectors(json_vectors: &Value) { &default_identifiers(max_signers as u16), ) .unwrap(); - let secret_shares: HashMap<_, _> = secret_shares + let secret_shares: BTreeMap<_, _> = secret_shares .iter() .map(|share| (share.identifier, share)) .collect(); @@ -275,7 +275,7 @@ pub fn check_sign_with_test_vectors(json_vectors: &Value) { assert_eq!(*binding_factor, binding_factors[identifier]); } - let mut our_signature_shares = HashMap::new(); + let mut our_signature_shares = BTreeMap::new(); // Each participant generates their signature share for identifier in signer_nonces.keys() { diff --git a/frost-ed25519/README.md b/frost-ed25519/README.md index 596ebe3..6560d5b 100644 --- a/frost-ed25519/README.md +++ b/frost-ed25519/README.md @@ -12,7 +12,7 @@ scenario in a single thread and it abstracts away any communication between peer # // ANCHOR: tkg_gen use frost_ed25519 as frost; use rand::thread_rng; -use std::collections::{BTreeMap, HashMap}; +use std::collections::BTreeMap; let mut rng = thread_rng(); let max_signers = 5; @@ -25,10 +25,10 @@ let (shares, pubkey_package) = frost::keys::generate_with_dealer( )?; # // ANCHOR_END: tkg_gen -// Verifies the secret shares from the dealer and store them in a HashMap. +// Verifies the secret shares from the dealer and store them in a BTreeMap. // In practice, the KeyPackages must be sent to its respective participants // through a confidential and authenticated channel. -let mut key_packages: HashMap<_, _> = HashMap::new(); +let mut key_packages: BTreeMap<_, _> = BTreeMap::new(); for (identifier, secret_share) in shares { # // ANCHOR: tkg_verify @@ -37,7 +37,7 @@ for (identifier, secret_share) in shares { key_packages.insert(identifier, key_package); } -let mut nonces_map = HashMap::new(); +let mut nonces_map = BTreeMap::new(); let mut commitments_map = BTreeMap::new(); //////////////////////////////////////////////////////////////////////////// @@ -67,7 +67,7 @@ for participant_index in 1..(min_signers as u16 + 1) { // This is what the signature aggregator / coordinator needs to do: // - decide what message to sign // - take one (unused) commitment per signing participant -let mut signature_shares = HashMap::new(); +let mut signature_shares = BTreeMap::new(); # // ANCHOR: round2_package let message = "message to sign".as_bytes(); # // In practice, the SigningPackage must be sent to all participants diff --git a/frost-ed25519/dkg.md b/frost-ed25519/dkg.md index 3c2119b..797422c 100644 --- a/frost-ed25519/dkg.md +++ b/frost-ed25519/dkg.md @@ -27,7 +27,7 @@ they can proceed to sign messages with FROST. ```rust # // ANCHOR: dkg_import use rand::thread_rng; -use std::collections::HashMap; +use std::collections::BTreeMap; use frost_ed25519 as frost; @@ -44,12 +44,12 @@ let min_signers = 3; // Keep track of each participant's round 1 secret package. // In practice each participant will keep its copy; no one // will have all the participant's packages. -let mut round1_secret_packages = HashMap::new(); +let mut round1_secret_packages = BTreeMap::new(); // Keep track of all round 1 packages sent to the given participant. // This is used to simulate the broadcast; in practice the packages // will be sent through some communication channel. -let mut received_round1_packages = HashMap::new(); +let mut received_round1_packages = BTreeMap::new(); // For each participant, perform the first part of the DKG protocol. // In practice, each participant will perform this on their own environments. @@ -69,7 +69,7 @@ for participant_index in 1..=max_signers { round1_secret_packages.insert(participant_identifier, round1_secret_package); // "Send" the round 1 package to all other participants. In this - // test this is simulated using a HashMap; in practice this will be + // test this is simulated using a BTreeMap; in practice this will be // sent through some communication channel. for receiver_participant_index in 1..=max_signers { if receiver_participant_index == participant_index { @@ -80,7 +80,7 @@ for participant_index in 1..=max_signers { .expect("should be nonzero"); received_round1_packages .entry(receiver_participant_identifier) - .or_insert_with(HashMap::new) + .or_insert_with(BTreeMap::new) .insert(participant_identifier, round1_package.clone()); } } @@ -92,12 +92,12 @@ for participant_index in 1..=max_signers { // Keep track of each participant's round 2 secret package. // In practice each participant will keep its copy; no one // will have all the participant's packages. -let mut round2_secret_packages = HashMap::new(); +let mut round2_secret_packages = BTreeMap::new(); // Keep track of all round 2 packages sent to the given participant. // This is used to simulate the broadcast; in practice the packages // will be sent through some communication channel. -let mut received_round2_packages = HashMap::new(); +let mut received_round2_packages = BTreeMap::new(); // For each participant, perform the second part of the DKG protocol. // In practice, each participant will perform this on their own environments. @@ -117,14 +117,14 @@ for participant_index in 1..=max_signers { round2_secret_packages.insert(participant_identifier, round2_secret_package); // "Send" the round 2 package to all other participants. In this - // test this is simulated using a HashMap; in practice this will be + // test this is simulated using a BTreeMap; in practice this will be // sent through some communication channel. // Note that, in contrast to the previous part, here each other participant // gets its own specific package. for (receiver_identifier, round2_package) in round2_packages { received_round2_packages .entry(receiver_identifier) - .or_insert_with(HashMap::new) + .or_insert_with(BTreeMap::new) .insert(participant_identifier, round2_package); } } @@ -136,13 +136,13 @@ for participant_index in 1..=max_signers { // Keep track of each participant's long-lived key package. // In practice each participant will keep its copy; no one // will have all the participant's packages. -let mut key_packages = HashMap::new(); +let mut key_packages = BTreeMap::new(); // Keep track of each participant's public key package. // In practice, if there is a Coordinator, only they need to store the set. // If there is not, then all candidates must store their own sets. // All participants will have the same exact public key package. -let mut pubkey_packages = HashMap::new(); +let mut pubkey_packages = BTreeMap::new(); // For each participant, perform the third part of the DKG protocol. // In practice, each participant will perform this on their own environments. diff --git a/frost-ed25519/src/keys/dkg.rs b/frost-ed25519/src/keys/dkg.rs index 304565b..0824775 100644 --- a/frost-ed25519/src/keys/dkg.rs +++ b/frost-ed25519/src/keys/dkg.rs @@ -64,8 +64,8 @@ pub fn part1( /// must be sent to other participants. pub fn part2( secret_package: round1::SecretPackage, - round1_packages: &HashMap, -) -> Result<(round2::SecretPackage, HashMap), Error> { + round1_packages: &BTreeMap, +) -> Result<(round2::SecretPackage, BTreeMap), Error> { frost::keys::dkg::part2(secret_package, round1_packages) } @@ -80,8 +80,8 @@ pub fn part2( /// signatures. pub fn part3( round2_secret_package: &round2::SecretPackage, - round1_packages: &HashMap, - round2_packages: &HashMap, + round1_packages: &BTreeMap, + round2_packages: &BTreeMap, ) -> Result<(KeyPackage, PublicKeyPackage), Error> { frost::keys::dkg::part3(round2_secret_package, round1_packages, round2_packages) } diff --git a/frost-ed25519/src/keys/repairable.rs b/frost-ed25519/src/keys/repairable.rs index bed454b..deb5a83 100644 --- a/frost-ed25519/src/keys/repairable.rs +++ b/frost-ed25519/src/keys/repairable.rs @@ -4,7 +4,7 @@ //! The RTS is used to help a signer (participant) repair their lost share. This is achieved //! using a subset of the other signers know here as `helpers`. -use std::collections::HashMap; +use std::collections::BTreeMap; // This is imported separately to make `gencode` work. // (if it were below, the position of the import would vary between ciphersuites @@ -20,13 +20,13 @@ use super::{SecretShare, VerifiableSecretSharingCommitment}; /// where `helpers` contains the identifiers of all the helpers (including `helper_i`), and `share_i` /// is the share of `helper_i`. /// -/// Returns a HashMap mapping which value should be sent to which participant. +/// Returns a BTreeMap mapping which value should be sent to which participant. pub fn repair_share_step_1( helpers: &[Identifier], share_i: &SecretShare, rng: &mut R, participant: Identifier, -) -> Result, Error> { +) -> Result, Error> { frost::keys::repairable::repair_share_step_1(helpers, share_i, rng, participant) } diff --git a/frost-ed25519/src/lib.rs b/frost-ed25519/src/lib.rs index aae0855..4de4640 100644 --- a/frost-ed25519/src/lib.rs +++ b/frost-ed25519/src/lib.rs @@ -5,7 +5,7 @@ #![doc = include_str!("../README.md")] #![doc = document_features::document_features!()] -use std::collections::HashMap; +use std::collections::BTreeMap; use curve25519_dalek::{ constants::ED25519_BASEPOINT_POINT, @@ -216,7 +216,7 @@ pub type Identifier = frost::Identifier; /// FROST(Ed25519, SHA-512) keys, key generation, key shares. pub mod keys { - use std::collections::HashMap; + use std::collections::BTreeMap; use super::*; @@ -230,7 +230,7 @@ pub mod keys { min_signers: u16, identifiers: IdentifierList, mut rng: RNG, - ) -> Result<(HashMap, PublicKeyPackage), Error> { + ) -> Result<(BTreeMap, PublicKeyPackage), Error> { frost::keys::generate_with_dealer(max_signers, min_signers, identifiers, &mut rng) } @@ -246,7 +246,7 @@ pub mod keys { min_signers: u16, identifiers: IdentifierList, rng: &mut R, - ) -> Result<(HashMap, PublicKeyPackage), Error> { + ) -> Result<(BTreeMap, PublicKeyPackage), Error> { frost::keys::split(secret, max_signers, min_signers, identifiers, rng) } @@ -395,7 +395,7 @@ pub type Signature = frost_core::Signature; /// service attack due to publishing an invalid signature. pub fn aggregate( signing_package: &SigningPackage, - signature_shares: &HashMap, + signature_shares: &BTreeMap, pubkeys: &keys::PublicKeyPackage, ) -> Result { frost::aggregate(signing_package, signature_shares, pubkeys) diff --git a/frost-ed25519/tests/helpers/samples.rs b/frost-ed25519/tests/helpers/samples.rs index 621e659..35ad8fb 100644 --- a/frost-ed25519/tests/helpers/samples.rs +++ b/frost-ed25519/tests/helpers/samples.rs @@ -1,6 +1,6 @@ //! Generate sample, fixed instances of structs for testing. -use std::collections::{BTreeMap, HashMap}; +use std::collections::BTreeMap; use frost_core::{Ciphersuite, Element, Group, Scalar}; use frost_ed25519::{ @@ -90,7 +90,7 @@ pub fn public_key_package() -> PublicKeyPackage { let verifying_share = VerifyingShare::deserialize(serialized_element).unwrap(); let serialized_element = ::Group::serialize(&element1()); let verifying_key = VerifyingKey::deserialize(serialized_element).unwrap(); - let verifying_shares = HashMap::from([(identifier, verifying_share)]); + let verifying_shares = BTreeMap::from([(identifier, verifying_share)]); PublicKeyPackage::new(verifying_shares, verifying_key) } diff --git a/frost-ed448/README.md b/frost-ed448/README.md index 4b5ae86..74d8fa6 100644 --- a/frost-ed448/README.md +++ b/frost-ed448/README.md @@ -12,7 +12,7 @@ scenario in a single thread and it abstracts away any communication between peer # // ANCHOR: tkg_gen use frost_ed448 as frost; use rand::thread_rng; -use std::collections::{BTreeMap, HashMap}; +use std::collections::BTreeMap; let mut rng = thread_rng(); let max_signers = 5; @@ -25,10 +25,10 @@ let (shares, pubkey_package) = frost::keys::generate_with_dealer( )?; # // ANCHOR_END: tkg_gen -// Verifies the secret shares from the dealer and store them in a HashMap. +// Verifies the secret shares from the dealer and store them in a BTreeMap. // In practice, the KeyPackages must be sent to its respective participants // through a confidential and authenticated channel. -let mut key_packages: HashMap<_, _> = HashMap::new(); +let mut key_packages: BTreeMap<_, _> = BTreeMap::new(); for (identifier, secret_share) in shares { # // ANCHOR: tkg_verify @@ -37,7 +37,7 @@ for (identifier, secret_share) in shares { key_packages.insert(identifier, key_package); } -let mut nonces_map = HashMap::new(); +let mut nonces_map = BTreeMap::new(); let mut commitments_map = BTreeMap::new(); //////////////////////////////////////////////////////////////////////////// @@ -67,7 +67,7 @@ for participant_index in 1..(min_signers as u16 + 1) { // This is what the signature aggregator / coordinator needs to do: // - decide what message to sign // - take one (unused) commitment per signing participant -let mut signature_shares = HashMap::new(); +let mut signature_shares = BTreeMap::new(); # // ANCHOR: round2_package let message = "message to sign".as_bytes(); # // In practice, the SigningPackage must be sent to all participants diff --git a/frost-ed448/dkg.md b/frost-ed448/dkg.md index 05fb701..2d60b14 100644 --- a/frost-ed448/dkg.md +++ b/frost-ed448/dkg.md @@ -27,7 +27,7 @@ they can proceed to sign messages with FROST. ```rust # // ANCHOR: dkg_import use rand::thread_rng; -use std::collections::HashMap; +use std::collections::BTreeMap; use frost_ed448 as frost; @@ -44,12 +44,12 @@ let min_signers = 3; // Keep track of each participant's round 1 secret package. // In practice each participant will keep its copy; no one // will have all the participant's packages. -let mut round1_secret_packages = HashMap::new(); +let mut round1_secret_packages = BTreeMap::new(); // Keep track of all round 1 packages sent to the given participant. // This is used to simulate the broadcast; in practice the packages // will be sent through some communication channel. -let mut received_round1_packages = HashMap::new(); +let mut received_round1_packages = BTreeMap::new(); // For each participant, perform the first part of the DKG protocol. // In practice, each participant will perform this on their own environments. @@ -69,7 +69,7 @@ for participant_index in 1..=max_signers { round1_secret_packages.insert(participant_identifier, round1_secret_package); // "Send" the round 1 package to all other participants. In this - // test this is simulated using a HashMap; in practice this will be + // test this is simulated using a BTreeMap; in practice this will be // sent through some communication channel. for receiver_participant_index in 1..=max_signers { if receiver_participant_index == participant_index { @@ -80,7 +80,7 @@ for participant_index in 1..=max_signers { .expect("should be nonzero"); received_round1_packages .entry(receiver_participant_identifier) - .or_insert_with(HashMap::new) + .or_insert_with(BTreeMap::new) .insert(participant_identifier, round1_package.clone()); } } @@ -92,12 +92,12 @@ for participant_index in 1..=max_signers { // Keep track of each participant's round 2 secret package. // In practice each participant will keep its copy; no one // will have all the participant's packages. -let mut round2_secret_packages = HashMap::new(); +let mut round2_secret_packages = BTreeMap::new(); // Keep track of all round 2 packages sent to the given participant. // This is used to simulate the broadcast; in practice the packages // will be sent through some communication channel. -let mut received_round2_packages = HashMap::new(); +let mut received_round2_packages = BTreeMap::new(); // For each participant, perform the second part of the DKG protocol. // In practice, each participant will perform this on their own environments. @@ -117,14 +117,14 @@ for participant_index in 1..=max_signers { round2_secret_packages.insert(participant_identifier, round2_secret_package); // "Send" the round 2 package to all other participants. In this - // test this is simulated using a HashMap; in practice this will be + // test this is simulated using a BTreeMap; in practice this will be // sent through some communication channel. // Note that, in contrast to the previous part, here each other participant // gets its own specific package. for (receiver_identifier, round2_package) in round2_packages { received_round2_packages .entry(receiver_identifier) - .or_insert_with(HashMap::new) + .or_insert_with(BTreeMap::new) .insert(participant_identifier, round2_package); } } @@ -136,13 +136,13 @@ for participant_index in 1..=max_signers { // Keep track of each participant's long-lived key package. // In practice each participant will keep its copy; no one // will have all the participant's packages. -let mut key_packages = HashMap::new(); +let mut key_packages = BTreeMap::new(); // Keep track of each participant's public key package. // In practice, if there is a Coordinator, only they need to store the set. // If there is not, then all candidates must store their own sets. // All participants will have the same exact public key package. -let mut pubkey_packages = HashMap::new(); +let mut pubkey_packages = BTreeMap::new(); // For each participant, perform the third part of the DKG protocol. // In practice, each participant will perform this on their own environments. diff --git a/frost-ed448/src/keys/dkg.rs b/frost-ed448/src/keys/dkg.rs index 304565b..0824775 100644 --- a/frost-ed448/src/keys/dkg.rs +++ b/frost-ed448/src/keys/dkg.rs @@ -64,8 +64,8 @@ pub fn part1( /// must be sent to other participants. pub fn part2( secret_package: round1::SecretPackage, - round1_packages: &HashMap, -) -> Result<(round2::SecretPackage, HashMap), Error> { + round1_packages: &BTreeMap, +) -> Result<(round2::SecretPackage, BTreeMap), Error> { frost::keys::dkg::part2(secret_package, round1_packages) } @@ -80,8 +80,8 @@ pub fn part2( /// signatures. pub fn part3( round2_secret_package: &round2::SecretPackage, - round1_packages: &HashMap, - round2_packages: &HashMap, + round1_packages: &BTreeMap, + round2_packages: &BTreeMap, ) -> Result<(KeyPackage, PublicKeyPackage), Error> { frost::keys::dkg::part3(round2_secret_package, round1_packages, round2_packages) } diff --git a/frost-ed448/src/keys/repairable.rs b/frost-ed448/src/keys/repairable.rs index 16b307c..b44709f 100644 --- a/frost-ed448/src/keys/repairable.rs +++ b/frost-ed448/src/keys/repairable.rs @@ -4,7 +4,7 @@ //! The RTS is used to help a signer (participant) repair their lost share. This is achieved //! using a subset of the other signers know here as `helpers`. -use std::collections::HashMap; +use std::collections::BTreeMap; // This is imported separately to make `gencode` work. // (if it were below, the position of the import would vary between ciphersuites @@ -20,13 +20,13 @@ use super::{SecretShare, VerifiableSecretSharingCommitment}; /// where `helpers` contains the identifiers of all the helpers (including `helper_i`), and `share_i` /// is the share of `helper_i`. /// -/// Returns a HashMap mapping which value should be sent to which participant. +/// Returns a BTreeMap mapping which value should be sent to which participant. pub fn repair_share_step_1( helpers: &[Identifier], share_i: &SecretShare, rng: &mut R, participant: Identifier, -) -> Result, Error> { +) -> Result, Error> { frost::keys::repairable::repair_share_step_1(helpers, share_i, rng, participant) } diff --git a/frost-ed448/src/lib.rs b/frost-ed448/src/lib.rs index eddec87..ccd1d45 100644 --- a/frost-ed448/src/lib.rs +++ b/frost-ed448/src/lib.rs @@ -5,7 +5,7 @@ #![doc = include_str!("../README.md")] #![doc = document_features::document_features!()] -use std::collections::HashMap; +use std::collections::BTreeMap; use ed448_goldilocks::{ curve::{edwards::CompressedEdwardsY, ExtendedPoint}, @@ -212,7 +212,7 @@ pub type Identifier = frost::Identifier; /// FROST(Ed448, SHAKE256) keys, key generation, key shares. pub mod keys { use super::*; - use std::collections::HashMap; + use std::collections::BTreeMap; /// The identifier list to use when generating key shares. pub type IdentifierList<'a> = frost::keys::IdentifierList<'a, E>; @@ -224,7 +224,7 @@ pub mod keys { min_signers: u16, identifiers: IdentifierList, mut rng: RNG, - ) -> Result<(HashMap, PublicKeyPackage), Error> { + ) -> Result<(BTreeMap, PublicKeyPackage), Error> { frost::keys::generate_with_dealer(max_signers, min_signers, identifiers, &mut rng) } @@ -240,7 +240,7 @@ pub mod keys { min_signers: u16, identifiers: IdentifierList, rng: &mut R, - ) -> Result<(HashMap, PublicKeyPackage), Error> { + ) -> Result<(BTreeMap, PublicKeyPackage), Error> { frost::keys::split(secret, max_signers, min_signers, identifiers, rng) } @@ -389,7 +389,7 @@ pub type Signature = frost_core::Signature; /// service attack due to publishing an invalid signature. pub fn aggregate( signing_package: &SigningPackage, - signature_shares: &HashMap, + signature_shares: &BTreeMap, pubkeys: &keys::PublicKeyPackage, ) -> Result { frost::aggregate(signing_package, signature_shares, pubkeys) diff --git a/frost-ed448/tests/helpers/samples.rs b/frost-ed448/tests/helpers/samples.rs index 88bbbb2..9e609b8 100644 --- a/frost-ed448/tests/helpers/samples.rs +++ b/frost-ed448/tests/helpers/samples.rs @@ -1,6 +1,6 @@ //! Generate sample, fixed instances of structs for testing. -use std::collections::{BTreeMap, HashMap}; +use std::collections::BTreeMap; use frost_core::{Ciphersuite, Element, Group, Scalar}; use frost_ed448::{ @@ -90,7 +90,7 @@ pub fn public_key_package() -> PublicKeyPackage { let verifying_share = VerifyingShare::deserialize(serialized_element).unwrap(); let serialized_element = ::Group::serialize(&element1()); let verifying_key = VerifyingKey::deserialize(serialized_element).unwrap(); - let verifying_shares = HashMap::from([(identifier, verifying_share)]); + let verifying_shares = BTreeMap::from([(identifier, verifying_share)]); PublicKeyPackage::new(verifying_shares, verifying_key) } diff --git a/frost-p256/README.md b/frost-p256/README.md index d5830fb..7f0a20f 100644 --- a/frost-p256/README.md +++ b/frost-p256/README.md @@ -12,7 +12,7 @@ scenario in a single thread and it abstracts away any communication between peer # // ANCHOR: tkg_gen use frost_p256 as frost; use rand::thread_rng; -use std::collections::{BTreeMap, HashMap}; +use std::collections::BTreeMap; let mut rng = thread_rng(); let max_signers = 5; @@ -25,10 +25,10 @@ let (shares, pubkey_package) = frost::keys::generate_with_dealer( )?; # // ANCHOR_END: tkg_gen -// Verifies the secret shares from the dealer and store them in a HashMap. +// Verifies the secret shares from the dealer and store them in a BTreeMap. // In practice, the KeyPackages must be sent to its respective participants // through a confidential and authenticated channel. -let mut key_packages: HashMap<_, _> = HashMap::new(); +let mut key_packages: BTreeMap<_, _> = BTreeMap::new(); for (identifier, secret_share) in shares { # // ANCHOR: tkg_verify @@ -37,7 +37,7 @@ for (identifier, secret_share) in shares { key_packages.insert(identifier, key_package); } -let mut nonces_map = HashMap::new(); +let mut nonces_map = BTreeMap::new(); let mut commitments_map = BTreeMap::new(); //////////////////////////////////////////////////////////////////////////// @@ -67,7 +67,7 @@ for participant_index in 1..(min_signers as u16 + 1) { // This is what the signature aggregator / coordinator needs to do: // - decide what message to sign // - take one (unused) commitment per signing participant -let mut signature_shares = HashMap::new(); +let mut signature_shares = BTreeMap::new(); # // ANCHOR: round2_package let message = "message to sign".as_bytes(); # // In practice, the SigningPackage must be sent to all participants diff --git a/frost-p256/dkg.md b/frost-p256/dkg.md index 9993cbb..9a3c432 100644 --- a/frost-p256/dkg.md +++ b/frost-p256/dkg.md @@ -27,7 +27,7 @@ they can proceed to sign messages with FROST. ```rust # // ANCHOR: dkg_import use rand::thread_rng; -use std::collections::HashMap; +use std::collections::BTreeMap; use frost_p256 as frost; @@ -44,12 +44,12 @@ let min_signers = 3; // Keep track of each participant's round 1 secret package. // In practice each participant will keep its copy; no one // will have all the participant's packages. -let mut round1_secret_packages = HashMap::new(); +let mut round1_secret_packages = BTreeMap::new(); // Keep track of all round 1 packages sent to the given participant. // This is used to simulate the broadcast; in practice the packages // will be sent through some communication channel. -let mut received_round1_packages = HashMap::new(); +let mut received_round1_packages = BTreeMap::new(); // For each participant, perform the first part of the DKG protocol. // In practice, each participant will perform this on their own environments. @@ -69,7 +69,7 @@ for participant_index in 1..=max_signers { round1_secret_packages.insert(participant_identifier, round1_secret_package); // "Send" the round 1 package to all other participants. In this - // test this is simulated using a HashMap; in practice this will be + // test this is simulated using a BTreeMap; in practice this will be // sent through some communication channel. for receiver_participant_index in 1..=max_signers { if receiver_participant_index == participant_index { @@ -80,7 +80,7 @@ for participant_index in 1..=max_signers { .expect("should be nonzero"); received_round1_packages .entry(receiver_participant_identifier) - .or_insert_with(HashMap::new) + .or_insert_with(BTreeMap::new) .insert(participant_identifier, round1_package.clone()); } } @@ -92,12 +92,12 @@ for participant_index in 1..=max_signers { // Keep track of each participant's round 2 secret package. // In practice each participant will keep its copy; no one // will have all the participant's packages. -let mut round2_secret_packages = HashMap::new(); +let mut round2_secret_packages = BTreeMap::new(); // Keep track of all round 2 packages sent to the given participant. // This is used to simulate the broadcast; in practice the packages // will be sent through some communication channel. -let mut received_round2_packages = HashMap::new(); +let mut received_round2_packages = BTreeMap::new(); // For each participant, perform the second part of the DKG protocol. // In practice, each participant will perform this on their own environments. @@ -117,14 +117,14 @@ for participant_index in 1..=max_signers { round2_secret_packages.insert(participant_identifier, round2_secret_package); // "Send" the round 2 package to all other participants. In this - // test this is simulated using a HashMap; in practice this will be + // test this is simulated using a BTreeMap; in practice this will be // sent through some communication channel. // Note that, in contrast to the previous part, here each other participant // gets its own specific package. for (receiver_identifier, round2_package) in round2_packages { received_round2_packages .entry(receiver_identifier) - .or_insert_with(HashMap::new) + .or_insert_with(BTreeMap::new) .insert(participant_identifier, round2_package); } } @@ -136,13 +136,13 @@ for participant_index in 1..=max_signers { // Keep track of each participant's long-lived key package. // In practice each participant will keep its copy; no one // will have all the participant's packages. -let mut key_packages = HashMap::new(); +let mut key_packages = BTreeMap::new(); // Keep track of each participant's public key package. // In practice, if there is a Coordinator, only they need to store the set. // If there is not, then all candidates must store their own sets. // All participants will have the same exact public key package. -let mut pubkey_packages = HashMap::new(); +let mut pubkey_packages = BTreeMap::new(); // For each participant, perform the third part of the DKG protocol. // In practice, each participant will perform this on their own environments. diff --git a/frost-p256/src/keys/dkg.rs b/frost-p256/src/keys/dkg.rs index 7d5480f..ae7dec6 100644 --- a/frost-p256/src/keys/dkg.rs +++ b/frost-p256/src/keys/dkg.rs @@ -64,8 +64,8 @@ pub fn part1( /// must be sent to other participants. pub fn part2( secret_package: round1::SecretPackage, - round1_packages: &HashMap, -) -> Result<(round2::SecretPackage, HashMap), Error> { + round1_packages: &BTreeMap, +) -> Result<(round2::SecretPackage, BTreeMap), Error> { frost::keys::dkg::part2(secret_package, round1_packages) } @@ -80,8 +80,8 @@ pub fn part2( /// signatures. pub fn part3( round2_secret_package: &round2::SecretPackage, - round1_packages: &HashMap, - round2_packages: &HashMap, + round1_packages: &BTreeMap, + round2_packages: &BTreeMap, ) -> Result<(KeyPackage, PublicKeyPackage), Error> { frost::keys::dkg::part3(round2_secret_package, round1_packages, round2_packages) } diff --git a/frost-p256/src/keys/repairable.rs b/frost-p256/src/keys/repairable.rs index 749d628..310a26f 100644 --- a/frost-p256/src/keys/repairable.rs +++ b/frost-p256/src/keys/repairable.rs @@ -4,7 +4,7 @@ //! The RTS is used to help a signer (participant) repair their lost share. This is achieved //! using a subset of the other signers know here as `helpers`. -use std::collections::HashMap; +use std::collections::BTreeMap; // This is imported separately to make `gencode` work. // (if it were below, the position of the import would vary between ciphersuites @@ -20,13 +20,13 @@ use super::{SecretShare, VerifiableSecretSharingCommitment}; /// where `helpers` contains the identifiers of all the helpers (including `helper_i`), and `share_i` /// is the share of `helper_i`. /// -/// Returns a HashMap mapping which value should be sent to which participant. +/// Returns a BTreeMap mapping which value should be sent to which participant. pub fn repair_share_step_1( helpers: &[Identifier], share_i: &SecretShare, rng: &mut R, participant: Identifier, -) -> Result, Error> { +) -> Result, Error> { frost::keys::repairable::repair_share_step_1(helpers, share_i, rng, participant) } diff --git a/frost-p256/src/lib.rs b/frost-p256/src/lib.rs index dc9d382..85c4742 100644 --- a/frost-p256/src/lib.rs +++ b/frost-p256/src/lib.rs @@ -5,7 +5,7 @@ #![doc = include_str!("../README.md")] #![doc = document_features::document_features!()] -use std::collections::HashMap; +use std::collections::BTreeMap; use p256::{ elliptic_curve::{ @@ -242,7 +242,7 @@ type P = P256Sha256; pub type Identifier = frost::Identifier

; /// FROST(P-256, SHA-256) keys, key generation, key shares. pub mod keys { - use std::collections::HashMap; + use std::collections::BTreeMap; use super::*; @@ -256,7 +256,7 @@ pub mod keys { min_signers: u16, identifiers: IdentifierList, mut rng: RNG, - ) -> Result<(HashMap, PublicKeyPackage), Error> { + ) -> Result<(BTreeMap, PublicKeyPackage), Error> { frost::keys::generate_with_dealer(max_signers, min_signers, identifiers, &mut rng) } @@ -272,7 +272,7 @@ pub mod keys { min_signers: u16, identifiers: IdentifierList, rng: &mut R, - ) -> Result<(HashMap, PublicKeyPackage), Error> { + ) -> Result<(BTreeMap, PublicKeyPackage), Error> { frost::keys::split(secret, max_signers, min_signers, identifiers, rng) } @@ -421,7 +421,7 @@ pub type Signature = frost_core::Signature

; /// service attack due to publishing an invalid signature. pub fn aggregate( signing_package: &SigningPackage, - signature_shares: &HashMap, + signature_shares: &BTreeMap, pubkeys: &keys::PublicKeyPackage, ) -> Result { frost::aggregate(signing_package, signature_shares, pubkeys) diff --git a/frost-p256/tests/helpers/samples.rs b/frost-p256/tests/helpers/samples.rs index 67c1a97..c55d0a0 100644 --- a/frost-p256/tests/helpers/samples.rs +++ b/frost-p256/tests/helpers/samples.rs @@ -1,6 +1,6 @@ //! Generate sample, fixed instances of structs for testing. -use std::collections::{BTreeMap, HashMap}; +use std::collections::BTreeMap; use frost_core::{Ciphersuite, Element, Group, Scalar}; use frost_p256::{ @@ -90,7 +90,7 @@ pub fn public_key_package() -> PublicKeyPackage { let verifying_share = VerifyingShare::deserialize(serialized_element).unwrap(); let serialized_element = ::Group::serialize(&element1()); let verifying_key = VerifyingKey::deserialize(serialized_element).unwrap(); - let verifying_shares = HashMap::from([(identifier, verifying_share)]); + let verifying_shares = BTreeMap::from([(identifier, verifying_share)]); PublicKeyPackage::new(verifying_shares, verifying_key) } diff --git a/frost-rerandomized/src/lib.rs b/frost-rerandomized/src/lib.rs index 3fec51c..1a8276b 100644 --- a/frost-rerandomized/src/lib.rs +++ b/frost-rerandomized/src/lib.rs @@ -14,7 +14,7 @@ #[cfg(any(test, feature = "test-impl"))] pub mod tests; -use std::collections::HashMap; +use std::collections::BTreeMap; use derive_getters::Getters; pub use frost_core; @@ -132,7 +132,7 @@ pub fn sign( /// See [`frost::aggregate`] for documentation on the other parameters. pub fn aggregate( signing_package: &frost::SigningPackage, - signature_shares: &HashMap, frost::round2::SignatureShare>, + signature_shares: &BTreeMap, frost::round2::SignatureShare>, pubkeys: &frost::keys::PublicKeyPackage, randomized_params: &RandomizedParams, ) -> Result, Error> diff --git a/frost-rerandomized/src/tests.rs b/frost-rerandomized/src/tests.rs index 1029101..d29fe90 100644 --- a/frost-rerandomized/src/tests.rs +++ b/frost-rerandomized/src/tests.rs @@ -1,6 +1,6 @@ //! Ciphersuite-generic test functions for re-randomized FROST. -use std::collections::{BTreeMap, HashMap}; +use std::collections::BTreeMap; use crate::{frost_core::frost, frost_core::Ciphersuite, RandomizedParams, Randomizer}; use frost_core::{Signature, VerifyingKey}; @@ -27,14 +27,15 @@ pub fn check_randomized_sign_with_dealer .unwrap(); // Verifies the secret shares from the dealer - let mut key_packages: HashMap, frost::keys::KeyPackage> = - HashMap::new(); + let mut key_packages: BTreeMap, frost::keys::KeyPackage> = + BTreeMap::new(); for (k, v) in shares { key_packages.insert(k, frost::keys::KeyPackage::try_from(v).unwrap()); } - let mut nonces: HashMap, frost::round1::SigningNonces> = HashMap::new(); + let mut nonces: BTreeMap, frost::round1::SigningNonces> = + BTreeMap::new(); let mut commitments: BTreeMap, frost::round1::SigningCommitments> = BTreeMap::new(); @@ -64,8 +65,8 @@ pub fn check_randomized_sign_with_dealer // This is what the signature aggregator / coordinator needs to do: // - decide what message to sign // - take one (unused) commitment per signing participant - let mut signature_shares: HashMap, frost::round2::SignatureShare<_>> = - HashMap::new(); + let mut signature_shares: BTreeMap, frost::round2::SignatureShare<_>> = + BTreeMap::new(); let message = "message to sign".as_bytes(); let signing_package = frost::SigningPackage::new(commitments, message); diff --git a/frost-ristretto255/README.md b/frost-ristretto255/README.md index cfd397b..436b953 100644 --- a/frost-ristretto255/README.md +++ b/frost-ristretto255/README.md @@ -12,7 +12,7 @@ scenario in a single thread and it abstracts away any communication between peer # // ANCHOR: tkg_gen use frost_ristretto255 as frost; use rand::thread_rng; -use std::collections::{BTreeMap, HashMap}; +use std::collections::BTreeMap; let mut rng = thread_rng(); let max_signers = 5; @@ -25,10 +25,10 @@ let (shares, pubkey_package) = frost::keys::generate_with_dealer( )?; # // ANCHOR_END: tkg_gen -// Verifies the secret shares from the dealer and store them in a HashMap. +// Verifies the secret shares from the dealer and store them in a BTreeMap. // In practice, the KeyPackages must be sent to its respective participants // through a confidential and authenticated channel. -let mut key_packages: HashMap<_, _> = HashMap::new(); +let mut key_packages: BTreeMap<_, _> = BTreeMap::new(); for (identifier, secret_share) in shares { # // ANCHOR: tkg_verify @@ -37,7 +37,7 @@ for (identifier, secret_share) in shares { key_packages.insert(identifier, key_package); } -let mut nonces_map = HashMap::new(); +let mut nonces_map = BTreeMap::new(); let mut commitments_map = BTreeMap::new(); //////////////////////////////////////////////////////////////////////////// @@ -67,7 +67,7 @@ for participant_index in 1..(min_signers as u16 + 1) { // This is what the signature aggregator / coordinator needs to do: // - decide what message to sign // - take one (unused) commitment per signing participant -let mut signature_shares = HashMap::new(); +let mut signature_shares = BTreeMap::new(); # // ANCHOR: round2_package let message = "message to sign".as_bytes(); # // In practice, the SigningPackage must be sent to all participants diff --git a/frost-ristretto255/dkg.md b/frost-ristretto255/dkg.md index b4ac5dd..481f24a 100644 --- a/frost-ristretto255/dkg.md +++ b/frost-ristretto255/dkg.md @@ -27,7 +27,7 @@ they can proceed to sign messages with FROST. ```rust # // ANCHOR: dkg_import use rand::thread_rng; -use std::collections::HashMap; +use std::collections::BTreeMap; use frost_ristretto255 as frost; @@ -44,12 +44,12 @@ let min_signers = 3; // Keep track of each participant's round 1 secret package. // In practice each participant will keep its copy; no one // will have all the participant's packages. -let mut round1_secret_packages = HashMap::new(); +let mut round1_secret_packages = BTreeMap::new(); // Keep track of all round 1 packages sent to the given participant. // This is used to simulate the broadcast; in practice the packages // will be sent through some communication channel. -let mut received_round1_packages = HashMap::new(); +let mut received_round1_packages = BTreeMap::new(); // For each participant, perform the first part of the DKG protocol. // In practice, each participant will perform this on their own environments. @@ -69,7 +69,7 @@ for participant_index in 1..=max_signers { round1_secret_packages.insert(participant_identifier, round1_secret_package); // "Send" the round 1 package to all other participants. In this - // test this is simulated using a HashMap; in practice this will be + // test this is simulated using a BTreeMap; in practice this will be // sent through some communication channel. for receiver_participant_index in 1..=max_signers { if receiver_participant_index == participant_index { @@ -80,7 +80,7 @@ for participant_index in 1..=max_signers { .expect("should be nonzero"); received_round1_packages .entry(receiver_participant_identifier) - .or_insert_with(HashMap::new) + .or_insert_with(BTreeMap::new) .insert(participant_identifier, round1_package.clone()); } } @@ -92,12 +92,12 @@ for participant_index in 1..=max_signers { // Keep track of each participant's round 2 secret package. // In practice each participant will keep its copy; no one // will have all the participant's packages. -let mut round2_secret_packages = HashMap::new(); +let mut round2_secret_packages = BTreeMap::new(); // Keep track of all round 2 packages sent to the given participant. // This is used to simulate the broadcast; in practice the packages // will be sent through some communication channel. -let mut received_round2_packages = HashMap::new(); +let mut received_round2_packages = BTreeMap::new(); // For each participant, perform the second part of the DKG protocol. // In practice, each participant will perform this on their own environments. @@ -117,14 +117,14 @@ for participant_index in 1..=max_signers { round2_secret_packages.insert(participant_identifier, round2_secret_package); // "Send" the round 2 package to all other participants. In this - // test this is simulated using a HashMap; in practice this will be + // test this is simulated using a BTreeMap; in practice this will be // sent through some communication channel. // Note that, in contrast to the previous part, here each other participant // gets its own specific package. for (receiver_identifier, round2_package) in round2_packages { received_round2_packages .entry(receiver_identifier) - .or_insert_with(HashMap::new) + .or_insert_with(BTreeMap::new) .insert(participant_identifier, round2_package); } } @@ -136,13 +136,13 @@ for participant_index in 1..=max_signers { // Keep track of each participant's long-lived key package. // In practice each participant will keep its copy; no one // will have all the participant's packages. -let mut key_packages = HashMap::new(); +let mut key_packages = BTreeMap::new(); // Keep track of each participant's public key package. // In practice, if there is a Coordinator, only they need to store the set. // If there is not, then all candidates must store their own sets. // All participants will have the same exact public key package. -let mut pubkey_packages = HashMap::new(); +let mut pubkey_packages = BTreeMap::new(); // For each participant, perform the third part of the DKG protocol. // In practice, each participant will perform this on their own environments. diff --git a/frost-ristretto255/src/keys/dkg.rs b/frost-ristretto255/src/keys/dkg.rs index ece47a9..6f8b712 100644 --- a/frost-ristretto255/src/keys/dkg.rs +++ b/frost-ristretto255/src/keys/dkg.rs @@ -64,8 +64,8 @@ pub fn part1( /// must be sent to other participants. pub fn part2( secret_package: round1::SecretPackage, - round1_packages: &HashMap, -) -> Result<(round2::SecretPackage, HashMap), Error> { + round1_packages: &BTreeMap, +) -> Result<(round2::SecretPackage, BTreeMap), Error> { frost::keys::dkg::part2(secret_package, round1_packages) } @@ -80,8 +80,8 @@ pub fn part2( /// signatures. pub fn part3( round2_secret_package: &round2::SecretPackage, - round1_packages: &HashMap, - round2_packages: &HashMap, + round1_packages: &BTreeMap, + round2_packages: &BTreeMap, ) -> Result<(KeyPackage, PublicKeyPackage), Error> { frost::keys::dkg::part3(round2_secret_package, round1_packages, round2_packages) } diff --git a/frost-ristretto255/src/keys/repairable.rs b/frost-ristretto255/src/keys/repairable.rs index d5713fd..a303828 100644 --- a/frost-ristretto255/src/keys/repairable.rs +++ b/frost-ristretto255/src/keys/repairable.rs @@ -4,7 +4,7 @@ //! The RTS is used to help a signer (participant) repair their lost share. This is achieved //! using a subset of the other signers know here as `helpers`. -use std::collections::HashMap; +use std::collections::BTreeMap; // This is imported separately to make `gencode` work. // (if it were below, the position of the import would vary between ciphersuites @@ -20,13 +20,13 @@ use super::{SecretShare, VerifiableSecretSharingCommitment}; /// where `helpers` contains the identifiers of all the helpers (including `helper_i`), and `share_i` /// is the share of `helper_i`. /// -/// Returns a HashMap mapping which value should be sent to which participant. +/// Returns a BTreeMap mapping which value should be sent to which participant. pub fn repair_share_step_1( helpers: &[Identifier], share_i: &SecretShare, rng: &mut R, participant: Identifier, -) -> Result, Error> { +) -> Result, Error> { frost::keys::repairable::repair_share_step_1(helpers, share_i, rng, participant) } diff --git a/frost-ristretto255/src/lib.rs b/frost-ristretto255/src/lib.rs index 26d7362..986b584 100644 --- a/frost-ristretto255/src/lib.rs +++ b/frost-ristretto255/src/lib.rs @@ -2,7 +2,7 @@ #![deny(missing_docs)] #![doc = include_str!("../README.md")] -use std::collections::HashMap; +use std::collections::BTreeMap; use curve25519_dalek::{ constants::RISTRETTO_BASEPOINT_POINT, @@ -203,7 +203,7 @@ pub type Identifier = frost::Identifier; /// FROST(ristretto255, SHA-512) keys, key generation, key shares. pub mod keys { use super::*; - use std::collections::HashMap; + use std::collections::BTreeMap; /// The identifier list to use when generating key shares. pub type IdentifierList<'a> = frost::keys::IdentifierList<'a, R>; @@ -215,7 +215,7 @@ pub mod keys { min_signers: u16, identifiers: IdentifierList, mut rng: RNG, - ) -> Result<(HashMap, PublicKeyPackage), Error> { + ) -> Result<(BTreeMap, PublicKeyPackage), Error> { frost::keys::generate_with_dealer(max_signers, min_signers, identifiers, &mut rng) } @@ -231,7 +231,7 @@ pub mod keys { min_signers: u16, identifiers: IdentifierList, rng: &mut R, - ) -> Result<(HashMap, PublicKeyPackage), Error> { + ) -> Result<(BTreeMap, PublicKeyPackage), Error> { frost::keys::split(secret, max_signers, min_signers, identifiers, rng) } @@ -380,7 +380,7 @@ pub type Signature = frost_core::Signature; /// service attack due to publishing an invalid signature. pub fn aggregate( signing_package: &SigningPackage, - signature_shares: &HashMap, + signature_shares: &BTreeMap, pubkeys: &keys::PublicKeyPackage, ) -> Result { frost::aggregate(signing_package, signature_shares, pubkeys) diff --git a/frost-ristretto255/tests/helpers/samples.rs b/frost-ristretto255/tests/helpers/samples.rs index 550b7cf..4553949 100644 --- a/frost-ristretto255/tests/helpers/samples.rs +++ b/frost-ristretto255/tests/helpers/samples.rs @@ -1,6 +1,6 @@ //! Generate sample, fixed instances of structs for testing. -use std::collections::{BTreeMap, HashMap}; +use std::collections::BTreeMap; use frost_core::{Ciphersuite, Element, Group, Scalar}; use frost_ristretto255::{ @@ -90,7 +90,7 @@ pub fn public_key_package() -> PublicKeyPackage { let verifying_share = VerifyingShare::deserialize(serialized_element).unwrap(); let serialized_element = ::Group::serialize(&element1()); let verifying_key = VerifyingKey::deserialize(serialized_element).unwrap(); - let verifying_shares = HashMap::from([(identifier, verifying_share)]); + let verifying_shares = BTreeMap::from([(identifier, verifying_share)]); PublicKeyPackage::new(verifying_shares, verifying_key) } diff --git a/frost-secp256k1/README.md b/frost-secp256k1/README.md index f609049..0d42073 100644 --- a/frost-secp256k1/README.md +++ b/frost-secp256k1/README.md @@ -12,7 +12,7 @@ scenario in a single thread and it abstracts away any communication between peer # // ANCHOR: tkg_gen use frost_secp256k1 as frost; use rand::thread_rng; -use std::collections::{BTreeMap, HashMap}; +use std::collections::BTreeMap; let mut rng = thread_rng(); let max_signers = 5; @@ -25,10 +25,10 @@ let (shares, pubkey_package) = frost::keys::generate_with_dealer( )?; # // ANCHOR_END: tkg_gen -// Verifies the secret shares from the dealer and store them in a HashMap. +// Verifies the secret shares from the dealer and store them in a BTreeMap. // In practice, the KeyPackages must be sent to its respective participants // through a confidential and authenticated channel. -let mut key_packages: HashMap<_, _> = HashMap::new(); +let mut key_packages: BTreeMap<_, _> = BTreeMap::new(); for (identifier, secret_share) in shares { # // ANCHOR: tkg_verify @@ -37,7 +37,7 @@ for (identifier, secret_share) in shares { key_packages.insert(identifier, key_package); } -let mut nonces_map = HashMap::new(); +let mut nonces_map = BTreeMap::new(); let mut commitments_map = BTreeMap::new(); //////////////////////////////////////////////////////////////////////////// @@ -67,7 +67,7 @@ for participant_index in 1..(min_signers as u16 + 1) { // This is what the signature aggregator / coordinator needs to do: // - decide what message to sign // - take one (unused) commitment per signing participant -let mut signature_shares = HashMap::new(); +let mut signature_shares = BTreeMap::new(); # // ANCHOR: round2_package let message = "message to sign".as_bytes(); # // In practice, the SigningPackage must be sent to all participants diff --git a/frost-secp256k1/dkg.md b/frost-secp256k1/dkg.md index 5a73374..ac0980b 100644 --- a/frost-secp256k1/dkg.md +++ b/frost-secp256k1/dkg.md @@ -27,7 +27,7 @@ they can proceed to sign messages with FROST. ```rust # // ANCHOR: dkg_import use rand::thread_rng; -use std::collections::HashMap; +use std::collections::BTreeMap; use frost_secp256k1 as frost; @@ -44,12 +44,12 @@ let min_signers = 3; // Keep track of each participant's round 1 secret package. // In practice each participant will keep its copy; no one // will have all the participant's packages. -let mut round1_secret_packages = HashMap::new(); +let mut round1_secret_packages = BTreeMap::new(); // Keep track of all round 1 packages sent to the given participant. // This is used to simulate the broadcast; in practice the packages // will be sent through some communication channel. -let mut received_round1_packages = HashMap::new(); +let mut received_round1_packages = BTreeMap::new(); // For each participant, perform the first part of the DKG protocol. // In practice, each participant will perform this on their own environments. @@ -69,7 +69,7 @@ for participant_index in 1..=max_signers { round1_secret_packages.insert(participant_identifier, round1_secret_package); // "Send" the round 1 package to all other participants. In this - // test this is simulated using a HashMap; in practice this will be + // test this is simulated using a BTreeMap; in practice this will be // sent through some communication channel. for receiver_participant_index in 1..=max_signers { if receiver_participant_index == participant_index { @@ -80,7 +80,7 @@ for participant_index in 1..=max_signers { .expect("should be nonzero"); received_round1_packages .entry(receiver_participant_identifier) - .or_insert_with(HashMap::new) + .or_insert_with(BTreeMap::new) .insert(participant_identifier, round1_package.clone()); } } @@ -92,12 +92,12 @@ for participant_index in 1..=max_signers { // Keep track of each participant's round 2 secret package. // In practice each participant will keep its copy; no one // will have all the participant's packages. -let mut round2_secret_packages = HashMap::new(); +let mut round2_secret_packages = BTreeMap::new(); // Keep track of all round 2 packages sent to the given participant. // This is used to simulate the broadcast; in practice the packages // will be sent through some communication channel. -let mut received_round2_packages = HashMap::new(); +let mut received_round2_packages = BTreeMap::new(); // For each participant, perform the second part of the DKG protocol. // In practice, each participant will perform this on their own environments. @@ -117,14 +117,14 @@ for participant_index in 1..=max_signers { round2_secret_packages.insert(participant_identifier, round2_secret_package); // "Send" the round 2 package to all other participants. In this - // test this is simulated using a HashMap; in practice this will be + // test this is simulated using a BTreeMap; in practice this will be // sent through some communication channel. // Note that, in contrast to the previous part, here each other participant // gets its own specific package. for (receiver_identifier, round2_package) in round2_packages { received_round2_packages .entry(receiver_identifier) - .or_insert_with(HashMap::new) + .or_insert_with(BTreeMap::new) .insert(participant_identifier, round2_package); } } @@ -136,13 +136,13 @@ for participant_index in 1..=max_signers { // Keep track of each participant's long-lived key package. // In practice each participant will keep its copy; no one // will have all the participant's packages. -let mut key_packages = HashMap::new(); +let mut key_packages = BTreeMap::new(); // Keep track of each participant's public key package. // In practice, if there is a Coordinator, only they need to store the set. // If there is not, then all candidates must store their own sets. // All participants will have the same exact public key package. -let mut pubkey_packages = HashMap::new(); +let mut pubkey_packages = BTreeMap::new(); // For each participant, perform the third part of the DKG protocol. // In practice, each participant will perform this on their own environments. diff --git a/frost-secp256k1/src/keys/dkg.rs b/frost-secp256k1/src/keys/dkg.rs index 81a8e66..91c6286 100644 --- a/frost-secp256k1/src/keys/dkg.rs +++ b/frost-secp256k1/src/keys/dkg.rs @@ -64,8 +64,8 @@ pub fn part1( /// must be sent to other participants. pub fn part2( secret_package: round1::SecretPackage, - round1_packages: &HashMap, -) -> Result<(round2::SecretPackage, HashMap), Error> { + round1_packages: &BTreeMap, +) -> Result<(round2::SecretPackage, BTreeMap), Error> { frost::keys::dkg::part2(secret_package, round1_packages) } @@ -80,8 +80,8 @@ pub fn part2( /// signatures. pub fn part3( round2_secret_package: &round2::SecretPackage, - round1_packages: &HashMap, - round2_packages: &HashMap, + round1_packages: &BTreeMap, + round2_packages: &BTreeMap, ) -> Result<(KeyPackage, PublicKeyPackage), Error> { frost::keys::dkg::part3(round2_secret_package, round1_packages, round2_packages) } diff --git a/frost-secp256k1/src/keys/repairable.rs b/frost-secp256k1/src/keys/repairable.rs index eb4bfd1..01bb964 100644 --- a/frost-secp256k1/src/keys/repairable.rs +++ b/frost-secp256k1/src/keys/repairable.rs @@ -4,7 +4,7 @@ //! The RTS is used to help a signer (participant) repair their lost share. This is achieved //! using a subset of the other signers know here as `helpers`. -use std::collections::HashMap; +use std::collections::BTreeMap; // This is imported separately to make `gencode` work. // (if it were below, the position of the import would vary between ciphersuites @@ -20,13 +20,13 @@ use super::{SecretShare, VerifiableSecretSharingCommitment}; /// where `helpers` contains the identifiers of all the helpers (including `helper_i`), and `share_i` /// is the share of `helper_i`. /// -/// Returns a HashMap mapping which value should be sent to which participant. +/// Returns a BTreeMap mapping which value should be sent to which participant. pub fn repair_share_step_1( helpers: &[Identifier], share_i: &SecretShare, rng: &mut R, participant: Identifier, -) -> Result, Error> { +) -> Result, Error> { frost::keys::repairable::repair_share_step_1(helpers, share_i, rng, participant) } diff --git a/frost-secp256k1/src/lib.rs b/frost-secp256k1/src/lib.rs index 9ecba56..e8a5b5b 100644 --- a/frost-secp256k1/src/lib.rs +++ b/frost-secp256k1/src/lib.rs @@ -5,7 +5,7 @@ #![doc = include_str!("../README.md")] #![doc = document_features::document_features!()] -use std::collections::HashMap; +use std::collections::BTreeMap; use k256::{ elliptic_curve::{ @@ -243,7 +243,7 @@ pub type Identifier = frost::Identifier; /// FROST(secp256k1, SHA-256) keys, key generation, key shares. pub mod keys { use super::*; - use std::collections::HashMap; + use std::collections::BTreeMap; /// The identifier list to use when generating key shares. pub type IdentifierList<'a> = frost::keys::IdentifierList<'a, S>; @@ -255,7 +255,7 @@ pub mod keys { min_signers: u16, identifiers: IdentifierList, mut rng: RNG, - ) -> Result<(HashMap, PublicKeyPackage), Error> { + ) -> Result<(BTreeMap, PublicKeyPackage), Error> { frost::keys::generate_with_dealer(max_signers, min_signers, identifiers, &mut rng) } @@ -271,7 +271,7 @@ pub mod keys { min_signers: u16, identifiers: IdentifierList, rng: &mut R, - ) -> Result<(HashMap, PublicKeyPackage), Error> { + ) -> Result<(BTreeMap, PublicKeyPackage), Error> { frost::keys::split(secret, max_signers, min_signers, identifiers, rng) } @@ -420,7 +420,7 @@ pub type Signature = frost_core::Signature; /// service attack due to publishing an invalid signature. pub fn aggregate( signing_package: &SigningPackage, - signature_shares: &HashMap, + signature_shares: &BTreeMap, pubkeys: &keys::PublicKeyPackage, ) -> Result { frost::aggregate(signing_package, signature_shares, pubkeys) diff --git a/frost-secp256k1/tests/helpers/samples.rs b/frost-secp256k1/tests/helpers/samples.rs index fc1d266..21e8b82 100644 --- a/frost-secp256k1/tests/helpers/samples.rs +++ b/frost-secp256k1/tests/helpers/samples.rs @@ -1,6 +1,6 @@ //! Generate sample, fixed instances of structs for testing. -use std::collections::{BTreeMap, HashMap}; +use std::collections::BTreeMap; use frost_core::{Ciphersuite, Element, Group, Scalar}; use frost_secp256k1::{ @@ -90,7 +90,7 @@ pub fn public_key_package() -> PublicKeyPackage { let verifying_share = VerifyingShare::deserialize(serialized_element).unwrap(); let serialized_element = ::Group::serialize(&element1()); let verifying_key = VerifyingKey::deserialize(serialized_element).unwrap(); - let verifying_shares = HashMap::from([(identifier, verifying_share)]); + let verifying_shares = BTreeMap::from([(identifier, verifying_share)]); PublicKeyPackage::new(verifying_shares, verifying_key) } diff --git a/gencode/src/main.rs b/gencode/src/main.rs index 2a55dc4..f4c74d7 100644 --- a/gencode/src/main.rs +++ b/gencode/src/main.rs @@ -20,7 +20,7 @@ //! - The repairable.rs module (it uses the frost-core docs as canonical) use std::{ - collections::HashMap, + collections::BTreeMap, env, fs, io::Write, iter::zip, @@ -115,7 +115,7 @@ fn write_docs( let original_code = code.clone(); // Map documentations by their identifiers - let docs: HashMap = + let docs: BTreeMap = docs.iter().map(|x| (x.0.clone(), x.clone())).collect(); // To be able to replace the documentation properly, start from the end, which