From f9171c4946fcfeb62d3aad2282921b7c0feeeba1 Mon Sep 17 00:00:00 2001 From: Jerry Date: Tue, 25 Apr 2023 12:03:04 -0700 Subject: [PATCH] Add ParallelExecFailedError Parallel execution can fail due to bad dependencies. In the case of bad dependencies, the result of serial execution should be used. --- core/blockchain.go | 13 +++++++++++++ core/blockstm/executor.go | 10 +++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/core/blockchain.go b/core/blockchain.go index c485c002a4..6a44a3acff 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -42,6 +42,7 @@ import ( "github.com/ethereum/go-ethereum/common/prque" "github.com/ethereum/go-ethereum/common/tracing" "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/core/blockstm" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state/snapshot" @@ -500,6 +501,18 @@ func (bc *BlockChain) ProcessBlock(block *types.Block, parent *types.Header) (ty } result := <-resultChan + + if _, ok := result.err.(blockstm.ParallelExecFailedError); ok { + log.Warn("Parallel state processor failed", "err", result.err) + + // If the parallel processor failed, we will fallback to the serial processor if enabled + if processorCount == 2 { + result.statedb.StopPrefetcher() + result = <-resultChan + processorCount-- + } + } + result.counter.Inc(1) // Make sure we are not leaking any prefetchers diff --git a/core/blockstm/executor.go b/core/blockstm/executor.go index 9d42153623..a685fe0707 100644 --- a/core/blockstm/executor.go +++ b/core/blockstm/executor.go @@ -69,6 +69,14 @@ func (e ErrExecAbortError) Error() string { } } +type ParallelExecFailedError struct { + Msg string +} + +func (e ParallelExecFailedError) Error() string { + return e.Msg +} + type IntHeap []int func (h IntHeap) Len() int { return len(h) } @@ -384,7 +392,7 @@ func (pe *ParallelExecutor) Prepare() error { tx := pe.execTasks.takeNextPending() if tx == -1 { - return fmt.Errorf("no transaction to execute") + return ParallelExecFailedError{"no executable transactions due to bad dependency"} } pe.cntExec++