diff --git a/core/block_validator.go b/core/block_validator.go index c6a35f1fdf..4cf53a6cdc 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -20,6 +20,7 @@ import ( "fmt" "time" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" @@ -140,10 +141,8 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD if err := statedb.WaitPipeVerification(); err != nil { return err } - statedb.CorrectAccountsRoot() + statedb.CorrectAccountsRoot(common.Hash{}) statedb.Finalise(v.config.IsEIP158(header.Number)) - // State verification pipeline - accounts root are not calculated here, just populate needed fields for process - statedb.PopulateSnapAccountAndStorage() return nil }) } else { diff --git a/core/state/statedb.go b/core/state/statedb.go index 76983b2a9c..ade1b5804f 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -975,12 +975,23 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash { } //CorrectAccountsRoot will fix account roots in pipecommit mode -func (s *StateDB) CorrectAccountsRoot() { - if accounts, err := s.snap.Accounts(); err == nil && accounts != nil { +func (s *StateDB) CorrectAccountsRoot(blockRoot common.Hash) { + var snapshot snapshot.Snapshot + if blockRoot == (common.Hash{}) { + snapshot = s.snap + } else if s.snaps != nil { + snapshot = s.snaps.Snapshot(blockRoot) + } + + if snapshot == nil { + return + } + if accounts, err := snapshot.Accounts(); err == nil && accounts != nil { for _, obj := range s.stateObjects { if !obj.deleted && !obj.rootCorrected && obj.data.Root == dummyRoot { if account, exist := accounts[crypto.Keccak256Hash(obj.address[:])]; exist && len(account.Root) != 0 { obj.data.Root = common.BytesToHash(account.Root) + obj.rootCorrected = true } } } @@ -1465,6 +1476,8 @@ func (s *StateDB) Commit(failPostCommitFunc func(), postCommitFuncs ...func() er } if s.pipeCommit { defer close(snapUpdated) + // State verification pipeline - accounts root are not calculated here, just populate needed fields for process + s.PopulateSnapAccountAndStorage() } diffLayer.Destructs, diffLayer.Accounts, diffLayer.Storages = s.SnapToDiffLayer() // Only update if there's a state transition (skip empty Clique blocks) diff --git a/miner/worker.go b/miner/worker.go index 6715213e94..2b9bf43305 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -1009,6 +1009,9 @@ func (w *worker) commit(uncles []*types.Header, interval func(), update bool, st if err != nil { return err } + + s.CorrectAccountsRoot(w.chain.CurrentBlock().Root()) + block, receipts, err := w.engine.FinalizeAndAssemble(w.chain, types.CopyHeader(w.current.header), s, w.current.txs, uncles, w.current.receipts) if err != nil { return err