From 90beffbaf80aa2a0b7b6d79c933f37741dab3af5 Mon Sep 17 00:00:00 2001
From: Guillaume Ballet <3272758+gballet@users.noreply.github.com>
Date: Mon, 22 Sep 2025 18:06:58 +0200
Subject: [PATCH 1/4] core/vm, crypto: add crypto package for hashing
---
core/vm/evm.go | 3 +-
crypto/platcrypto/keccak.go | 42 +++++++++++++
crypto/platcrypto/keccak_ziren.go | 101 ++++++++++++++++++++++++++++++
trie/secure_trie.go | 24 +++----
4 files changed, 157 insertions(+), 13 deletions(-)
create mode 100644 crypto/platcrypto/keccak.go
create mode 100644 crypto/platcrypto/keccak_ziren.go
diff --git a/core/vm/evm.go b/core/vm/evm.go
index 88ef1cf121e..0874fbe4ee0 100644
--- a/core/vm/evm.go
+++ b/core/vm/evm.go
@@ -26,6 +26,7 @@ import (
"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/crypto/platcrypto"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/holiman/uint256"
@@ -144,7 +145,7 @@ func NewEVM(blockCtx BlockContext, statedb StateDB, chainConfig *params.ChainCon
chainConfig: chainConfig,
chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time),
jumpDests: newMapJumpDests(),
- hasher: crypto.NewKeccakState(),
+ hasher: platcrypto.NewKeccakState(),
}
evm.precompiles = activePrecompiledContracts(evm.chainRules)
diff --git a/crypto/platcrypto/keccak.go b/crypto/platcrypto/keccak.go
new file mode 100644
index 00000000000..a070e8c4536
--- /dev/null
+++ b/crypto/platcrypto/keccak.go
@@ -0,0 +1,42 @@
+// Copyright 2025 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+//go:build !ziren
+
+package platcrypto
+
+import (
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+)
+
+// Keccak256 calculates and returns the Keccak256 hash using the standard implementation.
+// This is used for geth, evm, and other regular programs.
+func Keccak256(data ...[]byte) []byte {
+ return crypto.Keccak256(data...)
+}
+
+// Keccak256Hash calculates and returns the Keccak256 hash as a Hash using the standard implementation.
+// This is used for geth, evm, and other regular programs.
+func Keccak256Hash(data ...[]byte) common.Hash {
+ return crypto.Keccak256Hash(data...)
+}
+
+// NewKeccakState returns a new keccak state hasher using the standard implementation.
+// This is used for geth, evm, and other regular programs.
+func NewKeccakState() crypto.KeccakState {
+ return crypto.NewKeccakState()
+}
diff --git a/crypto/platcrypto/keccak_ziren.go b/crypto/platcrypto/keccak_ziren.go
new file mode 100644
index 00000000000..b0fa74ae6c0
--- /dev/null
+++ b/crypto/platcrypto/keccak_ziren.go
@@ -0,0 +1,101 @@
+// Copyright 2025 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+//go:build ziren
+
+package platcrypto
+
+import (
+ "errors"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+ zkruntime "github.com/zkMIPS/zkMIPS/crates/go-runtime/zkm_runtime"
+)
+
+// zirenKeccak implements keccak256 using the ziren platform precompile
+func zirenKeccak(data []byte) []byte {
+ return zkruntime.Keccak(data)
+}
+
+// zirenKeccakState wraps the ziren platform keccak precompile to implement crypto.KeccakState interface
+type zirenKeccakState struct {
+ data []byte
+}
+
+func (k *zirenKeccakState) Reset() {
+ k.data = k.data[:0]
+}
+
+func (k *zirenKeccakState) Clone() crypto.KeccakState {
+ clone := &zirenKeccakState{
+ data: make([]byte, len(k.data)),
+ }
+ copy(clone.data, k.data)
+ return clone
+}
+
+func (k *zirenKeccakState) Write(data []byte) (int, error) {
+ k.data = append(k.data, data...)
+ return len(data), nil
+}
+
+func (k *zirenKeccakState) Read(hash []byte) (int, error) {
+ if len(hash) < 32 {
+ return 0, errors.New("hash slice too short")
+ }
+
+ result := zirenKeccak(k.data)
+ copy(hash[:32], result)
+ return 32, nil
+}
+
+func (k *zirenKeccakState) Sum(data []byte) []byte {
+ hash := make([]byte, 32)
+ k.Read(hash)
+ return append(data, hash...)
+}
+
+func (k *zirenKeccakState) Size() int {
+ return 32
+}
+
+func (k *zirenKeccakState) BlockSize() int {
+ return 136 // keccak256 block size
+}
+
+// Keccak256 calculates and returns the Keccak256 hash using the ziren platform precompile.
+func Keccak256(data ...[]byte) []byte {
+ hasher := &zirenKeccakState{}
+ for _, b := range data {
+ hasher.Write(b)
+ }
+ hash := make([]byte, 32)
+ hasher.Read(hash)
+ return hash
+}
+
+// Keccak256Hash calculates and returns the Keccak256 hash as a Hash using the ziren platform precompile.
+func Keccak256Hash(data ...[]byte) (h common.Hash) {
+ hash := Keccak256(data...)
+ copy(h[:], hash)
+ return h
+}
+
+// NewKeccakState returns a new keccak state hasher using the ziren platform precompile.
+func NewKeccakState() crypto.KeccakState {
+ return &zirenKeccakState{}
+}
diff --git a/trie/secure_trie.go b/trie/secure_trie.go
index 7c7bd184bf8..588ca698ebf 100644
--- a/trie/secure_trie.go
+++ b/trie/secure_trie.go
@@ -19,7 +19,7 @@ package trie
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/crypto/platcrypto"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie/trienode"
"github.com/ethereum/go-ethereum/triedb/database"
@@ -102,14 +102,14 @@ func NewStateTrie(id *ID, db database.NodeDatabase) (*StateTrie, error) {
// This function will omit any encountered error but just
// print out an error message.
func (t *StateTrie) MustGet(key []byte) []byte {
- return t.trie.MustGet(crypto.Keccak256(key))
+ return t.trie.MustGet(platcrypto.Keccak256(key))
}
// GetAccount attempts to retrieve an account with provided account address.
// If the specified account is not in the trie, nil will be returned.
// If a trie node is not found in the database, a MissingNodeError is returned.
func (t *StateTrie) GetAccount(address common.Address) (*types.StateAccount, error) {
- res, err := t.trie.Get(crypto.Keccak256(address.Bytes()))
+ res, err := t.trie.Get(platcrypto.Keccak256(address.Bytes()))
if res == nil || err != nil {
return nil, err
}
@@ -136,7 +136,7 @@ func (t *StateTrie) GetAccountByHash(addrHash common.Hash) (*types.StateAccount,
func (t *StateTrie) PrefetchAccount(addresses []common.Address) error {
var keys [][]byte
for _, addr := range addresses {
- keys = append(keys, crypto.Keccak256(addr.Bytes()))
+ keys = append(keys, platcrypto.Keccak256(addr.Bytes()))
}
return t.trie.Prefetch(keys)
}
@@ -146,7 +146,7 @@ func (t *StateTrie) PrefetchAccount(addresses []common.Address) error {
// If the specified storage slot is not in the trie, nil will be returned.
// If a trie node is not found in the database, a MissingNodeError is returned.
func (t *StateTrie) GetStorage(_ common.Address, key []byte) ([]byte, error) {
- enc, err := t.trie.Get(crypto.Keccak256(key))
+ enc, err := t.trie.Get(platcrypto.Keccak256(key))
if err != nil || len(enc) == 0 {
return nil, err
}
@@ -159,7 +159,7 @@ func (t *StateTrie) GetStorage(_ common.Address, key []byte) ([]byte, error) {
func (t *StateTrie) PrefetchStorage(_ common.Address, keys [][]byte) error {
var keylist [][]byte
for _, key := range keys {
- keylist = append(keylist, crypto.Keccak256(key))
+ keylist = append(keylist, platcrypto.Keccak256(key))
}
return t.trie.Prefetch(keylist)
}
@@ -182,7 +182,7 @@ func (t *StateTrie) GetNode(path []byte) ([]byte, int, error) {
// This function will omit any encountered error but just print out an
// error message.
func (t *StateTrie) MustUpdate(key, value []byte) {
- hk := crypto.Keccak256(key)
+ hk := platcrypto.Keccak256(key)
t.trie.MustUpdate(hk, value)
if t.preimages != nil {
t.secKeyCache[common.Hash(hk)] = common.CopyBytes(key)
@@ -198,7 +198,7 @@ func (t *StateTrie) MustUpdate(key, value []byte) {
//
// If a node is not found in the database, a MissingNodeError is returned.
func (t *StateTrie) UpdateStorage(_ common.Address, key, value []byte) error {
- hk := crypto.Keccak256(key)
+ hk := platcrypto.Keccak256(key)
v, _ := rlp.EncodeToBytes(value)
err := t.trie.Update(hk, v)
if err != nil {
@@ -212,7 +212,7 @@ func (t *StateTrie) UpdateStorage(_ common.Address, key, value []byte) error {
// UpdateAccount will abstract the write of an account to the secure trie.
func (t *StateTrie) UpdateAccount(address common.Address, acc *types.StateAccount, _ int) error {
- hk := crypto.Keccak256(address.Bytes())
+ hk := platcrypto.Keccak256(address.Bytes())
data, err := rlp.EncodeToBytes(acc)
if err != nil {
return err
@@ -233,7 +233,7 @@ func (t *StateTrie) UpdateContractCode(_ common.Address, _ common.Hash, _ []byte
// MustDelete removes any existing value for key from the trie. This function
// will omit any encountered error but just print out an error message.
func (t *StateTrie) MustDelete(key []byte) {
- hk := crypto.Keccak256(key)
+ hk := platcrypto.Keccak256(key)
if t.preimages != nil {
delete(t.secKeyCache, common.Hash(hk))
}
@@ -244,7 +244,7 @@ func (t *StateTrie) MustDelete(key []byte) {
// If the specified trie node is not in the trie, nothing will be changed.
// If a node is not found in the database, a MissingNodeError is returned.
func (t *StateTrie) DeleteStorage(_ common.Address, key []byte) error {
- hk := crypto.Keccak256(key)
+ hk := platcrypto.Keccak256(key)
if t.preimages != nil {
delete(t.secKeyCache, common.Hash(hk))
}
@@ -253,7 +253,7 @@ func (t *StateTrie) DeleteStorage(_ common.Address, key []byte) error {
// DeleteAccount abstracts an account deletion from the trie.
func (t *StateTrie) DeleteAccount(address common.Address) error {
- hk := crypto.Keccak256(address.Bytes())
+ hk := platcrypto.Keccak256(address.Bytes())
if t.preimages != nil {
delete(t.secKeyCache, common.Hash(hk))
}
From c14034a4872912879adac9c8868057382e980ca7 Mon Sep 17 00:00:00 2001
From: Guillaume Ballet <3272758+gballet@users.noreply.github.com>
Date: Mon, 22 Sep 2025 21:05:15 +0200
Subject: [PATCH 2/4] rework to replace the module
---
cmd/keeper/crypto_ziren/crypto.go | 281 ++++++++++++++++++++++++++++++
cmd/keeper/crypto_ziren/go.mod | 3 +
cmd/keeper/go.ziren.mod | 49 ++++++
core/vm/evm.go | 3 +-
crypto/platcrypto/keccak.go | 42 -----
crypto/platcrypto/keccak_ziren.go | 101 -----------
trie/secure_trie.go | 24 +--
7 files changed, 346 insertions(+), 157 deletions(-)
create mode 100644 cmd/keeper/crypto_ziren/crypto.go
create mode 100644 cmd/keeper/crypto_ziren/go.mod
create mode 100644 cmd/keeper/go.ziren.mod
delete mode 100644 crypto/platcrypto/keccak.go
delete mode 100644 crypto/platcrypto/keccak_ziren.go
diff --git a/cmd/keeper/crypto_ziren/crypto.go b/cmd/keeper/crypto_ziren/crypto.go
new file mode 100644
index 00000000000..5580e19e775
--- /dev/null
+++ b/cmd/keeper/crypto_ziren/crypto.go
@@ -0,0 +1,281 @@
+// Copyright 2025 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+package crypto
+
+import (
+ "errors"
+ "syscall"
+ "unsafe"
+
+ "github.com/ethereum/go-ethereum/common"
+ originalcrypto "github.com/ethereum/go-ethereum/crypto"
+)
+
+// Ziren zkVM system call numbers
+const (
+ // SYS_KECCAK_SPONGE is the system call number for keccak sponge compression in Ziren zkVM
+ // This performs the keccak-f[1600] permutation on a 1600-bit (200-byte) state
+ SYS_KECCAK_SPONGE = 0x010109
+)
+
+// Keccak256 constants
+const (
+ keccakRate = 136 // 1088 bits = 136 bytes for keccak256
+ keccakCapacity = 64 // 512 bits = 64 bytes
+ keccakStateSize = 200 // 1600 bits = 200 bytes
+)
+
+// zirenKeccakSponge calls the Ziren zkVM keccak sponge compression function
+// This performs the keccak-f[1600] permutation on the 200-byte state
+func zirenKeccakSponge(state *[keccakStateSize]byte) error {
+ _, _, errno := syscall.Syscall(
+ SYS_KECCAK_SPONGE,
+ uintptr(unsafe.Pointer(state)), // State pointer (input/output)
+ 0, 0, // Unused parameters
+ )
+
+ if errno != 0 {
+ return errors.New("keccak sponge syscall failed")
+ }
+
+ return nil
+}
+
+// zirenKeccak256 implements full keccak256 using the Ziren sponge syscall
+func zirenKeccak256(data []byte) []byte {
+ // Initialize state to zeros
+ var state [keccakStateSize]byte
+
+ // Pad input according to keccak256 specification
+ // Padding: append 0x01, then zero or more 0x00 bytes, then 0x80
+ padded := make([]byte, len(data))
+ copy(padded, data)
+ padded = append(padded, 0x01) // Domain separator for keccak256
+
+ // Pad to multiple of rate (136 bytes for keccak256)
+ for len(padded)%keccakRate != (keccakRate - 1) {
+ padded = append(padded, 0x00)
+ }
+ padded = append(padded, 0x80) // Final padding bit
+
+ // Absorb phase: process input in chunks of rate size
+ for i := 0; i < len(padded); i += keccakRate {
+ // XOR current chunk with state
+ for j := 0; j < keccakRate && i+j < len(padded); j++ {
+ state[j] ^= padded[i+j]
+ }
+
+ // Apply keccak-f[1600] permutation via syscall
+ if err := zirenKeccakSponge(&state); err != nil {
+ // Fallback to standard implementation on error
+ return originalcrypto.Keccak256(data)
+ }
+ }
+
+ // Squeeze phase: extract 32 bytes (256 bits) for keccak256
+ result := make([]byte, 32)
+ copy(result, state[:32])
+
+ return result
+}
+
+// Re-export everything from original crypto package except the parts we're overriding
+var (
+ S256 = originalcrypto.S256
+ PubkeyToAddress = originalcrypto.PubkeyToAddress
+ Ecrecover = originalcrypto.Ecrecover
+ SigToPub = originalcrypto.SigToPub
+ Sign = originalcrypto.Sign
+ VerifySignature = originalcrypto.VerifySignature
+ DecompressPubkey = originalcrypto.DecompressPubkey
+ CompressPubkey = originalcrypto.CompressPubkey
+ HexToECDSA = originalcrypto.HexToECDSA
+ LoadECDSA = originalcrypto.LoadECDSA
+ SaveECDSA = originalcrypto.SaveECDSA
+ GenerateKey = originalcrypto.GenerateKey
+ ValidateSignatureValues = originalcrypto.ValidateSignatureValues
+ Keccak512 = originalcrypto.Keccak512
+)
+
+// Re-export types
+type (
+ KeccakState = originalcrypto.KeccakState
+)
+
+// zirenKeccakState implements crypto.KeccakState using the Ziren sponge precompile
+type zirenKeccakState struct {
+ state [keccakStateSize]byte // 200-byte keccak state
+ absorbed int // Number of bytes absorbed into current block
+ buffer [keccakRate]byte // Rate-sized buffer for current block
+ finalized bool // Whether absorption is complete
+}
+
+func (k *zirenKeccakState) Reset() {
+ for i := range k.state {
+ k.state[i] = 0
+ }
+ for i := range k.buffer {
+ k.buffer[i] = 0
+ }
+ k.absorbed = 0
+ k.finalized = false
+}
+
+func (k *zirenKeccakState) Clone() KeccakState {
+ clone := &zirenKeccakState{
+ absorbed: k.absorbed,
+ finalized: k.finalized,
+ }
+ copy(clone.state[:], k.state[:])
+ copy(clone.buffer[:], k.buffer[:])
+ return clone
+}
+
+func (k *zirenKeccakState) Write(data []byte) (int, error) {
+ if k.finalized {
+ panic("write to finalized keccak state")
+ }
+
+ written := 0
+ for len(data) > 0 {
+ // Fill current block
+ canWrite := keccakRate - k.absorbed
+ if canWrite > len(data) {
+ canWrite = len(data)
+ }
+
+ copy(k.buffer[k.absorbed:], data[:canWrite])
+ k.absorbed += canWrite
+ data = data[canWrite:]
+ written += canWrite
+
+ // If block is full, absorb it
+ if k.absorbed == keccakRate {
+ k.absorbBlock()
+ }
+ }
+
+ return written, nil
+}
+
+// absorbBlock XORs the current buffer into state and applies the sponge permutation
+func (k *zirenKeccakState) absorbBlock() {
+ // XOR buffer into state
+ for i := 0; i < keccakRate; i++ {
+ k.state[i] ^= k.buffer[i]
+ }
+
+ // Apply keccak-f[1600] permutation via Ziren syscall
+ if err := zirenKeccakSponge(&k.state); err != nil {
+ // On error, fallback to standard Go implementation
+ // This shouldn't happen in production but provides safety
+ fallbackState := originalcrypto.NewKeccakState()
+ fallbackState.Reset()
+ fallbackState.Write(k.buffer[:k.absorbed])
+ fallbackState.Read(k.state[:32])
+ }
+
+ // Reset buffer
+ k.absorbed = 0
+ for i := range k.buffer {
+ k.buffer[i] = 0
+ }
+}
+
+func (k *zirenKeccakState) Read(hash []byte) (int, error) {
+ if len(hash) < 32 {
+ return 0, errors.New("hash slice too short")
+ }
+
+ if !k.finalized {
+ k.finalize()
+ }
+
+ copy(hash[:32], k.state[:32])
+ return 32, nil
+}
+
+// finalize completes the absorption phase with padding
+func (k *zirenKeccakState) finalize() {
+ // Add keccak256 padding: 0x01, then zeros, then 0x80
+ k.buffer[k.absorbed] = 0x01
+ k.absorbed++
+
+ // Pad with zeros until we have room for final bit
+ for k.absorbed < keccakRate-1 {
+ k.buffer[k.absorbed] = 0x00
+ k.absorbed++
+ }
+
+ // Add final padding bit
+ k.buffer[keccakRate-1] = 0x80
+ k.absorbed = keccakRate
+
+ // Absorb final block
+ k.absorbBlock()
+ k.finalized = true
+}
+
+func (k *zirenKeccakState) Sum(data []byte) []byte {
+ hash := make([]byte, 32)
+ k.Read(hash)
+ return append(data, hash...)
+}
+
+func (k *zirenKeccakState) Size() int {
+ return 32
+}
+
+func (k *zirenKeccakState) BlockSize() int {
+ return 136 // keccak256 block size
+}
+
+// Keccak256 calculates and returns the Keccak256 hash using the ziren platform precompile.
+func Keccak256(data ...[]byte) []byte {
+ // For multiple data chunks, concatenate them
+ if len(data) == 0 {
+ return zirenKeccak256(nil)
+ }
+ if len(data) == 1 {
+ return zirenKeccak256(data[0])
+ }
+
+ // Concatenate multiple data chunks
+ var totalLen int
+ for _, d := range data {
+ totalLen += len(d)
+ }
+
+ combined := make([]byte, 0, totalLen)
+ for _, d := range data {
+ combined = append(combined, d...)
+ }
+
+ return zirenKeccak256(combined)
+}
+
+// Keccak256Hash calculates and returns the Keccak256 hash as a Hash using the ziren platform precompile.
+func Keccak256Hash(data ...[]byte) (h common.Hash) {
+ hash := Keccak256(data...)
+ copy(h[:], hash)
+ return h
+}
+
+// NewKeccakState returns a new keccak state hasher using the ziren platform precompile.
+func NewKeccakState() KeccakState {
+ return &zirenKeccakState{}
+}
diff --git a/cmd/keeper/crypto_ziren/go.mod b/cmd/keeper/crypto_ziren/go.mod
new file mode 100644
index 00000000000..b537b19c2c5
--- /dev/null
+++ b/cmd/keeper/crypto_ziren/go.mod
@@ -0,0 +1,3 @@
+module github.com/ethereum/go-ethereum/crypto
+
+go 1.24.0
diff --git a/cmd/keeper/go.ziren.mod b/cmd/keeper/go.ziren.mod
new file mode 100644
index 00000000000..f7e8c7895c9
--- /dev/null
+++ b/cmd/keeper/go.ziren.mod
@@ -0,0 +1,49 @@
+module github.com/ethereum/go-ethereum/cmd/keeper
+
+go 1.24.0
+
+require (
+ github.com/ethereum/go-ethereum v0.0.0-00010101000000-000000000000
+ github.com/zkMIPS/zkMIPS/crates/go-runtime/zkm_runtime v0.0.0-20250915074013-fbc07aa2c6f5
+)
+
+require (
+ github.com/StackExchange/wmi v1.2.1 // indirect
+ github.com/VictoriaMetrics/fastcache v1.12.2 // indirect
+ github.com/bits-and-blooms/bitset v1.20.0 // indirect
+ github.com/cespare/xxhash/v2 v2.3.0 // indirect
+ github.com/consensys/gnark-crypto v0.18.0 // indirect
+ github.com/crate-crypto/go-eth-kzg v1.3.0 // indirect
+ github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect
+ github.com/deckarep/golang-set/v2 v2.6.0 // indirect
+ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
+ github.com/emicklei/dot v1.6.2 // indirect
+ github.com/ethereum/c-kzg-4844/v2 v2.1.0 // indirect
+ github.com/ethereum/go-verkle v0.2.2 // indirect
+ github.com/ferranbt/fastssz v0.1.4 // indirect
+ github.com/go-ole/go-ole v1.3.0 // indirect
+ github.com/gofrs/flock v0.12.1 // indirect
+ github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
+ github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
+ github.com/holiman/uint256 v1.3.2 // indirect
+ github.com/klauspost/cpuid/v2 v2.0.9 // indirect
+ github.com/mattn/go-runewidth v0.0.13 // indirect
+ github.com/minio/sha256-simd v1.0.0 // indirect
+ github.com/mitchellh/mapstructure v1.4.1 // indirect
+ github.com/olekukonko/tablewriter v0.0.5 // indirect
+ github.com/rivo/uniseg v0.2.0 // indirect
+ github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
+ github.com/supranational/blst v0.3.14 // indirect
+ github.com/tklauser/go-sysconf v0.3.12 // indirect
+ github.com/tklauser/numcpus v0.6.1 // indirect
+ golang.org/x/crypto v0.36.0 // indirect
+ golang.org/x/sync v0.12.0 // indirect
+ golang.org/x/sys v0.31.0 // indirect
+ gopkg.in/yaml.v2 v2.4.0 // indirect
+)
+
+replace (
+ github.com/ethereum/go-ethereum => ../../
+ github.com/ethereum/go-ethereum/crypto => ./crypto_ziren
+ github.com/zkMIPS/zkMIPS/crates/go-runtime/zkm_runtime => github.com/weilzkm/zkMIPS/crates/go-runtime/zkvm_runtime v0.0.0-20250915074013-fbc07aa2c6f5
+)
diff --git a/core/vm/evm.go b/core/vm/evm.go
index 0874fbe4ee0..88ef1cf121e 100644
--- a/core/vm/evm.go
+++ b/core/vm/evm.go
@@ -26,7 +26,6 @@ import (
"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/crypto/platcrypto"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/holiman/uint256"
@@ -145,7 +144,7 @@ func NewEVM(blockCtx BlockContext, statedb StateDB, chainConfig *params.ChainCon
chainConfig: chainConfig,
chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time),
jumpDests: newMapJumpDests(),
- hasher: platcrypto.NewKeccakState(),
+ hasher: crypto.NewKeccakState(),
}
evm.precompiles = activePrecompiledContracts(evm.chainRules)
diff --git a/crypto/platcrypto/keccak.go b/crypto/platcrypto/keccak.go
deleted file mode 100644
index a070e8c4536..00000000000
--- a/crypto/platcrypto/keccak.go
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2025 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-//go:build !ziren
-
-package platcrypto
-
-import (
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/crypto"
-)
-
-// Keccak256 calculates and returns the Keccak256 hash using the standard implementation.
-// This is used for geth, evm, and other regular programs.
-func Keccak256(data ...[]byte) []byte {
- return crypto.Keccak256(data...)
-}
-
-// Keccak256Hash calculates and returns the Keccak256 hash as a Hash using the standard implementation.
-// This is used for geth, evm, and other regular programs.
-func Keccak256Hash(data ...[]byte) common.Hash {
- return crypto.Keccak256Hash(data...)
-}
-
-// NewKeccakState returns a new keccak state hasher using the standard implementation.
-// This is used for geth, evm, and other regular programs.
-func NewKeccakState() crypto.KeccakState {
- return crypto.NewKeccakState()
-}
diff --git a/crypto/platcrypto/keccak_ziren.go b/crypto/platcrypto/keccak_ziren.go
deleted file mode 100644
index b0fa74ae6c0..00000000000
--- a/crypto/platcrypto/keccak_ziren.go
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2025 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-//go:build ziren
-
-package platcrypto
-
-import (
- "errors"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/crypto"
- zkruntime "github.com/zkMIPS/zkMIPS/crates/go-runtime/zkm_runtime"
-)
-
-// zirenKeccak implements keccak256 using the ziren platform precompile
-func zirenKeccak(data []byte) []byte {
- return zkruntime.Keccak(data)
-}
-
-// zirenKeccakState wraps the ziren platform keccak precompile to implement crypto.KeccakState interface
-type zirenKeccakState struct {
- data []byte
-}
-
-func (k *zirenKeccakState) Reset() {
- k.data = k.data[:0]
-}
-
-func (k *zirenKeccakState) Clone() crypto.KeccakState {
- clone := &zirenKeccakState{
- data: make([]byte, len(k.data)),
- }
- copy(clone.data, k.data)
- return clone
-}
-
-func (k *zirenKeccakState) Write(data []byte) (int, error) {
- k.data = append(k.data, data...)
- return len(data), nil
-}
-
-func (k *zirenKeccakState) Read(hash []byte) (int, error) {
- if len(hash) < 32 {
- return 0, errors.New("hash slice too short")
- }
-
- result := zirenKeccak(k.data)
- copy(hash[:32], result)
- return 32, nil
-}
-
-func (k *zirenKeccakState) Sum(data []byte) []byte {
- hash := make([]byte, 32)
- k.Read(hash)
- return append(data, hash...)
-}
-
-func (k *zirenKeccakState) Size() int {
- return 32
-}
-
-func (k *zirenKeccakState) BlockSize() int {
- return 136 // keccak256 block size
-}
-
-// Keccak256 calculates and returns the Keccak256 hash using the ziren platform precompile.
-func Keccak256(data ...[]byte) []byte {
- hasher := &zirenKeccakState{}
- for _, b := range data {
- hasher.Write(b)
- }
- hash := make([]byte, 32)
- hasher.Read(hash)
- return hash
-}
-
-// Keccak256Hash calculates and returns the Keccak256 hash as a Hash using the ziren platform precompile.
-func Keccak256Hash(data ...[]byte) (h common.Hash) {
- hash := Keccak256(data...)
- copy(h[:], hash)
- return h
-}
-
-// NewKeccakState returns a new keccak state hasher using the ziren platform precompile.
-func NewKeccakState() crypto.KeccakState {
- return &zirenKeccakState{}
-}
diff --git a/trie/secure_trie.go b/trie/secure_trie.go
index 588ca698ebf..7c7bd184bf8 100644
--- a/trie/secure_trie.go
+++ b/trie/secure_trie.go
@@ -19,7 +19,7 @@ package trie
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/crypto/platcrypto"
+ "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie/trienode"
"github.com/ethereum/go-ethereum/triedb/database"
@@ -102,14 +102,14 @@ func NewStateTrie(id *ID, db database.NodeDatabase) (*StateTrie, error) {
// This function will omit any encountered error but just
// print out an error message.
func (t *StateTrie) MustGet(key []byte) []byte {
- return t.trie.MustGet(platcrypto.Keccak256(key))
+ return t.trie.MustGet(crypto.Keccak256(key))
}
// GetAccount attempts to retrieve an account with provided account address.
// If the specified account is not in the trie, nil will be returned.
// If a trie node is not found in the database, a MissingNodeError is returned.
func (t *StateTrie) GetAccount(address common.Address) (*types.StateAccount, error) {
- res, err := t.trie.Get(platcrypto.Keccak256(address.Bytes()))
+ res, err := t.trie.Get(crypto.Keccak256(address.Bytes()))
if res == nil || err != nil {
return nil, err
}
@@ -136,7 +136,7 @@ func (t *StateTrie) GetAccountByHash(addrHash common.Hash) (*types.StateAccount,
func (t *StateTrie) PrefetchAccount(addresses []common.Address) error {
var keys [][]byte
for _, addr := range addresses {
- keys = append(keys, platcrypto.Keccak256(addr.Bytes()))
+ keys = append(keys, crypto.Keccak256(addr.Bytes()))
}
return t.trie.Prefetch(keys)
}
@@ -146,7 +146,7 @@ func (t *StateTrie) PrefetchAccount(addresses []common.Address) error {
// If the specified storage slot is not in the trie, nil will be returned.
// If a trie node is not found in the database, a MissingNodeError is returned.
func (t *StateTrie) GetStorage(_ common.Address, key []byte) ([]byte, error) {
- enc, err := t.trie.Get(platcrypto.Keccak256(key))
+ enc, err := t.trie.Get(crypto.Keccak256(key))
if err != nil || len(enc) == 0 {
return nil, err
}
@@ -159,7 +159,7 @@ func (t *StateTrie) GetStorage(_ common.Address, key []byte) ([]byte, error) {
func (t *StateTrie) PrefetchStorage(_ common.Address, keys [][]byte) error {
var keylist [][]byte
for _, key := range keys {
- keylist = append(keylist, platcrypto.Keccak256(key))
+ keylist = append(keylist, crypto.Keccak256(key))
}
return t.trie.Prefetch(keylist)
}
@@ -182,7 +182,7 @@ func (t *StateTrie) GetNode(path []byte) ([]byte, int, error) {
// This function will omit any encountered error but just print out an
// error message.
func (t *StateTrie) MustUpdate(key, value []byte) {
- hk := platcrypto.Keccak256(key)
+ hk := crypto.Keccak256(key)
t.trie.MustUpdate(hk, value)
if t.preimages != nil {
t.secKeyCache[common.Hash(hk)] = common.CopyBytes(key)
@@ -198,7 +198,7 @@ func (t *StateTrie) MustUpdate(key, value []byte) {
//
// If a node is not found in the database, a MissingNodeError is returned.
func (t *StateTrie) UpdateStorage(_ common.Address, key, value []byte) error {
- hk := platcrypto.Keccak256(key)
+ hk := crypto.Keccak256(key)
v, _ := rlp.EncodeToBytes(value)
err := t.trie.Update(hk, v)
if err != nil {
@@ -212,7 +212,7 @@ func (t *StateTrie) UpdateStorage(_ common.Address, key, value []byte) error {
// UpdateAccount will abstract the write of an account to the secure trie.
func (t *StateTrie) UpdateAccount(address common.Address, acc *types.StateAccount, _ int) error {
- hk := platcrypto.Keccak256(address.Bytes())
+ hk := crypto.Keccak256(address.Bytes())
data, err := rlp.EncodeToBytes(acc)
if err != nil {
return err
@@ -233,7 +233,7 @@ func (t *StateTrie) UpdateContractCode(_ common.Address, _ common.Hash, _ []byte
// MustDelete removes any existing value for key from the trie. This function
// will omit any encountered error but just print out an error message.
func (t *StateTrie) MustDelete(key []byte) {
- hk := platcrypto.Keccak256(key)
+ hk := crypto.Keccak256(key)
if t.preimages != nil {
delete(t.secKeyCache, common.Hash(hk))
}
@@ -244,7 +244,7 @@ func (t *StateTrie) MustDelete(key []byte) {
// If the specified trie node is not in the trie, nothing will be changed.
// If a node is not found in the database, a MissingNodeError is returned.
func (t *StateTrie) DeleteStorage(_ common.Address, key []byte) error {
- hk := platcrypto.Keccak256(key)
+ hk := crypto.Keccak256(key)
if t.preimages != nil {
delete(t.secKeyCache, common.Hash(hk))
}
@@ -253,7 +253,7 @@ func (t *StateTrie) DeleteStorage(_ common.Address, key []byte) error {
// DeleteAccount abstracts an account deletion from the trie.
func (t *StateTrie) DeleteAccount(address common.Address) error {
- hk := platcrypto.Keccak256(address.Bytes())
+ hk := crypto.Keccak256(address.Bytes())
if t.preimages != nil {
delete(t.secKeyCache, common.Hash(hk))
}
From cbf86b4715029ff22f9995b0a500e891f2bfb556 Mon Sep 17 00:00:00 2001
From: Guillaume Ballet <3272758+gballet@users.noreply.github.com>
Date: Tue, 30 Sep 2025 16:17:15 -0400
Subject: [PATCH 3/4] use my keccak PR
---
cmd/keeper/crypto_ziren/crypto.go | 231 +++---------------------------
1 file changed, 20 insertions(+), 211 deletions(-)
diff --git a/cmd/keeper/crypto_ziren/crypto.go b/cmd/keeper/crypto_ziren/crypto.go
index 5580e19e775..7803a04643e 100644
--- a/cmd/keeper/crypto_ziren/crypto.go
+++ b/cmd/keeper/crypto_ziren/crypto.go
@@ -14,85 +14,17 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
+//go:build ziren
+// +build ziren
+
package crypto
import (
- "errors"
- "syscall"
- "unsafe"
-
+ "github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime"
"github.com/ethereum/go-ethereum/common"
originalcrypto "github.com/ethereum/go-ethereum/crypto"
)
-// Ziren zkVM system call numbers
-const (
- // SYS_KECCAK_SPONGE is the system call number for keccak sponge compression in Ziren zkVM
- // This performs the keccak-f[1600] permutation on a 1600-bit (200-byte) state
- SYS_KECCAK_SPONGE = 0x010109
-)
-
-// Keccak256 constants
-const (
- keccakRate = 136 // 1088 bits = 136 bytes for keccak256
- keccakCapacity = 64 // 512 bits = 64 bytes
- keccakStateSize = 200 // 1600 bits = 200 bytes
-)
-
-// zirenKeccakSponge calls the Ziren zkVM keccak sponge compression function
-// This performs the keccak-f[1600] permutation on the 200-byte state
-func zirenKeccakSponge(state *[keccakStateSize]byte) error {
- _, _, errno := syscall.Syscall(
- SYS_KECCAK_SPONGE,
- uintptr(unsafe.Pointer(state)), // State pointer (input/output)
- 0, 0, // Unused parameters
- )
-
- if errno != 0 {
- return errors.New("keccak sponge syscall failed")
- }
-
- return nil
-}
-
-// zirenKeccak256 implements full keccak256 using the Ziren sponge syscall
-func zirenKeccak256(data []byte) []byte {
- // Initialize state to zeros
- var state [keccakStateSize]byte
-
- // Pad input according to keccak256 specification
- // Padding: append 0x01, then zero or more 0x00 bytes, then 0x80
- padded := make([]byte, len(data))
- copy(padded, data)
- padded = append(padded, 0x01) // Domain separator for keccak256
-
- // Pad to multiple of rate (136 bytes for keccak256)
- for len(padded)%keccakRate != (keccakRate - 1) {
- padded = append(padded, 0x00)
- }
- padded = append(padded, 0x80) // Final padding bit
-
- // Absorb phase: process input in chunks of rate size
- for i := 0; i < len(padded); i += keccakRate {
- // XOR current chunk with state
- for j := 0; j < keccakRate && i+j < len(padded); j++ {
- state[j] ^= padded[i+j]
- }
-
- // Apply keccak-f[1600] permutation via syscall
- if err := zirenKeccakSponge(&state); err != nil {
- // Fallback to standard implementation on error
- return originalcrypto.Keccak256(data)
- }
- }
-
- // Squeeze phase: extract 32 bytes (256 bits) for keccak256
- result := make([]byte, 32)
- copy(result, state[:32])
-
- return result
-}
-
// Re-export everything from original crypto package except the parts we're overriding
var (
S256 = originalcrypto.S256
@@ -116,166 +48,43 @@ type (
KeccakState = originalcrypto.KeccakState
)
-// zirenKeccakState implements crypto.KeccakState using the Ziren sponge precompile
-type zirenKeccakState struct {
- state [keccakStateSize]byte // 200-byte keccak state
- absorbed int // Number of bytes absorbed into current block
- buffer [keccakRate]byte // Rate-sized buffer for current block
- finalized bool // Whether absorption is complete
-}
-
-func (k *zirenKeccakState) Reset() {
- for i := range k.state {
- k.state[i] = 0
- }
- for i := range k.buffer {
- k.buffer[i] = 0
- }
- k.absorbed = 0
- k.finalized = false
-}
-
-func (k *zirenKeccakState) Clone() KeccakState {
- clone := &zirenKeccakState{
- absorbed: k.absorbed,
- finalized: k.finalized,
- }
- copy(clone.state[:], k.state[:])
- copy(clone.buffer[:], k.buffer[:])
- return clone
-}
-
-func (k *zirenKeccakState) Write(data []byte) (int, error) {
- if k.finalized {
- panic("write to finalized keccak state")
- }
-
- written := 0
- for len(data) > 0 {
- // Fill current block
- canWrite := keccakRate - k.absorbed
- if canWrite > len(data) {
- canWrite = len(data)
- }
-
- copy(k.buffer[k.absorbed:], data[:canWrite])
- k.absorbed += canWrite
- data = data[canWrite:]
- written += canWrite
-
- // If block is full, absorb it
- if k.absorbed == keccakRate {
- k.absorbBlock()
- }
- }
-
- return written, nil
-}
-
-// absorbBlock XORs the current buffer into state and applies the sponge permutation
-func (k *zirenKeccakState) absorbBlock() {
- // XOR buffer into state
- for i := 0; i < keccakRate; i++ {
- k.state[i] ^= k.buffer[i]
- }
-
- // Apply keccak-f[1600] permutation via Ziren syscall
- if err := zirenKeccakSponge(&k.state); err != nil {
- // On error, fallback to standard Go implementation
- // This shouldn't happen in production but provides safety
- fallbackState := originalcrypto.NewKeccakState()
- fallbackState.Reset()
- fallbackState.Write(k.buffer[:k.absorbed])
- fallbackState.Read(k.state[:32])
- }
-
- // Reset buffer
- k.absorbed = 0
- for i := range k.buffer {
- k.buffer[i] = 0
- }
-}
-
-func (k *zirenKeccakState) Read(hash []byte) (int, error) {
- if len(hash) < 32 {
- return 0, errors.New("hash slice too short")
- }
-
- if !k.finalized {
- k.finalize()
- }
-
- copy(hash[:32], k.state[:32])
- return 32, nil
-}
-
-// finalize completes the absorption phase with padding
-func (k *zirenKeccakState) finalize() {
- // Add keccak256 padding: 0x01, then zeros, then 0x80
- k.buffer[k.absorbed] = 0x01
- k.absorbed++
-
- // Pad with zeros until we have room for final bit
- for k.absorbed < keccakRate-1 {
- k.buffer[k.absorbed] = 0x00
- k.absorbed++
- }
-
- // Add final padding bit
- k.buffer[keccakRate-1] = 0x80
- k.absorbed = keccakRate
-
- // Absorb final block
- k.absorbBlock()
- k.finalized = true
-}
-
-func (k *zirenKeccakState) Sum(data []byte) []byte {
- hash := make([]byte, 32)
- k.Read(hash)
- return append(data, hash...)
-}
-
-func (k *zirenKeccakState) Size() int {
- return 32
-}
-
-func (k *zirenKeccakState) BlockSize() int {
- return 136 // keccak256 block size
-}
-
-// Keccak256 calculates and returns the Keccak256 hash using the ziren platform precompile.
+// Keccak256 calculates and returns the Keccak256 hash using the Ziren zkvm_runtime implementation.
func Keccak256(data ...[]byte) []byte {
// For multiple data chunks, concatenate them
if len(data) == 0 {
- return zirenKeccak256(nil)
+ result := zkvm_runtime.Keccak256(nil)
+ return result[:]
}
if len(data) == 1 {
- return zirenKeccak256(data[0])
+ result := zkvm_runtime.Keccak256(data[0])
+ return result[:]
}
-
+
// Concatenate multiple data chunks
var totalLen int
for _, d := range data {
totalLen += len(d)
}
-
+
combined := make([]byte, 0, totalLen)
for _, d := range data {
combined = append(combined, d...)
}
-
- return zirenKeccak256(combined)
+
+ result := zkvm_runtime.Keccak256(combined)
+ return result[:]
}
-// Keccak256Hash calculates and returns the Keccak256 hash as a Hash using the ziren platform precompile.
+// Keccak256Hash calculates and returns the Keccak256 hash as a Hash using the Ziren zkvm_runtime implementation.
func Keccak256Hash(data ...[]byte) (h common.Hash) {
hash := Keccak256(data...)
copy(h[:], hash)
return h
}
-// NewKeccakState returns a new keccak state hasher using the ziren platform precompile.
+// NewKeccakState returns a new keccak state hasher.
+// For now, we fallback to the original implementation for the stateful interface.
+// TODO: Implement a stateful wrapper around zkvm_runtime.Keccak256 if needed.
func NewKeccakState() KeccakState {
- return &zirenKeccakState{}
-}
+ return originalcrypto.NewKeccakState()
+}
\ No newline at end of file
From b26b3e800143d8662c4ce32ae628aa6d90ea54a1 Mon Sep 17 00:00:00 2001
From: Guillaume Ballet <3272758+gballet@users.noreply.github.com>
Date: Sun, 5 Oct 2025 13:09:59 +0200
Subject: [PATCH 4/4] update ziren ref + use tags for crypto module
---
cmd/keeper/crypto_ziren/go.mod | 3 -
cmd/keeper/getpayload_ziren.go | 2 +-
cmd/keeper/go.mod | 7 +-
cmd/keeper/go.sum | 2 +
cmd/keeper/go.ziren.mod | 49 ----------
crypto/crypto.go | 65 --------------
crypto/keccak.go | 89 +++++++++++++++++++
.../crypto.go => crypto/keccak_ziren.go | 59 ++++++------
go.mod | 1 +
go.sum | 2 +
10 files changed, 127 insertions(+), 152 deletions(-)
delete mode 100644 cmd/keeper/crypto_ziren/go.mod
delete mode 100644 cmd/keeper/go.ziren.mod
create mode 100644 crypto/keccak.go
rename cmd/keeper/crypto_ziren/crypto.go => crypto/keccak_ziren.go (64%)
diff --git a/cmd/keeper/crypto_ziren/go.mod b/cmd/keeper/crypto_ziren/go.mod
deleted file mode 100644
index b537b19c2c5..00000000000
--- a/cmd/keeper/crypto_ziren/go.mod
+++ /dev/null
@@ -1,3 +0,0 @@
-module github.com/ethereum/go-ethereum/crypto
-
-go 1.24.0
diff --git a/cmd/keeper/getpayload_ziren.go b/cmd/keeper/getpayload_ziren.go
index 11c5845bcc1..bc373db94f5 100644
--- a/cmd/keeper/getpayload_ziren.go
+++ b/cmd/keeper/getpayload_ziren.go
@@ -19,7 +19,7 @@
package main
import (
- zkruntime "github.com/zkMIPS/zkMIPS/crates/go-runtime/zkm_runtime"
+ zkruntime "github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime"
)
// getInput reads the input payload from the zkVM runtime environment.
diff --git a/cmd/keeper/go.mod b/cmd/keeper/go.mod
index 16094d16b1d..24220fd15c7 100644
--- a/cmd/keeper/go.mod
+++ b/cmd/keeper/go.mod
@@ -4,7 +4,7 @@ go 1.24.0
require (
github.com/ethereum/go-ethereum v0.0.0-00010101000000-000000000000
- github.com/zkMIPS/zkMIPS/crates/go-runtime/zkm_runtime v0.0.0-20250915074013-fbc07aa2c6f5
+ github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6
)
require (
@@ -43,7 +43,4 @@ require (
gopkg.in/yaml.v2 v2.4.0 // indirect
)
-replace (
- github.com/ethereum/go-ethereum => ../../
- github.com/zkMIPS/zkMIPS/crates/go-runtime/zkm_runtime => github.com/weilzkm/zkMIPS/crates/go-runtime/zkvm_runtime v0.0.0-20250915074013-fbc07aa2c6f5
-)
+replace github.com/ethereum/go-ethereum => ../../
diff --git a/cmd/keeper/go.sum b/cmd/keeper/go.sum
index 3eaef469dcc..79a25a4e6df 100644
--- a/cmd/keeper/go.sum
+++ b/cmd/keeper/go.sum
@@ -1,5 +1,7 @@
github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ=
github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
+github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6 h1:1zYrtlhrZ6/b6SAjLSfKzWtdgqK0U+HtH/VcBWh1BaU=
+github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI=
github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
github.com/VictoriaMetrics/fastcache v1.13.0 h1:AW4mheMR5Vd9FkAPUv+NH6Nhw+fmbTMGMsNAoA/+4G0=
diff --git a/cmd/keeper/go.ziren.mod b/cmd/keeper/go.ziren.mod
deleted file mode 100644
index f7e8c7895c9..00000000000
--- a/cmd/keeper/go.ziren.mod
+++ /dev/null
@@ -1,49 +0,0 @@
-module github.com/ethereum/go-ethereum/cmd/keeper
-
-go 1.24.0
-
-require (
- github.com/ethereum/go-ethereum v0.0.0-00010101000000-000000000000
- github.com/zkMIPS/zkMIPS/crates/go-runtime/zkm_runtime v0.0.0-20250915074013-fbc07aa2c6f5
-)
-
-require (
- github.com/StackExchange/wmi v1.2.1 // indirect
- github.com/VictoriaMetrics/fastcache v1.12.2 // indirect
- github.com/bits-and-blooms/bitset v1.20.0 // indirect
- github.com/cespare/xxhash/v2 v2.3.0 // indirect
- github.com/consensys/gnark-crypto v0.18.0 // indirect
- github.com/crate-crypto/go-eth-kzg v1.3.0 // indirect
- github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect
- github.com/deckarep/golang-set/v2 v2.6.0 // indirect
- github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
- github.com/emicklei/dot v1.6.2 // indirect
- github.com/ethereum/c-kzg-4844/v2 v2.1.0 // indirect
- github.com/ethereum/go-verkle v0.2.2 // indirect
- github.com/ferranbt/fastssz v0.1.4 // indirect
- github.com/go-ole/go-ole v1.3.0 // indirect
- github.com/gofrs/flock v0.12.1 // indirect
- github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
- github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
- github.com/holiman/uint256 v1.3.2 // indirect
- github.com/klauspost/cpuid/v2 v2.0.9 // indirect
- github.com/mattn/go-runewidth v0.0.13 // indirect
- github.com/minio/sha256-simd v1.0.0 // indirect
- github.com/mitchellh/mapstructure v1.4.1 // indirect
- github.com/olekukonko/tablewriter v0.0.5 // indirect
- github.com/rivo/uniseg v0.2.0 // indirect
- github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
- github.com/supranational/blst v0.3.14 // indirect
- github.com/tklauser/go-sysconf v0.3.12 // indirect
- github.com/tklauser/numcpus v0.6.1 // indirect
- golang.org/x/crypto v0.36.0 // indirect
- golang.org/x/sync v0.12.0 // indirect
- golang.org/x/sys v0.31.0 // indirect
- gopkg.in/yaml.v2 v2.4.0 // indirect
-)
-
-replace (
- github.com/ethereum/go-ethereum => ../../
- github.com/ethereum/go-ethereum/crypto => ./crypto_ziren
- github.com/zkMIPS/zkMIPS/crates/go-runtime/zkm_runtime => github.com/weilzkm/zkMIPS/crates/go-runtime/zkvm_runtime v0.0.0-20250915074013-fbc07aa2c6f5
-)
diff --git a/crypto/crypto.go b/crypto/crypto.go
index 09596c05ce8..6eacf41de9a 100644
--- a/crypto/crypto.go
+++ b/crypto/crypto.go
@@ -24,16 +24,13 @@ import (
"encoding/hex"
"errors"
"fmt"
- "hash"
"io"
"math/big"
"os"
- "sync"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/rlp"
- "golang.org/x/crypto/sha3"
)
// SignatureLength indicates the byte length required to carry a signature with recovery id.
@@ -61,68 +58,6 @@ type EllipticCurve interface {
Unmarshal(data []byte) (x, y *big.Int)
}
-// KeccakState 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 {
- hash.Hash
- Read([]byte) (int, error)
-}
-
-// NewKeccakState creates a new KeccakState
-func NewKeccakState() KeccakState {
- return sha3.NewLegacyKeccak256().(KeccakState)
-}
-
-var hasherPool = sync.Pool{
- New: func() any {
- return sha3.NewLegacyKeccak256().(KeccakState)
- },
-}
-
-// 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
-}
-
-// Keccak256 calculates and returns the Keccak256 hash of the input data.
-func Keccak256(data ...[]byte) []byte {
- b := make([]byte, 32)
- d := hasherPool.Get().(KeccakState)
- d.Reset()
- for _, b := range data {
- d.Write(b)
- }
- d.Read(b)
- hasherPool.Put(d)
- 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)
- return h
-}
-
-// Keccak512 calculates and returns the Keccak512 hash of the input data.
-func Keccak512(data ...[]byte) []byte {
- d := sha3.NewLegacyKeccak512()
- for _, b := range data {
- d.Write(b)
- }
- return d.Sum(nil)
-}
-
// 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/keccak.go b/crypto/keccak.go
new file mode 100644
index 00000000000..9eb782d1194
--- /dev/null
+++ b/crypto/keccak.go
@@ -0,0 +1,89 @@
+// Copyright 2025 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+//go:build !ziren
+
+package crypto
+
+import (
+ "hash"
+ "sync"
+
+ "github.com/ethereum/go-ethereum/common"
+ "golang.org/x/crypto/sha3"
+)
+
+// KeccakState 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 {
+ hash.Hash
+ Read([]byte) (int, error)
+}
+
+// NewKeccakState creates a new KeccakState
+func NewKeccakState() KeccakState {
+ return sha3.NewLegacyKeccak256().(KeccakState)
+}
+
+var hasherPool = sync.Pool{
+ New: func() any {
+ return sha3.NewLegacyKeccak256().(KeccakState)
+ },
+}
+
+// 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
+}
+
+// Keccak256 calculates and returns the Keccak256 hash of the input data.
+func Keccak256(data ...[]byte) []byte {
+ b := make([]byte, 32)
+ d := hasherPool.Get().(KeccakState)
+ d.Reset()
+ for _, b := range data {
+ d.Write(b)
+ }
+ d.Read(b)
+ hasherPool.Put(d)
+ 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)
+ return h
+}
+
+// Keccak512 calculates and returns the Keccak512 hash of the input data.
+func Keccak512(data ...[]byte) []byte {
+ d := sha3.NewLegacyKeccak512()
+ for _, b := range data {
+ d.Write(b)
+ }
+ return d.Sum(nil)
+}
diff --git a/cmd/keeper/crypto_ziren/crypto.go b/crypto/keccak_ziren.go
similarity index 64%
rename from cmd/keeper/crypto_ziren/crypto.go
rename to crypto/keccak_ziren.go
index 7803a04643e..081e3e634e0 100644
--- a/cmd/keeper/crypto_ziren/crypto.go
+++ b/crypto/keccak_ziren.go
@@ -15,38 +15,40 @@
// along with the go-ethereum library. If not, see .
//go:build ziren
-// +build ziren
package crypto
import (
+ "hash"
+
"github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime"
"github.com/ethereum/go-ethereum/common"
- originalcrypto "github.com/ethereum/go-ethereum/crypto"
+ "golang.org/x/crypto/sha3"
)
-// Re-export everything from original crypto package except the parts we're overriding
-var (
- S256 = originalcrypto.S256
- PubkeyToAddress = originalcrypto.PubkeyToAddress
- Ecrecover = originalcrypto.Ecrecover
- SigToPub = originalcrypto.SigToPub
- Sign = originalcrypto.Sign
- VerifySignature = originalcrypto.VerifySignature
- DecompressPubkey = originalcrypto.DecompressPubkey
- CompressPubkey = originalcrypto.CompressPubkey
- HexToECDSA = originalcrypto.HexToECDSA
- LoadECDSA = originalcrypto.LoadECDSA
- SaveECDSA = originalcrypto.SaveECDSA
- GenerateKey = originalcrypto.GenerateKey
- ValidateSignatureValues = originalcrypto.ValidateSignatureValues
- Keccak512 = originalcrypto.Keccak512
-)
+// KeccakState 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 {
+ hash.Hash
+ Read([]byte) (int, error)
+}
-// Re-export types
-type (
- KeccakState = originalcrypto.KeccakState
-)
+// NewKeccakState creates a new KeccakState
+// For now, we fallback to the original implementation for the stateful interface.
+// TODO: Implement a stateful wrapper around zkvm_runtime.Keccak256 if needed.
+func NewKeccakState() KeccakState {
+ return sha3.NewLegacyKeccak256().(KeccakState)
+}
+
+// HashData hashes the provided data using the KeccakState and returns a 32 byte hash
+// For now, we fallback to the original implementation for the stateful interface.
+func HashData(kh KeccakState, data []byte) (h common.Hash) {
+ kh.Reset()
+ kh.Write(data)
+ kh.Read(h[:])
+ return h
+}
// Keccak256 calculates and returns the Keccak256 hash using the Ziren zkvm_runtime implementation.
func Keccak256(data ...[]byte) []byte {
@@ -82,9 +84,8 @@ func Keccak256Hash(data ...[]byte) (h common.Hash) {
return h
}
-// NewKeccakState returns a new keccak state hasher.
-// For now, we fallback to the original implementation for the stateful interface.
-// TODO: Implement a stateful wrapper around zkvm_runtime.Keccak256 if needed.
-func NewKeccakState() KeccakState {
- return originalcrypto.NewKeccakState()
-}
\ No newline at end of file
+// Keccak512 calculates and returns the Keccak512 hash of the input data.
+func Keccak512(data ...[]byte) []byte {
+ panic("Keccak512 not implemented in ziren mode")
+}
+
diff --git a/go.mod b/go.mod
index c91cc81d21c..ae5e4cc1141 100644
--- a/go.mod
+++ b/go.mod
@@ -81,6 +81,7 @@ require (
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect
github.com/DataDog/zstd v1.4.5 // indirect
+ github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6
github.com/StackExchange/wmi v1.2.1 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.13 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.43 // indirect
diff --git a/go.sum b/go.sum
index 779bcde8467..8122f4b5486 100644
--- a/go.sum
+++ b/go.sum
@@ -14,6 +14,8 @@ github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ=
github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
+github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6 h1:1zYrtlhrZ6/b6SAjLSfKzWtdgqK0U+HtH/VcBWh1BaU=
+github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20251001021608-1fe7b43fc4d6/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI=
github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
github.com/VictoriaMetrics/fastcache v1.13.0 h1:AW4mheMR5Vd9FkAPUv+NH6Nhw+fmbTMGMsNAoA/+4G0=