arcium-primitives 0.4.4

Arcium primitives
Documentation
use itertools::izip;
use num_traits::identities::{One, Zero};

use crate::{
    algebra::{
        field::{binary::Gf2_128, FieldExtension, SubfieldElement},
        ops::transpose,
    },
    correlated_randomness::dabits::{DaBit, DaBits},
    random::{CryptoRngCore, Random, RandomWith},
    sharing::{BitShare, FieldShare, GlobalFieldKey},
    types::Positive,
};
// -------------------------
// |   Random Generation   |
// -------------------------

impl<F: FieldExtension>
    RandomWith<(
        Vec<Vec<GlobalFieldKey<F>>>,
        Vec<Vec<GlobalFieldKey<Gf2_128>>>,
    )> for DaBit<F>
{
    fn random_with(
        _rng: impl CryptoRngCore,
        _data: (
            Vec<Vec<GlobalFieldKey<F>>>,
            Vec<Vec<GlobalFieldKey<Gf2_128>>>,
        ),
    ) -> Self {
        unimplemented!("DaBits 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,
        (alphas_f, alphas_gf2): (
            Vec<Vec<GlobalFieldKey<F>>>,
            Vec<Vec<GlobalFieldKey<Gf2_128>>>,
        ),
    ) -> Container {
        let bit = SubfieldElement::<Gf2_128>::random(&mut rng);
        let bit_shares: Vec<_> = BitShare::random_n_with(&mut rng, n_parties, (bit, alphas_gf2));

        let field_value = if SubfieldElement::<Gf2_128>::one() == bit {
            SubfieldElement::<F>::one()
        } else {
            SubfieldElement::<F>::zero()
        };
        let field_shares: Vec<_> =
            FieldShare::random_n_with(&mut rng, n_parties, (field_value, alphas_f));

        izip!(bit_shares, field_shares)
            .map(|(bit, field_share)| DaBit::new(bit, field_share))
            .collect()
    }
}

impl<F: FieldExtension, M: Positive>
    RandomWith<(
        Vec<Vec<GlobalFieldKey<F>>>,
        Vec<Vec<GlobalFieldKey<Gf2_128>>>,
    )> for DaBits<F, M>
{
    fn random_with(
        _rng: impl CryptoRngCore,
        _data: (
            Vec<Vec<GlobalFieldKey<F>>>,
            Vec<Vec<GlobalFieldKey<Gf2_128>>>,
        ),
    ) -> Self {
        unimplemented!("DaBits 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,
        (alphas_f, alphas_gf2): (
            Vec<Vec<GlobalFieldKey<F>>>,
            Vec<Vec<GlobalFieldKey<Gf2_128>>>,
        ),
    ) -> Container {
        transpose(
            (0..M::USIZE)
                .map(|_| {
                    DaBit::<F>::random_n_with::<Vec<_>>(
                        &mut rng,
                        n_parties,
                        (alphas_f.clone(), alphas_gf2.clone()),
                    )
                })
                .collect::<Vec<_>>(),
        )
        .into_iter()
        .map(|dabits| {
            let (bits, field_shares) = dabits
                .into_iter()
                .map(|dabit| {
                    let DaBit { bit, field } = dabit;
                    (bit, field)
                })
                .unzip::<_, _, Vec<_>, Vec<_>>();

            let bits = bits.into_iter().collect();
            let field_shares = field_shares.into_iter().collect();

            DaBits::new(bits, field_shares)
        })
        .collect()
    }
}