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=