crypto,core/state: lru cache address to hash

This commit is contained in:
weixie.cui 2026-01-14 16:18:40 +08:00
parent 3b17e78274
commit 0ec5e59b64
6 changed files with 38 additions and 7 deletions

View file

@ -261,7 +261,7 @@ func (db *CachingDB) OpenStorageTrie(stateRoot common.Hash, address common.Addre
if db.triedb.IsVerkle() { if db.triedb.IsVerkle() {
return self, nil return self, nil
} }
tr, err := trie.NewStateTrie(trie.StorageTrieID(stateRoot, crypto.Keccak256Hash(address.Bytes()), root), db.triedb) tr, err := trie.NewStateTrie(trie.StorageTrieID(stateRoot, crypto.Keccak256AddressHash(address), root), db.triedb)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -254,7 +254,7 @@ func (r *flatReader) Account(addr common.Address) (*types.StateAccount, error) {
// //
// The returned storage slot might be empty if it's not existent. // The returned storage slot might be empty if it's not existent.
func (r *flatReader) Storage(addr common.Address, key common.Hash) (common.Hash, error) { func (r *flatReader) Storage(addr common.Address, key common.Hash) (common.Hash, error) {
addrHash := crypto.Keccak256Hash(addr.Bytes()) addrHash := crypto.Keccak256AddressHash(addr)
slotHash := crypto.Keccak256Hash(key.Bytes()) slotHash := crypto.Keccak256Hash(key.Bytes())
ret, err := r.reader.Storage(addrHash, slotHash) ret, err := r.reader.Storage(addrHash, slotHash)
if err != nil { if err != nil {
@ -402,7 +402,7 @@ func (r *trieReader) Storage(addr common.Address, key common.Hash) (common.Hash,
root = r.subRoots[addr] root = r.subRoots[addr]
} }
var err error var err error
tr, err = trie.NewStateTrie(trie.StorageTrieID(r.root, crypto.Keccak256Hash(addr.Bytes()), root), r.db) tr, err = trie.NewStateTrie(trie.StorageTrieID(r.root, crypto.Keccak256AddressHash(addr), root), r.db)
if err != nil { if err != nil {
return common.Hash{}, err return common.Hash{}, err
} }

View file

@ -99,10 +99,11 @@ func newObject(db *StateDB, address common.Address, acct *types.StateAccount) *s
if acct == nil { if acct == nil {
acct = types.NewEmptyStateAccount() acct = types.NewEmptyStateAccount()
} }
return &stateObject{ return &stateObject{
db: db, db: db,
address: address, address: address,
addrHash: crypto.Keccak256Hash(address[:]), addrHash: crypto.Keccak256AddressHash(address),
origin: origin, origin: origin,
data: *acct, data: *acct,
originStorage: make(Storage), originStorage: make(Storage),

View file

@ -28,6 +28,7 @@ import (
"time" "time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/lru"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state/snapshot" "github.com/ethereum/go-ethereum/core/state/snapshot"
"github.com/ethereum/go-ethereum/core/stateless" "github.com/ethereum/go-ethereum/core/stateless"
@ -52,6 +53,17 @@ const (
deletion deletion
) )
var addressHashCache = lru.NewCache[common.Address, common.Hash](10240)
func getAddressHash(addr common.Address) common.Hash {
if hash, ok := addressHashCache.Get(addr); ok {
return hash
}
hash := crypto.Keccak256Hash(addr.Bytes())
addressHashCache.Add(addr, hash)
return hash
}
type mutation struct { type mutation struct {
typ mutationType typ mutationType
applied bool applied bool
@ -1126,7 +1138,7 @@ func (s *StateDB) handleDestruction(noStorageWiping bool) (map[common.Hash]*acco
continue continue
} }
// The account was existent, it can be either case (c) or (d). // The account was existent, it can be either case (c) or (d).
addrHash := crypto.Keccak256Hash(addr.Bytes()) addrHash := crypto.Keccak256AddressHash(addr)
op := &accountDelete{ op := &accountDelete{
address: addr, address: addr,
origin: types.SlimAccountRLP(*prev), origin: types.SlimAccountRLP(*prev),

View file

@ -241,7 +241,7 @@ func (sc *stateUpdate) ToTracingUpdate() (*tracing.StateUpdate, error) {
} }
// Gather all account changes // Gather all account changes
for addr, oldData := range sc.accountsOrigin { for addr, oldData := range sc.accountsOrigin {
addrHash := crypto.Keccak256Hash(addr.Bytes()) addrHash := crypto.Keccak256AddressHash(addr)
newData, exists := sc.accounts[addrHash] newData, exists := sc.accounts[addrHash]
if !exists { if !exists {
return nil, fmt.Errorf("account %x not found", addr) return nil, fmt.Errorf("account %x not found", addr)
@ -277,7 +277,8 @@ func (sc *stateUpdate) ToTracingUpdate() (*tracing.StateUpdate, error) {
// Gather all storage slot changes // Gather all storage slot changes
for addr, slots := range sc.storagesOrigin { for addr, slots := range sc.storagesOrigin {
addrHash := crypto.Keccak256Hash(addr.Bytes()) addrHash := crypto.Keccak256AddressHash(addr)
subset, exists := sc.storages[addrHash] subset, exists := sc.storages[addrHash]
if !exists { if !exists {
return nil, fmt.Errorf("storage %x not found", addr) return nil, fmt.Errorf("storage %x not found", addr)

View file

@ -22,9 +22,16 @@ import (
"sync" "sync"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/lru"
"golang.org/x/crypto/sha3" "golang.org/x/crypto/sha3"
) )
const Keccak256AddressHashCache = 10240
var getKeccak256AddressHashCache = sync.OnceValue(func() *lru.Cache[common.Address, common.Hash] {
return lru.NewCache[common.Address, common.Hash](Keccak256AddressHashCache)
})
// NewKeccakState creates a new KeccakState // NewKeccakState creates a new KeccakState
func NewKeccakState() KeccakState { func NewKeccakState() KeccakState {
return sha3.NewLegacyKeccak256().(KeccakState) return sha3.NewLegacyKeccak256().(KeccakState)
@ -61,3 +68,13 @@ func Keccak256Hash(data ...[]byte) (h common.Hash) {
hasherPool.Put(d) hasherPool.Put(d)
return h return h
} }
func Keccak256AddressHash(address common.Address) (h common.Hash) {
cache := getKeccak256AddressHashCache()
if hash, ok := cache.Get(address); ok {
return hash
}
h = Keccak256Hash(address.Bytes())
cache.Add(address, h)
return h
}