diff --git a/core/blockchain.go b/core/blockchain.go index 6667f64911..574d934bd5 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1952,7 +1952,11 @@ func (bc *BlockChain) processBlock(block *types.Block, statedb *state.StateDB, s } if bc.logger != nil && bc.logger.OnBlockEnd != nil { defer func() { - bc.logger.OnBlockEnd(blockEndErr) + if recovered := recover(); recovered != nil { + panic(recovered) + } else { + bc.logger.OnBlockEnd(blockEndErr) + } }() } diff --git a/core/blockchain_test.go b/core/blockchain_test.go index 134deee237..f787df4e70 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -36,6 +36,7 @@ import ( "github.com/ethereum/go-ethereum/core/history" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm/program" @@ -4390,3 +4391,43 @@ func testInsertChainWithCutoff(t *testing.T, cutoff uint64, ancientLimit uint64, } } } + +func TestTracingBlockEndNotCalledOnPanic(t *testing.T) { + genDb, _, blockchain, err := newCanonical(ethash.NewFaker(), 0, true, "path") + if err != nil { + t.Fatalf("failed to create pristine chain: %v", err) + } + defer blockchain.Stop() + + blockEndCalled := false + hooks := &tracing.Hooks{ + // This simulates a panic in the tracer + OnBalanceChange: func(addr common.Address, prev, new *big.Int, reason tracing.BalanceChangeReason) { + panic("panic") + }, + OnBlockEnd: func(err error) { + blockEndCalled = true + }, + } + + blockchain.logger = hooks + blockchain.vmConfig.Tracer = hooks + + blocks := makeBlockChain(blockchain.chainConfig, blockchain.GetBlockByHash(blockchain.CurrentBlock().Hash()), 1, ethash.NewFullFaker(), genDb, 0) + + func() { + defer func() { + if r := recover(); r == nil { + t.Fatalf("Expected panic, but got none, ensure that OnBalanceChange hook is called correctly to generate the panic") + } + }() + + if _, err := blockchain.InsertChain(blocks); err != nil { + t.Fatalf("Failed to insert block: %v", err) + } + }() + + if blockEndCalled { + t.Fatalf("OnBlockEnd should not be called on panic within the tracer") + } +}