diff --git a/nomos-da/kzgrs/src/fft.rs b/nomos-da/kzgrs/src/fft.rs index 6ecfb38b..9aec9c92 100644 --- a/nomos-da/kzgrs/src/fft.rs +++ b/nomos-da/kzgrs/src/fft.rs @@ -1,7 +1,11 @@ -use ark_bls12_381::{Fr, G1Affine}; -use ark_ec::CurveGroup; +use ark_bls12_381::{Bls12_381, Fr, G1Affine}; +use ark_ec::pairing::Pairing; +use ark_ec::{AffineRepr, CurveGroup}; +use ark_ff::{BigInt, BigInteger, FftField, Field, PrimeField}; +use blst::BLS12_381_G1; pub fn fft_g1(vals: &[G1Affine], roots_of_unity: &[Fr]) -> Vec { + debug_assert_eq!(vals.len(), roots_of_unity.len()); if vals.len() == 1 { return vals.to_vec(); } @@ -47,3 +51,42 @@ pub fn fft_g1(vals: &[G1Affine], roots_of_unity: &[Fr]) -> Vec { }) .collect() } + +pub fn ifft_g1(vals: &[G1Affine], roots_of_unity: &[Fr]) -> Vec { + debug_assert_eq!(vals.len(), roots_of_unity.len()); + let mut mod_min_2 = BigInt::new(::MODULUS.0); + mod_min_2.sub_with_borrow(&BigInt::<4>::from(2u64)); + let invlen = Fr::from(vals.len() as u64).pow(mod_min_2).into_bigint(); + fft_g1(vals, roots_of_unity) + .into_iter() + .map(|g| g.mul_bigint(invlen).into_affine()) + .collect() +} + +#[cfg(test)] +mod test { + use crate::fft::{fft_g1, ifft_g1}; + use ark_bls12_381::{Fr, G1Affine}; + use ark_ec::{AffineRepr, CurveGroup}; + use ark_ff::{BigInt, FftField, Field}; + + #[test] + fn test_fft_ifft_g1() { + for size in [16usize, 32, 64, 128, 256, 512, 1024, 2048, 4096] { + let primitive_root = ::get_root_of_unity(size as u64).unwrap(); + let roots_of_unity: Vec<_> = (1..=size) + .map(|i| primitive_root.pow::>(BigInt::from(i as u64))) + .collect(); + let buff: Vec = (0..size) + .map(|i| { + G1Affine::identity() + .mul_bigint(BigInt::<4>::from(i as u64)) + .into_affine() + }) + .collect(); + let fft = fft_g1(&buff, &roots_of_unity); + let ifft = ifft_g1(&fft, &roots_of_unity); + assert_eq!(buff, ifft); + } + } +}