diff --git a/core/state/state_object.go b/core/state/state_object.go index 8b862c2865..cf89d774cd 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -798,6 +798,15 @@ func (s *stateObject) deepCopy(db *StateDB) *stateObject { return object } +// rebase is similar with deepCopy, instead of do copy, it just rebase the db of the Object. +// it is used for the case that the original state object in the mainDB is obsoleted or does not exist, +// so that we can reuse the one generated in slot execution. +func (object *stateObject) rebase(db *StateDB) *stateObject { + object.db = db.getBaseStateDB() + object.dbItf = db + return object +} + func (s *stateObject) MergeSlotObject(db Database, dirtyObjs *stateObject, keys StateKeys) { for key := range keys { // In parallel mode, always GetState by StateDB, not by StateObject directly, diff --git a/core/state/statedb.go b/core/state/statedb.go index ac888ec415..076f062955 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -2512,7 +2512,12 @@ func (s *StateDB) MergeSlotDB(slotDb *ParallelStateDB, slotReceipt *types.Receip mainObj, exist := s.loadStateObj(addr) if !exist || mainObj.deleted { // addr not exist on main DB, the object is created in the merging tx. - mainObj = dirtyObj.deepCopy(s) + if slotDb.parallel.useDAG { + // if use DAG, unconfirmed DB is not touched, so the dirtyObj can be used directly + mainObj = dirtyObj.rebase(s) + } else { + mainObj = dirtyObj.deepCopy(s) + } if !dirtyObj.deleted { mainObj.finalise(true) } @@ -2554,7 +2559,12 @@ func (s *StateDB) MergeSlotDB(slotDb *ParallelStateDB, slotReceipt *types.Receip // may not empty until block validation. so the pendingStorage filled by the execution of previous txs // in same block may get overwritten by deepCopy here, which causes issue in root calculation. if _, created := s.parallel.createdObjectRecord[addr]; created { - newMainObj = dirtyObj.deepCopy(s) + if slotDb.parallel.useDAG { + // if use DAG, unconfirmed DB is not touched, so the dirtyObj can be used directly + newMainObj = dirtyObj.rebase(s) + } else { + newMainObj = dirtyObj.deepCopy(s) + } } else { // Merge the dirtyObject with mainObject if _, balanced := slotDb.parallel.balanceChangesInSlot[addr]; balanced { @@ -2579,7 +2589,12 @@ func (s *StateDB) MergeSlotDB(slotDb *ParallelStateDB, slotReceipt *types.Receip } } else { // The object is deleted in the TX. - newMainObj = dirtyObj.deepCopy(s) + if slotDb.parallel.useDAG { + // if use DAG, unconfirmed DB is not touched, so the dirtyObj can be used directly + newMainObj = dirtyObj.rebase(s) + } else { + newMainObj = dirtyObj.deepCopy(s) + } } // All cases with addrStateChange set to true/false can be deleted. so handle it here.