From 104c6618028eacfa4c316794dfb965b6fd95b1f4 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Fri, 28 Nov 2025 15:04:18 +0100 Subject: [PATCH 1/4] add hashbuffer to avoid allocs in compute hash --- crates/common/types/transaction.rs | 9 +++- crates/common/utils.rs | 81 +++++++++++++++++++++++++++++- 2 files changed, 87 insertions(+), 3 deletions(-) diff --git a/crates/common/types/transaction.rs b/crates/common/types/transaction.rs index cdc7a9a0a5c..10324077398 100644 --- a/crates/common/types/transaction.rs +++ b/crates/common/types/transaction.rs @@ -1,6 +1,9 @@ use std::{cmp::min, fmt::Display}; -use crate::{errors::EcdsaError, utils::keccak}; +use crate::{ + errors::EcdsaError, + utils::{HashBuffer, keccak}, +}; use bytes::Bytes; use ethereum_types::{Address, H256, Signature, U256}; use ethrex_crypto::keccak::keccak_hash; @@ -1362,7 +1365,9 @@ impl Transaction { if let Transaction::PrivilegedL2Transaction(tx) = self { return tx.get_privileged_hash().unwrap_or_default(); } - crate::utils::keccak(self.encode_canonical_to_vec()) + let mut hasher = HashBuffer::new(); + self.encode_canonical(&mut hasher); + H256::from_slice(&hasher.finalize()) } pub fn hash(&self) -> H256 { diff --git a/crates/common/utils.rs b/crates/common/utils.rs index ab0009c0e9b..d3c57d42381 100644 --- a/crates/common/utils.rs +++ b/crates/common/utils.rs @@ -1,6 +1,7 @@ use crate::H256; +use bytes::{Buf, BufMut}; use ethereum_types::U256; -use ethrex_crypto::keccak::keccak_hash; +use ethrex_crypto::keccak::{Keccak256, keccak_hash}; use hex::FromHexError; pub const ZERO_U256: U256 = U256([0, 0, 0, 0]); @@ -79,6 +80,84 @@ pub fn truncate_array(data: [u8; N]) -> [u8; M] res } +/// A buffer to hash the data passed by the trait BufMut, to avoid creating a temporary (Vec) buffer when hashing for example RLP encoded transactions. +pub struct HashBuffer { + hasher: Keccak256, +} + +impl Default for HashBuffer { + fn default() -> Self { + Self::new() + } +} + +impl HashBuffer { + #[inline] + pub fn new() -> Self { + Self { + hasher: Keccak256::new(), + } + } + + #[inline] + pub fn finalize(self) -> [u8; 32] { + self.hasher.finalize() + } +} + +unsafe impl BufMut for HashBuffer { + #[inline] + fn remaining_mut(&self) -> usize { + usize::MAX + } + + unsafe fn advance_mut(&mut self, _cnt: usize) { + unreachable!("advance_mut should not be called on HashBuffer") + } + + fn chunk_mut(&mut self) -> &mut bytes::buf::UninitSlice { + unreachable!("chunk_mut should not be called on HashBuffer") + } + + #[inline] + fn put_u8(&mut self, n: u8) { + self.hasher.update([n]); + } + + #[inline] + fn put_slice(&mut self, src: &[u8]) { + self.hasher.update(src); + } + + #[inline] + fn put_bytes(&mut self, val: u8, mut cnt: usize) { + const CHUNK: [u8; 64] = [0u8; 64]; + while cnt > 0 { + let take = cnt.min(CHUNK.len()); + if val == 0 { + self.hasher.update(&CHUNK[..take]); + } else { + let mut tmp = CHUNK; + tmp[..take].fill(val); + self.hasher.update(&tmp[..take]); + } + cnt -= take; + } + } + + #[inline] + fn put(&mut self, mut src: T) + where + Self: Sized, + { + while src.has_remaining() { + let chunk = src.chunk(); + self.hasher.update(chunk); + src.advance(chunk.len()); + } + } +} + #[cfg(test)] mod test { use ethereum_types::U256; From df8732ec93b73a3979c8a5e4d476a832972271ea Mon Sep 17 00:00:00 2001 From: Edgar Date: Fri, 28 Nov 2025 15:48:17 +0100 Subject: [PATCH 2/4] Update crates/common/utils.rs Co-authored-by: Mario Rugiero --- crates/common/utils.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/crates/common/utils.rs b/crates/common/utils.rs index d3c57d42381..59f34fb8ee9 100644 --- a/crates/common/utils.rs +++ b/crates/common/utils.rs @@ -131,18 +131,12 @@ unsafe impl BufMut for HashBuffer { #[inline] fn put_bytes(&mut self, val: u8, mut cnt: usize) { - const CHUNK: [u8; 64] = [0u8; 64]; - while cnt > 0 { - let take = cnt.min(CHUNK.len()); - if val == 0 { - self.hasher.update(&CHUNK[..take]); - } else { - let mut tmp = CHUNK; - tmp[..take].fill(val); - self.hasher.update(&tmp[..take]); - } - cnt -= take; + let chunk = [val, 64]; + while cnt >= 64 { + self.hasher.update(&chunk); + cnt -= 64; } + self.hasher.update(&chunk[..cnt]); } #[inline] From 5f6117457ed5e0465d00225a31e1659750e11e97 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Fri, 28 Nov 2025 15:57:08 +0100 Subject: [PATCH 3/4] edit --- crates/common/utils.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/crates/common/utils.rs b/crates/common/utils.rs index 59f34fb8ee9..fc8c5c20743 100644 --- a/crates/common/utils.rs +++ b/crates/common/utils.rs @@ -131,12 +131,16 @@ unsafe impl BufMut for HashBuffer { #[inline] fn put_bytes(&mut self, val: u8, mut cnt: usize) { - let chunk = [val, 64]; + let chunk = [val; 64]; + while cnt >= 64 { self.hasher.update(&chunk); cnt -= 64; } - self.hasher.update(&chunk[..cnt]); + + if cnt > 0 { + self.hasher.update(&chunk[..cnt]); + } } #[inline] From 44d5c971a761fafa048df7c58da42c7517001a5b Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Fri, 28 Nov 2025 15:57:57 +0100 Subject: [PATCH 4/4] lint --- crates/common/utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/common/utils.rs b/crates/common/utils.rs index fc8c5c20743..98df29dbfe1 100644 --- a/crates/common/utils.rs +++ b/crates/common/utils.rs @@ -134,7 +134,7 @@ unsafe impl BufMut for HashBuffer { let chunk = [val; 64]; while cnt >= 64 { - self.hasher.update(&chunk); + self.hasher.update(chunk); cnt -= 64; }