core/vm, crypto: add crypto package for hashing

This commit is contained in:
Guillaume Ballet 2025-09-22 18:06:58 +02:00
parent 057667151b
commit 90beffbaf8
4 changed files with 157 additions and 13 deletions

View file

@ -26,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/platcrypto"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/holiman/uint256" "github.com/holiman/uint256"
@ -144,7 +145,7 @@ func NewEVM(blockCtx BlockContext, statedb StateDB, chainConfig *params.ChainCon
chainConfig: chainConfig, chainConfig: chainConfig,
chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time), chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time),
jumpDests: newMapJumpDests(), jumpDests: newMapJumpDests(),
hasher: crypto.NewKeccakState(), hasher: platcrypto.NewKeccakState(),
} }
evm.precompiles = activePrecompiledContracts(evm.chainRules) evm.precompiles = activePrecompiledContracts(evm.chainRules)

View file

@ -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 <http://www.gnu.org/licenses/>.
//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()
}

View file

@ -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 <http://www.gnu.org/licenses/>.
//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{}
}

View file

@ -19,7 +19,7 @@ package trie
import ( import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "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/rlp"
"github.com/ethereum/go-ethereum/trie/trienode" "github.com/ethereum/go-ethereum/trie/trienode"
"github.com/ethereum/go-ethereum/triedb/database" "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 // This function will omit any encountered error but just
// print out an error message. // print out an error message.
func (t *StateTrie) MustGet(key []byte) []byte { 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. // GetAccount attempts to retrieve an account with provided account address.
// If the specified account is not in the trie, nil will be returned. // 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. // If a trie node is not found in the database, a MissingNodeError is returned.
func (t *StateTrie) GetAccount(address common.Address) (*types.StateAccount, error) { 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 { if res == nil || err != nil {
return nil, err return nil, err
} }
@ -136,7 +136,7 @@ func (t *StateTrie) GetAccountByHash(addrHash common.Hash) (*types.StateAccount,
func (t *StateTrie) PrefetchAccount(addresses []common.Address) error { func (t *StateTrie) PrefetchAccount(addresses []common.Address) error {
var keys [][]byte var keys [][]byte
for _, addr := range addresses { for _, addr := range addresses {
keys = append(keys, crypto.Keccak256(addr.Bytes())) keys = append(keys, platcrypto.Keccak256(addr.Bytes()))
} }
return t.trie.Prefetch(keys) 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 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. // If a trie node is not found in the database, a MissingNodeError is returned.
func (t *StateTrie) GetStorage(_ common.Address, key []byte) ([]byte, error) { 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 { if err != nil || len(enc) == 0 {
return nil, err 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 { func (t *StateTrie) PrefetchStorage(_ common.Address, keys [][]byte) error {
var keylist [][]byte var keylist [][]byte
for _, key := range keys { for _, key := range keys {
keylist = append(keylist, crypto.Keccak256(key)) keylist = append(keylist, platcrypto.Keccak256(key))
} }
return t.trie.Prefetch(keylist) 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 // This function will omit any encountered error but just print out an
// error message. // error message.
func (t *StateTrie) MustUpdate(key, value []byte) { func (t *StateTrie) MustUpdate(key, value []byte) {
hk := crypto.Keccak256(key) hk := platcrypto.Keccak256(key)
t.trie.MustUpdate(hk, value) t.trie.MustUpdate(hk, value)
if t.preimages != nil { if t.preimages != nil {
t.secKeyCache[common.Hash(hk)] = common.CopyBytes(key) 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. // If a node is not found in the database, a MissingNodeError is returned.
func (t *StateTrie) UpdateStorage(_ common.Address, key, value []byte) error { func (t *StateTrie) UpdateStorage(_ common.Address, key, value []byte) error {
hk := crypto.Keccak256(key) hk := platcrypto.Keccak256(key)
v, _ := rlp.EncodeToBytes(value) v, _ := rlp.EncodeToBytes(value)
err := t.trie.Update(hk, v) err := t.trie.Update(hk, v)
if err != nil { 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. // UpdateAccount will abstract the write of an account to the secure trie.
func (t *StateTrie) UpdateAccount(address common.Address, acc *types.StateAccount, _ int) error { 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) data, err := rlp.EncodeToBytes(acc)
if err != nil { if err != nil {
return err 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 // MustDelete removes any existing value for key from the trie. This function
// will omit any encountered error but just print out an error message. // will omit any encountered error but just print out an error message.
func (t *StateTrie) MustDelete(key []byte) { func (t *StateTrie) MustDelete(key []byte) {
hk := crypto.Keccak256(key) hk := platcrypto.Keccak256(key)
if t.preimages != nil { if t.preimages != nil {
delete(t.secKeyCache, common.Hash(hk)) 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 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. // If a node is not found in the database, a MissingNodeError is returned.
func (t *StateTrie) DeleteStorage(_ common.Address, key []byte) error { func (t *StateTrie) DeleteStorage(_ common.Address, key []byte) error {
hk := crypto.Keccak256(key) hk := platcrypto.Keccak256(key)
if t.preimages != nil { if t.preimages != nil {
delete(t.secKeyCache, common.Hash(hk)) 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. // DeleteAccount abstracts an account deletion from the trie.
func (t *StateTrie) DeleteAccount(address common.Address) error { func (t *StateTrie) DeleteAccount(address common.Address) error {
hk := crypto.Keccak256(address.Bytes()) hk := platcrypto.Keccak256(address.Bytes())
if t.preimages != nil { if t.preimages != nil {
delete(t.secKeyCache, common.Hash(hk)) delete(t.secKeyCache, common.Hash(hk))
} }