diff --git a/ferveo-python/test/test_ferveo.py b/ferveo-python/test/test_ferveo.py index 6f00b6df..c3874d40 100644 --- a/ferveo-python/test/test_ferveo.py +++ b/ferveo-python/test/test_ferveo.py @@ -135,6 +135,79 @@ def test_precomputed_tdec_doesnt_have_enough_messages(): FerveoVariant.Precomputed, shares_num=4, threshold=4, shares_to_use=3 ) +def test_dkg_has_min_shares(): + total_shares_num = 5 + min_shares_num = 3 + threshold = 3 + + tau = 1 + validator_keypairs = [Keypair.random() for _ in range(0, total_shares_num)] + validators = [ + Validator(gen_eth_addr(i), keypair.public_key()) + for i, keypair in enumerate(validator_keypairs) + ] + validators.sort(key=lambda v: v.address) + + messages = [] + for sender in validators: + dkg = Dkg( + tau=tau, + shares_num=min_shares_num, + security_threshold=threshold, + validators=validators, + me=sender, + ) + messages.append(ValidatorMessage(sender, dkg.generate_transcript())) + + dkg = Dkg( + tau=tau, + shares_num=min_shares_num, + security_threshold=threshold, + validators=validators, + me=validators[0], + ) + pvss_aggregated = dkg.aggregate_transcripts(messages) + assert pvss_aggregated.verify(min_shares_num, messages) + + dkg_pk_bytes = bytes(dkg.public_key) + dkg_pk = DkgPublicKey.from_bytes(dkg_pk_bytes) + + msg = "abc".encode() + aad = "my-aad".encode() + ciphertext = encrypt(msg, aad, dkg_pk) + + decryption_shares = [] + for validator, validator_keypair in zip(validators, validator_keypairs): + dkg = Dkg( + tau=tau, + shares_num=total_shares_num, + security_threshold=threshold, + validators=validators, + me=validator, + ) + pvss_aggregated = dkg.aggregate_transcripts(messages) + assert pvss_aggregated.verify(total_shares_num, messages) + + decryption_share = decryption_share_for_variant(variant, pvss_aggregated)( + dkg, ciphertext.header, aad, validator_keypair + ) + decryption_shares.append(decryption_share) + + shared_secret = combine_shares_for_variant(variant, decryption_shares) + + if variant == FerveoVariant.Simple and len(decryption_shares) < threshold: + with pytest.raises(ThresholdEncryptionError): + decrypt_with_shared_secret(ciphertext, aad, shared_secret) + return + + if variant == FerveoVariant.Precomputed and len(decryption_shares) < total_shares_num: + with pytest.raises(ThresholdEncryptionError): + decrypt_with_shared_secret(ciphertext, aad, shared_secret) + return + + plaintext = decrypt_with_shared_secret(ciphertext, aad, shared_secret) + assert bytes(plaintext) == msg + PARAMS = [ (1, FerveoVariant.Simple), diff --git a/ferveo-wasm/tests/node.rs b/ferveo-wasm/tests/node.rs index b4234d07..4ac71429 100644 --- a/ferveo-wasm/tests/node.rs +++ b/ferveo-wasm/tests/node.rs @@ -8,8 +8,8 @@ use wasm_bindgen_test::*; type TestSetup = ( u32, - usize, - usize, + u32, + u32, Vec, Vec, ValidatorArray, @@ -21,11 +21,12 @@ type TestSetup = ( fn setup_dkg() -> TestSetup { let tau = 1; - let shares_num = 16; + let shares_num: u32 = 16; let security_threshold = shares_num * 2 / 3; - let validator_keypairs = - (0..shares_num).map(gen_keypair).collect::>(); + let validator_keypairs = (0..shares_num as usize) + .map(gen_keypair) + .collect::>(); let validators = validator_keypairs .iter() .enumerate() @@ -38,8 +39,8 @@ fn setup_dkg() -> TestSetup { let messages = validators.iter().map(|sender| { let dkg = Dkg::new( tau, - shares_num as u32, - security_threshold as u32, + shares_num, + security_threshold, &validators_js, sender, ) @@ -54,8 +55,8 @@ fn setup_dkg() -> TestSetup { let mut dkg = Dkg::new( tau, - shares_num as u32, - security_threshold as u32, + shares_num, + security_threshold, &validators_js, &validators[0], ) @@ -112,8 +113,8 @@ fn tdec_simple() { .map(|(validator, keypair)| { let mut dkg = Dkg::new( tau, - shares_num as u32, - security_threshold as u32, + shares_num, + security_threshold, &validators_js, &validator, ) @@ -166,8 +167,8 @@ fn tdec_precomputed() { .map(|(validator, keypair)| { let mut dkg = Dkg::new( tau, - shares_num as u32, - security_threshold as u32, + shares_num, + security_threshold, &validators_js, &validator, ) diff --git a/ferveo/benches/benchmarks/validity_checks.rs b/ferveo/benches/benchmarks/validity_checks.rs index a6dd9f48..cc7266f7 100644 --- a/ferveo/benches/benchmarks/validity_checks.rs +++ b/ferveo/benches/benchmarks/validity_checks.rs @@ -45,11 +45,7 @@ fn setup_dkg( let me = validators[validator].clone(); PubliclyVerifiableDkg::new( &validators, - &DkgParams { - tau: 0, - security_threshold: shares_num / 3, - shares_num, - }, + &DkgParams::new(0, shares_num / 3, shares_num).unwrap(), &me, ) .expect("Setup failed") diff --git a/ferveo/examples/bench_primitives_size.rs b/ferveo/examples/bench_primitives_size.rs index 18adf673..79afb8a4 100644 --- a/ferveo/examples/bench_primitives_size.rs +++ b/ferveo/examples/bench_primitives_size.rs @@ -80,11 +80,7 @@ fn setup_dkg( let me = validators[validator].clone(); PubliclyVerifiableDkg::new( &validators, - &DkgParams { - tau: 0, - security_threshold, - shares_num, - }, + &DkgParams::new(0, security_threshold, shares_num).unwrap(), &me, ) .expect("Setup failed") diff --git a/ferveo/src/api.rs b/ferveo/src/api.rs index af3edcd4..1221269f 100644 --- a/ferveo/src/api.rs +++ b/ferveo/src/api.rs @@ -203,11 +203,8 @@ impl Dkg { validators: &[Validator], me: &Validator, ) -> Result { - let dkg_params = crate::DkgParams { - tau, - security_threshold, - shares_num, - }; + let dkg_params = + crate::DkgParams::new(tau, security_threshold, shares_num)?; let dkg = crate::PubliclyVerifiableDkg::::new( validators, &dkg_params, @@ -312,7 +309,7 @@ impl AggregatedTranscript { .0 .domain .elements() - .take(dkg.0.dkg_params.shares_num as usize) + .take(dkg.0.dkg_params.shares_num() as usize) .collect(); self.0.make_decryption_share_simple_precomputed( &ciphertext_header.0, @@ -627,6 +624,95 @@ mod test_ferveo_api { } } + #[test] + fn test_server_api_tdec_simple_with_min_shares() { + let rng = &mut StdRng::seed_from_u64(0); + + // Works for both power of 2 and non-power of 2 + for shares_num in [4, 7] { + let tau = 1; + let security_threshold = shares_num - 1; + + let (messages, validators, validator_keypairs) = + make_test_inputs(rng, tau, security_threshold, shares_num); + + // Now that every validator holds a dkg instance and a transcript for every other validator, + // every validator can aggregate the transcripts + let mut dkg = Dkg::new( + tau, + shares_num, + security_threshold, + &validators, + &validators[0], + ) + .unwrap(); + + let pvss_aggregated = dkg.aggregate_transcripts(&messages).unwrap(); + assert!(pvss_aggregated.verify(shares_num, &messages).unwrap()); + + // At this point, any given validator should be able to provide a DKG public key + let public_key = dkg.public_key(); + + // In the meantime, the client creates a ciphertext and decryption request + let msg = "my-msg".as_bytes().to_vec(); + let aad: &[u8] = "my-aad".as_bytes(); + let ciphertext = + encrypt(SecretBox::new(msg.clone()), aad, &public_key).unwrap(); + + // Having aggregated the transcripts, the validators can now create decryption shares + let decryption_shares: Vec<_> = + izip!(&validators, &validator_keypairs) + .map(|(validator, validator_keypair)| { + // Each validator holds their own instance of DKG and creates their own aggregate + let mut dkg = Dkg::new( + tau, + shares_num, + security_threshold, + &validators, + validator, + ) + .unwrap(); + let aggregate = + dkg.aggregate_transcripts(&messages).unwrap(); + assert!(aggregate + .verify(shares_num, &messages) + .unwrap()); + aggregate + .create_decryption_share_simple( + &dkg, + &ciphertext.header().unwrap(), + aad, + validator_keypair, + ) + .unwrap() + }) + .collect(); + + // Now, the decryption share can be used to decrypt the ciphertext + // This part is part of the client API + + // In simple variant, we only need `security_threshold` shares to be able to decrypt + let decryption_shares = + decryption_shares[..security_threshold as usize].to_vec(); + + let shared_secret = combine_shares_simple(&decryption_shares); + let plaintext = + decrypt_with_shared_secret(&ciphertext, aad, &shared_secret) + .unwrap(); + assert_eq!(plaintext, msg); + + // Let's say that we've only received `security_threshold - 1` shares + // In this case, we should not be able to decrypt + let decryption_shares = + decryption_shares[..security_threshold as usize - 1].to_vec(); + + let shared_secret = combine_shares_simple(&decryption_shares); + let result = + decrypt_with_shared_secret(&ciphertext, aad, &shared_secret); + assert!(result.is_err()); + } + } + #[test] fn server_side_local_verification() { let rng = &mut StdRng::seed_from_u64(0); @@ -647,7 +733,7 @@ mod test_ferveo_api { let local_aggregate = dkg.aggregate_transcripts(&messages).unwrap(); assert!(local_aggregate - .verify(dkg.0.dkg_params.shares_num, &messages) + .verify(dkg.0.dkg_params.shares_num(), &messages) .is_ok()); } diff --git a/ferveo/src/bindings_python.rs b/ferveo/src/bindings_python.rs index ed965f3e..00c455a3 100644 --- a/ferveo/src/bindings_python.rs +++ b/ferveo/src/bindings_python.rs @@ -93,7 +93,17 @@ impl From for PyErr { } Error::InvalidVariant(variant) => { InvalidVariant::new_err(variant.to_string()) - } + }, + Error::InvalidDkgParameters(num_shares, security_threshold) => { + InvalidDkgParameters::new_err(format!( + "num_shares: {num_shares}, security_threshold: {security_threshold}" + )) + }, + Error::InvalidShareIndex(index) => { + InvalidShareIndex::new_err(format!( + "{index}" + )) + }, }, _ => default(), } @@ -128,6 +138,8 @@ create_exception!(exceptions, ValidatorPublicKeyMismatch, PyValueError); create_exception!(exceptions, SerializationError, PyValueError); create_exception!(exceptions, InvalidByteLength, PyValueError); create_exception!(exceptions, InvalidVariant, PyValueError); +create_exception!(exceptions, InvalidDkgParameters, PyValueError); +create_exception!(exceptions, InvalidShareIndex, PyValueError); fn from_py_bytes(bytes: &[u8]) -> PyResult { T::from_bytes(bytes) diff --git a/ferveo/src/bindings_wasm.rs b/ferveo/src/bindings_wasm.rs index e412b6e0..5b03f188 100644 --- a/ferveo/src/bindings_wasm.rs +++ b/ferveo/src/bindings_wasm.rs @@ -510,15 +510,13 @@ impl AggregatedTranscript { #[wasm_bindgen] pub fn verify( &self, - shares_num: usize, + shares_num: u32, messages: &ValidatorMessageArray, ) -> JsResult { set_panic_hook(); let messages = unwrap_messages_js(messages)?; - let is_valid = self - .0 - .verify(shares_num as u32, &messages) - .map_err(map_js_err)?; + let is_valid = + self.0.verify(shares_num, &messages).map_err(map_js_err)?; Ok(is_valid) } diff --git a/ferveo/src/dkg.rs b/ferveo/src/dkg.rs index 3f7fc09d..50c475bc 100644 --- a/ferveo/src/dkg.rs +++ b/ferveo/src/dkg.rs @@ -15,9 +15,47 @@ use crate::{ #[derive(Copy, Clone, Debug, Serialize, Deserialize)] pub struct DkgParams { - pub tau: u32, - pub security_threshold: u32, - pub shares_num: u32, + tau: u32, + security_threshold: u32, + shares_num: u32, +} + +impl DkgParams { + /// Create new DKG parameters + /// `tau` is a unique identifier for the DKG (ritual id) + /// `security_threshold` is the minimum number of shares required to reconstruct the key + /// `shares_num` is the total number of shares to be generated + /// Returns an error if the parameters are invalid + /// Parameters must hold: `shares_num` >= `security_threshold` + pub fn new( + tau: u32, + security_threshold: u32, + shares_num: u32, + ) -> Result { + if shares_num < security_threshold { + return Err(Error::InvalidDkgParameters( + shares_num, + security_threshold, + )); + } + Ok(Self { + tau, + security_threshold, + shares_num, + }) + } + + pub fn tau(&self) -> u32 { + self.tau + } + + pub fn security_threshold(&self) -> u32 { + self.security_threshold + } + + pub fn shares_num(&self) -> u32 { + self.shares_num + } } #[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] @@ -77,7 +115,8 @@ impl PubliclyVerifiableDkg { me: &Validator, ) -> Result { let domain = ark_poly::GeneralEvaluationDomain::::new( - dkg_params.shares_num as usize, + // dkg_params.shares_num as usize, + validators.len(), ) .expect("unable to construct domain"); @@ -151,6 +190,7 @@ impl PubliclyVerifiableDkg { } } + // TODO: Make private, use `share` instead pub fn create_share( &self, rng: &mut R, @@ -348,22 +388,32 @@ pub(crate) mod test_common { pub type TestSetup = (PubliclyVerifiableDkg, Vec>); - pub fn setup_dkg_for_n_validators( + pub fn setup_dkg_for_me( security_threshold: u32, shares_num: u32, my_index: usize, ) -> TestSetup { - let keypairs = gen_keypairs(shares_num); + setup_dkg_for_me_with_n_validators( + security_threshold, + shares_num, + my_index, + shares_num, + ) + } + + pub fn setup_dkg_for_me_with_n_validators( + security_threshold: u32, + shares_num: u32, + my_index: usize, + n_validators: u32, + ) -> TestSetup { + let keypairs = gen_keypairs(n_validators); let mut validators = gen_validators(keypairs.as_slice()); validators.sort(); let me = validators[my_index].clone(); let dkg = PubliclyVerifiableDkg::new( &validators, - &DkgParams { - tau: 0, - security_threshold, - shares_num, - }, + &DkgParams::new(0, security_threshold, shares_num).unwrap(), &me, ) .expect("Setup failed"); @@ -373,8 +423,8 @@ pub(crate) mod test_common { /// Create a test dkg /// /// The [`test_dkg_init`] module checks correctness of this setup - pub fn setup_dkg(validator: usize) -> TestSetup { - setup_dkg_for_n_validators(2, 4, validator) + pub fn setup_dkg() -> TestSetup { + setup_dkg_for_me(2, 4, 0) } /// Set up a dkg with enough pvss transcripts to meet the threshold @@ -393,7 +443,7 @@ pub(crate) mod test_common { // Gather everyone's transcripts let messages: Vec<_> = (0..shares_num) .map(|my_index| { - let (mut dkg, _) = setup_dkg_for_n_validators( + let (mut dkg, _) = setup_dkg_for_me( security_threshold, shares_num, my_index as usize, @@ -406,7 +456,8 @@ pub(crate) mod test_common { // Create a test DKG instance let (mut dkg, keypairs) = - setup_dkg_for_n_validators(security_threshold, shares_num, 0); + setup_dkg_for_me(security_threshold, shares_num, 0); + messages.iter().for_each(|(sender, message)| { dkg.apply_message(sender, message).expect("Setup failed"); }); @@ -454,25 +505,34 @@ mod test_dealing { use super::test_common::*; use crate::DkgState::Dealt; - /// Test that dealing correct PVSS transcripts - /// pass verification an application and that - /// state is updated correctly - #[test] - fn test_pvss_dealing() { - let rng = &mut ark_std::test_rng(); + fn assert_pvss_dealing( + threshold: u32, + shares_num: u32, + validator_num: u32, + ) { + // Create a test DKG instance + let (mut dkg, _) = setup_dkg_for_me_with_n_validators( + threshold, + shares_num, + 0, + validator_num, + ); // Gather everyone's transcripts let mut messages = vec![]; - for i in 0..4 { - let (mut dkg, _) = setup_dkg(i); + let rng = &mut ark_std::test_rng(); + for i in 0..validator_num { + let (mut dkg, _) = setup_dkg_for_me_with_n_validators( + threshold, + shares_num, + i as usize, + validator_num, + ); let message = dkg.share(rng).unwrap(); let sender = dkg.me.validator.clone(); messages.push((sender, message)); } - // Create a test DKG instance - let (mut dkg, _) = setup_dkg(0); - let mut expected = 0u32; for (sender, pvss) in messages.iter() { // Check the verification passes @@ -483,7 +543,7 @@ mod test_dealing { expected += 1; if expected < dkg.dkg_params.security_threshold { - // check that shares accumulates correctly + // Check that shares accumulates correctly match dkg.state { DkgState::Sharing { accumulated_shares, .. @@ -499,13 +559,30 @@ mod test_dealing { } } + /// Test that dealing correct PVSS transcripts pass verification an application and that + /// state is updated correctly + #[test] + fn test_pvss_dealing() { + let threshold = 3; + let shares_num = 4; + assert_pvss_dealing(threshold, shares_num, shares_num); + } + + #[test] + fn test_pvss_dealing_with_extra_shares() { + let threshold = 3; + let shares_num = 4; + let validator_num = shares_num + 2; + assert_pvss_dealing(threshold, shares_num, validator_num); + } + /// Test the verification and application of /// pvss transcripts from unknown validators /// are rejected #[test] fn test_pvss_from_unknown_dealer_rejected() { let rng = &mut ark_std::test_rng(); - let (mut dkg, _) = setup_dkg(0); + let (mut dkg, _) = setup_dkg(); assert!(matches!( dkg.state, DkgState::Sharing { @@ -538,7 +615,7 @@ mod test_dealing { #[test] fn test_pvss_sent_twice_rejected() { let rng = &mut ark_std::test_rng(); - let (mut dkg, _) = setup_dkg(0); + let (mut dkg, _) = setup_dkg(); // We start with an empty state assert!(matches!( dkg.state, @@ -573,7 +650,7 @@ mod test_dealing { #[test] fn test_own_pvss() { let rng = &mut ark_std::test_rng(); - let (mut dkg, _) = setup_dkg(0); + let (mut dkg, _) = setup_dkg(); // We start with an empty state assert!(matches!( dkg.state, @@ -613,7 +690,7 @@ mod test_dealing { #[test] fn test_pvss_cannot_share_from_wrong_state() { let rng = &mut ark_std::test_rng(); - let (mut dkg, _) = setup_dkg(0); + let (mut dkg, _) = setup_dkg(); assert!(matches!( dkg.state, DkgState::Sharing { @@ -638,7 +715,7 @@ mod test_dealing { #[test] fn test_share_message_state_guards() { let rng = &mut ark_std::test_rng(); - let (mut dkg, _) = setup_dkg(0); + let (mut dkg, _) = setup_dkg(); let pvss = dkg.share(rng).unwrap(); assert!(matches!( dkg.state, @@ -751,3 +828,21 @@ mod test_aggregation { assert!(dkg.verify_message(&sender, &aggregate).is_err()); } } + +/// Test DKG parameters +#[cfg(test)] +mod test_dkg_params { + const TAU: u32 = 0; + + #[test] + fn test_shares_num_less_than_security_threshold() { + let dkg_params = super::DkgParams::new(TAU, 4, 3); + assert!(dkg_params.is_err()); + } + + #[test] + fn test_valid_dkg_params() { + let dkg_params = super::DkgParams::new(TAU, 2, 3); + assert!(dkg_params.is_ok()); + } +} diff --git a/ferveo/src/lib.rs b/ferveo/src/lib.rs index 59a44024..4a29f099 100644 --- a/ferveo/src/lib.rs +++ b/ferveo/src/lib.rs @@ -101,6 +101,12 @@ pub enum Error { #[error("Invalid variant: {0}")] InvalidVariant(String), + + #[error("Invalid DKG parameters: number of shares {0}, threshold {1}")] + InvalidDkgParameters(u32, u32), + + #[error("Invalid share index: {0}")] + InvalidShareIndex(u32), } pub type Result = std::result::Result; @@ -410,7 +416,7 @@ mod test_dkg_full { &domain_points, &dkg.pvss_params.h.into_affine(), &x_r, - dkg.dkg_params.security_threshold as usize, + dkg.dkg_params.security_threshold() as usize, rng, ); (v_addr.clone(), deltas_i) @@ -439,11 +445,13 @@ mod test_dkg_full { // Creates updated private key shares // TODO: Why not using dkg.aggregate()? let pvss_aggregated = aggregate(&dkg.vss); - pvss_aggregated.update_private_key_share_for_recovery( - &decryption_key, - validator.share_index, - updates_for_participant.as_slice(), - ) + pvss_aggregated + .update_private_key_share_for_recovery( + &decryption_key, + validator.share_index, + updates_for_participant.as_slice(), + ) + .unwrap() }) .collect(); @@ -552,7 +560,7 @@ mod test_dkg_full { let deltas_i = prepare_share_updates_for_refresh::( &domain_points, &dkg.pvss_params.h.into_affine(), - dkg.dkg_params.security_threshold as usize, + dkg.dkg_params.security_threshold() as usize, rng, ); (v_addr.clone(), deltas_i) @@ -582,11 +590,13 @@ mod test_dkg_full { // Creates updated private key shares // TODO: Why not using dkg.aggregate()? let pvss_aggregated = aggregate(&dkg.vss); - pvss_aggregated.update_private_key_share_for_recovery( - &decryption_key, - validator.share_index, - updates_for_participant.as_slice(), - ) + pvss_aggregated + .update_private_key_share_for_recovery( + &decryption_key, + validator.share_index, + updates_for_participant.as_slice(), + ) + .unwrap() }) .collect(); diff --git a/ferveo/src/pvss.rs b/ferveo/src/pvss.rs index 4f63da82..99a3b686 100644 --- a/ferveo/src/pvss.rs +++ b/ferveo/src/pvss.rs @@ -138,7 +138,7 @@ impl PubliclyVerifiableSS { ) -> Result { let phi = SecretPolynomial::::new( s, - (dkg.dkg_params.security_threshold - 1) as usize, + (dkg.dkg_params.security_threshold() - 1) as usize, rng, ); @@ -158,10 +158,11 @@ impl PubliclyVerifiableSS { )[0] }) .collect::>>(); - if shares.len() != dkg.validators.len() { + + if shares.len() < dkg.dkg_params.shares_num() as usize { return Err(Error::InsufficientValidators( shares.len() as u32, - dkg.validators.len() as u32, + dkg.dkg_params.shares_num(), )); } @@ -311,19 +312,19 @@ impl PubliclyVerifiableSS { &self, validator_decryption_key: &E::ScalarField, share_index: usize, - ) -> PrivateKeyShare { + ) -> Result> { // Decrypt private key shares https://nikkolasg.github.io/ferveo/pvss.html#validator-decryption-of-private-key-shares let private_key_share = self .shares .get(share_index) - .unwrap() + .ok_or(Error::InvalidShareIndex(share_index as u32))? .mul( validator_decryption_key .inverse() .expect("Validator decryption key must have an inverse"), ) .into_affine(); - PrivateKeyShare { private_key_share } + Ok(PrivateKeyShare { private_key_share }) } pub fn make_decryption_share_simple( @@ -335,7 +336,7 @@ impl PubliclyVerifiableSS { g_inv: &E::G1Prepared, ) -> Result> { let private_key_share = self - .decrypt_private_key_share(validator_decryption_key, share_index); + .decrypt_private_key_share(validator_decryption_key, share_index)?; DecryptionShareSimple::create( validator_decryption_key, &private_key_share, @@ -356,7 +357,7 @@ impl PubliclyVerifiableSS { g_inv: &E::G1Prepared, ) -> Result> { let private_key_share = self - .decrypt_private_key_share(validator_decryption_key, share_index); + .decrypt_private_key_share(validator_decryption_key, share_index)?; // We use the `prepare_combine_simple` function to precompute the lagrange coefficients let lagrange_coeffs = prepare_combine_simple::(domain_points); @@ -379,13 +380,16 @@ impl PubliclyVerifiableSS { validator_decryption_key: &E::ScalarField, share_index: usize, share_updates: &[E::G2], - ) -> PrivateKeyShare { + ) -> Result> { // Retrieves their private key share let private_key_share = self - .decrypt_private_key_share(validator_decryption_key, share_index); + .decrypt_private_key_share(validator_decryption_key, share_index)?; // And updates their share - apply_updates_to_private_share::(&private_key_share, share_updates) + Ok(apply_updates_to_private_share::( + &private_key_share, + share_updates, + )) } } @@ -473,7 +477,7 @@ mod test_pvss { #[test] fn test_new_pvss() { let rng = &mut ark_std::test_rng(); - let (dkg, _) = setup_dkg(0); + let (dkg, _) = setup_dkg(); let s = ScalarField::rand(rng); let pvss = PubliclyVerifiableSS::::new(&s, &dkg, rng) .expect("Test failed"); @@ -482,7 +486,7 @@ mod test_pvss { // Check that a polynomial of the correct degree was created assert_eq!( pvss.coeffs.len(), - dkg.dkg_params.security_threshold as usize + dkg.dkg_params.security_threshold() as usize ); // Check that the correct number of shares were created assert_eq!(pvss.shares.len(), dkg.validators.len()); @@ -499,7 +503,7 @@ mod test_pvss { #[test] fn test_verify_pvss_wrong_proof_of_knowledge() { let rng = &mut ark_std::test_rng(); - let (dkg, _) = setup_dkg(0); + let (dkg, _) = setup_dkg(); let mut s = ScalarField::rand(rng); // Ensure that the proof of knowledge is not zero while s == ScalarField::zero() { @@ -517,7 +521,7 @@ mod test_pvss { #[test] fn test_verify_pvss_bad_shares() { let rng = &mut ark_std::test_rng(); - let (dkg, _) = setup_dkg(0); + let (dkg, _) = setup_dkg(); let s = ScalarField::rand(rng); let pvss = PubliclyVerifiableSS::::new(&s, &dkg, rng).unwrap(); @@ -543,7 +547,6 @@ mod test_pvss { let rng = &mut ark_std::test_rng(); let shares_num = 4; - let security_threshold = shares_num - 1; let keypairs = gen_keypairs(shares_num); let mut validators = gen_validators(&keypairs); let me = validators[0].clone(); @@ -555,11 +558,7 @@ mod test_pvss { // And because of that the DKG should fail let result = PubliclyVerifiableDkg::new( &validators, - &DkgParams { - tau: 0, - security_threshold, - shares_num, - }, + &DkgParams::new(0, 2, shares_num).unwrap(), &me, ); assert!(result.is_err()); @@ -578,7 +577,7 @@ mod test_pvss { // Check that a polynomial of the correct degree was created assert_eq!( aggregate.coeffs.len(), - dkg.dkg_params.security_threshold as usize + dkg.dkg_params.security_threshold() as usize ); // Check that the correct number of shares were created assert_eq!(aggregate.shares.len(), dkg.validators.len()); @@ -597,7 +596,7 @@ mod test_pvss { let (dkg, _) = setup_dealt_dkg(); let mut aggregated = aggregate(&dkg.vss); while aggregated.coeffs[0] == G1::zero() { - let (dkg, _) = setup_dkg(0); + let (dkg, _) = setup_dkg(); aggregated = aggregate(&dkg.vss); } aggregated.coeffs[0] = G1::zero();