core/state: store storageOrigin in one map

Signed-off-by: jsvisa <delweng@gmail.com>
This commit is contained in:
jsvisa 2025-03-25 12:18:28 +00:00
parent 6928ec5d92
commit f595cb6653
3 changed files with 24 additions and 26 deletions

View file

@ -375,7 +375,7 @@ func (s *stateObject) updateRoot() {
// commitStorage overwrites the clean storage with the storage changes and // commitStorage overwrites the clean storage with the storage changes and
// fulfills the storage diffs into the given accountUpdate struct. // fulfills the storage diffs into the given accountUpdate struct.
func (s *stateObject) commitStorage(op *accountUpdate) { func (s *stateObject) commitStorage(op *accountUpdate, rawStorageKey bool) {
var ( var (
buf = crypto.NewKeccakState() buf = crypto.NewKeccakState()
encode = func(val common.Hash) []byte { encode = func(val common.Hash) []byte {
@ -400,15 +400,15 @@ func (s *stateObject) commitStorage(op *accountUpdate) {
} }
op.storages[hash] = encode(val) op.storages[hash] = encode(val)
if op.storagesOriginByKey == nil { if op.storagesOrigin == nil {
op.storagesOriginByKey = make(map[common.Hash][]byte) op.storagesOrigin = make(map[common.Hash][]byte)
}
if op.storagesOriginByHash == nil {
op.storagesOriginByHash = make(map[common.Hash][]byte)
} }
origin := encode(s.originStorage[key]) origin := encode(s.originStorage[key])
op.storagesOriginByKey[key] = origin if rawStorageKey {
op.storagesOriginByHash[hash] = origin op.storagesOrigin[key] = origin
} else {
op.storagesOrigin[hash] = origin
}
// Overwrite the clean value of storage slots // Overwrite the clean value of storage slots
s.originStorage[key] = val s.originStorage[key] = val
@ -421,7 +421,7 @@ func (s *stateObject) commitStorage(op *accountUpdate) {
// //
// Note, commit may run concurrently across all the state objects. Do not assume // Note, commit may run concurrently across all the state objects. Do not assume
// thread-safe access to the statedb. // thread-safe access to the statedb.
func (s *stateObject) commit() (*accountUpdate, *trienode.NodeSet, error) { func (s *stateObject) commit(rawStorageKey bool) (*accountUpdate, *trienode.NodeSet, error) {
// commit the account metadata changes // commit the account metadata changes
op := &accountUpdate{ op := &accountUpdate{
address: s.address, address: s.address,
@ -439,7 +439,7 @@ func (s *stateObject) commit() (*accountUpdate, *trienode.NodeSet, error) {
s.dirtyCode = false // reset the dirty flag s.dirtyCode = false // reset the dirty flag
} }
// Commit storage changes and the associated storage trie // Commit storage changes and the associated storage trie
s.commitStorage(op) s.commitStorage(op, rawStorageKey)
if len(op.storages) == 0 { if len(op.storages) == 0 {
// nothing changed, don't bother to commit the trie // nothing changed, don't bother to commit the trie
s.origin = s.data.Copy() s.origin = s.data.Copy()

View file

@ -1213,7 +1213,7 @@ func (s *StateDB) commit(deleteEmptyObjects bool, noStorageWiping bool) (*stateU
// Run the storage updates concurrently to one another // Run the storage updates concurrently to one another
workers.Go(func() error { workers.Go(func() error {
// Write any storage changes in the state object to its storage trie // Write any storage changes in the state object to its storage trie
update, set, err := obj.commit() update, set, err := obj.commit(noStorageWiping)
if err != nil { if err != nil {
return err return err
} }

View file

@ -46,18 +46,19 @@ type accountDelete struct {
// accountUpdate represents an operation for updating an Ethereum account. // accountUpdate represents an operation for updating an Ethereum account.
type accountUpdate struct { type accountUpdate struct {
address common.Address // address is the unique account identifier address common.Address // address is the unique account identifier
data []byte // data is the slim-RLP encoded account data. data []byte // data is the slim-RLP encoded account data.
origin []byte // origin is the original value of account data in slim-RLP encoding. origin []byte // origin is the original value of account data in slim-RLP encoding.
code *contractCode // code represents mutated contract code; nil means it's not modified. code *contractCode // code represents mutated contract code; nil means it's not modified.
storages map[common.Hash][]byte // storages stores mutated slots in prefix-zero-trimmed RLP format.
// storagesOriginByKey and storagesOriginByHash both store the original values // storages stores mutated slots in prefix-zero-trimmed RLP format,
// of mutated slots in prefix-zero-trimmed RLP format. The difference is that // The map key refers to the **HASH** of the raw storage slot key.
// storagesOriginByKey uses the **raw** storage slot key as the map ID, while storages map[common.Hash][]byte
// storagesOriginByHash uses the **hash** of the storage slot key instead.
storagesOriginByKey map[common.Hash][]byte // storagesOrigin store the original values of mutated slots in prefix-zero-trimmed RLP format.
storagesOriginByHash map[common.Hash][]byte // if `rawStorageKey` is true, the map key refers to the **RAW** storage slot key,
// else the **HASH** of the raw storage slot key.
storagesOrigin map[common.Hash][]byte
} }
// stateUpdate represents the difference between two states resulting from state // stateUpdate represents the difference between two states resulting from state
@ -144,10 +145,7 @@ func newStateUpdate(rawStorageKey bool, originRoot common.Hash, root common.Hash
} }
// Aggregate the storage original values. If the slot is already present // Aggregate the storage original values. If the slot is already present
// in aggregated storagesOrigin set, skip it. // in aggregated storagesOrigin set, skip it.
storageOriginSet := op.storagesOriginByHash storageOriginSet := op.storagesOrigin
if rawStorageKey {
storageOriginSet = op.storagesOriginByKey
}
if len(storageOriginSet) > 0 { if len(storageOriginSet) > 0 {
origin, exist := storagesOrigin[addr] origin, exist := storagesOrigin[addr]
if !exist { if !exist {