This commit is contained in:
Marius van der Wijden 2026-05-21 21:54:50 -07:00 committed by GitHub
commit 42f6d02f08
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 104 additions and 55 deletions

View file

@ -154,8 +154,7 @@ func ecrecover(header *types.Header, sigcache *sigLRU) (common.Address, error) {
if err != nil {
return common.Address{}, err
}
var signer common.Address
copy(signer[:], crypto.Keccak256(pubkey[1:])[12:])
signer := crypto.Keccak256Address(pubkey[1:])
sigcache.Add(hash, signer)
return signer, nil
@ -627,9 +626,9 @@ func (c *Clique) Close() error {
// SealHash returns the hash of a block prior to it being sealed.
func SealHash(header *types.Header) (hash common.Hash) {
hasher := keccak.NewLegacyKeccak256()
hasher := keccak.NewLegacyKeccak256State()
encodeSigHeader(hasher, header)
hasher.(crypto.KeccakState).Read(hash[:])
hasher.Read(hash[:])
return hash
}

View file

@ -23,7 +23,7 @@ import (
"github.com/ethereum/go-ethereum/common/bitutil"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/keccak"
)
type bytesBacked interface {
@ -141,7 +141,7 @@ 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 := hasherPool.Get().(*keccak.KeccakState)
sha.Reset()
sha.Write(data)
sha.Read(hashbuf[:])

View file

@ -24,6 +24,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/keccak"
"github.com/ethereum/go-ethereum/rlp"
)
@ -55,7 +56,7 @@ 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)
sha := hasherPool.Get().(*keccak.KeccakState)
defer hasherPool.Put(sha)
sha.Reset()
rlp.Encode(sha, x)
@ -66,7 +67,7 @@ func rlpHash(x interface{}) (h common.Hash) {
// 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)
sha := hasherPool.Get().(*keccak.KeccakState)
defer hasherPool.Put(sha)
sha.Reset()
sha.Write([]byte{prefix})

View file

@ -498,8 +498,9 @@ func recoverPlain(sighash common.Hash, R, S, Vb *big.Int, homestead bool) (commo
if len(pub) == 0 || pub[0] != 4 {
return common.Address{}, errors.New("invalid public key")
}
hash := crypto.Keccak256Hash(pub[1:])
var addr common.Address
copy(addr[:], crypto.Keccak256(pub[1:])[12:])
copy(addr[:], hash[12:])
return addr, nil
}

View file

@ -136,9 +136,7 @@ func (a *SetCodeAuthorization) Authority() (common.Address, error) {
if len(pub) == 0 || pub[0] != 4 {
return common.Address{}, errors.New("invalid public key")
}
var addr common.Address
copy(addr[:], crypto.Keccak256(pub[1:])[12:])
return addr, nil
return crypto.Keccak256Address(pub[1:]), nil
}
// copy creates a deep copy of the transaction data and initializes all fields.

View file

@ -316,7 +316,7 @@ func (c *ecrecover) Run(input []byte) ([]byte, error) {
}
// the first byte of pubkey is bitcoin heritage
return common.LeftPadBytes(crypto.Keccak256(pubKey[1:])[12:], 32), nil
return common.LeftPadBytes(crypto.Keccak256Address(pubKey[1:]).Bytes(), 32), nil
}
func (c *ecrecover) Name() string {

View file

@ -24,13 +24,13 @@ import (
"encoding/hex"
"errors"
"fmt"
"hash"
"io"
"math/big"
"os"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/crypto/keccak"
"github.com/ethereum/go-ethereum/rlp"
)
@ -59,16 +59,8 @@ 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)
}
// HashData hashes the provided data using the KeccakState and returns a 32 byte hash
func HashData(kh KeccakState, data []byte) (h common.Hash) {
func HashData(kh *keccak.KeccakState, data []byte) (h common.Hash) {
kh.Reset()
kh.Write(data)
kh.Read(h[:])
@ -78,7 +70,7 @@ func HashData(kh KeccakState, data []byte) (h common.Hash) {
// 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})
return common.BytesToAddress(Keccak256(data)[12:])
return Keccak256Address(data)
}
// CreateAddress2 creates an ethereum address given the address bytes, initial
@ -252,7 +244,7 @@ func ValidateSignatureValues(v byte, r, s *big.Int, homestead bool) bool {
func PubkeyToAddress(p ecdsa.PublicKey) common.Address {
pubBytes := FromECDSAPub(&p)
return common.BytesToAddress(Keccak256(pubBytes[1:])[12:])
return Keccak256Address(pubBytes[1:])
}
func zeroBytes(bytes []byte) {

View file

@ -65,6 +65,20 @@ func BenchmarkSha3(b *testing.B) {
}
}
func BenchmarkSha3_2(b *testing.B) {
a := []byte("hello world")
for b.Loop() {
Keccak256Hash(a)
}
}
func BenchmarkKeccak256Address(b *testing.B) {
a := []byte("hello world hello world hello world") // 36 bytes to simulate pubkey
for b.Loop() {
Keccak256Address(a)
}
}
func TestUnmarshalPubkey(t *testing.T) {
key, err := UnmarshalPubkey(nil)
if err != errInvalidPubkey || key != nil {

View file

@ -26,20 +26,20 @@ import (
)
// NewKeccakState creates a new KeccakState
func NewKeccakState() KeccakState {
return keccak.NewLegacyKeccak256().(KeccakState)
func NewKeccakState() *keccak.KeccakState {
return keccak.NewLegacyKeccak256State()
}
var hasherPool = sync.Pool{
New: func() any {
return keccak.NewLegacyKeccak256().(KeccakState)
return keccak.NewLegacyKeccak256State()
},
}
// 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 := hasherPool.Get().(*keccak.KeccakState)
d.Reset()
for _, b := range data {
d.Write(b)
@ -51,8 +51,19 @@ func Keccak256(data ...[]byte) []byte {
// 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)
func Keccak256Hash(data []byte) (h common.Hash) {
d := hasherPool.Get().(*keccak.KeccakState)
d.Reset()
d.Write(data)
d.Read(h[:])
hasherPool.Put(d)
return h
}
// Keccak256HashV calculates and returns the Keccak256 hash of the input data,
// converting it to an internal Hash data structure.
func Keccak256HashV(data ...[]byte) (h common.Hash) {
d := hasherPool.Get().(*keccak.KeccakState)
d.Reset()
for _, b := range data {
d.Write(b)
@ -61,3 +72,11 @@ func Keccak256Hash(data ...[]byte) (h common.Hash) {
hasherPool.Put(d)
return h
}
// Keccak256Address calculates the Keccak256 hash of the input data and
// returns the last 20 bytes as an address.
func Keccak256Address(data []byte) (a common.Address) {
hash := Keccak256Hash(data)
copy(a[:], hash[12:])
return a
}

View file

@ -0,0 +1,12 @@
package keccak
// 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 struct {
state
}
func NewLegacyKeccak256State() *KeccakState {
return &KeccakState{state{rate: rateK512, outputLen: 32, dsbyte: dsbyteKeccak}}
}

View file

@ -141,7 +141,6 @@ func (d *state) Read(out []byte) (n int, err error) {
}
n = len(out)
// Now, do the squeezing.
for len(out) > 0 {
// Apply the permutation if we've squeezed the sponge dry.
@ -157,6 +156,16 @@ func (d *state) Read(out []byte) (n int, err error) {
return
}
// Sum256 finalizes the hash and returns the 256-bit digest.
// Returns the result by value to avoid heap allocation.
func (d *state) Sum256() (out [32]byte) {
if d.state == spongeAbsorbing {
d.padAndPermute()
}
copy(out[:], d.a[:32])
return out
}
// Sum applies padding to the hash state and then squeezes out the desired
// number of output bytes. It panics if any output has already been read.
func (d *state) Sum(in []byte) []byte {

View file

@ -458,7 +458,7 @@ type testBackend struct {
}
func fakeBlockHash(txh common.Hash) common.Hash {
return crypto.Keccak256Hash([]byte("testblock"), txh.Bytes())
return crypto.Keccak256HashV([]byte("testblock"), txh.Bytes())
}
func newTestBackend(t *testing.T, n int, gspec *core.Genesis, engine consensus.Engine, generator func(i int, b *core.BlockGen)) *testBackend {

View file

@ -22,13 +22,14 @@ import (
"sync"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/keccak"
"github.com/ethereum/go-ethereum/rlp"
)
// hasher is a type used for the trie Hash operation. A hasher has some
// internal preallocated temp space
type hasher struct {
sha crypto.KeccakState
sha *keccak.KeccakState
tmp []byte
encbuf rlp.EncoderBuffer
parallel bool // Whether to use parallel threads when hashing

View file

@ -102,14 +102,16 @@ 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))
hk := crypto.Keccak256Hash(key)
return t.trie.MustGet(hk[:])
}
// 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()))
hk := crypto.Keccak256Hash(address.Bytes())
res, err := t.trie.Get(hk[:])
if res == nil || err != nil {
return nil, err
}
@ -146,7 +148,8 @@ 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))
hk := crypto.Keccak256Hash(key)
enc, err := t.trie.Get(hk[:])
if err != nil || len(enc) == 0 {
return nil, err
}
@ -182,10 +185,10 @@ 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)
t.trie.MustUpdate(hk, value)
hk := crypto.Keccak256Hash(key)
t.trie.MustUpdate(hk[:], value)
if t.preimages != nil {
t.secKeyCache[common.Hash(hk)] = common.CopyBytes(key)
t.secKeyCache[hk] = common.CopyBytes(key)
}
}
@ -198,30 +201,30 @@ 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 := crypto.Keccak256Hash(key)
v, _ := rlp.EncodeToBytes(value)
err := t.trie.Update(hk, v)
err := t.trie.Update(hk[:], v)
if err != nil {
return err
}
if t.preimages != nil {
t.secKeyCache[common.Hash(hk)] = common.CopyBytes(key)
t.secKeyCache[hk] = common.CopyBytes(key)
}
return nil
}
// 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 := crypto.Keccak256Hash(address.Bytes())
data, err := rlp.EncodeToBytes(acc)
if err != nil {
return err
}
if err := t.trie.Update(hk, data); err != nil {
if err := t.trie.Update(hk[:], data); err != nil {
return err
}
if t.preimages != nil {
t.secKeyCache[common.Hash(hk)] = address.Bytes()
t.secKeyCache[hk] = address.Bytes()
}
return nil
}
@ -233,31 +236,31 @@ 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 := crypto.Keccak256Hash(key)
if t.preimages != nil {
delete(t.secKeyCache, common.Hash(hk))
delete(t.secKeyCache, hk)
}
t.trie.MustDelete(hk)
t.trie.MustDelete(hk[:])
}
// DeleteStorage removes any existing storage slot from the trie.
// 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 := crypto.Keccak256Hash(key)
if t.preimages != nil {
delete(t.secKeyCache, common.Hash(hk))
delete(t.secKeyCache, hk)
}
return t.trie.Delete(hk)
return t.trie.Delete(hk[:])
}
// DeleteAccount abstracts an account deletion from the trie.
func (t *StateTrie) DeleteAccount(address common.Address) error {
hk := crypto.Keccak256(address.Bytes())
hk := crypto.Keccak256Hash(address.Bytes())
if t.preimages != nil {
delete(t.secKeyCache, common.Hash(hk))
delete(t.secKeyCache, hk)
}
return t.trie.Delete(hk)
return t.trie.Delete(hk[:])
}
// GetKey returns the sha3 preimage of a hashed key that was