//! This module exercises the `ff_derive` procedural macros, to ensure that changes to the //! `ff` crate are reflected in `ff_derive`. It also uses the resulting field to test some //! of the APIs provided by `ff`, such as batch inversion. #[macro_use] extern crate ff; /// The BLS12-381 scalar field. #[derive(PrimeField)] #[PrimeFieldModulus = "52435875175126190479447740508185965837690552500527637822603658699938581184513"] #[PrimeFieldGenerator = "7"] #[PrimeFieldReprEndianness = "little"] struct Bls381K12Scalar([u64; 4]); mod fermat { /// The largest known Fermat prime, used to test the case `t = 1`. #[derive(PrimeField)] #[PrimeFieldModulus = "65537"] #[PrimeFieldGenerator = "3"] #[PrimeFieldReprEndianness = "little"] struct Fermat65537Field([u64; 1]); } mod full_limbs { #[derive(PrimeField)] #[PrimeFieldModulus = "39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319"] #[PrimeFieldGenerator = "19"] #[PrimeFieldReprEndianness = "little"] struct F384p([u64; 7]); #[test] fn random_masking_does_not_overflow() { use ff::Field; use rand::rngs::OsRng; let _ = F384p::random(OsRng); } } #[test] fn constants() { use ff::{Field, PrimeField}; assert_eq!( Bls381K12Scalar::MODULUS, "0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", ); assert_eq!( Bls381K12Scalar::from(2) * Bls381K12Scalar::TWO_INV, Bls381K12Scalar::ONE, ); assert_eq!( Bls381K12Scalar::ROOT_OF_UNITY * Bls381K12Scalar::ROOT_OF_UNITY_INV, Bls381K12Scalar::ONE, ); // ROOT_OF_UNITY^{2^s} mod m == 1 assert_eq!( Bls381K12Scalar::ROOT_OF_UNITY.pow(&[1u64 << Bls381K12Scalar::S, 0, 0, 0]), Bls381K12Scalar::ONE, ); // DELTA^{t} mod m == 1 assert_eq!( Bls381K12Scalar::DELTA.pow(&[ 0xfffe5bfeffffffff, 0x09a1d80553bda402, 0x299d7d483339d808, 0x73eda753, ]), Bls381K12Scalar::ONE, ); } #[test] fn from_u128() { use ff::{Field, PrimeField}; assert_eq!(Bls381K12Scalar::from_u128(1), Bls381K12Scalar::ONE); assert_eq!(Bls381K12Scalar::from_u128(2), Bls381K12Scalar::from(2)); assert_eq!( Bls381K12Scalar::from_u128(u128::MAX), Bls381K12Scalar::from_str_vartime("340282366920938463463374607431768211455").unwrap(), ); } #[test] fn batch_inversion() { use ff::{BatchInverter, Field}; let one = Bls381K12Scalar::ONE; // [1, 2, 3, 4] let values: Vec<_> = (0..4) .scan(one, |acc, _| { let ret = *acc; *acc += &one; Some(ret) }) .collect(); // Test BatchInverter::invert_with_external_scratch { let mut elements = values.clone(); let mut scratch_space = vec![Bls381K12Scalar::ZERO; elements.len()]; BatchInverter::invert_with_external_scratch(&mut elements, &mut scratch_space); for (a, a_inv) in values.iter().zip(elements.into_iter()) { assert_eq!(*a * a_inv, one); } } // Test BatchInverter::invert_with_internal_scratch { let mut items: Vec<_> = values.iter().cloned().map(|p| (p, one)).collect(); BatchInverter::invert_with_internal_scratch( &mut items, |item| &mut item.0, |item| &mut item.1, ); for (a, (a_inv, _)) in values.iter().zip(items.into_iter()) { assert_eq!(*a * a_inv, one); } } // Test BatchInvert trait #[cfg(feature = "alloc")] { use ff::BatchInvert; let mut elements = values.clone(); elements.iter_mut().batch_invert(); for (a, a_inv) in values.iter().zip(elements.into_iter()) { assert_eq!(*a * a_inv, one); } } }