Skip to content

Commit f46920b

Browse files
authored
core, eth, internal: improve getBadBlocks to return full block rlp ethereum#16902 (#1595)
1 parent 0ece852 commit f46920b

File tree

3 files changed

+54
-26
lines changed

3 files changed

+54
-26
lines changed

core/blockchain.go

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ type BlockChain struct {
197197
resultProcess *lru.Cache[common.Hash, *ResultProcessBlock] // Cache for processed blocks
198198
calculatingBlock *lru.Cache[common.Hash, *CalculatedBlock] // Cache for processing blocks
199199
downloadingBlock *lru.Cache[common.Hash, struct{}] // Cache for downloading blocks (avoid duplication from fetcher)
200-
badBlocks *lru.Cache[common.Hash, *types.Header] // Bad block cache
200+
badBlocks *lru.Cache[common.Hash, *types.Block] // Bad block cache
201201

202202
// future blocks are blocks added for later processing
203203
futureBlocks *lru.Cache[common.Hash, *types.Block]
@@ -262,7 +262,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
262262
engine: engine,
263263
vmConfig: vmConfig,
264264
logger: vmConfig.Tracer,
265-
badBlocks: lru.NewCache[common.Hash, *types.Header](badBlockLimit),
265+
badBlocks: lru.NewCache[common.Hash, *types.Block](badBlockLimit),
266266
blocksHashCache: lru.NewCache[uint64, []common.Hash](blocksHashCacheLimit),
267267
resultTrade: lru.NewCache[common.Hash, interface{}](tradingstate.OrderCacheLimit),
268268
rejectedOrders: lru.NewCache[common.Hash, interface{}](tradingstate.OrderCacheLimit),
@@ -2574,26 +2574,20 @@ func (bc *BlockChain) futureBlocksLoop() {
25742574
}
25752575
}
25762576

