Skip to content

Commit

Permalink
fix using bad number of domain points
Browse files Browse the repository at this point in the history
  • Loading branch information
piotr-roslaniec committed Jul 6, 2023
1 parent 8f45430 commit d5ec5e0
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 87 deletions.
9 changes: 8 additions & 1 deletion ferveo/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,12 @@ impl AggregatedTranscript {
aad: &[u8],
validator_keypair: &Keypair,
) -> Result<DecryptionSharePrecomputed> {
let domain_points: Vec<_> = dkg.0.domain.elements().collect();
let domain_points: Vec<_> = dkg
.0
.domain
.elements()
.take(dkg.0.dkg_params.shares_num as usize)
.collect();
self.0.make_decryption_share_simple_precomputed(
ciphertext,
aad,
Expand Down Expand Up @@ -428,6 +433,8 @@ mod test_ferveo_api {
assert!(pvss_aggregated
.verify(shares_num, &messages)
.unwrap());

// And then each validator creates their own decryption share
aggregate
.create_decryption_share_precomputed(
&dkg,
Expand Down
170 changes: 92 additions & 78 deletions ferveo/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,17 +166,17 @@ mod test_dkg_full {
})
.collect();

let domain = &dkg
let domain_points = &dkg
.domain
.elements()
.take(decryption_shares.len())
.collect::<Vec<_>>();
assert_eq!(domain.len(), decryption_shares.len());
assert_eq!(domain_points.len(), decryption_shares.len());

// TODO: Consider refactor this part into tpke::combine_simple and expose it
// as a public API in tpke::api

let lagrange_coeffs = tpke::prepare_combine_simple::<E>(domain);
let lagrange_coeffs = tpke::prepare_combine_simple::<E>(domain_points);
let shared_secret = tpke::share_combine_simple::<E>(
&decryption_shares,
&lagrange_coeffs,
Expand All @@ -189,89 +189,103 @@ mod test_dkg_full {
fn test_dkg_simple_tdec() {
let rng = &mut test_rng();

let (dkg, validator_keypairs) = setup_dealt_dkg_with_n_validators(3, 4);
let msg = "my-msg".as_bytes().to_vec();
let aad: &[u8] = "my-aad".as_bytes();
let public_key = dkg.public_key();
let ciphertext = tpke::encrypt::<E>(
SecretBox::new(msg.clone()),
aad,
&public_key,
rng,
)
.unwrap();
// Works for both power of 2 and non-power of 2
for shares_num in [4, 7] {
let threshold = shares_num / 2 + 1;
let (dkg, validator_keypairs) =
setup_dealt_dkg_with_n_validators(threshold, shares_num);
let msg = "my-msg".as_bytes().to_vec();
let aad: &[u8] = "my-aad".as_bytes();
let public_key = dkg.public_key();
let ciphertext = tpke::encrypt::<E>(
SecretBox::new(msg.clone()),
aad,
&public_key,
rng,
)
.unwrap();

let (_, _, shared_secret) = make_shared_secret_simple_tdec(
&dkg,
aad,
&ciphertext,
&validator_keypairs,
);
let (_, _, shared_secret) = make_shared_secret_simple_tdec(
&dkg,
aad,
&ciphertext,
&validator_keypairs,
);

let plaintext = tpke::decrypt_with_shared_secret(
&ciphertext,
aad,
&shared_secret,
&dkg.pvss_params.g_inv(),
)
.unwrap();
assert_eq!(plaintext, msg);
let plaintext = tpke::decrypt_with_shared_secret(
&ciphertext,
aad,
&shared_secret,
&dkg.pvss_params.g_inv(),
)
.unwrap();
assert_eq!(plaintext, msg);
}
}

#[test]
fn test_dkg_simple_tdec_precomputed() {
let rng = &mut test_rng();

let (dkg, validator_keypairs) = setup_dealt_dkg_with_n_validators(3, 4);
let msg = "my-msg".as_bytes().to_vec();
let aad: &[u8] = "my-aad".as_bytes();
let public_key = dkg.public_key();
let ciphertext = tpke::encrypt::<E>(
SecretBox::new(msg.clone()),
aad,
&public_key,
rng,
)
.unwrap();

let pvss_aggregated = aggregate(&dkg.vss);
pvss_aggregated.verify_aggregation(&dkg).unwrap();
let domain_points = dkg
.domain
.elements()
.take(validator_keypairs.len())
.collect::<Vec<_>>();

let decryption_shares: Vec<DecryptionSharePrecomputed<E>> =
validator_keypairs
.iter()
.enumerate()
.map(|(validator_address, validator_keypair)| {
pvss_aggregated
.make_decryption_share_simple_precomputed(
&ciphertext,
aad,
&validator_keypair.decryption_key,
validator_address,
&domain_points,
&dkg.pvss_params.g_inv(),
)
.unwrap()
})
.collect();

let shared_secret =
tpke::share_combine_precomputed::<E>(&decryption_shares);

// Combination works, let's decrypt
let plaintext = tpke::decrypt_with_shared_secret(
&ciphertext,
aad,
&shared_secret,
&dkg.pvss_params.g_inv(),
)
.unwrap();
assert_eq!(plaintext, msg);
// Works for both power of 2 and non-power of 2
for shares_num in [4, 7] {
// In precomputed variant, threshold must be equal to shares_num
let threshold = shares_num;
let (dkg, validator_keypairs) =
setup_dealt_dkg_with_n_validators(threshold, shares_num);
let msg = "my-msg".as_bytes().to_vec();
let aad: &[u8] = "my-aad".as_bytes();
let public_key = dkg.public_key();
let ciphertext = tpke::encrypt::<E>(
SecretBox::new(msg.clone()),
aad,
&public_key,
rng,
)
.unwrap();

let pvss_aggregated = aggregate(&dkg.vss);
pvss_aggregated.verify_aggregation(&dkg).unwrap();
let domain_points = dkg
.domain
.elements()
.take(validator_keypairs.len())
.collect::<Vec<_>>();

let decryption_shares: Vec<DecryptionSharePrecomputed<E>> =
validator_keypairs
.iter()
.map(|validator_keypair| {
let validator = dkg
.get_validator(&validator_keypair.public_key())
.unwrap();
pvss_aggregated
.make_decryption_share_simple_precomputed(
&ciphertext,
aad,
&validator_keypair.decryption_key,
validator.share_index,
&domain_points,
&dkg.pvss_params.g_inv(),
)
.unwrap()
})
.collect();
assert_eq!(domain_points.len(), decryption_shares.len());

let shared_secret =
tpke::share_combine_precomputed::<E>(&decryption_shares);

// Combination works, let's decrypt
let plaintext = tpke::decrypt_with_shared_secret(
&ciphertext,
aad,
&shared_secret,
&dkg.pvss_params.g_inv(),
)
.unwrap();
assert_eq!(plaintext, msg);
}
}

#[test]
Expand Down
2 changes: 2 additions & 0 deletions ferveo/src/pvss.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@ impl<E: Pairing, T: Aggregate> PubliclyVerifiableSS<E, T> {
)
.map_err(|e| e.into())
}

pub fn make_decryption_share_simple_precomputed(
&self,
ciphertext: &Ciphertext<E>,
Expand All @@ -358,6 +359,7 @@ impl<E: Pairing, T: Aggregate> PubliclyVerifiableSS<E, T> {
let private_key_share = self
.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::<E>(domain_points);

DecryptionSharePrecomputed::new(
Expand Down
4 changes: 2 additions & 2 deletions subproductdomain/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use ark_ec::{
use ark_ff::{FftField, Field, Zero};
use ark_poly::{
univariate::DensePolynomial, DenseUVPolynomial, EvaluationDomain,
Polynomial, Radix2EvaluationDomain,
MixedRadixEvaluationDomain, Polynomial,
};

/// Compute a fast multiexp of many scalars times the same base
Expand Down Expand Up @@ -342,7 +342,7 @@ pub fn toeplitz_mul<E: Pairing, const NORMALIZE: bool>(
let m = polynomial.coeffs.len() - 1;
let size = ark_std::cmp::max(size, m);

let domain = Radix2EvaluationDomain::<E::ScalarField>::new(2 * size)
let domain = MixedRadixEvaluationDomain::<E::ScalarField>::new(2 * size)
.ok_or_else(|| {
anyhow::anyhow!("toeplitz multiplication on too large a domain")
})?;
Expand Down
3 changes: 2 additions & 1 deletion tpke/src/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,8 @@ mod tests {
use ark_poly::EvaluationDomain;
use ark_std::One;
let fft_domain =
ark_poly::Radix2EvaluationDomain::<ScalarField>::new(500).unwrap();
ark_poly::MixedRadixEvaluationDomain::<ScalarField>::new(500)
.unwrap();

let mut domain = Vec::with_capacity(500);
let mut point = ScalarField::one();
Expand Down
1 change: 0 additions & 1 deletion tpke/src/decryption.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,6 @@ impl<E: Pairing> DecryptionSharePrecomputed<E> {
g_inv: &E::G1Prepared,
) -> Result<Self> {
check_ciphertext_validity::<E>(ciphertext, aad, g_inv)?;

Self::create_unchecked(
validator_index,
validator_decryption_key,
Expand Down
12 changes: 8 additions & 4 deletions tpke/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,10 @@ pub mod test_common {
DensePolynomial::<E::ScalarField>::rand(threshold - 1, rng);
// Domain, or omega Ω
let fft_domain =
ark_poly::Radix2EvaluationDomain::<E::ScalarField>::new(shares_num)
.unwrap();
ark_poly::MixedRadixEvaluationDomain::<E::ScalarField>::new(
shares_num,
)
.unwrap();
// `evals` are evaluations of the polynomial f over the domain, omega: f(ω_j) for ω_j in Ω
let evals = threshold_poly.evaluate_over_domain_by_ref(fft_domain);

Expand Down Expand Up @@ -193,8 +195,10 @@ pub mod test_common {
DensePolynomial::<E::ScalarField>::rand(threshold - 1, rng);
// Domain, or omega Ω
let fft_domain =
ark_poly::Radix2EvaluationDomain::<E::ScalarField>::new(shares_num)
.unwrap();
ark_poly::MixedRadixEvaluationDomain::<E::ScalarField>::new(
shares_num,
)
.unwrap();
// `evals` are evaluations of the polynomial f over the domain, omega: f(ω_j) for ω_j in Ω
let evals = threshold_poly.evaluate_over_domain_by_ref(fft_domain);

Expand Down

0 comments on commit d5ec5e0

Please sign in to comment.