Skip to content

Commit

Permalink
fix 'invalid merkle root': fetch objects without updating maindb's cache
Browse files Browse the repository at this point in the history
  • Loading branch information
andyzhang2023 committed Nov 20, 2024
1 parent 8cba3f3 commit 340cacd
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 24 deletions.
28 changes: 4 additions & 24 deletions core/state/pevm_statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ func (pst *UncommittedDB) getDeletedObject(addr common.Address, maindb *StateDB)
return pst.cache[addr]
}
// it reads the cache from the maindb
obj := maindb.getDeletedStateObject(addr)
obj := maindb.getDeleteStateObjectWithoutUpdate(addr)
defer func() {
pst.reads.recordOnce(addr, copyObj(obj))
}()
Expand Down Expand Up @@ -609,26 +609,6 @@ func (pst *UncommittedDB) getOrNewObject(addr common.Address) *state {
return pst.cache.create(addr)
}

func (pst *UncommittedDB) getObjectWithCode(addr common.Address) *state {
obj := pst.getObject(addr)
if obj == nil {
return nil
}
if obj.codeIsLoaded() {
return obj
}
// try to load the code from maindb
deletedObject := pst.maindb.getStateObject(addr)
if deletedObject == nil {
return nil
}
code, codeHash := deletedObject.Code(), common.BytesToHash(deletedObject.CodeHash())
obj.code = code
obj.codeHash = codeHash[:]
obj.codeSize = len(code)
return obj
}

// getDeletedObjectWithCode return an object with code, and load the code from maindb if it is not loaded.
func (pst *UncommittedDB) getDeletedObjectWithCode(addr common.Address, maindb *StateDB) (o *state) {
o = pst.getDeletedObject(addr, maindb)
Expand All @@ -640,7 +620,7 @@ func (pst *UncommittedDB) getDeletedObjectWithCode(addr common.Address, maindb *
return o
}
// load code from maindb
deletedObj := pst.maindb.getDeletedStateObject(addr)
deletedObj := pst.maindb.getDeleteStateObjectWithoutUpdate(addr)
var code = []byte{}
var codeHash = common.Hash{}
if deletedObj == nil {
Expand Down Expand Up @@ -668,7 +648,7 @@ func (pst *UncommittedDB) getDeletedObjectWithState(addr common.Address, maindb
}
// first, load code from maindb and record the previous state
// we can't use getStateObject() here , because the state of deletedObj will be used for conflict check.
deletedObj := pst.maindb.getDeletedStateObject(addr)
deletedObj := pst.maindb.getDeleteStateObjectWithoutUpdate(addr)
if deletedObj != nil {
// record the previous state for conflict check.
pst.reads.recordKVOnce(addr, hash, deletedObj.GetState(hash))
Expand Down Expand Up @@ -731,7 +711,7 @@ func (s *state) markAllModified() {
// check whether the state of current object is conflicted with the maindb
func (s state) conflicts(maindb *StateDB) error {
addr := s.addr
obj := maindb.getDeletedStateObject(addr)
obj := maindb.getDeleteStateObjectWithoutUpdate(addr)
// created == true means it doen't exist in the maindb
if s.created != (obj == nil) {
return errors.New("conflict: created")
Expand Down
14 changes: 14 additions & 0 deletions core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -970,6 +970,20 @@ func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject {
return obj
}

// only used for parallel evm.
func (s *StateDB) getDeleteStateObjectWithoutUpdate(addr common.Address) *stateObject {
// Prefer live objects if any is available
if obj, _ := s.getStateObjectFromStateObjects(addr); obj != nil {
return obj
}

data, ok := s.getStateObjectFromSnapshotOrTrie(addr)
if !ok {
return nil
}
return newObject(s, true, addr, data)
}

func (s *StateDB) setStateObject(object *stateObject) {
if s.isParallel {
if s.parallel.isSlotDB {
Expand Down

0 comments on commit 340cacd

Please sign in to comment.