diff --git a/core/state/snapshot/difflayer.go b/core/state/snapshot/difflayer.go index 65b2729d9c..e45c1ec7ce 100644 --- a/core/state/snapshot/difflayer.go +++ b/core/state/snapshot/difflayer.go @@ -379,6 +379,18 @@ func (dl *diffLayer) accountRLP(hash common.Hash, depth int) ([]byte, error) { return dl.parent.AccountRLP(hash) } +// StaleOrGenerating returns whether the snapshot is stale or generating +func (dl *diffLayer) StaleOrGenerating() bool { + dl.lock.RLock() + defer dl.lock.RUnlock() + + if dl.Stale() { + return true + } + + return dl.parent.Stale() +} + // Storage directly retrieves the storage data associated with a particular hash, // within a particular account. If the slot is unknown to this diff, it's parent // is consulted. diff --git a/core/state/snapshot/disklayer.go b/core/state/snapshot/disklayer.go index c1de41782c..a5896e2235 100644 --- a/core/state/snapshot/disklayer.go +++ b/core/state/snapshot/disklayer.go @@ -128,6 +128,18 @@ func (dl *diskLayer) AccountRLP(hash common.Hash) ([]byte, error) { return blob, nil } +// StaleOrGenerating returns whether the snapshot is stale or generating +func (dl *diskLayer) StaleOrGenerating() bool { + dl.lock.RLock() + defer dl.lock.RUnlock() + + if dl.Stale() || dl.genMarker != nil { + return true + } + + return false +} + // Storage directly retrieves the storage data associated with a particular hash, // within a particular account. func (dl *diskLayer) Storage(accountHash, storageHash common.Hash) ([]byte, error) { diff --git a/core/state/snapshot/snapshot.go b/core/state/snapshot/snapshot.go index 8ac93f28e4..9f06b5cbc8 100644 --- a/core/state/snapshot/snapshot.go +++ b/core/state/snapshot/snapshot.go @@ -121,6 +121,9 @@ type Snapshot interface { // Storage directly retrieves the storage data associated with a particular hash, // within a particular account. Storage(accountHash, storageHash common.Hash) ([]byte, error) + + // StaleOrGenerating returns whether the snapshot is stale or generating + StaleOrGenerating() bool } // snapshot is the internal version of the snapshot data layer that supports some diff --git a/core/state/statedb.go b/core/state/statedb.go index a29e72085a..b6c5b63589 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -311,6 +311,14 @@ func newStateDB(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, return sdb, nil } +func (s *StateDB) SnapshotAvailable() bool { + if s.snap == nil { + return false + } + + return !s.snap.StaleOrGenerating() +} + func (s *StateDB) getBaseStateDB() *StateDB { return s } diff --git a/core/state_processor.go b/core/state_processor.go index b0163b8e1a..6daac4b955 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -948,6 +948,11 @@ func (p *ParallelStateProcessor) doCleanUp() { // Implement BEP-130: Parallel Transaction Execution. func (p *ParallelStateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (*state.StateDB, types.Receipts, []*types.Log, uint64, error) { + // if snapshot is nil or generating, fall back to sequential process + if !statedb.SnapshotAvailable() { + return p.StateProcessor.Process(block, statedb, cfg) + } + var ( usedGas = new(uint64) header = block.Header()