Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 2 additions & 10 deletions cmd/devp2p/internal/ethtest/snap.go
Original file line number Diff line number Diff line change
Expand Up @@ -900,16 +900,12 @@ func (s *Suite) snapGetByteCodes(t *utesting.T, tc *byteCodesTest) error {
// that the serving node is missing
var (
bytecodes = res.Codes
hasher = crypto.NewKeccakState()
hash = make([]byte, 32)
codes = make([][]byte, len(req.Hashes))
)

for i, j := 0, 0; i < len(bytecodes); i++ {
// Find the next hash that we've been served, leaving misses with nils
hasher.Reset()
hasher.Write(bytecodes[i])
hasher.Read(hash)
hash := crypto.Keccak256(bytecodes[i])

for j < len(req.Hashes) && !bytes.Equal(hash, req.Hashes[j][:]) {
j++
Expand Down Expand Up @@ -959,16 +955,12 @@ func (s *Suite) snapGetTrieNodes(t *utesting.T, tc *trieNodesTest) error {

// Cross reference the requested trienodes with the response to find gaps
// that the serving node is missing
hasher := crypto.NewKeccakState()
hash := make([]byte, 32)
trienodes := res.Nodes
if got, want := len(trienodes), len(tc.expHashes); got != want {
return fmt.Errorf("wrong trienode count, got %d, want %d", got, want)
}
for i, trienode := range trienodes {
hasher.Reset()
hasher.Write(trienode)
hasher.Read(hash)
hash := crypto.Keccak256(trienode[:])
if got, want := hash, tc.expHashes[i]; !bytes.Equal(got, want[:]) {
t.Logf(" hash %d wrong, got %#x, want %#x\n", i, got, want)
err = fmt.Errorf("hash %d wrong, got %#x, want %#x", i, got, want)
Expand Down
6 changes: 1 addition & 5 deletions cmd/geth/dbcmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -354,8 +354,6 @@ func checkStateContent(ctx *cli.Context) error {
defer db.Close()
var (
it = rawdb.NewKeyLengthIterator(db.NewIterator(prefix, start), 32)
hasher = crypto.NewKeccakState()
got = make([]byte, 32)
errs int
count int
startTime = time.Now()
Expand All @@ -365,9 +363,7 @@ func checkStateContent(ctx *cli.Context) error {
count++
k := it.Key()
v := it.Value()
hasher.Reset()
hasher.Write(v)
hasher.Read(got)
got := crypto.Keccak256(v)
if !bytes.Equal(k, got) {
errs++
fmt.Printf("Error at %#x\n", k)
Expand Down
10 changes: 2 additions & 8 deletions cmd/geth/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -434,8 +434,6 @@ func traverseRawState(ctx *cli.Context) error {
codes int
lastReport time.Time
start = time.Now()
hasher = crypto.NewKeccakState()
got = make([]byte, 32)
)
accIter, err := t.NodeIterator(nil)
if err != nil {
Expand All @@ -459,9 +457,7 @@ func traverseRawState(ctx *cli.Context) error {
log.Error("Missing trie node(account)", "hash", node)
return errors.New("missing account")
}
hasher.Reset()
hasher.Write(blob)
hasher.Read(got)
got := crypto.Keccak256(blob)
if !bytes.Equal(got, node.Bytes()) {
log.Error("Invalid trie node(account)", "hash", node.Hex(), "value", blob)
return errors.New("invalid account node")
Expand Down Expand Up @@ -500,9 +496,7 @@ func traverseRawState(ctx *cli.Context) error {
log.Error("Missing trie node(storage)", "hash", node)
return errors.New("missing storage")
}
hasher.Reset()
hasher.Write(blob)
hasher.Read(got)
got := crypto.Keccak256(blob)
if !bytes.Equal(got, node.Bytes()) {
log.Error("Invalid trie node(storage)", "hash", node.Hex(), "value", blob)
return errors.New("invalid storage node")
Expand Down
5 changes: 2 additions & 3 deletions cmd/workload/historytestgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,8 @@ func generateHistoryTests(clictx *cli.Context) error {
}

func calcReceiptsHash(rcpt []*types.Receipt) common.Hash {
h := crypto.NewKeccakState()
rlp.Encode(h, rcpt)
return common.Hash(h.Sum(nil))
encoded, _ := rlp.EncodeToBytes(rcpt)
return crypto.Keccak256Hash(encoded)
}

func writeJSON(fileName string, value any) {
Expand Down
2 changes: 1 addition & 1 deletion consensus/clique/clique.go
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,7 @@ func (c *Clique) Close() error {
func SealHash(header *types.Header) (hash common.Hash) {
hasher := sha3.NewLegacyKeccak256()
encodeSigHeader(hasher, header)
hasher.(crypto.KeccakState).Read(hash[:])
hasher.(crypto.KeccakSponge).Read(hash[:])
return hash
}

Expand Down
18 changes: 3 additions & 15 deletions core/stateless/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,33 +34,21 @@ import (
//
// Acceleration structures built would need to explicitly validate the witness.
func (w *Witness) MakeHashDB() ethdb.Database {
var (
memdb = rawdb.NewMemoryDatabase()
hasher = crypto.NewKeccakState()
hash = make([]byte, 32)
)
var memdb = rawdb.NewMemoryDatabase()
// Inject all the "block hashes" (i.e. headers) into the ephemeral database
for _, header := range w.Headers {
rawdb.WriteHeader(memdb, header)
}
// Inject all the bytecodes into the ephemeral database
for code := range w.Codes {
blob := []byte(code)

hasher.Reset()
hasher.Write(blob)
hasher.Read(hash)

hash := crypto.Keccak256(blob)
rawdb.WriteCode(memdb, common.BytesToHash(hash), blob)
}
// Inject all the MPT trie nodes into the ephemeral database
for node := range w.State {
blob := []byte(node)

hasher.Reset()
hasher.Write(blob)
hasher.Read(hash)

hash := crypto.Keccak256(blob)
rawdb.WriteLegacyTrieNode(memdb, common.BytesToHash(hash), blob)
}
return memdb
Expand Down
7 changes: 2 additions & 5 deletions core/types/bloom9.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,8 @@ func Bloom9(data []byte) []byte {

// bloomValues returns the bytes (index-value pairs) to set for the given data
func bloomValues(data []byte, hashbuf *[6]byte) (uint, byte, uint, byte, uint, byte) {
sha := hasherPool.Get().(crypto.KeccakState)
sha.Reset()
sha.Write(data)
sha.Read(hashbuf[:])
hasherPool.Put(sha)
hash := crypto.Keccak256(data)
copy(hashbuf[:], hash[:6])
// The actual bits to flip
v1 := byte(1 << (hashbuf[1] & 0x7))
v2 := byte(1 << (hashbuf[3] & 0x7))
Expand Down
22 changes: 4 additions & 18 deletions core/types/hashing.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,6 @@ import (
"github.com/ethereum/go-ethereum/rlp"
)

// hasherPool holds LegacyKeccak256 buffer for rlpHash.
var hasherPool = sync.Pool{
New: func() interface{} { return crypto.NewKeccakState() },
}

// encodeBufferPool holds temporary encoder buffers for DeriveSha and TX encoding.
var encodeBufferPool = sync.Pool{
New: func() interface{} { return new(bytes.Buffer) },
Expand All @@ -55,24 +50,15 @@ func getPooledBuffer(size uint64) ([]byte, *bytes.Buffer, error) {

// rlpHash encodes x and hashes the encoded bytes.
func rlpHash(x interface{}) (h common.Hash) {
sha := hasherPool.Get().(crypto.KeccakState)
defer hasherPool.Put(sha)
sha.Reset()
rlp.Encode(sha, x)
sha.Read(h[:])
return h
encoded, _ := rlp.EncodeToBytes(x)
return crypto.Keccak256Hash(encoded)
}

// prefixedRlpHash writes the prefix into the hasher before rlp-encoding x.
// It's used for typed transactions.
func prefixedRlpHash(prefix byte, x interface{}) (h common.Hash) {
sha := hasherPool.Get().(crypto.KeccakState)
defer hasherPool.Put(sha)
sha.Reset()
sha.Write([]byte{prefix})
rlp.Encode(sha, x)
sha.Read(h[:])
return h
encoded, _ := rlp.EncodeToBytes(x)
return crypto.Keccak256Hash([]byte{prefix}, encoded)
}

// ListHasher defines the interface for computing the hash of a derivable list.
Expand Down
6 changes: 1 addition & 5 deletions core/vm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,6 @@ type EVM struct {
// jumpDests stores results of JUMPDEST analysis.
jumpDests JumpDestCache

hasher crypto.KeccakState // Keccak256 hasher instance shared across opcodes
hasherBuf common.Hash // Keccak256 hasher result array shared across opcodes

readOnly bool // Whether to throw on stateful modifications
returnData []byte // Last CALL's return data for subsequent reuse
}
Expand All @@ -152,7 +149,6 @@ func NewEVM(blockCtx BlockContext, statedb StateDB, chainConfig *params.ChainCon
chainConfig: chainConfig,
chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time, blockCtx.ArbOSVersion),
jumpDests: newMapJumpDests(),
hasher: crypto.NewKeccakState(),
}
evm.ProcessingHook = DefaultTxProcessor{evm: evm}
evm.precompiles = activePrecompiledContracts(evm.chainRules)
Expand Down Expand Up @@ -703,7 +699,7 @@ func (evm *EVM) Create(caller common.Address, code []byte, gas uint64, value *ui
// The different between Create2 with Create is Create2 uses keccak256(0xff ++ msg.sender ++ salt ++ keccak256(init_code))[12:]
// instead of the usual sender-and-nonce-hash as the address where the contract is initialized at.
func (evm *EVM) Create2(caller common.Address, code []byte, gas uint64, endowment *uint256.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, usedMultiGas multigas.MultiGas, err error) {
inithash := crypto.HashData(evm.hasher, code)
inithash := crypto.Keccak256Hash(code)
contractAddr = crypto.CreateAddress2(caller, salt.Bytes32(), inithash[:])
return evm.create(caller, code, gas, endowment, contractAddr, CREATE2)
}
Expand Down
10 changes: 4 additions & 6 deletions core/vm/instructions.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/holiman/uint256"
)
Expand Down Expand Up @@ -235,15 +236,12 @@ func opSAR(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
func opKeccak256(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
offset, size := scope.Stack.pop(), scope.Stack.peek()
data := scope.Memory.GetPtr(offset.Uint64(), size.Uint64())

evm.hasher.Reset()
evm.hasher.Write(data)
evm.hasher.Read(evm.hasherBuf[:])
hasherBuf := crypto.Keccak256Hash(data)

if evm.Config.EnablePreimageRecording {
evm.StateDB.AddPreimage(evm.hasherBuf, data)
evm.StateDB.AddPreimage(hasherBuf, data)
}
size.SetBytes(evm.hasherBuf[:])
size.SetBytes(hasherBuf[:])
return nil, nil
}

Expand Down
12 changes: 2 additions & 10 deletions crypto/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,22 +59,14 @@ type EllipticCurve interface {
Unmarshal(data []byte) (x, y *big.Int)
}

// KeccakState wraps sha3.state. In addition to the usual hash methods, it also supports
// KeccakSponge wraps sha3.state. In addition to the usual hash methods, it also supports
// Read to get a variable amount of data from the hash state. Read is faster than Sum
// because it doesn't copy the internal state, but also modifies the internal state.
type KeccakState interface {
type KeccakSponge interface {
hash.Hash
Read([]byte) (int, error)
}

// HashData hashes the provided data using the KeccakState and returns a 32 byte hash
func HashData(kh KeccakState, data []byte) (h common.Hash) {
kh.Reset()
kh.Write(data)
kh.Read(h[:])
return h
}

// CreateAddress creates an ethereum address given the bytes and the nonce
func CreateAddress(b common.Address, nonce uint64) common.Address {
data, _ := rlp.EncodeToBytes([]interface{}{b, nonce})
Expand Down
22 changes: 1 addition & 21 deletions crypto/crypto_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ func TestKeccak256Hash(t *testing.T) {
func TestKeccak256Hasher(t *testing.T) {
msg := []byte("abc")
exp, _ := hex.DecodeString("4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45")
hasher := NewKeccakState()
checkhash(t, "Sha3-256-array", func(in []byte) []byte { h := HashData(hasher, in); return h[:] }, msg, exp)
checkhash(t, "Sha3-256-array", func(in []byte) []byte { h := Keccak256Hash(in); return h[:] }, msg, exp)
}

func TestToECDSAErrors(t *testing.T) {
Expand Down Expand Up @@ -314,22 +313,3 @@ func BenchmarkKeccak256Hash(b *testing.B) {
Keccak256Hash(input[:])
}
}

// goos: darwin
// goarch: arm64
// pkg: github.com/ethereum/go-ethereum/crypto
// cpu: Apple M1 Pro
// BenchmarkHashData
// BenchmarkHashData-8 793386 1278 ns/op 32 B/op 1 allocs/op
func BenchmarkHashData(b *testing.B) {
var (
input [512]byte
buffer = NewKeccakState()
)
rand.Read(input[:])

b.ReportAllocs()
for b.Loop() {
HashData(buffer, input[:])
}
}
31 changes: 15 additions & 16 deletions crypto/keccak.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,39 +25,38 @@ import (
"golang.org/x/crypto/sha3"
)

// NewKeccakState creates a new KeccakState
func NewKeccakState() KeccakState {
return sha3.NewLegacyKeccak256().(KeccakState)
// NewKeccakSponge creates a new KeccakSponge
func NewKeccakSponge() KeccakSponge {
return sha3.NewLegacyKeccak256().(KeccakSponge)
}

var hasherPool = sync.Pool{
New: func() any {
return sha3.NewLegacyKeccak256().(KeccakState)
return sha3.NewLegacyKeccak256().(KeccakSponge)
},
}

// Keccak256 calculates and returns the Keccak256 hash of the input data.
func Keccak256(data ...[]byte) []byte {
b := make([]byte, 32)
d := hasherPool.Get().(KeccakState)
// keccak256 is a helper that hashes the input data using the provided KeccakSponge and writes the result to out.
func keccak256(out []byte, data ...[]byte) {
d := hasherPool.Get().(KeccakSponge)
d.Reset()
for _, b := range data {
d.Write(b)
}
d.Read(b)
d.Read(out)
hasherPool.Put(d)
}

// Keccak256 calculates and returns the Keccak256 hash of the input data.
func Keccak256(data ...[]byte) []byte {
b := make([]byte, 32)
keccak256(b, data...)
return b
}

// Keccak256Hash calculates and returns the Keccak256 hash of the input data,
// converting it to an internal Hash data structure.
func Keccak256Hash(data ...[]byte) (h common.Hash) {
d := hasherPool.Get().(KeccakState)
d.Reset()
for _, b := range data {
d.Write(b)
}
d.Read(h[:])
hasherPool.Put(d)
keccak256(h[:], data...)
return h
}
8 changes: 4 additions & 4 deletions crypto/keccak_ziren.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ import (
"github.com/ethereum/go-ethereum/common"
)

// zirenKeccakState implements the KeccakState interface using the Ziren zkvm_runtime.
// zirenKeccakState implements the KeccakSponge interface using the Ziren zkvm_runtime.
// It accumulates data written to it and uses the zkvm's Keccak256 system call for hashing.
type zirenKeccakState struct {
buf []byte // accumulated data
result []byte // cached result
dirty bool // whether new data has been written since last hash
}

func newZirenKeccakState() KeccakState {
func newZirenKeccakState() KeccakSponge {
return &zirenKeccakState{
buf: make([]byte, 0, 512), // pre-allocate reasonable capacity
}
Expand Down Expand Up @@ -83,9 +83,9 @@ func (s *zirenKeccakState) computeHashIfNeeded() {
}
}

// NewKeccakState creates a new KeccakState
// NewKeccakSponge creates a new KeccakSponge
// This uses a Ziren-optimized implementation that leverages the zkvm_runtime.Keccak256 system call.
func NewKeccakState() KeccakState {
func NewKeccakState() KeccakSponge {
return newZirenKeccakState()
}

Expand Down
Loading
Loading