From 9e3d92178baff1b7e3b5626f93690e05222e6af9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Miko=C5=82ajczyk?= Date: Mon, 17 Nov 2025 14:50:36 +0100 Subject: [PATCH 01/13] snap.go --- cmd/devp2p/internal/ethtest/snap.go | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/cmd/devp2p/internal/ethtest/snap.go b/cmd/devp2p/internal/ethtest/snap.go index f4fce0931f..3d4474a77b 100644 --- a/cmd/devp2p/internal/ethtest/snap.go +++ b/cmd/devp2p/internal/ethtest/snap.go @@ -900,16 +900,12 @@ func (s *Suite) snapGetByteCodes(t *utesting.T, tc *byteCodesTest) error { // that the serving node is missing var ( bytecodes = res.Codes - hasher = crypto.NewKeccakState() - hash = make([]byte, 32) codes = make([][]byte, len(req.Hashes)) ) for i, j := 0, 0; i < len(bytecodes); i++ { // Find the next hash that we've been served, leaving misses with nils - hasher.Reset() - hasher.Write(bytecodes[i]) - hasher.Read(hash) + hash := crypto.Keccak256(bytecodes[i]) for j < len(req.Hashes) && !bytes.Equal(hash, req.Hashes[j][:]) { j++ @@ -959,16 +955,12 @@ func (s *Suite) snapGetTrieNodes(t *utesting.T, tc *trieNodesTest) error { // Cross reference the requested trienodes with the response to find gaps // that the serving node is missing - hasher := crypto.NewKeccakState() - hash := make([]byte, 32) trienodes := res.Nodes if got, want := len(trienodes), len(tc.expHashes); got != want { return fmt.Errorf("wrong trienode count, got %d, want %d", got, want) } for i, trienode := range trienodes { - hasher.Reset() - hasher.Write(trienode) - hasher.Read(hash) + hash := crypto.Keccak256(trienode[:]) if got, want := hash, tc.expHashes[i]; !bytes.Equal(got, want[:]) { t.Logf(" hash %d wrong, got %#x, want %#x\n", i, got, want) err = fmt.Errorf("hash %d wrong, got %#x, want %#x", i, got, want) From f2189f3350b9fff439eb10fb196b5c9d6af2c759 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Miko=C5=82ajczyk?= Date: Mon, 17 Nov 2025 14:52:22 +0100 Subject: [PATCH 02/13] cmd/geth --- cmd/geth/dbcmd.go | 6 +----- cmd/geth/snapshot.go | 10 ++-------- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/cmd/geth/dbcmd.go b/cmd/geth/dbcmd.go index c57add0656..184a2f654b 100644 --- a/cmd/geth/dbcmd.go +++ b/cmd/geth/dbcmd.go @@ -354,8 +354,6 @@ func checkStateContent(ctx *cli.Context) error { defer db.Close() var ( it = rawdb.NewKeyLengthIterator(db.NewIterator(prefix, start), 32) - hasher = crypto.NewKeccakState() - got = make([]byte, 32) errs int count int startTime = time.Now() @@ -365,9 +363,7 @@ func checkStateContent(ctx *cli.Context) error { count++ k := it.Key() v := it.Value() - hasher.Reset() - hasher.Write(v) - hasher.Read(got) + got := crypto.Keccak256(v) if !bytes.Equal(k, got) { errs++ fmt.Printf("Error at %#x\n", k) diff --git a/cmd/geth/snapshot.go b/cmd/geth/snapshot.go index fe0bf97db8..f10ed36a4e 100644 --- a/cmd/geth/snapshot.go +++ b/cmd/geth/snapshot.go @@ -434,8 +434,6 @@ func traverseRawState(ctx *cli.Context) error { codes int lastReport time.Time start = time.Now() - hasher = crypto.NewKeccakState() - got = make([]byte, 32) ) accIter, err := t.NodeIterator(nil) if err != nil { @@ -459,9 +457,7 @@ func traverseRawState(ctx *cli.Context) error { log.Error("Missing trie node(account)", "hash", node) return errors.New("missing account") } - hasher.Reset() - hasher.Write(blob) - hasher.Read(got) + got := crypto.Keccak256(blob) if !bytes.Equal(got, node.Bytes()) { log.Error("Invalid trie node(account)", "hash", node.Hex(), "value", blob) return errors.New("invalid account node") @@ -500,9 +496,7 @@ func traverseRawState(ctx *cli.Context) error { log.Error("Missing trie node(storage)", "hash", node) return errors.New("missing storage") } - hasher.Reset() - hasher.Write(blob) - hasher.Read(got) + got := crypto.Keccak256(blob) if !bytes.Equal(got, node.Bytes()) { log.Error("Invalid trie node(storage)", "hash", node.Hex(), "value", blob) return errors.New("invalid storage node") From 392213abf80d88b8852c2e1aaed2ae9a450877f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Miko=C5=82ajczyk?= Date: Mon, 17 Nov 2025 14:56:11 +0100 Subject: [PATCH 03/13] stateless database --- core/stateless/database.go | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/core/stateless/database.go b/core/stateless/database.go index f54c123dda..5655bc28bf 100644 --- a/core/stateless/database.go +++ b/core/stateless/database.go @@ -34,11 +34,7 @@ import ( // // Acceleration structures built would need to explicitly validate the witness. func (w *Witness) MakeHashDB() ethdb.Database { - var ( - memdb = rawdb.NewMemoryDatabase() - hasher = crypto.NewKeccakState() - hash = make([]byte, 32) - ) + var memdb = rawdb.NewMemoryDatabase() // Inject all the "block hashes" (i.e. headers) into the ephemeral database for _, header := range w.Headers { rawdb.WriteHeader(memdb, header) @@ -46,21 +42,13 @@ func (w *Witness) MakeHashDB() ethdb.Database { // Inject all the bytecodes into the ephemeral database for code := range w.Codes { blob := []byte(code) - - hasher.Reset() - hasher.Write(blob) - hasher.Read(hash) - + hash := crypto.Keccak256(blob) rawdb.WriteCode(memdb, common.BytesToHash(hash), blob) } // Inject all the MPT trie nodes into the ephemeral database for node := range w.State { blob := []byte(node) - - hasher.Reset() - hasher.Write(blob) - hasher.Read(hash) - + hash := crypto.Keccak256(blob) rawdb.WriteLegacyTrieNode(memdb, common.BytesToHash(hash), blob) } return memdb From b73c5c98dc2e3421fcd3a2ca310989b2e09fbce5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Miko=C5=82ajczyk?= Date: Mon, 17 Nov 2025 14:59:17 +0100 Subject: [PATCH 04/13] trie hasher --- trie/hasher.go | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/trie/hasher.go b/trie/hasher.go index a2a1f5b662..40e95c7afe 100644 --- a/trie/hasher.go +++ b/trie/hasher.go @@ -28,7 +28,6 @@ import ( // hasher is a type used for the trie Hash operation. A hasher has some // internal preallocated temp space type hasher struct { - sha crypto.KeccakState tmp []byte encbuf rlp.EncoderBuffer parallel bool // Whether to use parallel threads when hashing @@ -39,7 +38,6 @@ var hasherPool = sync.Pool{ New: func() any { return &hasher{ tmp: make([]byte, 0, 550), // cap is as large as a full fullNode. - sha: crypto.NewKeccakState(), encbuf: rlp.NewEncoderBuffer(nil), } }, @@ -74,7 +72,7 @@ func (h *hasher) hash(n node, force bool) []byte { copy(buf, enc) return buf } - hash := h.hashData(enc) + hash := crypto.Keccak256(enc) n.flags.hash = hash return hash @@ -89,7 +87,7 @@ func (h *hasher) hash(n node, force bool) []byte { copy(buf, enc) return buf } - hash := h.hashData(enc) + hash := crypto.Keccak256(enc) n.flags.hash = hash return hash @@ -186,24 +184,6 @@ func (h *hasher) encodedBytes() []byte { return h.tmp } -// hashData hashes the provided data. It is safe to modify the returned slice after -// the function returns. -func (h *hasher) hashData(data []byte) []byte { - n := make([]byte, 32) - h.sha.Reset() - h.sha.Write(data) - h.sha.Read(n) - return n -} - -// hashDataTo hashes the provided data to the given destination buffer. The caller -// must ensure that the dst buffer is of appropriate size. -func (h *hasher) hashDataTo(dst, data []byte) { - h.sha.Reset() - h.sha.Write(data) - h.sha.Read(dst) -} - // proofHash is used to construct trie proofs, returning the rlp-encoded node blobs. // Note, only resolved node (shortNode or fullNode) is expected for proofing. // From 65aa53135c47c43849f0378f77fd40077f666002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Miko=C5=82ajczyk?= Date: Mon, 17 Nov 2025 15:17:17 +0100 Subject: [PATCH 05/13] sync --- eth/protocols/snap/sync.go | 25 +++++-------------------- eth/protocols/snap/sync_test.go | 12 ++---------- 2 files changed, 7 insertions(+), 30 deletions(-) diff --git a/eth/protocols/snap/sync.go b/eth/protocols/snap/sync.go index cf4e494645..0c919f8886 100644 --- a/eth/protocols/snap/sync.go +++ b/eth/protocols/snap/sync.go @@ -2672,15 +2672,10 @@ func (s *Syncer) onByteCodes(peer SyncPeer, id uint64, bytecodes [][]byte) error // Cross reference the requested bytecodes with the response to find gaps // that the serving node is missing - hasher := crypto.NewKeccakState() - hash := make([]byte, 32) - codes := make([][]byte, len(req.hashes)) for i, j := 0, 0; i < len(bytecodes); i++ { // Find the next hash that we've been served, leaving misses with nils - hasher.Reset() - hasher.Write(bytecodes[i]) - hasher.Read(hash) + hash := crypto.Keccak256(bytecodes[i]) for j < len(req.hashes) && !bytes.Equal(hash, req.hashes[j][:]) { j++ @@ -2920,16 +2915,12 @@ func (s *Syncer) OnTrieNodes(peer SyncPeer, id uint64, trienodes [][]byte) error // Cross reference the requested trienodes with the response to find gaps // that the serving node is missing var ( - hasher = crypto.NewKeccakState() - hash = make([]byte, 32) - nodes = make([][]byte, len(req.hashes)) - fills uint64 + nodes = make([][]byte, len(req.hashes)) + fills uint64 ) for i, j := 0, 0; i < len(trienodes); i++ { // Find the next hash that we've been served, leaving misses with nils - hasher.Reset() - hasher.Write(trienodes[i]) - hasher.Read(hash) + hash := crypto.Keccak256(trienodes[i]) for j < len(req.hashes) && !bytes.Equal(hash, req.hashes[j][:]) { j++ @@ -3026,16 +3017,10 @@ func (s *Syncer) onHealByteCodes(peer SyncPeer, id uint64, bytecodes [][]byte) e // Cross reference the requested bytecodes with the response to find gaps // that the serving node is missing - hasher := crypto.NewKeccakState() - hash := make([]byte, 32) - codes := make([][]byte, len(req.hashes)) for i, j := 0, 0; i < len(bytecodes); i++ { // Find the next hash that we've been served, leaving misses with nils - hasher.Reset() - hasher.Write(bytecodes[i]) - hasher.Read(hash) - + hash := crypto.Keccak256(bytecodes[i]) for j < len(req.hashes) && !bytes.Equal(hash, req.hashes[j][:]) { j++ } diff --git a/eth/protocols/snap/sync_test.go b/eth/protocols/snap/sync_test.go index 713b358ff8..175bade62d 100644 --- a/eth/protocols/snap/sync_test.go +++ b/eth/protocols/snap/sync_test.go @@ -64,12 +64,8 @@ func TestHashing(t *testing.T) { } } var new = func() { - hasher := crypto.NewKeccakState() - var hash = make([]byte, 32) for i := 0; i < len(bytecodes); i++ { - hasher.Reset() - hasher.Write(bytecodes[i]) - hasher.Read(hash) + hash := crypto.Keccak256(bytecodes[i]) want = fmt.Sprintf("%v\n%v", want, hash) } } @@ -96,12 +92,8 @@ func BenchmarkHashing(b *testing.B) { } } var new = func() { - hasher := crypto.NewKeccakState() - var hash = make([]byte, 32) for i := 0; i < len(bytecodes); i++ { - hasher.Reset() - hasher.Write(bytecodes[i]) - hasher.Read(hash) + crypto.Keccak256(bytecodes[i]) } } b.Run("old", func(b *testing.B) { From 033fbb2cf29f1c4ce97029f82e10ff7bd116ffae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Miko=C5=82ajczyk?= Date: Mon, 17 Nov 2025 15:24:56 +0100 Subject: [PATCH 06/13] bloom9 --- core/types/bloom9.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/core/types/bloom9.go b/core/types/bloom9.go index 1d57e8e4bc..a766b2e89a 100644 --- a/core/types/bloom9.go +++ b/core/types/bloom9.go @@ -141,11 +141,8 @@ func Bloom9(data []byte) []byte { // bloomValues returns the bytes (index-value pairs) to set for the given data func bloomValues(data []byte, hashbuf *[6]byte) (uint, byte, uint, byte, uint, byte) { - sha := hasherPool.Get().(crypto.KeccakState) - sha.Reset() - sha.Write(data) - sha.Read(hashbuf[:]) - hasherPool.Put(sha) + hash := crypto.Keccak256(data) + copy(hashbuf[:], hash[:6]) // The actual bits to flip v1 := byte(1 << (hashbuf[1] & 0x7)) v2 := byte(1 << (hashbuf[3] & 0x7)) From 71f6a1d7366d50993c77b3a064021e1d0ff66d59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Miko=C5=82ajczyk?= Date: Mon, 17 Nov 2025 15:25:03 +0100 Subject: [PATCH 07/13] evm --- core/vm/evm.go | 6 +----- core/vm/instructions.go | 10 ++++------ 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/core/vm/evm.go b/core/vm/evm.go index ef637e4daf..864de09896 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -133,9 +133,6 @@ type EVM struct { // jumpDests stores results of JUMPDEST analysis. jumpDests JumpDestCache - hasher crypto.KeccakState // Keccak256 hasher instance shared across opcodes - hasherBuf common.Hash // Keccak256 hasher result array shared across opcodes - readOnly bool // Whether to throw on stateful modifications returnData []byte // Last CALL's return data for subsequent reuse } @@ -152,7 +149,6 @@ func NewEVM(blockCtx BlockContext, statedb StateDB, chainConfig *params.ChainCon chainConfig: chainConfig, chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time, blockCtx.ArbOSVersion), jumpDests: newMapJumpDests(), - hasher: crypto.NewKeccakState(), } evm.ProcessingHook = DefaultTxProcessor{evm: evm} evm.precompiles = activePrecompiledContracts(evm.chainRules) @@ -703,7 +699,7 @@ func (evm *EVM) Create(caller common.Address, code []byte, gas uint64, value *ui // The different between Create2 with Create is Create2 uses keccak256(0xff ++ msg.sender ++ salt ++ keccak256(init_code))[12:] // instead of the usual sender-and-nonce-hash as the address where the contract is initialized at. func (evm *EVM) Create2(caller common.Address, code []byte, gas uint64, endowment *uint256.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, usedMultiGas multigas.MultiGas, err error) { - inithash := crypto.HashData(evm.hasher, code) + inithash := crypto.Keccak256Hash(code) contractAddr = crypto.CreateAddress2(caller, salt.Bytes32(), inithash[:]) return evm.create(caller, code, gas, endowment, contractAddr, CREATE2) } diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 44346af5e8..2bd83651b5 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -25,6 +25,7 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" "github.com/holiman/uint256" ) @@ -235,15 +236,12 @@ func opSAR(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) { func opKeccak256(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) { offset, size := scope.Stack.pop(), scope.Stack.peek() data := scope.Memory.GetPtr(offset.Uint64(), size.Uint64()) - - evm.hasher.Reset() - evm.hasher.Write(data) - evm.hasher.Read(evm.hasherBuf[:]) + hasherBuf := crypto.Keccak256Hash(data) if evm.Config.EnablePreimageRecording { - evm.StateDB.AddPreimage(evm.hasherBuf, data) + evm.StateDB.AddPreimage(hasherBuf, data) } - size.SetBytes(evm.hasherBuf[:]) + size.SetBytes(hasherBuf[:]) return nil, nil } From 7dc0f04f86a8ca2f43cd73fa24892d7d515981db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Miko=C5=82ajczyk?= Date: Mon, 17 Nov 2025 15:26:53 +0100 Subject: [PATCH 08/13] keccak test --- crypto/crypto_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crypto/crypto_test.go b/crypto/crypto_test.go index d803ab27c5..dec82a5f68 100644 --- a/crypto/crypto_test.go +++ b/crypto/crypto_test.go @@ -45,8 +45,7 @@ func TestKeccak256Hash(t *testing.T) { func TestKeccak256Hasher(t *testing.T) { msg := []byte("abc") exp, _ := hex.DecodeString("4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45") - hasher := NewKeccakState() - checkhash(t, "Sha3-256-array", func(in []byte) []byte { h := HashData(hasher, in); return h[:] }, msg, exp) + checkhash(t, "Sha3-256-array", func(in []byte) []byte { h := Keccak256Hash(in); return h[:] }, msg, exp) } func TestToECDSAErrors(t *testing.T) { From 650d237302c3058e2dc3ab2bd2ad693aa584e83b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Miko=C5=82ajczyk?= Date: Mon, 17 Nov 2025 15:52:15 +0100 Subject: [PATCH 09/13] remove hashdata --- crypto/crypto.go | 8 -------- crypto/crypto_test.go | 19 ------------------- 2 files changed, 27 deletions(-) diff --git a/crypto/crypto.go b/crypto/crypto.go index db6b6ee071..1d575326df 100644 --- a/crypto/crypto.go +++ b/crypto/crypto.go @@ -67,14 +67,6 @@ type KeccakState interface { Read([]byte) (int, error) } -// HashData hashes the provided data using the KeccakState and returns a 32 byte hash -func HashData(kh KeccakState, data []byte) (h common.Hash) { - kh.Reset() - kh.Write(data) - kh.Read(h[:]) - return h -} - // CreateAddress creates an ethereum address given the bytes and the nonce func CreateAddress(b common.Address, nonce uint64) common.Address { data, _ := rlp.EncodeToBytes([]interface{}{b, nonce}) diff --git a/crypto/crypto_test.go b/crypto/crypto_test.go index dec82a5f68..bed51d76ac 100644 --- a/crypto/crypto_test.go +++ b/crypto/crypto_test.go @@ -313,22 +313,3 @@ func BenchmarkKeccak256Hash(b *testing.B) { Keccak256Hash(input[:]) } } - -// goos: darwin -// goarch: arm64 -// pkg: github.com/ethereum/go-ethereum/crypto -// cpu: Apple M1 Pro -// BenchmarkHashData -// BenchmarkHashData-8 793386 1278 ns/op 32 B/op 1 allocs/op -func BenchmarkHashData(b *testing.B) { - var ( - input [512]byte - buffer = NewKeccakState() - ) - rand.Read(input[:]) - - b.ReportAllocs() - for b.Loop() { - HashData(buffer, input[:]) - } -} From 64fbfba3ac41f6c51f2126af1d0f499ccbe4f3c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Miko=C5=82ajczyk?= Date: Mon, 17 Nov 2025 16:03:48 +0100 Subject: [PATCH 10/13] hashing --- core/types/hashing.go | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/core/types/hashing.go b/core/types/hashing.go index 98fe64e15a..31e0e91e99 100644 --- a/core/types/hashing.go +++ b/core/types/hashing.go @@ -27,11 +27,6 @@ import ( "github.com/ethereum/go-ethereum/rlp" ) -// hasherPool holds LegacyKeccak256 buffer for rlpHash. -var hasherPool = sync.Pool{ - New: func() interface{} { return crypto.NewKeccakState() }, -} - // encodeBufferPool holds temporary encoder buffers for DeriveSha and TX encoding. var encodeBufferPool = sync.Pool{ New: func() interface{} { return new(bytes.Buffer) }, @@ -55,24 +50,15 @@ func getPooledBuffer(size uint64) ([]byte, *bytes.Buffer, error) { // rlpHash encodes x and hashes the encoded bytes. func rlpHash(x interface{}) (h common.Hash) { - sha := hasherPool.Get().(crypto.KeccakState) - defer hasherPool.Put(sha) - sha.Reset() - rlp.Encode(sha, x) - sha.Read(h[:]) - return h + encoded, _ := rlp.EncodeToBytes(x) + return crypto.Keccak256Hash(encoded) } // prefixedRlpHash writes the prefix into the hasher before rlp-encoding x. // It's used for typed transactions. func prefixedRlpHash(prefix byte, x interface{}) (h common.Hash) { - sha := hasherPool.Get().(crypto.KeccakState) - defer hasherPool.Put(sha) - sha.Reset() - sha.Write([]byte{prefix}) - rlp.Encode(sha, x) - sha.Read(h[:]) - return h + encoded, _ := rlp.EncodeToBytes(x) + return crypto.Keccak256Hash([]byte{prefix}, encoded) } // ListHasher defines the interface for computing the hash of a derivable list. From 45b888ce2bbedc674df316e5f9f3fc95095709cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Miko=C5=82ajczyk?= Date: Mon, 17 Nov 2025 16:12:12 +0100 Subject: [PATCH 11/13] fix --- trie/stacktrie.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/trie/stacktrie.go b/trie/stacktrie.go index 18fe1eea78..9d16b937e2 100644 --- a/trie/stacktrie.go +++ b/trie/stacktrie.go @@ -23,6 +23,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" ) var ( @@ -414,8 +415,7 @@ func (t *StackTrie) hash(st *stNode, path []byte) { } // Write the hash to the 'val'. We allocate a new val here to not mutate // input values. - st.val = bPool.getWithSize(32) - t.h.hashDataTo(st.val, blob) + st.val = crypto.Keccak256(blob) // Invoke the callback it's provided. Notably, the path and blob slices are // volatile, please deep-copy the slices in callback if the contents need From c4e789b7e3609d27ae484a62bb0d8e9067e7be2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Miko=C5=82ajczyk?= Date: Mon, 17 Nov 2025 16:13:25 +0100 Subject: [PATCH 12/13] historytestgen.go --- cmd/workload/historytestgen.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cmd/workload/historytestgen.go b/cmd/workload/historytestgen.go index b88c8208da..121bb989d5 100644 --- a/cmd/workload/historytestgen.go +++ b/cmd/workload/historytestgen.go @@ -132,9 +132,8 @@ func generateHistoryTests(clictx *cli.Context) error { } func calcReceiptsHash(rcpt []*types.Receipt) common.Hash { - h := crypto.NewKeccakState() - rlp.Encode(h, rcpt) - return common.Hash(h.Sum(nil)) + encoded, _ := rlp.EncodeToBytes(rcpt) + return crypto.Keccak256Hash(encoded) } func writeJSON(fileName string, value any) { From c2a9d360fc6d4df46bdd528cb8b1a730fdd0e7f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Miko=C5=82ajczyk?= Date: Mon, 17 Nov 2025 16:17:01 +0100 Subject: [PATCH 13/13] refactor --- consensus/clique/clique.go | 2 +- crypto/crypto.go | 4 ++-- crypto/keccak.go | 31 +++++++++++++++---------------- crypto/keccak_ziren.go | 8 ++++---- trie/trie_test.go | 4 ++-- 5 files changed, 24 insertions(+), 25 deletions(-) diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index 5128a9d9f4..302c64f0ac 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -645,7 +645,7 @@ func (c *Clique) Close() error { func SealHash(header *types.Header) (hash common.Hash) { hasher := sha3.NewLegacyKeccak256() encodeSigHeader(hasher, header) - hasher.(crypto.KeccakState).Read(hash[:]) + hasher.(crypto.KeccakSponge).Read(hash[:]) return hash } diff --git a/crypto/crypto.go b/crypto/crypto.go index 1d575326df..2b82c1ae2c 100644 --- a/crypto/crypto.go +++ b/crypto/crypto.go @@ -59,10 +59,10 @@ type EllipticCurve interface { Unmarshal(data []byte) (x, y *big.Int) } -// KeccakState wraps sha3.state. In addition to the usual hash methods, it also supports +// KeccakSponge wraps sha3.state. In addition to the usual hash methods, it also supports // Read to get a variable amount of data from the hash state. Read is faster than Sum // because it doesn't copy the internal state, but also modifies the internal state. -type KeccakState interface { +type KeccakSponge interface { hash.Hash Read([]byte) (int, error) } diff --git a/crypto/keccak.go b/crypto/keccak.go index 0ad79a63c1..a93158fdac 100644 --- a/crypto/keccak.go +++ b/crypto/keccak.go @@ -25,39 +25,38 @@ import ( "golang.org/x/crypto/sha3" ) -// NewKeccakState creates a new KeccakState -func NewKeccakState() KeccakState { - return sha3.NewLegacyKeccak256().(KeccakState) +// NewKeccakSponge creates a new KeccakSponge +func NewKeccakSponge() KeccakSponge { + return sha3.NewLegacyKeccak256().(KeccakSponge) } var hasherPool = sync.Pool{ New: func() any { - return sha3.NewLegacyKeccak256().(KeccakState) + return sha3.NewLegacyKeccak256().(KeccakSponge) }, } -// Keccak256 calculates and returns the Keccak256 hash of the input data. -func Keccak256(data ...[]byte) []byte { - b := make([]byte, 32) - d := hasherPool.Get().(KeccakState) +// keccak256 is a helper that hashes the input data using the provided KeccakSponge and writes the result to out. +func keccak256(out []byte, data ...[]byte) { + d := hasherPool.Get().(KeccakSponge) d.Reset() for _, b := range data { d.Write(b) } - d.Read(b) + d.Read(out) hasherPool.Put(d) +} + +// Keccak256 calculates and returns the Keccak256 hash of the input data. +func Keccak256(data ...[]byte) []byte { + b := make([]byte, 32) + keccak256(b, data...) return b } // Keccak256Hash calculates and returns the Keccak256 hash of the input data, // converting it to an internal Hash data structure. func Keccak256Hash(data ...[]byte) (h common.Hash) { - d := hasherPool.Get().(KeccakState) - d.Reset() - for _, b := range data { - d.Write(b) - } - d.Read(h[:]) - hasherPool.Put(d) + keccak256(h[:], data...) return h } diff --git a/crypto/keccak_ziren.go b/crypto/keccak_ziren.go index 8e967c6dbf..e700127728 100644 --- a/crypto/keccak_ziren.go +++ b/crypto/keccak_ziren.go @@ -23,7 +23,7 @@ import ( "github.com/ethereum/go-ethereum/common" ) -// zirenKeccakState implements the KeccakState interface using the Ziren zkvm_runtime. +// zirenKeccakState implements the KeccakSponge interface using the Ziren zkvm_runtime. // It accumulates data written to it and uses the zkvm's Keccak256 system call for hashing. type zirenKeccakState struct { buf []byte // accumulated data @@ -31,7 +31,7 @@ type zirenKeccakState struct { dirty bool // whether new data has been written since last hash } -func newZirenKeccakState() KeccakState { +func newZirenKeccakState() KeccakSponge { return &zirenKeccakState{ buf: make([]byte, 0, 512), // pre-allocate reasonable capacity } @@ -83,9 +83,9 @@ func (s *zirenKeccakState) computeHashIfNeeded() { } } -// NewKeccakState creates a new KeccakState +// NewKeccakSponge creates a new KeccakSponge // This uses a Ziren-optimized implementation that leverages the zkvm_runtime.Keccak256 system call. -func NewKeccakState() KeccakState { +func NewKeccakState() KeccakSponge { return newZirenKeccakState() } diff --git a/trie/trie_test.go b/trie/trie_test.go index b8b8edb33e..2dde46b68c 100644 --- a/trie/trie_test.go +++ b/trie/trie_test.go @@ -899,7 +899,7 @@ func TestCommitSequence(t *testing.T) { addresses, accounts := makeAccounts(tc.count) // This spongeDb is used to check the sequence of disk-db-writes - s := &spongeDb{sponge: crypto.NewKeccakState()} + s := &spongeDb{sponge: crypto.NewKeccakSponge()} db := newTestDatabase(rawdb.NewDatabase(s), rawdb.HashScheme) // Fill the trie with elements @@ -933,7 +933,7 @@ func TestCommitSequenceRandomBlobs(t *testing.T) { } { // This spongeDb is used to check the sequence of disk-db-writes prng := rand.New(rand.NewSource(int64(i))) - s := &spongeDb{sponge: crypto.NewKeccakState()} + s := &spongeDb{sponge: crypto.NewKeccakSponge()} db := newTestDatabase(rawdb.NewDatabase(s), rawdb.HashScheme) // Fill the trie with elements