use ff::Field;
use crate::{
algebra::{
field::{FieldExtension, SubfieldElement},
BoxedUint,
},
correlated_randomness::pow::types::{PowPair, PowPairs},
izip_eq,
random::{CryptoRngCore, Random, RandomWith},
sharing::{FieldShare, FieldShares, GlobalFieldKey},
types::{heap_array::SubfieldElements, Positive},
};
impl<F: FieldExtension> RandomWith<BoxedUint> for PowPair<F> {
fn random_with(_rng: impl CryptoRngCore, _exp: BoxedUint) -> Self {
unimplemented!("PowPairs are correlated randomness. Use `random_n_with` to establish correlation for n_parties")
}
fn random_n_with<Container: FromIterator<Self>>(
mut rng: impl CryptoRngCore,
n_parties: usize,
exp: BoxedUint,
) -> Container {
let alphas = Vec::<GlobalFieldKey<F>>::random_n_with(&mut rng, n_parties, n_parties - 1);
PowPair::random_n_with(&mut rng, n_parties, (exp, alphas))
}
}
impl<F: FieldExtension> RandomWith<(BoxedUint, Vec<Vec<GlobalFieldKey<F>>>)> for PowPair<F> {
fn random_with(
_rng: impl CryptoRngCore,
_data: (BoxedUint, Vec<Vec<GlobalFieldKey<F>>>),
) -> Self {
unimplemented!("PowPairs are correlated randomness. Use `random_n_with` to establish correlation for n_parties")
}
fn random_n_with<Container: FromIterator<Self>>(
mut rng: impl CryptoRngCore,
n_parties: usize,
(exp, all_alphas): (BoxedUint, Vec<Vec<GlobalFieldKey<F>>>),
) -> Container {
assert_eq!(n_parties, all_alphas.len());
let mut lambda = <SubfieldElement<F> as Random>::random(&mut rng);
let mut lambda_pow_neg_exp = lambda.pow(&exp).invert().into_option();
while lambda_pow_neg_exp.is_none() {
let lambda_new = <SubfieldElement<F> as Random>::random(&mut rng);
let lambda_new_pow_neg_exp = lambda_new.pow(&exp).invert().into_option();
if let Some(lambda_new_pow_neg_exp) = lambda_new_pow_neg_exp {
lambda = lambda_new;
lambda_pow_neg_exp = Some(lambda_new_pow_neg_exp);
break;
}
}
let lambda_shares: Vec<_> =
FieldShare::<F>::random_n_with(&mut rng, n_parties, (lambda, all_alphas.clone()));
let lambda_pow_neg_exp_shares: Vec<_> = FieldShare::<F>::random_n_with(
&mut rng,
n_parties,
(
lambda_pow_neg_exp.expect("We sampled λ so that it was invertible"),
all_alphas,
),
);
izip_eq!(lambda_shares, lambda_pow_neg_exp_shares)
.map(PowPair::new)
.collect()
}
}
impl<F: FieldExtension, N: Positive> RandomWith<BoxedUint> for PowPairs<F, N> {
fn random_with(_rng: impl CryptoRngCore, _exp: BoxedUint) -> Self {
unimplemented!("PowPairs are correlated randomness. Use `random_n_with` to establish correlation for n_parties")
}
fn random_n_with<Container: FromIterator<Self>>(
mut rng: impl CryptoRngCore,
n_parties: usize,
exp: BoxedUint,
) -> Container {
let alphas = Vec::<GlobalFieldKey<F>>::random_n_with(&mut rng, n_parties, n_parties - 1);
PowPairs::random_n_with(&mut rng, n_parties, (exp, alphas))
}
}
impl<F: FieldExtension, M: Positive> RandomWith<(BoxedUint, Vec<Vec<GlobalFieldKey<F>>>)>
for PowPairs<F, M>
{
fn random_with(
_rng: impl CryptoRngCore,
_data: (BoxedUint, Vec<Vec<GlobalFieldKey<F>>>),
) -> Self {
unimplemented!("PowPairs are correlated randomness. Use `random_n_with` to establish correlation for n_parties")
}
fn random_n_with<Container: FromIterator<Self>>(
mut rng: impl CryptoRngCore,
n_parties: usize,
(exp, all_alphas): (BoxedUint, Vec<Vec<GlobalFieldKey<F>>>),
) -> Container {
assert_eq!(n_parties, all_alphas.len());
let lambdas = <SubfieldElements<F, M> as Random>::random(&mut rng);
let lambdas_pow_neg_exp = lambdas.pow(exp).invert().expect("λ^exp is not invertible");
let lambda_shares: Vec<_> =
FieldShares::<F, M>::random_n_with(&mut rng, n_parties, (lambdas, all_alphas.clone()));
let lambda_pow_neg_exp_shares: Vec<_> = FieldShares::<F, M>::random_n_with(
&mut rng,
n_parties,
(lambdas_pow_neg_exp, all_alphas),
);
izip_eq!(lambda_shares, lambda_pow_neg_exp_shares)
.map(PowPairs::new)
.collect()
}
}