core: use stateless keccak

This commit is contained in:
Piotr Mikołajczyk 2025-11-18 11:19:45 +01:00
parent 5c631f6206
commit bc9e3faed1
No known key found for this signature in database
GPG key ID: 2E4C2AAD5E71D22D
3 changed files with 9 additions and 39 deletions

View file

@ -34,11 +34,7 @@ import (
// //
// Acceleration structures built would need to explicitly validate the witness. // Acceleration structures built would need to explicitly validate the witness.
func (w *Witness) MakeHashDB() ethdb.Database { func (w *Witness) MakeHashDB() ethdb.Database {
var ( var memdb = rawdb.NewMemoryDatabase()
memdb = rawdb.NewMemoryDatabase()
hasher = crypto.NewKeccakState()
hash = make([]byte, 32)
)
// Inject all the "block hashes" (i.e. headers) into the ephemeral database // Inject all the "block hashes" (i.e. headers) into the ephemeral database
for _, header := range w.Headers { for _, header := range w.Headers {
rawdb.WriteHeader(memdb, header) rawdb.WriteHeader(memdb, header)
@ -46,21 +42,13 @@ func (w *Witness) MakeHashDB() ethdb.Database {
// Inject all the bytecodes into the ephemeral database // Inject all the bytecodes into the ephemeral database
for code := range w.Codes { for code := range w.Codes {
blob := []byte(code) blob := []byte(code)
hash := crypto.Keccak256(blob)
hasher.Reset()
hasher.Write(blob)
hasher.Read(hash)
rawdb.WriteCode(memdb, common.BytesToHash(hash), blob) rawdb.WriteCode(memdb, common.BytesToHash(hash), blob)
} }
// Inject all the MPT trie nodes into the ephemeral database // Inject all the MPT trie nodes into the ephemeral database
for node := range w.State { for node := range w.State {
blob := []byte(node) blob := []byte(node)
hash := crypto.Keccak256(blob)
hasher.Reset()
hasher.Write(blob)
hasher.Read(hash)
rawdb.WriteLegacyTrieNode(memdb, common.BytesToHash(hash), blob) rawdb.WriteLegacyTrieNode(memdb, common.BytesToHash(hash), blob)
} }
return memdb return memdb

View file

@ -27,11 +27,6 @@ import (
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
) )
// hasherPool holds LegacyKeccak256 buffer for rlpHash.
var hasherPool = sync.Pool{
New: func() interface{} { return crypto.NewKeccakState() },
}
// encodeBufferPool holds temporary encoder buffers for DeriveSha and TX encoding. // encodeBufferPool holds temporary encoder buffers for DeriveSha and TX encoding.
var encodeBufferPool = sync.Pool{ var encodeBufferPool = sync.Pool{
New: func() interface{} { return new(bytes.Buffer) }, New: func() interface{} { return new(bytes.Buffer) },
@ -55,24 +50,15 @@ func getPooledBuffer(size uint64) ([]byte, *bytes.Buffer, error) {
// rlpHash encodes x and hashes the encoded bytes. // rlpHash encodes x and hashes the encoded bytes.
func rlpHash(x interface{}) (h common.Hash) { func rlpHash(x interface{}) (h common.Hash) {
sha := hasherPool.Get().(crypto.KeccakState) encoded, _ := rlp.EncodeToBytes(x)
defer hasherPool.Put(sha) return crypto.Keccak256Hash(encoded)
sha.Reset()
rlp.Encode(sha, x)
sha.Read(h[:])
return h
} }
// prefixedRlpHash writes the prefix into the hasher before rlp-encoding x. // prefixedRlpHash writes the prefix into the hasher before rlp-encoding x.
// It's used for typed transactions. // It's used for typed transactions.
func prefixedRlpHash(prefix byte, x interface{}) (h common.Hash) { func prefixedRlpHash(prefix byte, x interface{}) (h common.Hash) {
sha := hasherPool.Get().(crypto.KeccakState) encoded, _ := rlp.EncodeToBytes(x)
defer hasherPool.Put(sha) return crypto.Keccak256Hash([]byte{prefix}, encoded)
sha.Reset()
sha.Write([]byte{prefix})
rlp.Encode(sha, x)
sha.Read(h[:])
return h
} }
// ListHasher defines the interface for computing the hash of a derivable list. // ListHasher defines the interface for computing the hash of a derivable list.

View file

@ -125,9 +125,6 @@ type EVM struct {
// jumpDests stores results of JUMPDEST analysis. // jumpDests stores results of JUMPDEST analysis.
jumpDests JumpDestCache jumpDests JumpDestCache
hasher crypto.KeccakState // Keccak256 hasher instance shared across opcodes
hasherBuf common.Hash // Keccak256 hasher result array shared across opcodes
readOnly bool // Whether to throw on stateful modifications readOnly bool // Whether to throw on stateful modifications
returnData []byte // Last CALL's return data for subsequent reuse returnData []byte // Last CALL's return data for subsequent reuse
} }
@ -144,7 +141,6 @@ 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(),
} }
evm.precompiles = activePrecompiledContracts(evm.chainRules) evm.precompiles = activePrecompiledContracts(evm.chainRules)
@ -618,8 +614,8 @@ func (evm *EVM) Create(caller common.Address, code []byte, gas uint64, value *ui
// The different between Create2 with Create is Create2 uses keccak256(0xff ++ msg.sender ++ salt ++ keccak256(init_code))[12:] // The different between Create2 with Create is Create2 uses keccak256(0xff ++ msg.sender ++ salt ++ keccak256(init_code))[12:]
// instead of the usual sender-and-nonce-hash as the address where the contract is initialized at. // instead of the usual sender-and-nonce-hash as the address where the contract is initialized at.
func (evm *EVM) Create2(caller common.Address, code []byte, gas uint64, endowment *uint256.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { func (evm *EVM) Create2(caller common.Address, code []byte, gas uint64, endowment *uint256.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) {
inithash := crypto.HashData(evm.hasher, code) inithash := crypto.Keccak256(code)
contractAddr = crypto.CreateAddress2(caller, salt.Bytes32(), inithash[:]) contractAddr = crypto.CreateAddress2(caller, salt.Bytes32(), inithash)
return evm.create(caller, code, gas, endowment, contractAddr, CREATE2) return evm.create(caller, code, gas, endowment, contractAddr, CREATE2)
} }