forked from cerc-io/plugeth
core, trie: track state change set with account address (#27815)
This commit is contained in:
parent
43a1a48ee2
commit
817553cc28
@ -173,10 +173,10 @@ func (ch resetObjectChange) revert(s *StateDB) {
|
|||||||
s.storages[ch.prev.addrHash] = ch.prevStorage
|
s.storages[ch.prev.addrHash] = ch.prevStorage
|
||||||
}
|
}
|
||||||
if ch.prevAccountOriginExist {
|
if ch.prevAccountOriginExist {
|
||||||
s.accountsOrigin[ch.prev.addrHash] = ch.prevAccountOrigin
|
s.accountsOrigin[ch.prev.address] = ch.prevAccountOrigin
|
||||||
}
|
}
|
||||||
if ch.prevStorageOrigin != nil {
|
if ch.prevStorageOrigin != nil {
|
||||||
s.storagesOrigin[ch.prev.addrHash] = ch.prevStorageOrigin
|
s.storagesOrigin[ch.prev.address] = ch.prevStorageOrigin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,9 +328,9 @@ func (s *stateObject) updateTrie() (Trie, error) {
|
|||||||
|
|
||||||
// Cache the original value of mutated storage slots
|
// Cache the original value of mutated storage slots
|
||||||
if origin == nil {
|
if origin == nil {
|
||||||
if origin = s.db.storagesOrigin[s.addrHash]; origin == nil {
|
if origin = s.db.storagesOrigin[s.address]; origin == nil {
|
||||||
origin = make(map[common.Hash][]byte)
|
origin = make(map[common.Hash][]byte)
|
||||||
s.db.storagesOrigin[s.addrHash] = origin
|
s.db.storagesOrigin[s.address] = origin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Track the original value of slot only if it's mutated first time
|
// Track the original value of slot only if it's mutated first time
|
||||||
|
@ -79,10 +79,10 @@ type StateDB struct {
|
|||||||
|
|
||||||
// These maps hold the state changes (including the corresponding
|
// These maps hold the state changes (including the corresponding
|
||||||
// original value) that occurred in this **block**.
|
// original value) that occurred in this **block**.
|
||||||
accounts map[common.Hash][]byte // The mutated accounts in 'slim RLP' encoding
|
accounts map[common.Hash][]byte // The mutated accounts in 'slim RLP' encoding
|
||||||
storages map[common.Hash]map[common.Hash][]byte // The mutated slots in prefix-zero trimmed rlp format
|
storages map[common.Hash]map[common.Hash][]byte // The mutated slots in prefix-zero trimmed rlp format
|
||||||
accountsOrigin map[common.Hash][]byte // The original value of mutated accounts in 'slim RLP' encoding
|
accountsOrigin map[common.Address][]byte // The original value of mutated accounts in 'slim RLP' encoding
|
||||||
storagesOrigin map[common.Hash]map[common.Hash][]byte // The original value of mutated slots in prefix-zero trimmed rlp format
|
storagesOrigin map[common.Address]map[common.Hash][]byte // The original value of mutated slots in prefix-zero trimmed rlp format
|
||||||
|
|
||||||
// This map holds 'live' objects, which will get modified while processing
|
// This map holds 'live' objects, which will get modified while processing
|
||||||
// a state transition.
|
// a state transition.
|
||||||
@ -157,8 +157,8 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error)
|
|||||||
snaps: snaps,
|
snaps: snaps,
|
||||||
accounts: make(map[common.Hash][]byte),
|
accounts: make(map[common.Hash][]byte),
|
||||||
storages: make(map[common.Hash]map[common.Hash][]byte),
|
storages: make(map[common.Hash]map[common.Hash][]byte),
|
||||||
accountsOrigin: make(map[common.Hash][]byte),
|
accountsOrigin: make(map[common.Address][]byte),
|
||||||
storagesOrigin: make(map[common.Hash]map[common.Hash][]byte),
|
storagesOrigin: make(map[common.Address]map[common.Hash][]byte),
|
||||||
stateObjects: make(map[common.Address]*stateObject),
|
stateObjects: make(map[common.Address]*stateObject),
|
||||||
stateObjectsPending: make(map[common.Address]struct{}),
|
stateObjectsPending: make(map[common.Address]struct{}),
|
||||||
stateObjectsDirty: make(map[common.Address]struct{}),
|
stateObjectsDirty: make(map[common.Address]struct{}),
|
||||||
@ -555,11 +555,11 @@ func (s *StateDB) updateStateObject(obj *stateObject) {
|
|||||||
// Track the original value of mutated account, nil means it was not present.
|
// Track the original value of mutated account, nil means it was not present.
|
||||||
// Skip if it has been tracked (because updateStateObject may be called
|
// Skip if it has been tracked (because updateStateObject may be called
|
||||||
// multiple times in a block).
|
// multiple times in a block).
|
||||||
if _, ok := s.accountsOrigin[obj.addrHash]; !ok {
|
if _, ok := s.accountsOrigin[obj.address]; !ok {
|
||||||
if obj.origin == nil {
|
if obj.origin == nil {
|
||||||
s.accountsOrigin[obj.addrHash] = nil
|
s.accountsOrigin[obj.address] = nil
|
||||||
} else {
|
} else {
|
||||||
s.accountsOrigin[obj.addrHash] = types.SlimAccountRLP(*obj.origin)
|
s.accountsOrigin[obj.address] = types.SlimAccountRLP(*obj.origin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -676,7 +676,7 @@ func (s *StateDB) createObject(addr common.Address) (newobj, prev *stateObject)
|
|||||||
// There may be some cached account/storage data already since IntermediateRoot
|
// There may be some cached account/storage data already since IntermediateRoot
|
||||||
// will be called for each transaction before byzantium fork which will always
|
// will be called for each transaction before byzantium fork which will always
|
||||||
// cache the latest account/storage data.
|
// cache the latest account/storage data.
|
||||||
prevAccount, ok := s.accountsOrigin[prev.addrHash]
|
prevAccount, ok := s.accountsOrigin[prev.address]
|
||||||
s.journal.append(resetObjectChange{
|
s.journal.append(resetObjectChange{
|
||||||
account: &addr,
|
account: &addr,
|
||||||
prev: prev,
|
prev: prev,
|
||||||
@ -685,12 +685,12 @@ func (s *StateDB) createObject(addr common.Address) (newobj, prev *stateObject)
|
|||||||
prevStorage: s.storages[prev.addrHash],
|
prevStorage: s.storages[prev.addrHash],
|
||||||
prevAccountOriginExist: ok,
|
prevAccountOriginExist: ok,
|
||||||
prevAccountOrigin: prevAccount,
|
prevAccountOrigin: prevAccount,
|
||||||
prevStorageOrigin: s.storagesOrigin[prev.addrHash],
|
prevStorageOrigin: s.storagesOrigin[prev.address],
|
||||||
})
|
})
|
||||||
delete(s.accounts, prev.addrHash)
|
delete(s.accounts, prev.addrHash)
|
||||||
delete(s.storages, prev.addrHash)
|
delete(s.storages, prev.addrHash)
|
||||||
delete(s.accountsOrigin, prev.addrHash)
|
delete(s.accountsOrigin, prev.address)
|
||||||
delete(s.storagesOrigin, prev.addrHash)
|
delete(s.storagesOrigin, prev.address)
|
||||||
}
|
}
|
||||||
|
|
||||||
newobj.created = true
|
newobj.created = true
|
||||||
@ -766,8 +766,8 @@ func (s *StateDB) Copy() *StateDB {
|
|||||||
originalRoot: s.originalRoot,
|
originalRoot: s.originalRoot,
|
||||||
accounts: make(map[common.Hash][]byte),
|
accounts: make(map[common.Hash][]byte),
|
||||||
storages: make(map[common.Hash]map[common.Hash][]byte),
|
storages: make(map[common.Hash]map[common.Hash][]byte),
|
||||||
accountsOrigin: make(map[common.Hash][]byte),
|
accountsOrigin: make(map[common.Address][]byte),
|
||||||
storagesOrigin: make(map[common.Hash]map[common.Hash][]byte),
|
storagesOrigin: make(map[common.Address]map[common.Hash][]byte),
|
||||||
stateObjects: make(map[common.Address]*stateObject, len(s.journal.dirties)),
|
stateObjects: make(map[common.Address]*stateObject, len(s.journal.dirties)),
|
||||||
stateObjectsPending: make(map[common.Address]struct{}, len(s.stateObjectsPending)),
|
stateObjectsPending: make(map[common.Address]struct{}, len(s.stateObjectsPending)),
|
||||||
stateObjectsDirty: make(map[common.Address]struct{}, len(s.journal.dirties)),
|
stateObjectsDirty: make(map[common.Address]struct{}, len(s.journal.dirties)),
|
||||||
@ -824,10 +824,10 @@ func (s *StateDB) Copy() *StateDB {
|
|||||||
}
|
}
|
||||||
// Deep copy the state changes made in the scope of block
|
// Deep copy the state changes made in the scope of block
|
||||||
// along with their original values.
|
// along with their original values.
|
||||||
state.accounts = copyAccounts(s.accounts)
|
state.accounts = copySet(s.accounts)
|
||||||
state.storages = copyStorages(s.storages)
|
state.storages = copy2DSet(s.storages)
|
||||||
state.accountsOrigin = copyAccounts(state.accountsOrigin)
|
state.accountsOrigin = copySet(state.accountsOrigin)
|
||||||
state.storagesOrigin = copyStorages(state.storagesOrigin)
|
state.storagesOrigin = copy2DSet(state.storagesOrigin)
|
||||||
|
|
||||||
// Deep copy the logs occurred in the scope of block
|
// Deep copy the logs occurred in the scope of block
|
||||||
for hash, logs := range s.logs {
|
for hash, logs := range s.logs {
|
||||||
@ -917,10 +917,10 @@ func (s *StateDB) Finalise(deleteEmptyObjects bool) {
|
|||||||
// Note, we can't do this only at the end of a block because multiple
|
// Note, we can't do this only at the end of a block because multiple
|
||||||
// transactions within the same block might self destruct and then
|
// transactions within the same block might self destruct and then
|
||||||
// resurrect an account; but the snapshotter needs both events.
|
// resurrect an account; but the snapshotter needs both events.
|
||||||
delete(s.accounts, obj.addrHash) // Clear out any previously updated account data (may be recreated via a resurrect)
|
delete(s.accounts, obj.addrHash) // Clear out any previously updated account data (may be recreated via a resurrect)
|
||||||
delete(s.storages, obj.addrHash) // Clear out any previously updated storage data (may be recreated via a resurrect)
|
delete(s.storages, obj.addrHash) // Clear out any previously updated storage data (may be recreated via a resurrect)
|
||||||
delete(s.accountsOrigin, obj.addrHash) // Clear out any previously updated account data (may be recreated via a resurrect)
|
delete(s.accountsOrigin, obj.address) // Clear out any previously updated account data (may be recreated via a resurrect)
|
||||||
delete(s.storagesOrigin, obj.addrHash) // Clear out any previously updated storage data (may be recreated via a resurrect)
|
delete(s.storagesOrigin, obj.address) // Clear out any previously updated storage data (may be recreated via a resurrect)
|
||||||
} else {
|
} else {
|
||||||
obj.finalise(true) // Prefetch slots in the background
|
obj.finalise(true) // Prefetch slots in the background
|
||||||
}
|
}
|
||||||
@ -1098,8 +1098,8 @@ func (s *StateDB) deleteStorage(addr common.Address, addrHash common.Hash, root
|
|||||||
//
|
//
|
||||||
// In case (d), **original** account along with its storages should be deleted,
|
// In case (d), **original** account along with its storages should be deleted,
|
||||||
// with their values be tracked as original value.
|
// with their values be tracked as original value.
|
||||||
func (s *StateDB) handleDestruction(nodes *trienode.MergedNodeSet) (map[common.Hash]struct{}, error) {
|
func (s *StateDB) handleDestruction(nodes *trienode.MergedNodeSet) (map[common.Address]struct{}, error) {
|
||||||
incomplete := make(map[common.Hash]struct{})
|
incomplete := make(map[common.Address]struct{})
|
||||||
for addr, prev := range s.stateObjectsDestruct {
|
for addr, prev := range s.stateObjectsDestruct {
|
||||||
// The original account was non-existing, and it's marked as destructed
|
// The original account was non-existing, and it's marked as destructed
|
||||||
// in the scope of block. It can be case (a) or (b).
|
// in the scope of block. It can be case (a) or (b).
|
||||||
@ -1109,12 +1109,12 @@ func (s *StateDB) handleDestruction(nodes *trienode.MergedNodeSet) (map[common.H
|
|||||||
addrHash := crypto.Keccak256Hash(addr[:])
|
addrHash := crypto.Keccak256Hash(addr[:])
|
||||||
if prev == nil {
|
if prev == nil {
|
||||||
if _, ok := s.accounts[addrHash]; ok {
|
if _, ok := s.accounts[addrHash]; ok {
|
||||||
s.accountsOrigin[addrHash] = nil // case (b)
|
s.accountsOrigin[addr] = nil // case (b)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// It can overwrite the data in s.accountsOrigin set by 'updateStateObject'.
|
// It can overwrite the data in s.accountsOrigin set by 'updateStateObject'.
|
||||||
s.accountsOrigin[addrHash] = types.SlimAccountRLP(*prev) // case (c) or (d)
|
s.accountsOrigin[addr] = types.SlimAccountRLP(*prev) // case (c) or (d)
|
||||||
|
|
||||||
// Short circuit if the storage was empty.
|
// Short circuit if the storage was empty.
|
||||||
if prev.Root == types.EmptyRootHash {
|
if prev.Root == types.EmptyRootHash {
|
||||||
@ -1130,17 +1130,17 @@ func (s *StateDB) handleDestruction(nodes *trienode.MergedNodeSet) (map[common.H
|
|||||||
// created. In this case, wipe the entire storage state diff because
|
// created. In this case, wipe the entire storage state diff because
|
||||||
// of aborted deletion.
|
// of aborted deletion.
|
||||||
if aborted {
|
if aborted {
|
||||||
incomplete[addrHash] = struct{}{}
|
incomplete[addr] = struct{}{}
|
||||||
delete(s.storagesOrigin, addrHash)
|
delete(s.storagesOrigin, addr)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if s.storagesOrigin[addrHash] == nil {
|
if s.storagesOrigin[addr] == nil {
|
||||||
s.storagesOrigin[addrHash] = slots
|
s.storagesOrigin[addr] = slots
|
||||||
} else {
|
} else {
|
||||||
// It can overwrite the data in s.storagesOrigin[addrHash] set by
|
// It can overwrite the data in s.storagesOrigin[addrHash] set by
|
||||||
// 'object.updateTrie'.
|
// 'object.updateTrie'.
|
||||||
for key, val := range slots {
|
for key, val := range slots {
|
||||||
s.storagesOrigin[addrHash][key] = val
|
s.storagesOrigin[addr][key] = val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := nodes.Merge(set); err != nil {
|
if err := nodes.Merge(set); err != nil {
|
||||||
@ -1290,8 +1290,8 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er
|
|||||||
// Clear all internal flags at the end of commit operation.
|
// Clear all internal flags at the end of commit operation.
|
||||||
s.accounts = make(map[common.Hash][]byte)
|
s.accounts = make(map[common.Hash][]byte)
|
||||||
s.storages = make(map[common.Hash]map[common.Hash][]byte)
|
s.storages = make(map[common.Hash]map[common.Hash][]byte)
|
||||||
s.accountsOrigin = make(map[common.Hash][]byte)
|
s.accountsOrigin = make(map[common.Address][]byte)
|
||||||
s.storagesOrigin = make(map[common.Hash]map[common.Hash][]byte)
|
s.storagesOrigin = make(map[common.Address]map[common.Hash][]byte)
|
||||||
s.stateObjectsDirty = make(map[common.Address]struct{})
|
s.stateObjectsDirty = make(map[common.Address]struct{})
|
||||||
s.stateObjectsDestruct = make(map[common.Address]*types.StateAccount)
|
s.stateObjectsDestruct = make(map[common.Address]*types.StateAccount)
|
||||||
return root, nil
|
return root, nil
|
||||||
@ -1387,18 +1387,18 @@ func (s *StateDB) convertAccountSet(set map[common.Address]*types.StateAccount)
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
// copyAccounts returns a deep-copied account set of the provided one.
|
// copySet returns a deep-copied set.
|
||||||
func copyAccounts(set map[common.Hash][]byte) map[common.Hash][]byte {
|
func copySet[k comparable](set map[k][]byte) map[k][]byte {
|
||||||
copied := make(map[common.Hash][]byte, len(set))
|
copied := make(map[k][]byte, len(set))
|
||||||
for key, val := range set {
|
for key, val := range set {
|
||||||
copied[key] = common.CopyBytes(val)
|
copied[key] = common.CopyBytes(val)
|
||||||
}
|
}
|
||||||
return copied
|
return copied
|
||||||
}
|
}
|
||||||
|
|
||||||
// copyStorages returns a deep-copied storage set of the provided one.
|
// copy2DSet returns a two-dimensional deep-copied set.
|
||||||
func copyStorages(set map[common.Hash]map[common.Hash][]byte) map[common.Hash]map[common.Hash][]byte {
|
func copy2DSet[k comparable](set map[k]map[common.Hash][]byte) map[k]map[common.Hash][]byte {
|
||||||
copied := make(map[common.Hash]map[common.Hash][]byte, len(set))
|
copied := make(map[k]map[common.Hash][]byte, len(set))
|
||||||
for addr, subset := range set {
|
for addr, subset := range set {
|
||||||
copied[addr] = make(map[common.Hash][]byte, len(subset))
|
copied[addr] = make(map[common.Hash][]byte, len(subset))
|
||||||
for key, val := range subset {
|
for key, val := range subset {
|
||||||
|
@ -32,6 +32,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
"github.com/ethereum/go-ethereum/trie/triestate"
|
"github.com/ethereum/go-ethereum/trie/triestate"
|
||||||
@ -171,11 +172,11 @@ func (test *stateTest) String() string {
|
|||||||
func (test *stateTest) run() bool {
|
func (test *stateTest) run() bool {
|
||||||
var (
|
var (
|
||||||
roots []common.Hash
|
roots []common.Hash
|
||||||
accountList []map[common.Hash][]byte
|
accountList []map[common.Address][]byte
|
||||||
storageList []map[common.Hash]map[common.Hash][]byte
|
storageList []map[common.Address]map[common.Hash][]byte
|
||||||
onCommit = func(states *triestate.Set) {
|
onCommit = func(states *triestate.Set) {
|
||||||
accountList = append(accountList, copyAccounts(states.Accounts))
|
accountList = append(accountList, copySet(states.Accounts))
|
||||||
storageList = append(storageList, copyStorages(states.Storages))
|
storageList = append(storageList, copy2DSet(states.Storages))
|
||||||
}
|
}
|
||||||
disk = rawdb.NewMemoryDatabase()
|
disk = rawdb.NewMemoryDatabase()
|
||||||
tdb = trie.NewDatabaseWithConfig(disk, &trie.Config{OnCommit: onCommit})
|
tdb = trie.NewDatabaseWithConfig(disk, &trie.Config{OnCommit: onCommit})
|
||||||
@ -235,8 +236,9 @@ func (test *stateTest) run() bool {
|
|||||||
// - the account was indeed not present in trie
|
// - the account was indeed not present in trie
|
||||||
// - the account is present in new trie, nil->nil is regarded as invalid
|
// - the account is present in new trie, nil->nil is regarded as invalid
|
||||||
// - the slots transition is correct
|
// - the slots transition is correct
|
||||||
func (test *stateTest) verifyAccountCreation(next common.Hash, db *trie.Database, otr, ntr *trie.Trie, addrHash common.Hash, slots map[common.Hash][]byte) error {
|
func (test *stateTest) verifyAccountCreation(next common.Hash, db *trie.Database, otr, ntr *trie.Trie, addr common.Address, slots map[common.Hash][]byte) error {
|
||||||
// Verify account change
|
// Verify account change
|
||||||
|
addrHash := crypto.Keccak256Hash(addr.Bytes())
|
||||||
oBlob, err := otr.Get(addrHash.Bytes())
|
oBlob, err := otr.Get(addrHash.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -285,8 +287,9 @@ func (test *stateTest) verifyAccountCreation(next common.Hash, db *trie.Database
|
|||||||
// - the account was indeed present in trie
|
// - the account was indeed present in trie
|
||||||
// - the account in old trie matches the provided value
|
// - the account in old trie matches the provided value
|
||||||
// - the slots transition is correct
|
// - the slots transition is correct
|
||||||
func (test *stateTest) verifyAccountUpdate(next common.Hash, db *trie.Database, otr, ntr *trie.Trie, addrHash common.Hash, origin []byte, slots map[common.Hash][]byte) error {
|
func (test *stateTest) verifyAccountUpdate(next common.Hash, db *trie.Database, otr, ntr *trie.Trie, addr common.Address, origin []byte, slots map[common.Hash][]byte) error {
|
||||||
// Verify account change
|
// Verify account change
|
||||||
|
addrHash := crypto.Keccak256Hash(addr.Bytes())
|
||||||
oBlob, err := otr.Get(addrHash.Bytes())
|
oBlob, err := otr.Get(addrHash.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -338,7 +341,7 @@ func (test *stateTest) verifyAccountUpdate(next common.Hash, db *trie.Database,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (test *stateTest) verify(root common.Hash, next common.Hash, db *trie.Database, accountsOrigin map[common.Hash][]byte, storagesOrigin map[common.Hash]map[common.Hash][]byte) error {
|
func (test *stateTest) verify(root common.Hash, next common.Hash, db *trie.Database, accountsOrigin map[common.Address][]byte, storagesOrigin map[common.Address]map[common.Hash][]byte) error {
|
||||||
otr, err := trie.New(trie.StateTrieID(root), db)
|
otr, err := trie.New(trie.StateTrieID(root), db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -347,12 +350,12 @@ func (test *stateTest) verify(root common.Hash, next common.Hash, db *trie.Datab
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for addrHash, account := range accountsOrigin {
|
for addr, account := range accountsOrigin {
|
||||||
var err error
|
var err error
|
||||||
if len(account) == 0 {
|
if len(account) == 0 {
|
||||||
err = test.verifyAccountCreation(next, db, otr, ntr, addrHash, storagesOrigin[addrHash])
|
err = test.verifyAccountCreation(next, db, otr, ntr, addr, storagesOrigin[addr])
|
||||||
} else {
|
} else {
|
||||||
err = test.verifyAccountUpdate(next, db, otr, ntr, addrHash, accountsOrigin[addrHash], storagesOrigin[addrHash])
|
err = test.verifyAccountUpdate(next, db, otr, ntr, addr, accountsOrigin[addr], storagesOrigin[addr])
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -22,7 +22,7 @@ import "github.com/ethereum/go-ethereum/common"
|
|||||||
// The value refers to the original content of state before the transition
|
// The value refers to the original content of state before the transition
|
||||||
// is made. Nil means that the state was not present previously.
|
// is made. Nil means that the state was not present previously.
|
||||||
type Set struct {
|
type Set struct {
|
||||||
Accounts map[common.Hash][]byte // Mutated account set, nil means the account was not present
|
Accounts map[common.Address][]byte // Mutated account set, nil means the account was not present
|
||||||
Storages map[common.Hash]map[common.Hash][]byte // Mutated storage set, nil means the slot was not present
|
Storages map[common.Address]map[common.Hash][]byte // Mutated storage set, nil means the slot was not present
|
||||||
Incomplete map[common.Hash]struct{} // Indicator whether the storage slot is incomplete due to large deletion
|
Incomplete map[common.Address]struct{} // Indicator whether the storage slot is incomplete due to large deletion
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user