arcium-primitives 0.4.2

Arcium primitives
Documentation
pub mod random;
pub mod sharing;
pub mod types;

pub use types::*;

#[cfg(test)]
mod tests {
    use crypto_bigint::{Random as _, U256};
    use ff::Field;

    use super::*;
    use crate::{
        algebra::{
            elliptic_curve::{Curve25519Ristretto, ScalarField},
            BoxedUint,
        },
        random::RandomWith,
        sharing::{GlobalFieldKey, Reconstructible},
    };

    pub type Fq = ScalarField<Curve25519Ristretto>;
    pub type BatchSize = typenum::U8;

    #[test]
    fn test_random_with_boxed_uint_generates_valid_pow_pairs() {
        let mut rng = crate::random::test_rng();
        let n_parties = 3;
        let exp = BoxedUint::from(U256::random(&mut rng));

        // Generate multiple sets of PowPairs and verify they're all valid
        for _ in 0..10 {
            let pow_pairs: Vec<PowPair<Fq>> =
                PowPair::random_n_with(&mut rng, n_parties, exp.clone());

            assert_eq!(pow_pairs.len(), n_parties);

            let (lambda, lambda_pow_neg_exp) = PowPair::<Fq>::reconstruct_all(pow_pairs).unwrap();
            let expected_lambda_pow_neg_exp = lambda.pow(exp.clone()).invert().unwrap();
            assert_eq!(lambda_pow_neg_exp, expected_lambda_pow_neg_exp);
        }
    }

    #[test]
    fn test_random_with_alphas_generates_valid_pow_pairs() {
        let mut rng = crate::random::test_rng();
        let n_parties = 4;
        let exp = BoxedUint::from(U256::random(&mut rng));

        // Generate alphas for each party
        let all_alphas: Vec<Vec<GlobalFieldKey<Fq>>> =
            Vec::random_n_with(&mut rng, n_parties, n_parties - 1);

        // Generate multiple sets of PowPairs and verify they're all valid
        for _ in 0..10 {
            let pow_pairs: Vec<PowPair<Fq>> =
                PowPair::random_n_with(&mut rng, n_parties, (exp.clone(), all_alphas.clone()));

            assert_eq!(pow_pairs.len(), n_parties);

            let (lambda, lambda_pow_neg_exp) = PowPair::<Fq>::reconstruct_all(pow_pairs).unwrap();
            let expected_lambda_pow_neg_exp = lambda.pow(exp.clone()).invert().unwrap();
            assert_eq!(lambda_pow_neg_exp, expected_lambda_pow_neg_exp);
        }
    }

    #[test]
    fn test_pow_pairs_random_with_boxed_uint() {
        let mut rng = crate::random::test_rng();
        let n_parties = 3;
        let exp = BoxedUint::from(U256::random(&mut rng));

        let pow_pairs_batch: Vec<PowPairs<Fq, BatchSize>> =
            PowPairs::random_n_with(&mut rng, n_parties, exp.clone());
        assert_eq!(pow_pairs_batch.len(), n_parties);

        // Each PowPairs should contain exactly 8 PowPairs
        for pow_pairs in &pow_pairs_batch {
            assert_eq!(pow_pairs.lambdas.n_parties(), n_parties);
            assert_eq!(pow_pairs.lambdas_pow_neg_exp.n_parties(), n_parties);
        }

        // Verify each individual PowPair in the batch using reconstruction
        let mut pow_pairs_iters: Vec<_> = pow_pairs_batch
            .into_iter()
            .map(|pow_pairs| pow_pairs.into_iter())
            .collect();
        for i in 0..8 {
            let pow_pair: Vec<PowPair<Fq>> = pow_pairs_iters
                .iter_mut()
                .map(|batch| batch.next().unwrap())
                .collect();

            let (lambda, lambda_pow_neg_exp) = PowPair::<Fq>::reconstruct_all(pow_pair).unwrap();
            let expected_lambda_pow_neg_exp = lambda.pow(exp.clone()).invert().unwrap();
            assert_eq!(
                lambda_pow_neg_exp, expected_lambda_pow_neg_exp,
                "PowPair {i} in batch does not satisfy λ^(-exp) relationship"
            );
        }
    }

    #[test]
    fn test_pow_pairs_random_with_alphas() {
        let mut rng = crate::random::test_rng();
        let n_parties = 4;
        let exp = BoxedUint::from(U256::random(&mut rng));

        // Generate alphas for each party
        let all_alphas: Vec<Vec<GlobalFieldKey<Fq>>> =
            Vec::random_n_with(&mut rng, n_parties, n_parties - 1);

        let pow_pairs_batch: Vec<PowPairs<Fq, BatchSize>> =
            PowPairs::random_n_with(&mut rng, n_parties, (exp.clone(), all_alphas));

        assert_eq!(pow_pairs_batch.len(), n_parties);

        // Each PowPairs should contain exactly 5 PowPairs
        for pow_pairs in &pow_pairs_batch {
            assert_eq!(pow_pairs.lambdas.n_parties(), n_parties);
            assert_eq!(pow_pairs.lambdas_pow_neg_exp.n_parties(), n_parties);
        }

        // Verify each individual PowPair in the batch using reconstruction
        let mut pow_pairs_iters: Vec<_> = pow_pairs_batch
            .into_iter()
            .map(|pow_pairs| pow_pairs.into_iter())
            .collect();
        for i in 0..5 {
            let individual_pow_pairs: Vec<PowPair<Fq>> = pow_pairs_iters
                .iter_mut()
                .map(|batch| batch.next().unwrap())
                .collect();

            let (lambda, lambda_pow_neg_exp) =
                PowPair::<Fq>::reconstruct_all(individual_pow_pairs).unwrap();
            let expected_lambda_pow_neg_exp = lambda.pow(exp.clone()).invert().unwrap();
            assert_eq!(
                lambda_pow_neg_exp, expected_lambda_pow_neg_exp,
                "Authenticated PowPair {i} in batch does not satisfy λ^(-exp) relationship"
            );
        }
    }
}