From e34bbe10c6735f410ed220125c26d0c9dd2fd58a Mon Sep 17 00:00:00 2001 From: Daniel Liu <139250065@qq.com> Date: Sat, 15 Nov 2025 19:21:21 +0800 Subject: [PATCH] core: persist bad blocks #21827 #27489 (#1771) --- core/rawdb/accessors_chain.go | 23 ++++++++--------------- core/rawdb/accessors_chain_test.go | 14 +++++++------- eth/api_debug.go | 2 +- eth/tracers/api.go | 12 ++++++++++++ internal/web3ext/web3ext.go | 6 ++++++ 5 files changed, 34 insertions(+), 23 deletions(-) diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go index 0893a6f1d7..4a520e5f82 100644 --- a/core/rawdb/accessors_chain.go +++ b/core/rawdb/accessors_chain.go @@ -21,7 +21,7 @@ import ( "encoding/binary" "errors" "math/big" - "sort" + "slices" "github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/core/types" @@ -608,23 +608,13 @@ type badBlock struct { Body *types.Body } -// badBlockList implements the sort interface to allow sorting a list of -// bad blocks by their number in the reverse order. -type badBlockList []*badBlock - -func (s badBlockList) Len() int { return len(s) } -func (s badBlockList) Less(i, j int) bool { - return s[i].Header.Number.Uint64() < s[j].Header.Number.Uint64() -} -func (s badBlockList) Swap(i, j int) { s[i], s[j] = s[j], s[i] } - // ReadBadBlock retrieves the bad block with the corresponding block hash. func ReadBadBlock(db ethdb.Reader, hash common.Hash) *types.Block { blob, err := db.Get(badBlockKey) if err != nil { return nil } - var badBlocks badBlockList + var badBlocks []*badBlock if err := rlp.DecodeBytes(blob, &badBlocks); err != nil { return nil } @@ -647,7 +637,7 @@ func ReadAllBadBlocks(db ethdb.Reader) []*types.Block { if err != nil { return nil } - var badBlocks badBlockList + var badBlocks []*badBlock if err := rlp.DecodeBytes(blob, &badBlocks); err != nil { return nil } @@ -669,7 +659,7 @@ func WriteBadBlock(db ethdb.KeyValueStore, block *types.Block) { if err != nil { log.Warn("Failed to load old bad blocks", "error", err) } - var badBlocks badBlockList + var badBlocks []*badBlock if len(blob) > 0 { if err := rlp.DecodeBytes(blob, &badBlocks); err != nil { log.Crit("Failed to decode old bad blocks", "error", err) @@ -685,7 +675,10 @@ func WriteBadBlock(db ethdb.KeyValueStore, block *types.Block) { Header: block.Header(), Body: block.Body(), }) - sort.Sort(sort.Reverse(badBlocks)) + slices.SortFunc(badBlocks, func(a, b *badBlock) int { + // Note: sorting in descending number order. + return -a.Header.Number.Cmp(b.Header.Number) + }) if len(badBlocks) > badBlockToKeep { badBlocks = badBlocks[:badBlockToKeep] } diff --git a/core/rawdb/accessors_chain_test.go b/core/rawdb/accessors_chain_test.go index 82f839ccd6..e886a94148 100644 --- a/core/rawdb/accessors_chain_test.go +++ b/core/rawdb/accessors_chain_test.go @@ -221,8 +221,8 @@ func TestBadBlockStorage(t *testing.T) { Number: big.NewInt(1), Extra: []byte("bad block"), UncleHash: types.EmptyUncleHash, - TxHash: types.EmptyRootHash, - ReceiptHash: types.EmptyRootHash, + TxHash: types.EmptyTxsHash, + ReceiptHash: types.EmptyReceiptsHash, }) if entry := ReadBadBlock(db, block.Hash()); entry != nil { t.Fatalf("Non existent block returned: %v", entry) @@ -239,8 +239,8 @@ func TestBadBlockStorage(t *testing.T) { Number: big.NewInt(2), Extra: []byte("bad block two"), UncleHash: types.EmptyUncleHash, - TxHash: types.EmptyRootHash, - ReceiptHash: types.EmptyRootHash, + TxHash: types.EmptyTxsHash, + ReceiptHash: types.EmptyReceiptsHash, }) WriteBadBlock(db, blockTwo) @@ -258,8 +258,8 @@ func TestBadBlockStorage(t *testing.T) { Number: big.NewInt(int64(n)), Extra: []byte("bad block"), UncleHash: types.EmptyUncleHash, - TxHash: types.EmptyRootHash, - ReceiptHash: types.EmptyRootHash, + TxHash: types.EmptyTxsHash, + ReceiptHash: types.EmptyReceiptsHash, }) WriteBadBlock(db, block) } @@ -269,7 +269,7 @@ func TestBadBlockStorage(t *testing.T) { } for i := 0; i < len(badBlocks)-1; i++ { if badBlocks[i].NumberU64() < badBlocks[i+1].NumberU64() { - t.Fatalf("The bad blocks are not sorted #[%d](%d) < #[%d](%d)", i, i+1, badBlocks[i].NumberU64(), badBlocks[i+1].NumberU64()) + t.Fatalf("The bad blocks are not sorted #[%d](%d) < #[%d](%d)", i, badBlocks[i].NumberU64(), i+1, badBlocks[i+1].NumberU64()) } } diff --git a/eth/api_debug.go b/eth/api_debug.go index 45edce5a54..103a158389 100644 --- a/eth/api_debug.go +++ b/eth/api_debug.go @@ -87,7 +87,7 @@ type BadBlockArgs struct { } // GetBadBlocks returns a list of the last 'bad blocks' that the client has seen on the network -// and returns them as a JSON list of block-hashes +// and returns them as a JSON list of block hashes. func (api *DebugAPI) GetBadBlocks(ctx context.Context) ([]*BadBlockArgs, error) { var ( blocks = rawdb.ReadAllBadBlocks(api.eth.chainDb) diff --git a/eth/tracers/api.go b/eth/tracers/api.go index 082e39206f..2f6d14b1bb 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -33,6 +33,7 @@ import ( "github.com/XinFinOrg/XDPoSChain/common/hexutil" "github.com/XinFinOrg/XDPoSChain/consensus" "github.com/XinFinOrg/XDPoSChain/core" + "github.com/XinFinOrg/XDPoSChain/core/rawdb" "github.com/XinFinOrg/XDPoSChain/core/state" "github.com/XinFinOrg/XDPoSChain/core/types" "github.com/XinFinOrg/XDPoSChain/core/vm" @@ -460,6 +461,17 @@ func (api *API) TraceBlock(ctx context.Context, blob hexutil.Bytes, config *Trac return api.traceBlock(ctx, block, config) } +// TraceBadBlock returns the structured logs created during the execution of +// EVM against a block pulled from the pool of bad ones and returns them as a JSON +// object. +func (api *API) TraceBadBlock(ctx context.Context, hash common.Hash, config *TraceConfig) ([]*txTraceResult, error) { + block := rawdb.ReadBadBlock(api.backend.ChainDb(), hash) + if block == nil { + return nil, fmt.Errorf("bad block %#x not found", hash) + } + return api.traceBlock(ctx, block, config) +} + // TraceBlockFromFile returns the structured logs created during the execution of // EVM and returns them as a JSON object. func (api *API) TraceBlockFromFile(ctx context.Context, file string, config *TraceConfig) ([]*txTraceResult, error) { diff --git a/internal/web3ext/web3ext.go b/internal/web3ext/web3ext.go index 519f6858d9..a9bc9b50af 100644 --- a/internal/web3ext/web3ext.go +++ b/internal/web3ext/web3ext.go @@ -418,6 +418,12 @@ web3._extend({ params: 2, inputFormatter: [null, null] }), + new web3._extend.Method({ + name: 'traceBadBlock', + call: 'debug_traceBadBlock', + params: 1, + inputFormatter: [null] + }), new web3._extend.Method({ name: 'intermediateRoots', call: 'debug_intermediateRoots',