use std::fmt::Debug;
use primitives::{
algebra::{
field::{binary::Gf2_128, FieldExtension},
BoxedUint,
},
correlated_randomness::{
dabits::{DaBit, DaBits},
pow::{PowPair, PowPairs},
singlets::{Singlet, Singlets},
triples::{Triple, Triples},
},
hashing::hash,
random::{BaseRng, CryptoRngCore, Random, RandomWith, Seed, SeedableRng},
sharing::GlobalFieldKey,
types::Positive,
utils::IntoExactSizeIterator,
};
use zeroize::Zeroize;
use super::{TestBatchSize, TrustedGenerator};
#[derive(Clone, Debug)]
pub struct GlobalDealer<M = TestBatchSize> {
n_parties: usize,
alphas_seed: Seed,
rng: BaseRng,
_marker: std::marker::PhantomData<M>,
}
impl<M> Drop for GlobalDealer<M> {
fn drop(&mut self) {
self.alphas_seed.zeroize();
}
}
impl<M> GlobalDealer<M> {
pub fn new_with(n_parties: usize, alphas_seed: Seed) -> Self {
let rng_seed = hash(&[alphas_seed.as_ref(), "global dealer".as_bytes()]).into();
Self {
n_parties,
alphas_seed,
rng: BaseRng::from_seed(rng_seed),
_marker: std::marker::PhantomData,
}
}
pub fn new(n_parties: usize) -> Self {
let alphas_seed = Seed::random(&mut rand::thread_rng());
Self::new_with(n_parties, alphas_seed)
}
pub fn n_parties(&self) -> usize {
self.n_parties
}
}
impl<M> RandomWith<usize> for GlobalDealer<M> {
fn random_with(mut rng: impl CryptoRngCore, n_parties: usize) -> Self {
Self {
n_parties,
alphas_seed: Seed::random(&mut rng),
rng: BaseRng::from_rng(&mut rng).unwrap(),
_marker: std::marker::PhantomData,
}
}
}
impl<M> GlobalDealer<M> {
#[inline]
pub fn get_alphas<F: FieldExtension>(&self) -> Vec<Vec<GlobalFieldKey<F>>> {
#[cfg(not(feature = "compatibility"))]
let mut alphas_rng = BaseRng::from_tagged_seed(self.alphas_seed, F::get_name());
#[cfg(feature = "compatibility")]
let mut alphas_rng = BaseRng::from_seed(self.alphas_seed);
let alphas: Vec<Vec<GlobalFieldKey<F>>> = (0..self.n_parties)
.map(|_| GlobalFieldKey::<F>::random_n(&mut alphas_rng, self.n_parties - 1))
.collect();
#[cfg(not(feature = "compatibility"))]
if F::get_name() == Gf2_128::get_name() {
for (i, alphas_i) in alphas.iter_mut().enumerate() {
for j in 0..self.n_parties {
if i == j {
continue;
}
let pos = if j < i { j } else { j - 1 };
let target_lsb = u8::from(i > j);
let current = alphas_i[pos].inner();
if current.to_le_bytes()[0] & 1 != target_lsb {
let tweaked = current + F::from(1u128);
alphas_i[pos] = GlobalFieldKey::new(FieldElement::new(tweaked));
}
}
}
}
alphas
}
}
impl<F: FieldExtension, M: Positive> TrustedGenerator<Singlet<F>> for GlobalDealer<M> {
#[inline]
fn generate_batch_for_each(
&mut self,
_associated_data: (),
) -> impl ExactSizeIterator<Item = impl IntoExactSizeIterator<Item = Singlet<F>>> {
let all_alphas = self.get_alphas::<F>();
let singlet_batch: Vec<_> = Singlets::<F, M>::random_n_with_each(&mut self.rng, all_alphas);
singlet_batch.into_iter()
}
}
impl<F: FieldExtension, M: Positive> TrustedGenerator<Triple<F>> for GlobalDealer<M> {
#[inline]
fn generate_batch_for_each(
&mut self,
_associated_data: (),
) -> impl ExactSizeIterator<Item = impl IntoExactSizeIterator<Item = Triple<F>>> {
let all_alphas = self.get_alphas::<F>();
let triple_batch: Vec<_> = Triples::<F, M>::random_n_with_each(&mut self.rng, all_alphas);
triple_batch.into_iter()
}
}
impl<F: FieldExtension, M: Positive> TrustedGenerator<PowPair<F>> for GlobalDealer<M> {
#[inline]
fn generate_batch_for_each(
&mut self,
exponent: BoxedUint,
) -> impl ExactSizeIterator<Item = impl IntoExactSizeIterator<Item = PowPair<F>>> {
let all_alphas = self.get_alphas::<F>();
let pow_pairs_batch: Vec<_> = PowPairs::<F, M>::random_n_with(
&mut self.rng,
self.n_parties,
(exponent.clone(), all_alphas),
);
pow_pairs_batch.into_iter()
}
}
impl<F: FieldExtension, M: Positive> TrustedGenerator<DaBit<F>> for GlobalDealer<M> {
#[inline]
fn generate_batch_for_each(
&mut self,
_associated_data: (),
) -> impl ExactSizeIterator<Item = impl IntoExactSizeIterator<Item = DaBit<F>>> {
let alphas_f = self.get_alphas::<F>();
let alphas_gf2 = self.get_alphas::<Gf2_128>();
let dabit_batch: Vec<_> =
DaBits::<F, M>::random_n_with(&mut self.rng, self.n_parties, (alphas_f, alphas_gf2));
dabit_batch.into_iter()
}
}
#[cfg(test)]
mod tests {
use primitives::{
algebra::elliptic_curve::{Curve, Curve25519Ristretto as C},
sharing::{Verifiable, VerifiableWith},
};
use super::*;
use crate::preprocessing::dealer::mock::MockDealer;
type M = typenum::U5;
type F = <C as Curve>::Scalar;
const N_PARTIES: usize = 3;
pub fn generate_local_dealers<M: Positive>(n_parties: usize, seed: Seed) -> Vec<MockDealer<M>> {
(0..n_parties)
.map(|local_party_pos| MockDealer::new(n_parties, local_party_pos, seed))
.collect()
}
#[tokio::test]
async fn test_local_dealers_triples() {
let seed = Seed::random(&mut primitives::random::test_rng());
let n_triples = 11;
let mut dealers = generate_local_dealers::<M>(N_PARTIES, seed);
let mut triples: Vec<Vec<Triple<F>>> = vec![];
for dealer in dealers.iter_mut() {
triples.push(
futures::future::try_join_all(dealer.request_n_triples(n_triples))
.await
.unwrap(),
)
}
assert_eq!(triples.len(), N_PARTIES);
triples.iter().for_each(|s| {
assert_eq!(s.len(), n_triples);
});
for i in 0..n_triples {
let triple = triples.iter().map(|s| s[i].clone()).collect::<Vec<_>>();
Triple::verify_all(triple).unwrap();
}
}
#[tokio::test]
async fn test_local_dealers_pow_pairs() {
let seed = Seed::random(&mut primitives::random::test_rng());
let n_pow_pairs = 17;
let exponent = BoxedUint::from(4u32);
let mut dealers = generate_local_dealers::<M>(N_PARTIES, seed);
let mut pow_pairs: Vec<Vec<PowPair<F>>> = vec![];
for dealer in dealers.iter_mut() {
pow_pairs.push(
futures::future::try_join_all(
dealer.request_n_pow_pairs(n_pow_pairs, exponent.clone()),
)
.await
.unwrap(),
)
}
assert_eq!(pow_pairs.len(), N_PARTIES);
pow_pairs.iter().for_each(|s| {
assert_eq!(s.len(), n_pow_pairs);
});
for i in 0..n_pow_pairs {
let pow_pair_vec = pow_pairs.iter().map(|s| s[i].clone()).collect::<Vec<_>>();
PowPair::verify_all_with(pow_pair_vec, exponent.clone()).unwrap();
}
}
#[tokio::test]
async fn test_global_queues_singlets() {
let seed = Seed::random(&mut primitives::random::test_rng());
let n_singlets = 13;
let mut dealer = GlobalDealer::<M>::new_with(N_PARTIES, seed);
let singlets: Vec<Vec<Singlet<F>>> = dealer.generate_n_for_each(n_singlets, ());
assert_eq!(singlets.len(), N_PARTIES);
singlets.iter().for_each(|s| {
assert_eq!(s.len(), n_singlets);
});
for i in 0..n_singlets {
let singlet = singlets.iter().map(|s| s[i].clone()).collect::<Vec<_>>();
Singlet::verify_all(singlet).unwrap();
}
}
#[tokio::test]
async fn test_global_queues_triples() {
let seed = Seed::random(&mut primitives::random::test_rng());
let n_triples = 11;
let mut dealer = GlobalDealer::<M>::new_with(N_PARTIES, seed);
let triples: Vec<Vec<Triple<F>>> = dealer.generate_n_for_each(n_triples, ());
assert_eq!(triples.len(), N_PARTIES);
triples.iter().for_each(|s| {
assert_eq!(s.len(), n_triples);
});
for i in 0..n_triples {
let triple = triples.iter().map(|s| s[i].clone()).collect::<Vec<_>>();
Triple::verify_all(triple).unwrap();
}
}
#[tokio::test]
async fn test_global_dealer_singlets() {
let seed = Seed::random(&mut primitives::random::test_rng());
let n_singlets = 13;
let mut dealer = GlobalDealer::<M>::new_with(N_PARTIES, seed);
let singlets: Vec<Vec<Singlet<F>>> = dealer.generate_n_for_each(n_singlets, ());
assert_eq!(singlets.len(), N_PARTIES);
singlets.iter().for_each(|s| {
assert_eq!(s.len(), n_singlets);
});
for i in 0..n_singlets {
let singlet = singlets.iter().map(|s| s[i].clone()).collect::<Vec<_>>();
Singlet::verify_all(singlet).unwrap();
}
}
#[tokio::test]
async fn test_global_dealer_triples() {
let seed = Seed::random(&mut primitives::random::test_rng());
let n_triples = 11;
let mut dealer = GlobalDealer::<M>::new_with(N_PARTIES, seed);
let triples: Vec<Vec<Triple<F>>> = dealer.generate_n_for_each(n_triples, ());
assert_eq!(triples.len(), N_PARTIES);
triples.iter().for_each(|s| {
assert_eq!(s.len(), n_triples);
});
for i in 0..n_triples {
let triple = triples.iter().map(|s| s[i].clone()).collect::<Vec<_>>();
Triple::verify_all(triple).unwrap();
}
}
#[tokio::test]
async fn test_global_dealer_pow_pairs() {
let seed = Seed::random(&mut primitives::random::test_rng());
let n_pow_pairs = 17;
let exponent = BoxedUint::from(4u32);
let mut dealer = GlobalDealer::<M>::new_with(N_PARTIES, seed);
let pow_pairs: Vec<Vec<PowPair<F>>> =
dealer.generate_n_for_each(n_pow_pairs, exponent.clone());
assert_eq!(pow_pairs.len(), N_PARTIES);
pow_pairs.iter().for_each(|s| {
assert_eq!(s.len(), n_pow_pairs);
});
for i in 0..n_pow_pairs {
let pow_pair_vec = pow_pairs.iter().map(|s| s[i].clone()).collect::<Vec<_>>();
PowPair::verify_all_with(pow_pair_vec, exponent.clone()).unwrap();
}
}
}