diff --git a/plonky2/field/src/cfft/concurrent.rs b/plonky2/field/src/cfft/concurrent.rs index de53b3e7..24e775f8 100644 --- a/plonky2/field/src/cfft/concurrent.rs +++ b/plonky2/field/src/cfft/concurrent.rs @@ -1,6 +1,6 @@ +use maybe_rayon::current_num_threads; use maybe_rayon::{ - current_num_threads, IndexedParallelIterator, MaybeParChunks, MaybeParChunksMut, - MaybeParIterMut, ParallelIterator, + IndexedParallelIterator, MaybeParChunks, MaybeParChunksMut, MaybeParIterMut, ParallelIterator, }; use plonky2_util::log2_strict; diff --git a/plonky2/plonky2/src/hash/mod.rs b/plonky2/plonky2/src/hash/mod.rs index a76b03ac..777ad525 100644 --- a/plonky2/plonky2/src/hash/mod.rs +++ b/plonky2/plonky2/src/hash/mod.rs @@ -11,3 +11,4 @@ pub mod poseidon; pub mod poseidon2; pub mod poseidon2_goldilocks; pub mod poseidon_goldilocks; +pub mod utils; diff --git a/plonky2/plonky2/src/hash/utils.rs b/plonky2/plonky2/src/hash/utils.rs new file mode 100644 index 00000000..c2553264 --- /dev/null +++ b/plonky2/plonky2/src/hash/utils.rs @@ -0,0 +1,48 @@ +use super::hash_types::RichField; +use crate::plonk::config::{GenericConfig, GenericHashOut, Hasher, PoseidonGoldilocksConfig}; +use maybe_rayon::{MaybeParIter, ParallelIterator}; +use plonky2_field::extension::Extendable; + +pub const GOLDILOCKS_FIELD_U8_LEN: usize = 8; + +pub fn poseidon_hash_bytes(input: &[u8]) -> [u8; 32] { + const D: usize = 2; + type C = PoseidonGoldilocksConfig; + type F = >::F; + hash_bytes::(input) +} + +pub fn hash_bytes, C: GenericConfig, const D: usize>( + input: &[u8], +) -> [u8; 32] { + let u64_arr = if input.len() % GOLDILOCKS_FIELD_U8_LEN == 0 { + bytes_to_u64s(input) + } else { + let padding_count = GOLDILOCKS_FIELD_U8_LEN - input.len() % GOLDILOCKS_FIELD_U8_LEN; + let mut bytes = vec![0 as u8; padding_count]; + bytes.extend_from_slice(input); + bytes_to_u64s(bytes.as_slice()) + }; + + let field_elements = u64_arr + .par_iter() + .map(|&i| F::from_canonical_u64(i)) + .collect::>(); + let hash = C::InnerHasher::hash_no_pad(&field_elements); + hash.to_bytes().as_slice().try_into().unwrap() +} + +pub fn bytes_to_u64s(bytes: &[u8]) -> Vec { + assert!( + bytes.len() % GOLDILOCKS_FIELD_U8_LEN == 0, + "Bytes must be divisible by 8" + ); + bytes + .chunks(GOLDILOCKS_FIELD_U8_LEN) + .map(|chunk| { + let mut bytes = [0u8; 8]; + bytes.copy_from_slice(chunk); + u64::from_be_bytes(bytes) + }) + .collect() +}