diff --git a/crates/ff_ext/src/babybear.rs b/crates/ff_ext/src/babybear.rs index 44f02f7..5f8fb89 100644 --- a/crates/ff_ext/src/babybear.rs +++ b/crates/ff_ext/src/babybear.rs @@ -1,5 +1,5 @@ pub mod impl_babybear { - use crate::array_try_from_uniform_bytes; + use crate::{array_try_from_uniform_bytes, wrapper::Wrapper}; use p3::{ self, babybear::{BabyBear, Poseidon2BabyBear}, @@ -94,20 +94,14 @@ pub mod impl_babybear { #[cfg(debug_assertions)] use crate::poseidon::impl_instruments::*; - #[cfg(debug_assertions)] - use p3::symmetric::CryptographicPermutation; - #[cfg(debug_assertions)] - impl CryptographicPermutation<[BabyBear; POSEIDON2_BABYBEAR_WIDTH]> - for Instrumented> - { - } + type WP = Wrapper, POSEIDON2_BABYBEAR_WIDTH>; impl PoseidonField for BabyBear { #[cfg(debug_assertions)] - type P = Instrumented>; + type P = Instrumented; #[cfg(not(debug_assertions))] - type P = Poseidon2BabyBear; + type P = WP; type T = DuplexChallenger; type S = PaddingFreeSponge; @@ -124,24 +118,34 @@ pub mod impl_babybear { #[cfg(debug_assertions)] fn get_default_perm() -> Self::P { - Instrumented::new(Poseidon2BabyBear::new( + Instrumented::new(Wrapper::new(Poseidon2BabyBear::new( ExternalLayerConstants::new( BABYBEAR_RC16_EXTERNAL_INITIAL.to_vec(), BABYBEAR_RC16_EXTERNAL_FINAL.to_vec(), ), BABYBEAR_RC16_INTERNAL.to_vec(), - )) + ))) } #[cfg(not(debug_assertions))] fn get_default_perm() -> Self::P { - Poseidon2BabyBear::new( + Wrapper::new(Poseidon2BabyBear::new( ExternalLayerConstants::new( BABYBEAR_RC16_EXTERNAL_INITIAL.to_vec(), BABYBEAR_RC16_EXTERNAL_FINAL.to_vec(), ), BABYBEAR_RC16_INTERNAL.to_vec(), - ) + )) + } + + fn get_default_perm_rc() -> Vec { + BABYBEAR_RC16_EXTERNAL_INITIAL + .iter() + .flatten() + .chain(BABYBEAR_RC16_INTERNAL.iter()) + .chain(BABYBEAR_RC16_EXTERNAL_FINAL.iter().flatten()) + .cloned() + .collect() } fn get_default_sponge() -> Self::S { diff --git a/crates/ff_ext/src/goldilock.rs b/crates/ff_ext/src/goldilock.rs index 3e31ffb..4031bc6 100644 --- a/crates/ff_ext/src/goldilock.rs +++ b/crates/ff_ext/src/goldilock.rs @@ -3,6 +3,7 @@ pub mod impl_goldilocks { ExtensionField, FieldFrom, FieldInto, FromUniformBytes, SmallField, array_try_from_uniform_bytes, impl_from_uniform_bytes_for_binomial_extension, poseidon::{PoseidonField, new_array}, + wrapper::Wrapper, }; use p3::{ challenger::DuplexChallenger, @@ -21,8 +22,6 @@ pub mod impl_goldilocks { #[cfg(debug_assertions)] use crate::poseidon::impl_instruments::*; - #[cfg(debug_assertions)] - use p3::symmetric::CryptographicPermutation; pub type GoldilocksExt2 = BinomialExtensionField; @@ -47,17 +46,13 @@ pub mod impl_goldilocks { pub const POSEIDON2_GOLDILICK_WIDTH: usize = 8; pub const POSEIDON2_GOLDILICK_RATE: usize = 4; - #[cfg(debug_assertions)] - impl CryptographicPermutation<[Goldilocks; POSEIDON2_GOLDILICK_WIDTH]> - for Instrumented> - { - } - + type WP = Wrapper, POSEIDON2_GOLDILICK_WIDTH>; impl PoseidonField for Goldilocks { #[cfg(debug_assertions)] - type P = Instrumented>; + type P = Instrumented; #[cfg(not(debug_assertions))] - type P = Poseidon2GoldilocksHL; + type P = WP; + type T = DuplexChallenger; type S = PaddingFreeSponge; @@ -71,24 +66,34 @@ pub mod impl_goldilocks { #[cfg(debug_assertions)] fn get_default_perm() -> Self::P { - Instrumented::new(Poseidon2GoldilocksHL::new( + Instrumented::new(Wrapper::new(Poseidon2GoldilocksHL::new( ExternalLayerConstants::::new_from_saved_array( HL_GOLDILOCKS_8_EXTERNAL_ROUND_CONSTANTS, new_array, ), new_array(HL_GOLDILOCKS_8_INTERNAL_ROUND_CONSTANTS).to_vec(), - )) + ))) } #[cfg(not(debug_assertions))] fn get_default_perm() -> Self::P { - Poseidon2GoldilocksHL::new( + Wrapper::new(Poseidon2GoldilocksHL::new( ExternalLayerConstants::::new_from_saved_array( HL_GOLDILOCKS_8_EXTERNAL_ROUND_CONSTANTS, new_array, ), new_array(HL_GOLDILOCKS_8_INTERNAL_ROUND_CONSTANTS).to_vec(), - ) + )) + } + + fn get_default_perm_rc() -> Vec { + HL_GOLDILOCKS_8_EXTERNAL_ROUND_CONSTANTS[0] + .iter() + .flatten() + .chain(HL_GOLDILOCKS_8_INTERNAL_ROUND_CONSTANTS.iter()) + .chain(HL_GOLDILOCKS_8_EXTERNAL_ROUND_CONSTANTS[1].iter().flatten()) + .map(|v| Self::from_canonical_u64(*v)) + .collect() } fn get_default_sponge() -> Self::S { diff --git a/crates/ff_ext/src/lib.rs b/crates/ff_ext/src/lib.rs index 4c2c370..6e3cfcb 100644 --- a/crates/ff_ext/src/lib.rs +++ b/crates/ff_ext/src/lib.rs @@ -10,6 +10,7 @@ use std::{ iter::{self, repeat_with}, }; mod babybear; +mod wrapper; pub use babybear::impl_babybear::*; mod goldilock; pub use goldilock::impl_goldilocks::*; diff --git a/crates/ff_ext/src/poseidon.rs b/crates/ff_ext/src/poseidon.rs index 80754d7..35e69d4 100644 --- a/crates/ff_ext/src/poseidon.rs +++ b/crates/ff_ext/src/poseidon.rs @@ -2,6 +2,7 @@ use p3::{ challenger::{FieldChallenger, GrindingChallenger}, commit::Mmcs, field::PrimeField, + symmetric::Permutation, }; use crate::{ExtensionField, SmallField}; @@ -19,7 +20,7 @@ pub trait FieldChallengerExt: FieldChallenger { pub trait PoseidonField: PrimeField + SmallField { // permutation - type P: Clone; + type P: Clone + Permutation> + Send + Sync; // sponge type S: Clone + Sync; // compression @@ -28,6 +29,7 @@ pub trait PoseidonField: PrimeField + SmallField { type T: FieldChallenger + Clone + GrindingChallenger; fn get_default_challenger() -> Self::T; fn get_default_perm() -> Self::P; + fn get_default_perm_rc() -> Vec; fn get_default_sponge() -> Self::S; fn get_default_compression() -> Self::C; fn get_default_mmcs() -> Self::MMCS; @@ -51,7 +53,7 @@ pub mod impl_instruments { }; use once_cell::sync::Lazy; - use p3::symmetric::Permutation; + use p3::symmetric::{CryptographicPermutation, Permutation}; pub type PermCount = Arc>; pub type LabelCounts = Arc>>; @@ -136,4 +138,6 @@ pub mod impl_instruments { self.inner_perm.permute(input) } } + + impl> CryptographicPermutation for Instrumented

{} } diff --git a/crates/ff_ext/src/wrapper.rs b/crates/ff_ext/src/wrapper.rs new file mode 100644 index 0000000..8630070 --- /dev/null +++ b/crates/ff_ext/src/wrapper.rs @@ -0,0 +1,50 @@ +use p3::symmetric::{CryptographicPermutation, Permutation}; +use std::array::from_fn; +#[derive(Clone)] +pub struct Wrapper { + inner: P, +} + +impl Wrapper { + pub fn new(inner: P) -> Self { + Self { inner } + } +} + +impl + Clone> Permutation> + for Wrapper +{ + fn permute(&self, input: Vec) -> Vec { + assert_eq!(input.len(), N, "Input vector must be of length {}", N); + + let mut array = from_fn(|i| input[i].clone()); + self.inner.permute_mut(&mut array); + + array.to_vec() + } + + fn permute_mut(&self, input: &mut Vec) { + assert_eq!(input.len(), N, "Input vector must be of length {}", N); + let mut array = from_fn(|i| input[i].clone()); + self.inner.permute_mut(&mut array); + input.iter_mut().zip(array).for_each(|(i, a)| { + *i = a; + }); + } +} +impl + Clone> Permutation<[T; N]> + for Wrapper +{ + fn permute(&self, input: [T; N]) -> [T; N] { + self.inner.permute(input) + } + + fn permute_mut(&self, input: &mut [T; N]) { + self.inner.permute_mut(input); + } +} + +impl + Clone> CryptographicPermutation<[T; N]> + for Wrapper +{ +}