Skip to main content

primitives/correlated_randomness/pow/
random.rs

1use ff::Field;
2
3use crate::{
4    algebra::{
5        field::{FieldExtension, SubfieldElement},
6        BoxedUint,
7    },
8    correlated_randomness::pow::types::{PowPair, PowPairs},
9    izip_eq,
10    random::{CryptoRngCore, Random, RandomWith},
11    sharing::{FieldShare, FieldShares, GlobalFieldKey},
12    types::{heap_array::SubfieldElements, Positive},
13};
14// -------------------------
15// |   Random Generation   |
16// -------------------------
17
18impl<F: FieldExtension> RandomWith<BoxedUint> for PowPair<F> {
19    fn random_with(_rng: impl CryptoRngCore, _exp: BoxedUint) -> Self {
20        unimplemented!("PowPairs are correlated randomness. Use `random_n_with` to establish correlation for n_parties")
21    }
22
23    fn random_n_with<Container: FromIterator<Self>>(
24        mut rng: impl CryptoRngCore,
25        n_parties: usize,
26        exp: BoxedUint,
27    ) -> Container {
28        let alphas = Vec::<GlobalFieldKey<F>>::random_n_with(&mut rng, n_parties, n_parties - 1);
29        PowPair::random_n_with(&mut rng, n_parties, (exp, alphas))
30    }
31}
32
33impl<F: FieldExtension> RandomWith<(BoxedUint, Vec<Vec<GlobalFieldKey<F>>>)> for PowPair<F> {
34    fn random_with(
35        _rng: impl CryptoRngCore,
36        _data: (BoxedUint, Vec<Vec<GlobalFieldKey<F>>>),
37    ) -> Self {
38        unimplemented!("PowPairs are correlated randomness. Use `random_n_with` to establish correlation for n_parties")
39    }
40
41    /// Generates a vector of `n_parties` `PowPair`s, where each `PowPair` is
42    /// generated with the same `exp` and authenticated toward all other parties.
43    fn random_n_with<Container: FromIterator<Self>>(
44        mut rng: impl CryptoRngCore,
45        n_parties: usize,
46        (exp, all_alphas): (BoxedUint, Vec<Vec<GlobalFieldKey<F>>>),
47    ) -> Container {
48        assert_eq!(n_parties, all_alphas.len());
49
50        let mut lambda = <SubfieldElement<F> as Random>::random(&mut rng);
51        let mut lambda_pow_neg_exp = lambda.pow(&exp).invert().into_option();
52        while lambda_pow_neg_exp.is_none() {
53            // If λ^(-exp) is not invertible, we need to resample λ until we get an invertible one.
54            let lambda_new = <SubfieldElement<F> as Random>::random(&mut rng);
55            let lambda_new_pow_neg_exp = lambda_new.pow(&exp).invert().into_option();
56            if let Some(lambda_new_pow_neg_exp) = lambda_new_pow_neg_exp {
57                lambda = lambda_new;
58                lambda_pow_neg_exp = Some(lambda_new_pow_neg_exp);
59                break;
60            }
61        }
62
63        let lambda_shares: Vec<_> =
64            FieldShare::<F>::random_n_with(&mut rng, n_parties, (lambda, all_alphas.clone()));
65        let lambda_pow_neg_exp_shares: Vec<_> = FieldShare::<F>::random_n_with(
66            &mut rng,
67            n_parties,
68            (
69                lambda_pow_neg_exp.expect("We sampled λ so that it was invertible"),
70                all_alphas,
71            ),
72        );
73
74        izip_eq!(lambda_shares, lambda_pow_neg_exp_shares)
75            .map(PowPair::new)
76            .collect()
77    }
78}
79
80impl<F: FieldExtension, N: Positive> RandomWith<BoxedUint> for PowPairs<F, N> {
81    fn random_with(_rng: impl CryptoRngCore, _exp: BoxedUint) -> Self {
82        unimplemented!("PowPairs are correlated randomness. Use `random_n_with` to establish correlation for n_parties")
83    }
84
85    fn random_n_with<Container: FromIterator<Self>>(
86        mut rng: impl CryptoRngCore,
87        n_parties: usize,
88        exp: BoxedUint,
89    ) -> Container {
90        let alphas = Vec::<GlobalFieldKey<F>>::random_n_with(&mut rng, n_parties, n_parties - 1);
91        PowPairs::random_n_with(&mut rng, n_parties, (exp, alphas))
92    }
93}
94
95impl<F: FieldExtension, M: Positive> RandomWith<(BoxedUint, Vec<Vec<GlobalFieldKey<F>>>)>
96    for PowPairs<F, M>
97{
98    fn random_with(
99        _rng: impl CryptoRngCore,
100        _data: (BoxedUint, Vec<Vec<GlobalFieldKey<F>>>),
101    ) -> Self {
102        unimplemented!("PowPairs are correlated randomness. Use `random_n_with` to establish correlation for n_parties")
103    }
104
105    fn random_n_with<Container: FromIterator<Self>>(
106        mut rng: impl CryptoRngCore,
107        n_parties: usize,
108        (exp, all_alphas): (BoxedUint, Vec<Vec<GlobalFieldKey<F>>>),
109    ) -> Container {
110        assert_eq!(n_parties, all_alphas.len());
111
112        // TODO: lambdas = <SubfieldElements<F, M> as RandomNonZero>::random_non_zero(rng);
113        let lambdas = <SubfieldElements<F, M> as Random>::random(&mut rng);
114        let lambdas_pow_neg_exp = lambdas.pow(exp).invert().expect("λ^exp is not invertible");
115
116        let lambda_shares: Vec<_> =
117            FieldShares::<F, M>::random_n_with(&mut rng, n_parties, (lambdas, all_alphas.clone()));
118        let lambda_pow_neg_exp_shares: Vec<_> = FieldShares::<F, M>::random_n_with(
119            &mut rng,
120            n_parties,
121            (lambdas_pow_neg_exp, all_alphas),
122        );
123
124        izip_eq!(lambda_shares, lambda_pow_neg_exp_shares)
125            .map(PowPairs::new)
126            .collect()
127    }
128}