From 9782992662c1c01e89d0c55de220a1235877abdc Mon Sep 17 00:00:00 2001 From: Bobbin Threadbare Date: Fri, 9 Dec 2022 13:51:16 -0800 Subject: [PATCH 1/4] feat: improve blake3 sequential hashing performance --- src/hash/blake/mod.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/hash/blake/mod.rs b/src/hash/blake/mod.rs index 6ffbfb5..b596ab9 100644 --- a/src/hash/blake/mod.rs +++ b/src/hash/blake/mod.rs @@ -276,13 +276,11 @@ where let digest = if Felt::IS_CANONICAL { blake3::hash(E::elements_as_bytes(elements)) } else { - E::as_base_elements(elements) - .iter() - .fold(blake3::Hasher::new(), |mut hasher, felt| { - hasher.update(&felt.as_int().to_le_bytes()); - hasher - }) - .finalize() + let mut hasher = blake3::Hasher::new(); + for element in E::as_base_elements(elements) { + hasher.update(&element.as_int().to_le_bytes()); + } + hasher.finalize() }; *shrink_bytes(&digest.into()) } From aa4e31369017c6093b171f4302c6908751b43575 Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Sat, 10 Dec 2022 11:48:19 +0400 Subject: [PATCH 2/4] chg: first convert all elements to little endian bytes and then consume them in a single call to blake3 hasher Signed-off-by: Anjan Roy --- src/hash/blake/mod.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/hash/blake/mod.rs b/src/hash/blake/mod.rs index b596ab9..e20391b 100644 --- a/src/hash/blake/mod.rs +++ b/src/hash/blake/mod.rs @@ -276,10 +276,15 @@ where let digest = if Felt::IS_CANONICAL { blake3::hash(E::elements_as_bytes(elements)) } else { - let mut hasher = blake3::Hasher::new(); - for element in E::as_base_elements(elements) { - hasher.update(&element.as_int().to_le_bytes()); + let blen = elements.len() << 3; + let mut bytes = vec![0u8; blen]; + + for (idx, element) in E::as_base_elements(elements).iter().enumerate() { + bytes[idx * 8..(idx + 1) * 8].copy_from_slice(&element.as_int().to_le_bytes()); } + + let mut hasher = blake3::Hasher::new(); + hasher.update(&bytes); hasher.finalize() }; *shrink_bytes(&digest.into()) From 0d713af4acc120f40259b2a0faaf0b67c5a794e2 Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Sat, 10 Dec 2022 12:49:38 +0400 Subject: [PATCH 3/4] chg: don't assume that default features are available on all targets Signed-off-by: Anjan Roy --- src/hash/blake/mod.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/hash/blake/mod.rs b/src/hash/blake/mod.rs index e20391b..c1ea386 100644 --- a/src/hash/blake/mod.rs +++ b/src/hash/blake/mod.rs @@ -5,6 +5,7 @@ use core::{ ops::Deref, slice::from_raw_parts, }; +use winter_utils::collections::Vec; #[cfg(test)] mod tests; @@ -277,7 +278,12 @@ where blake3::hash(E::elements_as_bytes(elements)) } else { let blen = elements.len() << 3; - let mut bytes = vec![0u8; blen]; + + let mut bytes = Vec::with_capacity(blen); + #[allow(clippy::uninit_vec)] + unsafe { + bytes.set_len(blen) + } for (idx, element) in E::as_base_elements(elements).iter().enumerate() { bytes[idx * 8..(idx + 1) * 8].copy_from_slice(&element.as_int().to_le_bytes()); From b4f9d6098170a70ff334e0f638d7540608176c60 Mon Sep 17 00:00:00 2001 From: Anjan Roy Date: Mon, 12 Dec 2022 09:49:33 +0400 Subject: [PATCH 4/4] chg: don't assume we're only working with base field elements, consider extension field elements too See https://github.com/0xPolygonMiden/crypto/pull/29#discussion_r1045108928 where it was suggested. Signed-off-by: Anjan Roy --- src/hash/blake/mod.rs | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/hash/blake/mod.rs b/src/hash/blake/mod.rs index c1ea386..488c8ba 100644 --- a/src/hash/blake/mod.rs +++ b/src/hash/blake/mod.rs @@ -1,11 +1,12 @@ use super::{Digest, ElementHasher, Felt, FieldElement, Hasher, StarkField}; -use crate::utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable}; +use crate::utils::{ + uninit_vector, ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable, +}; use core::{ mem::{size_of, transmute, transmute_copy}, ops::Deref, slice::from_raw_parts, }; -use winter_utils::collections::Vec; #[cfg(test)] mod tests; @@ -277,21 +278,15 @@ where let digest = if Felt::IS_CANONICAL { blake3::hash(E::elements_as_bytes(elements)) } else { - let blen = elements.len() << 3; - - let mut bytes = Vec::with_capacity(blen); - #[allow(clippy::uninit_vec)] - unsafe { - bytes.set_len(blen) - } + let base_elements = E::as_base_elements(elements); + let blen = base_elements.len() << 3; - for (idx, element) in E::as_base_elements(elements).iter().enumerate() { + let mut bytes = unsafe { uninit_vector(blen) }; + for (idx, element) in base_elements.iter().enumerate() { bytes[idx * 8..(idx + 1) * 8].copy_from_slice(&element.as_int().to_le_bytes()); } - let mut hasher = blake3::Hasher::new(); - hasher.update(&bytes); - hasher.finalize() + blake3::hash(&bytes) }; *shrink_bytes(&digest.into()) }