2577-
// BadBlockArgs represents the entries in the list returned when bad blocks are queried.
2578-
type BadBlockArgs struct {
2579-
Hash common.Hash `json:"hash"`
2580-
Header *types.Header `json:"header"`
2581-
}
2582-
25832577
// BadBlocks returns a list of the last 'bad blocks' that the client has seen on the network
2584-
func (bc *BlockChain) BadBlocks() ([]BadBlockArgs, error) {
2585-
headers := make([]BadBlockArgs, 0, bc.badBlocks.Len())
2578+
func (bc *BlockChain) BadBlocks() []*types.Block {
2579+
blocks := make([]*types.Block, 0, bc.badBlocks.Len())
25862580
for _, hash := range bc.badBlocks.Keys() {
2587-
if header, exist := bc.badBlocks.Peek(hash); exist {
2588-
headers = append(headers, BadBlockArgs{header.Hash(), header})
2581+
if blk, exist := bc.badBlocks.Peek(hash); exist {
2582+
blocks = append(blocks, blk)
25892583
}
25902584
}
2591-
return headers, nil
2585+
return blocks
25922586
}
25932587

25942588
// addBadBlock adds a bad block to the bad-block LRU cache
25952589
func (bc *BlockChain) addBadBlock(block *types.Block) {
2596-
bc.badBlocks.Add(block.Header().Hash(), block.Header())
2590+
bc.badBlocks.Add(block.Hash(), block)
25972591
}
25982592

25992593
// reportBlock logs a bad block error.

eth/api.go

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
3333
"github.com/XinFinOrg/XDPoSChain/core/state"
3434
"github.com/XinFinOrg/XDPoSChain/core/types"
35+
"github.com/XinFinOrg/XDPoSChain/internal/ethapi"
3536
"github.com/XinFinOrg/XDPoSChain/log"
3637
"github.com/XinFinOrg/XDPoSChain/miner"
3738
"github.com/XinFinOrg/XDPoSChain/params"
@@ -325,10 +326,34 @@ func (api *DebugAPI) Preimage(ctx context.Context, hash common.Hash) (hexutil.By
325326
return nil, errors.New("unknown preimage")
326327
}
327328

329+
// BadBlockArgs represents the entries in the list returned when bad blocks are queried.
330+
type BadBlockArgs struct {
331+
Hash common.Hash `json:"hash"`
332+
Block map[string]interface{} `json:"block"`
333+
RLP string `json:"rlp"`
334+
}
335+
328336
// GetBadBLocks returns a list of the last 'bad blocks' that the client has seen on the network
329337
// and returns them as a JSON list of block-hashes
330-
func (api *DebugAPI) GetBadBlocks(ctx context.Context) ([]core.BadBlockArgs, error) {
331-
return api.eth.BlockChain().BadBlocks()
338+
func (api *DebugAPI) GetBadBlocks(ctx context.Context) ([]*BadBlockArgs, error) {
339+
blocks := api.eth.BlockChain().BadBlocks()
340+
results := make([]*BadBlockArgs, len(blocks))
341+
342+
var err error
343+
for i, block := range blocks {
344+
results[i] = &BadBlockArgs{
345+
Hash: block.Hash(),
346+
}
347+
if rlpBytes, err := rlp.EncodeToBytes(block); err != nil {
348+
results[i].RLP = err.Error() // Hacky, but hey, it works
349+
} else {
350+
results[i].RLP = fmt.Sprintf("0x%x", rlpBytes)
351+
}
352+
if results[i].Block, err = ethapi.RPCMarshalBlock(block, true, true); err != nil {
353+
results[i].Block = map[string]interface{}{"error": err.Error()}
354+
}
355+
}
356+
return results, nil
332357
}
333358

334359
// AccountRangeMaxResults is the maximum number of results to be returned per call

internal/ethapi/api.go

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ func (s *BlockChainAPI) GetTransactionAndReceiptProof(ctx context.Context, hash
382382
func (s *BlockChainAPI) GetBlockByNumber(ctx context.Context, blockNr rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) {
383383
block, err := s.b.BlockByNumber(ctx, blockNr)
384384
if block != nil {
385-
response, err := s.rpcOutputBlock(block, true, fullTx, ctx)
385+
response, err := s.rpcOutputBlock(block, true, fullTx)
386386
if err == nil && blockNr == rpc.PendingBlockNumber {
387387
// Pending blocks need to nil out a few fields
388388
for _, field := range []string{"hash", "nonce", "miner"} {
@@ -399,7 +399,7 @@ func (s *BlockChainAPI) GetBlockByNumber(ctx context.Context, blockNr rpc.BlockN
399399
func (s *BlockChainAPI) GetBlockByHash(ctx context.Context, blockHash common.Hash, fullTx bool) (map[string]interface{}, error) {
400400
block, err := s.b.GetBlock(ctx, blockHash)
401401
if block != nil {
402-
return s.rpcOutputBlock(block, true, fullTx, ctx)
402+
return s.rpcOutputBlock(block, true, fullTx)
403403
}
404404
return nil, err
405405
}
@@ -415,7 +415,7 @@ func (s *BlockChainAPI) GetUncleByBlockNumberAndIndex(ctx context.Context, block
415415
return nil, nil
416416
}
417417
block = types.NewBlockWithHeader(uncles[index])
418-
return s.rpcOutputBlock(block, false, false, ctx)
418+
return s.rpcOutputBlock(block, false, false)
419419
}
420420
return nil, err
421421
}
@@ -432,7 +432,7 @@ func (s *BlockChainAPI) GetUncleByBlockHashAndIndex(ctx context.Context, blockHa
432432
return nil, nil
433433
}
434434
block = types.NewBlockWithHeader(uncles[index])
435-
return s.rpcOutputBlock(block, false, false, ctx)
435+
return s.rpcOutputBlock(block, false, false)
436436
}
437437
return nil, err
438438
}
@@ -1411,29 +1411,26 @@ func RPCMarshalHeader(head *types.Header) map[string]interface{} {
14111411
return result
14121412
}
14131413

1414-
// rpcOutputBlock converts the given block to the RPC output which depends on fullTx. If inclTx is true transactions are
1414+
// RPCMarshalBlock converts the given block to the RPC output which depends on fullTx. If inclTx is true transactions are
14151415
// returned. When fullTx is true the returned block contains full transaction details, otherwise it will only contain
14161416
// transaction hashes.
1417-
func (s *BlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx bool, ctx context.Context) (map[string]interface{}, error) {
1417+
func RPCMarshalBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) {
14181418
fields := RPCMarshalHeader(b.Header())
14191419
fields["size"] = hexutil.Uint64(b.Size())
1420-
fields["totalDifficulty"] = (*hexutil.Big)(s.b.GetTd(context.Background(), b.Hash()))
14211420

14221421
if inclTx {
14231422
formatTx := func(tx *types.Transaction) (interface{}, error) {
14241423
return tx.Hash(), nil
14251424
}
1426-
14271425
if fullTx {
14281426
formatTx = func(tx *types.Transaction) (interface{}, error) {
14291427
return newRPCTransactionFromBlockHash(b, tx.Hash()), nil
14301428
}
14311429
}
1432-
14331430
txs := b.Transactions()
14341431
transactions := make([]interface{}, len(txs))
14351432
var err error
1436-
for i, tx := range b.Transactions() {
1433+
for i, tx := range txs {
14371434
if transactions[i], err = formatTx(tx); err != nil {
14381435
return nil, err
14391436
}
@@ -1447,9 +1444,21 @@ func (s *BlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx bool,
14471444
uncleHashes[i] = uncle.Hash()
14481445
}
14491446
fields["uncles"] = uncleHashes
1447+
14501448
return fields, nil
14511449
}
14521450

1451+
// rpcOutputBlock uses the generalized output filler, then adds the total difficulty field, which requires
1452+
// a `BlockChainAPI`.
1453+
func (s *BlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) {
1454+
fields, err := RPCMarshalBlock(b, inclTx, fullTx)
1455+
if err != nil {
1456+
return nil, err
1457+
}
1458+
fields["totalDifficulty"] = (*hexutil.Big)(s.b.GetTd(context.Background(), b.Hash()))
1459+
return fields, err
1460+
}
1461+
14531462
// findNearestSignedBlock finds the nearest checkpoint from input block
14541463
func (s *BlockChainAPI) findNearestSignedBlock(ctx context.Context, b *types.Block) *types.Block {
14551464
if b.Number().Int64() <= 0 {

0 commit comments

Comments
 (0)