keccak256 on x86_64/aarch64 is the CRYPTOGAMS/OpenSSL single-lane scalar keccak-f1600 (crates/common/crypto/keccak/mod.rs, keccak1600-*.s). Every block hashes many independent inputs: trie nodes during root computation, the KECCAK256 opcode, address derivation, tx/receipt hashing. There's no multi-lane path.
1. 4-way AVX2 batched keccak (main win)
A KeccakP1600times4 kernel runs 4 permutations in ~1.3-1.6x one scalar permutation, so ~2.5-3.5x throughput on independent hashes.
- AVX2 is already forced on the prod target (
.cargo/config.toml), so no runtime dispatch.
- Trie hashing batches cleanly: siblings are hash-independent. Buffering points already exist in
trie_sorted.rs (write-queue) and node.rs (commit / compute_hash_no_alloc).
- Add
keccak256_batch(&[&[u8]]) next to Crypto::keccak256. Prototype a portable u64x4 kernel (~200 lines) before vendoring XKCP asm.
- Trie already parallelizes across subtries, so this multiplies per-thread throughput. Microbench first (item 5).
2. ARM FEAT_SHA3 (nearly free)
keccak1600-armv8-*.s already contains SHA3_absorb_cext / SHA3_squeeze_cext (EOR3/RAX1/XAR/BCAX), but Rust only calls the scalar SHA3_absorb. Wire it behind is_aarch64_feature_detected!("sha3"): ~1.5-2x on Apple Silicon / Graviton.
3. Devirtualize the hot call
NodeHash::from_encoded goes through &dyn Crypto::keccak256 (provider.rs:176), paying a vtable call per node and blocking inlining. trie_sorted.rs hard-codes &NativeCrypto but still routes through dyn Crypto. ~1-3%.
4. Hygiene / latent build breaks
SHA3_absorb / SHA3_squeeze / KeccakF1600 are unprefixed globals, same symbols as static OpenSSL libcrypto. Any static openssl-sys dep gives a duplicate-symbol link error. Prefix with ethrex_.
- x86_64 asm is ELF-only (
.type, .size, .note.gnu.property) but cfg'd for all x86_64, so darwin/windows builds fail. Gate to target_os = "linux", fall back elsewhere.
- aarch64 asm is gated
linux|macos but imp is arch-only, so aarch64 android/windows/freebsd fail to link.
- Keccak wrapper uses
get_unchecked relying on SHA3_absorb's rem < r return. Use checked indexing.
Keccak256::update(&mut self) -> Self returns a ~344 B self.clone() per call. Return &mut Self or ().
- Restore the CRYPTOGAMS BSD/GPL attribution stripped from the armv8 files.
5. Tests / benches (prerequisite)
No keccak known-answer tests for the asm path and no keccak bench (benches/ has only bls_single_op.rs). Add NIST KATs and a criterion bench before landing the above.
Found during an asm review while profiling BAL merkleization. Note: sstore_bloated merkle is insert-bound, not hash-bound, so batched keccak does not help that case; it helps the KECCAK256 opcode and normal state-heavy blocks.
keccak256on x86_64/aarch64 is the CRYPTOGAMS/OpenSSL single-lane scalar keccak-f1600 (crates/common/crypto/keccak/mod.rs,keccak1600-*.s). Every block hashes many independent inputs: trie nodes during root computation, theKECCAK256opcode, address derivation, tx/receipt hashing. There's no multi-lane path.1. 4-way AVX2 batched keccak (main win)
A
KeccakP1600times4kernel runs 4 permutations in ~1.3-1.6x one scalar permutation, so ~2.5-3.5x throughput on independent hashes..cargo/config.toml), so no runtime dispatch.trie_sorted.rs(write-queue) andnode.rs(commit/compute_hash_no_alloc).keccak256_batch(&[&[u8]])next toCrypto::keccak256. Prototype a portableu64x4kernel (~200 lines) before vendoring XKCP asm.2. ARM FEAT_SHA3 (nearly free)
keccak1600-armv8-*.salready containsSHA3_absorb_cext/SHA3_squeeze_cext(EOR3/RAX1/XAR/BCAX), but Rust only calls the scalarSHA3_absorb. Wire it behindis_aarch64_feature_detected!("sha3"): ~1.5-2x on Apple Silicon / Graviton.3. Devirtualize the hot call
NodeHash::from_encodedgoes through&dyn Crypto::keccak256(provider.rs:176), paying a vtable call per node and blocking inlining.trie_sorted.rshard-codes&NativeCryptobut still routes throughdyn Crypto. ~1-3%.4. Hygiene / latent build breaks
SHA3_absorb/SHA3_squeeze/KeccakF1600are unprefixed globals, same symbols as static OpenSSLlibcrypto. Any static openssl-sys dep gives a duplicate-symbol link error. Prefix withethrex_..type,.size,.note.gnu.property) but cfg'd for all x86_64, so darwin/windows builds fail. Gate totarget_os = "linux", fall back elsewhere.linux|macosbutimpis arch-only, so aarch64 android/windows/freebsd fail to link.get_uncheckedrelying onSHA3_absorb'srem < rreturn. Use checked indexing.Keccak256::update(&mut self) -> Selfreturns a ~344 Bself.clone()per call. Return&mut Selfor().5. Tests / benches (prerequisite)
No keccak known-answer tests for the asm path and no keccak bench (
benches/has onlybls_single_op.rs). Add NIST KATs and a criterion bench before landing the above.Found during an asm review while profiling BAL merkleization. Note:
sstore_bloatedmerkle is insert-bound, not hash-bound, so batched keccak does not help that case; it helps theKECCAK256opcode and normal state-heavy blocks.