From 0ec5e59b64a1b1a9d3a5c50c455adf7e17fa9625 Mon Sep 17 00:00:00 2001 From: "weixie.cui" Date: Wed, 14 Jan 2026 16:18:40 +0800 Subject: [PATCH] crypto,core/state: lru cache address to hash --- core/state/database.go | 2 +- core/state/reader.go | 4 ++-- core/state/state_object.go | 3 ++- core/state/statedb.go | 14 +++++++++++++- core/state/stateupdate.go | 5 +++-- crypto/keccak.go | 17 +++++++++++++++++ 6 files changed, 38 insertions(+), 7 deletions(-) diff --git a/core/state/database.go b/core/state/database.go index 4a5547d075..90b262cc92 100644 --- a/core/state/database.go +++ b/core/state/database.go @@ -261,7 +261,7 @@ func (db *CachingDB) OpenStorageTrie(stateRoot common.Hash, address common.Addre if db.triedb.IsVerkle() { 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 { return nil, err } diff --git a/core/state/reader.go b/core/state/reader.go index 2db9d1f9b4..3743ddbccc 100644 --- a/core/state/reader.go +++ b/core/state/reader.go @@ -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. 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()) ret, err := r.reader.Storage(addrHash, slotHash) if err != nil { @@ -402,7 +402,7 @@ func (r *trieReader) Storage(addr common.Address, key common.Hash) (common.Hash, root = r.subRoots[addr] } 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 { return common.Hash{}, err } diff --git a/core/state/state_object.go b/core/state/state_object.go index 3b11553f04..6c4cd1dbb0 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -99,10 +99,11 @@ func newObject(db *StateDB, address common.Address, acct *types.StateAccount) *s if acct == nil { acct = types.NewEmptyStateAccount() } + return &stateObject{ db: db, address: address, - addrHash: crypto.Keccak256Hash(address[:]), + addrHash: crypto.Keccak256AddressHash(address), origin: origin, data: *acct, originStorage: make(Storage), diff --git a/core/state/statedb.go b/core/state/statedb.go index fbfb02e8e4..b9b90ec521 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -28,6 +28,7 @@ import ( "time" "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/state/snapshot" "github.com/ethereum/go-ethereum/core/stateless" @@ -52,6 +53,17 @@ const ( 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 { typ mutationType applied bool @@ -1126,7 +1138,7 @@ func (s *StateDB) handleDestruction(noStorageWiping bool) (map[common.Hash]*acco continue } // The account was existent, it can be either case (c) or (d). - addrHash := crypto.Keccak256Hash(addr.Bytes()) + addrHash := crypto.Keccak256AddressHash(addr) op := &accountDelete{ address: addr, origin: types.SlimAccountRLP(*prev), diff --git a/core/state/stateupdate.go b/core/state/stateupdate.go index 0c1b76b4f8..b15d469781 100644 --- a/core/state/stateupdate.go +++ b/core/state/stateupdate.go @@ -241,7 +241,7 @@ func (sc *stateUpdate) ToTracingUpdate() (*tracing.StateUpdate, error) { } // Gather all account changes for addr, oldData := range sc.accountsOrigin { - addrHash := crypto.Keccak256Hash(addr.Bytes()) + addrHash := crypto.Keccak256AddressHash(addr) newData, exists := sc.accounts[addrHash] if !exists { 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 for addr, slots := range sc.storagesOrigin { - addrHash := crypto.Keccak256Hash(addr.Bytes()) + addrHash := crypto.Keccak256AddressHash(addr) + subset, exists := sc.storages[addrHash] if !exists { return nil, fmt.Errorf("storage %x not found", addr) diff --git a/crypto/keccak.go b/crypto/keccak.go index 0ad79a63c1..5a945e876b 100644 --- a/crypto/keccak.go +++ b/crypto/keccak.go @@ -22,9 +22,16 @@ import ( "sync" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/lru" "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 func NewKeccakState() KeccakState { return sha3.NewLegacyKeccak256().(KeccakState) @@ -61,3 +68,13 @@ func Keccak256Hash(data ...[]byte) (h common.Hash) { hasherPool.Put(d) 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 +}