From da8614a48c981b842bcaf47f9bfe49321439db9c Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Mon, 5 Feb 2024 11:31:35 +0100 Subject: [PATCH] wip --- ferveo-tdec/benches/tpke.rs | 6 +- ferveo-tdec/src/ciphertext.rs | 14 ++-- ferveo-tdec/src/decryption.rs | 16 ++++- ferveo-tdec/src/key_share.rs | 49 +++++++++++--- ferveo-tdec/src/lib.rs | 34 +++++++--- ferveo/src/api.rs | 16 +++-- ferveo/src/dkg.rs | 50 +++++++++----- ferveo/src/lib.rs | 23 ++++--- ferveo/src/pvss.rs | 33 ++++----- ferveo/src/refresh.rs | 123 ++++++++++++---------------------- 10 files changed, 203 insertions(+), 161 deletions(-) diff --git a/ferveo-tdec/benches/tpke.rs b/ferveo-tdec/benches/tpke.rs index 420bf869..0bbba434 100644 --- a/ferveo-tdec/benches/tpke.rs +++ b/ferveo-tdec/benches/tpke.rs @@ -1,6 +1,6 @@ #![allow(clippy::redundant_closure)] -use ark_bls12_381::{Bls12_381, Fr, G1Affine as G1, G2Affine as G2}; +use ark_bls12_381::{Bls12_381, Fr}; use ark_ec::pairing::Pairing; use criterion::{ black_box, criterion_group, criterion_main, BenchmarkId, Criterion, @@ -25,8 +25,8 @@ struct SetupShared { shares_num: usize, msg: Vec, aad: Vec, - pubkey: G1, - privkey: G2, + pubkey: PublicKeyShare, + privkey: PrivateKeyShare, ciphertext: Ciphertext, shared_secret: SharedSecret, } diff --git a/ferveo-tdec/src/ciphertext.rs b/ferveo-tdec/src/ciphertext.rs index 81f79389..cdaf956c 100644 --- a/ferveo-tdec/src/ciphertext.rs +++ b/ferveo-tdec/src/ciphertext.rs @@ -13,7 +13,10 @@ use serde_with::serde_as; use sha2::{digest::Digest, Sha256}; use zeroize::ZeroizeOnDrop; -use crate::{htp_bls12381_g2, Error, Result, SecretBox, SharedSecret}; +use crate::{ + htp_bls12381_g2, Error, PrivateKeyShare, PublicKeyShare, Result, SecretBox, + SharedSecret, +}; #[serde_as] #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] @@ -95,7 +98,7 @@ impl CiphertextHeader { pub fn encrypt( message: SecretBox>, aad: &[u8], - pubkey: &E::G1Affine, + pubkey: &PublicKeyShare, rng: &mut impl rand::Rng, ) -> Result> { // r @@ -105,7 +108,8 @@ pub fn encrypt( // h let h_gen = E::G2Affine::generator(); - let ry_prep = E::G1Prepared::from(pubkey.mul(rand_element).into()); + let ry_prep = + E::G1Prepared::from(pubkey.public_key_share.mul(rand_element).into()); // s let product = E::pairing(ry_prep, h_gen).0; // u @@ -140,13 +144,13 @@ pub fn encrypt( pub fn decrypt_symmetric( ciphertext: &Ciphertext, aad: &[u8], - private_key: &E::G2Affine, + private_key: &PrivateKeyShare, g_inv: &E::G1Prepared, ) -> Result> { ciphertext.check(aad, g_inv)?; let shared_secret = E::pairing( E::G1Prepared::from(ciphertext.commitment), - E::G2Prepared::from(*private_key), + E::G2Prepared::from(private_key.private_key_share), ) .0; let shared_secret = SharedSecret(shared_secret); diff --git a/ferveo-tdec/src/decryption.rs b/ferveo-tdec/src/decryption.rs index 0622e6a8..5c630113 100644 --- a/ferveo-tdec/src/decryption.rs +++ b/ferveo-tdec/src/decryption.rs @@ -2,6 +2,7 @@ use std::ops::Mul; use ark_ec::{pairing::Pairing, CurveGroup}; use ark_ff::{Field, One, Zero}; +use ark_std::UniformRand; use ferveo_common::serialization; use itertools::{izip, zip_eq}; use rand_core::RngCore; @@ -9,8 +10,8 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize}; use serde_with::serde_as; use crate::{ - generate_random, Ciphertext, CiphertextHeader, PrivateKeyShare, - PublicDecryptionContextFast, PublicDecryptionContextSimple, Result, + Ciphertext, CiphertextHeader, PrivateKeyShare, PublicDecryptionContextFast, + PublicDecryptionContextSimple, Result, }; #[serde_as] @@ -226,6 +227,15 @@ impl DecryptionSharePrecomputed { } } +pub fn generate_random_scalars( + n: usize, + rng: &mut R, +) -> Vec { + (0..n) + .map(|_| E::ScalarField::rand(rng)) + .collect::>() +} + // TODO: Remove this code? Currently only used in benchmarks. Move to benchmark suite? pub fn batch_verify_decryption_shares( pub_contexts: &[PublicDecryptionContextFast], @@ -249,7 +259,7 @@ pub fn batch_verify_decryption_shares( // For each ciphertext, generate num_shares random scalars let alpha_ij = (0..num_ciphertexts) - .map(|_| generate_random::<_, E>(num_shares, rng)) + .map(|_| generate_random_scalars::<_, E>(num_shares, rng)) .collect::>(); let mut pairings_a = Vec::with_capacity(num_shares + 1); diff --git a/ferveo-tdec/src/key_share.rs b/ferveo-tdec/src/key_share.rs index 2daaae56..a8c319ae 100644 --- a/ferveo-tdec/src/key_share.rs +++ b/ferveo-tdec/src/key_share.rs @@ -1,11 +1,14 @@ use std::ops::Mul; use ark_ec::{pairing::Pairing, AffineRepr, CurveGroup}; -use ark_ff::One; +use ark_ff::{One, Zero}; use ark_std::UniformRand; +use itertools::zip_eq; use rand_core::RngCore; use zeroize::ZeroizeOnDrop; +use crate::lagrange_basis_at; + #[derive(Debug, Clone)] pub struct PublicKeyShare { pub public_key_share: E::G1Affine, // A_{i, \omega_i} @@ -18,15 +21,6 @@ pub struct BlindedKeyShare { pub blinding_key_prepared: E::G2Prepared, } -pub fn generate_random( - n: usize, - rng: &mut R, -) -> Vec { - (0..n) - .map(|_| E::ScalarField::rand(rng)) - .collect::>() -} - impl BlindedKeyShare { pub fn verify_blinding( &self, @@ -72,4 +66,39 @@ impl PrivateKeyShare { blinded_key_share: self.private_key_share.mul(b).into_affine(), } } + + /// From PSS paper, section 4.2.3, (https://link.springer.com/content/pdf/10.1007/3-540-44750-4_27.pdf) + pub fn update_share( + &self, + share_updates: &[PrivateKeyShareUpdate], + ) -> PrivateKeyShare { + let updated_key_share = share_updates + .iter() + .fold(self.private_key_share.into_group(), |acc, delta| { + acc + delta.0 + }) + .into_affine(); + PrivateKeyShare { + private_key_share: updated_key_share, + } + } + + /// From the PSS paper, section 4.2.4, (https://link.springer.com/content/pdf/10.1007/3-540-44750-4_27.pdf) + pub fn recover_share_from_updated_private_shares( + x_r: &E::ScalarField, + domain_points: &[E::ScalarField], + updated_private_shares: &[PrivateKeyShare], + ) -> PrivateKeyShare { + // Interpolate new shares to recover y_r + let lagrange = lagrange_basis_at::(domain_points, x_r); + let prods = zip_eq(updated_private_shares, lagrange) + .map(|(y_j, l)| y_j.private_key_share.mul(l)); + let y_r = prods.fold(E::G2::zero(), |acc, y_j| acc + y_j); + PrivateKeyShare { + private_key_share: y_r.into_affine(), + } + } } + +#[derive(Debug, Clone, PartialEq, Eq, ZeroizeOnDrop)] +pub struct PrivateKeyShareUpdate(pub E::G2Affine); diff --git a/ferveo-tdec/src/lib.rs b/ferveo-tdec/src/lib.rs index 297b066c..b5ffed22 100644 --- a/ferveo-tdec/src/lib.rs +++ b/ferveo-tdec/src/lib.rs @@ -77,8 +77,8 @@ pub mod test_common { shares_num: usize, rng: &mut impl RngCore, ) -> ( - E::G1Affine, - E::G2Affine, + PublicKeyShare, + PrivateKeyShare, Vec>, ) { assert!(shares_num >= threshold); @@ -138,7 +138,7 @@ pub mod test_common { ) .enumerate() { - let private_key_share = PrivateKeyShare:: { + let private_key_share = PrivateKeyShare { private_key_share: *private, }; let b = E::ScalarField::rand(rng); @@ -171,7 +171,15 @@ pub mod test_common { private.public_decryption_contexts = public_contexts.clone(); } - (pubkey.into(), privkey.into(), private_contexts) + ( + PublicKeyShare { + public_key_share: pubkey.into(), + }, + PrivateKeyShare { + private_key_share: privkey.into(), + }, + private_contexts, + ) } pub fn setup_simple( @@ -179,8 +187,8 @@ pub mod test_common { shares_num: usize, rng: &mut impl rand::Rng, ) -> ( - E::G1Affine, - E::G2Affine, + PublicKeyShare, + PrivateKeyShare, Vec>, ) { assert!(shares_num >= threshold); @@ -259,15 +267,23 @@ pub mod test_common { private.public_decryption_contexts = public_contexts.clone(); } - (pubkey.into(), privkey.into(), private_contexts) + ( + PublicKeyShare { + public_key_share: pubkey.into(), + }, + PrivateKeyShare { + private_key_share: privkey.into(), + }, + private_contexts, + ) } pub fn setup_precomputed( shares_num: usize, rng: &mut impl rand::Rng, ) -> ( - E::G1Affine, - E::G2Affine, + PublicKeyShare, + PrivateKeyShare, Vec>, ) { // In precomputed variant, the security threshold is equal to the number of shares diff --git a/ferveo/src/api.rs b/ferveo/src/api.rs index caa0d9b4..64037704 100644 --- a/ferveo/src/api.rs +++ b/ferveo/src/api.rs @@ -9,6 +9,7 @@ pub use ferveo_tdec::api::{ prepare_combine_simple, share_combine_precomputed, share_combine_simple, Fr, G1Affine, G1Prepared, G2Affine, SecretBox, E, }; +use ferveo_tdec::PublicKeyShare; use generic_array::{ typenum::{Unsigned, U48}, GenericArray, @@ -58,8 +59,15 @@ pub fn encrypt( pubkey: &DkgPublicKey, ) -> Result { let mut rng = rand::thread_rng(); - let ciphertext = - ferveo_tdec::api::encrypt(message, aad, &pubkey.0, &mut rng)?; + let ciphertext = ferveo_tdec::api::encrypt( + message, + aad, + // &pubkey.0, + &PublicKeyShare { + public_key_share: pubkey.0, + }, + &mut rng, + )?; Ok(Ciphertext(ciphertext)) } @@ -91,7 +99,7 @@ impl Ciphertext { } } -#[serde_as] +#[serde_as] // TODO: Redundant serde_as? #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct CiphertextHeader(ferveo_tdec::api::CiphertextHeader); @@ -218,7 +226,7 @@ impl Dkg { } pub fn public_key(&self) -> DkgPublicKey { - DkgPublicKey(self.0.public_key()) + DkgPublicKey(self.0.public_key().public_key_share) } pub fn generate_transcript( diff --git a/ferveo/src/dkg.rs b/ferveo/src/dkg.rs index e8afbe30..b309449e 100644 --- a/ferveo/src/dkg.rs +++ b/ferveo/src/dkg.rs @@ -69,9 +69,14 @@ pub type PVSSMap = BTreeMap>; #[derive(Debug, Clone)] pub enum DkgState { // TODO: Do we need to keep track of the block number? - Sharing { accumulated_shares: u32, block: u32 }, + Sharing { + accumulated_shares: u32, + block: u32, + }, Dealt, - Success { public_key: E::G1Affine }, + Success { + public_key: ferveo_tdec::PublicKeyShare, + }, Invalid, } @@ -178,7 +183,7 @@ impl PubliclyVerifiableDkg { let pvss_list = self.vss.values().cloned().collect::>(); Ok(Message::Aggregate(Aggregation { vss: aggregate(&pvss_list)?, - public_key, + public_key: public_key.public_key_share, })) } _ => Err(Error::InvalidDkgStateToAggregate), @@ -186,12 +191,15 @@ impl PubliclyVerifiableDkg { } /// Returns the public key generated by the DKG - pub fn public_key(&self) -> E::G1Affine { - self.vss - .values() - .map(|vss| vss.coeffs[0].into_group()) - .sum::() - .into_affine() + pub fn public_key(&self) -> ferveo_tdec::PublicKeyShare { + ferveo_tdec::PublicKeyShare { + public_key_share: self + .vss + .values() + .map(|vss| vss.coeffs[0].into_group()) + .sum::() + .into_affine(), + } } /// Return a domain point for the share_index @@ -245,7 +253,7 @@ impl PubliclyVerifiableDkg { )) } else if vss.verify_aggregation(self).is_err() { Err(Error::InvalidTranscriptAggregate) - } else if &self.public_key() == public_key { + } else if &self.public_key().public_key_share == public_key { Ok(()) } else { Err(Error::InvalidDkgPublicKey) @@ -382,6 +390,7 @@ mod test_dkg_init { #[cfg(test)] mod test_dealing { use ark_ec::AffineRepr; + use ferveo_tdec::PublicKeyShare; use crate::{ test_common::*, DkgParams, DkgState, DkgState::Dealt, Error, @@ -587,7 +596,9 @@ mod test_dealing { )); dkg.state = DkgState::Success { - public_key: G1::zero(), + public_key: PublicKeyShare { + public_key_share: G1::zero(), + }, }; assert!(dkg.share(rng).is_err()); @@ -614,7 +625,9 @@ mod test_dealing { let sender = dkg.me.clone(); dkg.state = DkgState::Success { - public_key: G1::zero(), + public_key: PublicKeyShare { + public_key_share: G1::zero(), + }, }; assert!(dkg.verify_message(&sender, &pvss).is_err()); assert!(dkg.apply_message(&sender, &pvss).is_err()); @@ -631,6 +644,7 @@ mod test_dealing { #[cfg(test)] mod test_aggregation { use ark_ec::AffineRepr; + use ferveo_tdec::PublicKeyShare; use test_case::test_case; use crate::{dkg::*, test_common::*, DkgState, Message}; @@ -649,7 +663,7 @@ mod test_aggregation { if let Message::Aggregate(Aggregation { public_key, .. }) = &aggregate_msg { - assert_eq!(public_key, &dkg.public_key()); + assert_eq!(public_key, &dkg.public_key().public_key_share); } else { panic!("Expected aggregate message") } @@ -669,7 +683,9 @@ mod test_aggregation { }; assert!(dkg.aggregate().is_err()); dkg.state = DkgState::Success { - public_key: G1::zero(), + public_key: PublicKeyShare { + public_key_share: G1::zero(), + }, }; assert!(dkg.aggregate().is_err()); } @@ -690,7 +706,9 @@ mod test_aggregation { assert!(dkg.apply_message(&sender, &aggregate).is_err()); dkg.state = DkgState::Success { - public_key: G1::zero(), + public_key: PublicKeyShare { + public_key_share: G1::zero(), + }, }; assert!(dkg.verify_message(&sender, &aggregate).is_err()); assert!(dkg.apply_message(&sender, &aggregate).is_err()) @@ -713,7 +731,7 @@ mod test_aggregation { fn test_aggregate_wont_verify_if_wrong_key() { let (dkg, _) = setup_dealt_dkg(); let mut aggregate = dkg.aggregate().unwrap(); - while dkg.public_key() == G1::zero() { + while dkg.public_key().public_key_share == G1::zero() { let (_dkg, _) = setup_dealt_dkg(); } if let Message::Aggregate(Aggregation { public_key, .. }) = diff --git a/ferveo/src/lib.rs b/ferveo/src/lib.rs index f9d6c1a5..9a002306 100644 --- a/ferveo/src/lib.rs +++ b/ferveo/src/lib.rs @@ -136,8 +136,8 @@ mod test_dkg_full { use ark_std::test_rng; use ferveo_common::Keypair; use ferveo_tdec::{ - self, DecryptionSharePrecomputed, DecryptionShareSimple, SecretBox, - SharedSecret, + self, DecryptionSharePrecomputed, DecryptionShareSimple, + PrivateKeyShare, SecretBox, SharedSecret, }; use itertools::izip; use rand::seq::SliceRandom; @@ -444,8 +444,9 @@ mod test_dkg_full { let updates_for_participant: Vec<_> = share_updates .values() .map(|updates| { - *updates.get(validator.share_index as usize).unwrap() + updates.get(validator.share_index as usize).unwrap() }) + .cloned() .collect(); // Each validator uses their decryption key to update their share @@ -471,11 +472,12 @@ mod test_dkg_full { // TODO: Rename updated_private_shares to something that doesn't imply mutation (see #162, #163) // Now, we have to combine new share fragments into a new share - let new_private_key_share = recover_share_from_updated_private_shares( - &x_r, - &domain_points, - &updated_shares, - ); + let new_private_key_share = + PrivateKeyShare::recover_share_from_updated_private_shares( + &x_r, + &domain_points, + &updated_shares, + ); // Get decryption shares from remaining participants let mut remaining_validator_keypairs = validator_keypairs; @@ -588,7 +590,10 @@ mod test_dkg_full { let updates_for_participant: Vec<_> = share_updates .values() .map(|updates| { - *updates.get(validator.share_index as usize).unwrap() + updates + .get(validator.share_index as usize) + .cloned() + .unwrap() }) .collect(); diff --git a/ferveo/src/pvss.rs b/ferveo/src/pvss.rs index 34695bd3..a29c72b4 100644 --- a/ferveo/src/pvss.rs +++ b/ferveo/src/pvss.rs @@ -8,7 +8,7 @@ use ark_poly::{ }; use ferveo_tdec::{ prepare_combine_simple, CiphertextHeader, DecryptionSharePrecomputed, - DecryptionShareSimple, PrivateKeyShare, + DecryptionShareSimple, PrivateKeyShare, PrivateKeyShareUpdate, }; use itertools::Itertools; use rand::RngCore; @@ -18,9 +18,8 @@ use subproductdomain::fast_multiexp; use zeroize::{self, Zeroize, ZeroizeOnDrop}; use crate::{ - apply_updates_to_private_share, assert_no_share_duplicates, - batch_to_projective_g1, batch_to_projective_g2, Error, PVSSMap, - PubliclyVerifiableDkg, Result, Validator, + assert_no_share_duplicates, batch_to_projective_g1, batch_to_projective_g2, + Error, PVSSMap, PubliclyVerifiableDkg, Result, Validator, }; /// These are the blinded evaluations of shares of a single random polynomial @@ -304,7 +303,7 @@ impl PubliclyVerifiableSS { validator_decryption_key: &E::ScalarField, share_index: usize, ) -> Result> { - // Decrypt private key shares https://nikkolasg.github.io/ferveo/pvss.html#validator-decryption-of-private-key-shares + // Decrypt private key share https://nikkolasg.github.io/ferveo/pvss.html#validator-decryption-of-private-key-shares let private_key_share = self .shares .get(share_index) @@ -365,22 +364,16 @@ impl PubliclyVerifiableSS { .map_err(|e| e.into()) } - // TODO: Consider relocate to different place, maybe PrivateKeyShare? (see #162, #163) pub fn update_private_key_share_for_recovery( &self, validator_decryption_key: &E::ScalarField, share_index: usize, - share_updates: &[E::G2], + share_updates: &[PrivateKeyShareUpdate], ) -> Result> { - // Retrieves their private key share - let private_key_share = self - .decrypt_private_key_share(validator_decryption_key, share_index)?; - - // And updates their share - Ok(apply_updates_to_private_share::( - &private_key_share, - share_updates, - )) + // Retrieve the private key share and apply the updates + Ok(self + .decrypt_private_key_share(validator_decryption_key, share_index)? + .update_share(share_updates)) } } @@ -435,8 +428,8 @@ mod test_pvss { /// Test the happy flow such that the PVSS with the correct form is created /// and that appropriate validations pass - #[test_case(4,4; "number of validators is equal to the number of shares")] - #[test_case(4,6; "number of validators is greater than the number of shares")] + #[test_case(4, 4; "number of validators is equal to the number of shares")] + #[test_case(4, 6; "number of validators is greater than the number of shares")] fn test_new_pvss(shares_num: u32, validators_num: u32) { let rng = &mut ark_std::test_rng(); let security_threshold = shares_num - 1; @@ -510,8 +503,8 @@ mod test_pvss { /// Check that happy flow of aggregating PVSS transcripts /// has the correct form and it's validations passes - #[test_case(4,4; "number of validators is equal to the number of shares")] - #[test_case(4,6; "number of validators is greater than the number of shares")] + #[test_case(4, 4; "number of validators is equal to the number of shares")] + #[test_case(4, 6; "number of validators is greater than the number of shares")] fn test_aggregate_pvss(shares_num: u32, validators_num: u32) { let security_threshold = shares_num - 1; let (dkg, _) = setup_dealt_dkg_with_n_validators( diff --git a/ferveo/src/refresh.rs b/ferveo/src/refresh.rs index b02eba3b..90834204 100644 --- a/ferveo/src/refresh.rs +++ b/ferveo/src/refresh.rs @@ -1,10 +1,9 @@ use std::{ops::Mul, usize}; -use ark_ec::{pairing::Pairing, AffineRepr, CurveGroup}; +use ark_ec::{pairing::Pairing, CurveGroup}; use ark_ff::Zero; use ark_poly::{univariate::DensePolynomial, DenseUVPolynomial, Polynomial}; -use ferveo_tdec::{lagrange_basis_at, PrivateKeyShare}; -use itertools::zip_eq; +use ferveo_tdec::PrivateKeyShareUpdate; use rand_core::RngCore; // SHARE UPDATE FUNCTIONS: @@ -16,44 +15,11 @@ pub fn prepare_share_updates_for_recovery( x_r: &E::ScalarField, threshold: usize, rng: &mut impl RngCore, -) -> Vec { +) -> Vec> { // Update polynomial has root at x_r prepare_share_updates_with_root::(domain_points, h, x_r, threshold, rng) } -// TODO: Consider relocating to PrivateKeyShare (see #162, #163) -/// From PSS paper, section 4.2.3, (https://link.springer.com/content/pdf/10.1007/3-540-44750-4_27.pdf) -pub fn apply_updates_to_private_share( - private_key_share: &PrivateKeyShare, - share_updates: &[E::G2], -) -> PrivateKeyShare { - let private_key_share = share_updates - .iter() - .fold( - private_key_share.private_key_share.into_group(), - |acc, delta| acc + delta, - ) - .into_affine(); - PrivateKeyShare { private_key_share } -} - -/// From the PSS paper, section 4.2.4, (https://link.springer.com/content/pdf/10.1007/3-540-44750-4_27.pdf) -pub fn recover_share_from_updated_private_shares( - x_r: &E::ScalarField, - domain_points: &[E::ScalarField], - updated_private_shares: &[PrivateKeyShare], -) -> PrivateKeyShare { - // Interpolate new shares to recover y_r - let lagrange = lagrange_basis_at::(domain_points, x_r); - let prods = zip_eq(updated_private_shares, lagrange) - .map(|(y_j, l)| y_j.private_key_share.mul(l)); - let y_r = prods.fold(E::G2::zero(), |acc, y_j| acc + y_j); - - PrivateKeyShare { - private_key_share: y_r.into_affine(), - } -} - // SHARE REFRESH FUNCTIONS: pub fn prepare_share_updates_for_refresh( @@ -61,7 +27,7 @@ pub fn prepare_share_updates_for_refresh( h: &E::G2Affine, threshold: usize, rng: &mut impl RngCore, -) -> Vec { +) -> Vec> { // Update polynomial has root at 0 prepare_share_updates_with_root::( domain_points, @@ -80,7 +46,7 @@ fn prepare_share_updates_with_root( root: &E::ScalarField, threshold: usize, rng: &mut impl RngCore, -) -> Vec { +) -> Vec> { // Generate a new random polynomial with defined root let d_i = make_random_polynomial_with_root::(threshold - 1, root, rng); @@ -89,8 +55,9 @@ fn prepare_share_updates_with_root( .iter() .map(|x_i| { let eval = d_i.evaluate(x_i); - h.mul(eval) + h.mul(eval).into_affine() }) + .map(PrivateKeyShareUpdate) .collect() } @@ -130,9 +97,8 @@ mod tests_refresh { use test_case::test_matrix; use crate::{ - apply_updates_to_private_share, prepare_share_updates_for_recovery, - prepare_share_updates_for_refresh, - recover_share_from_updated_private_shares, test_common::*, + prepare_share_updates_for_recovery, prepare_share_updates_for_refresh, + test_common::*, }; fn make_new_share_fragments_for_recovery( @@ -170,14 +136,12 @@ mod tests_refresh { // Current participant receives updates from other participants let updates_for_participant: Vec<_> = share_updates .values() - .map(|updates| *updates.get(p.index).unwrap()) + .map(|updates| updates.get(p.index).cloned().unwrap()) .collect(); // And updates their share - apply_updates_to_private_share::( - &p.private_key_share, - &updates_for_participant, - ) + + p.private_key_share.update_share(&updates_for_participant) }) .collect(); @@ -225,18 +189,19 @@ mod tests_refresh { .iter() .map(|ctxt| ctxt.domain) .collect::>(); - let new_private_key_share = recover_share_from_updated_private_shares( - &x_r, - &domain_points[..security_threshold], - &new_share_fragments[..security_threshold], - ); + let new_private_key_share = + PrivateKeyShare::recover_share_from_updated_private_shares( + &x_r, + &domain_points[..security_threshold], + &new_share_fragments[..security_threshold], + ); assert_eq!(new_private_key_share, original_private_key_share); // If we don't have enough private share updates, the resulting private share will be incorrect assert_eq!(domain_points.len(), new_share_fragments.len()); let incorrect_private_key_share = - recover_share_from_updated_private_shares( + PrivateKeyShare::recover_share_from_updated_private_shares( &x_r, &domain_points[..(security_threshold - 1)], &new_share_fragments[..(security_threshold - 1)], @@ -283,11 +248,12 @@ mod tests_refresh { .iter() .map(|ctxt| ctxt.domain) .collect::>(); - let new_private_key_share = recover_share_from_updated_private_shares( - &x_r, - &domain_points[..threshold], - &new_share_fragments[..threshold], - ); + let new_private_key_share = + PrivateKeyShare::recover_share_from_updated_private_shares( + &x_r, + &domain_points[..threshold], + &new_share_fragments[..threshold], + ); let mut private_shares = contexts .iter() @@ -299,16 +265,14 @@ mod tests_refresh { domain_points.push(x_r); private_shares.push(new_private_key_share); let start_from = shares_num - threshold; - let new_shared_private_key = recover_share_from_updated_private_shares( - &ScalarField::zero(), - &domain_points[start_from..], - &private_shares[start_from..], - ); + let new_shared_private_key = + PrivateKeyShare::recover_share_from_updated_private_shares( + &ScalarField::zero(), + &domain_points[start_from..], + &private_shares[start_from..], + ); - assert_eq!( - shared_private_key, - new_shared_private_key.private_key_share - ); + assert_eq!(shared_private_key, new_shared_private_key); } /// Ñ parties (where t <= Ñ <= N) jointly execute a "share refresh" algorithm. @@ -350,27 +314,22 @@ mod tests_refresh { // Current participant receives updates from other participants let updates_for_participant: Vec<_> = share_updates .values() - .map(|updates| *updates.get(p.index).unwrap()) + .map(|updates| updates.get(p.index).cloned().unwrap()) .collect(); // And updates their share - apply_updates_to_private_share::( - &p.private_key_share, - &updates_for_participant, - ) + p.private_key_share.update_share(&updates_for_participant) }) .collect(); // Finally, let's recreate the shared private key from the refreshed shares - let new_shared_private_key = recover_share_from_updated_private_shares( - &ScalarField::zero(), - &domain_points[..threshold], - &refreshed_shares[..threshold], - ); + let new_shared_private_key = + PrivateKeyShare::recover_share_from_updated_private_shares( + &ScalarField::zero(), + &domain_points[..threshold], + &refreshed_shares[..threshold], + ); - assert_eq!( - shared_private_key, - new_shared_private_key.private_key_share - ); + assert_eq!(shared_private_key, new_shared_private_key); } }