From 08f541c9227d7f16beb08e33b292575f4a18b844 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Tue, 7 Feb 2017 12:33:53 +0100 Subject: [PATCH] core,eth,internal: Added `debug_getBadBlocks()` method When bad blocks are discovered, these are stored within geth. An RPC-endpoint makes them availablewithin the `debug` namespace. This feature makes it easier to discover network forks. ``` --- core/blockchain.go | 25 ++++++++++++++++++++++++- eth/api.go | 7 +++++++ internal/web3ext/web3ext.go | 7 ++++++- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/core/blockchain.go b/core/blockchain.go index 281f28f361..97b2964553 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -60,6 +60,7 @@ const ( // must be bumped when consensus algorithm is changed, this forces the upgradedb // command to be run (forces the blocks to be imported again using the new algorithm) BlockChainVersion = 3 + badBlockLimit = 10 ) // BlockChain represents the canonical chain given a database with a genesis @@ -108,6 +109,8 @@ type BlockChain struct { processor Processor // block processor interface validator Validator // block and state validator interface vmConfig vm.Config + + badBlocks *lru.Cache // Bad block cache } // NewBlockChain returns a fully initialised block chain using information @@ -118,6 +121,7 @@ func NewBlockChain(chainDb ethdb.Database, config *params.ChainConfig, pow pow.P bodyRLPCache, _ := lru.New(bodyCacheLimit) blockCache, _ := lru.New(blockCacheLimit) futureBlocks, _ := lru.New(maxFutureBlocks) + badBlocks,_ := lru.New(badBlockLimit) bc := &BlockChain{ config: config, @@ -130,6 +134,7 @@ func NewBlockChain(chainDb ethdb.Database, config *params.ChainConfig, pow pow.P futureBlocks: futureBlocks, pow: pow, vmConfig: vmConfig, + badBlocks: badBlocks, } bc.SetValidator(NewBlockValidator(config, bc, pow)) bc.SetProcessor(NewStateProcessor(config, bc)) @@ -893,7 +898,6 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) { glog.V(logger.Debug).Infoln("Premature abort during block chain processing") break } - bstart := time.Now() // Wait for block i's nonce to be verified before processing // its state transition. @@ -1241,9 +1245,28 @@ func (self *BlockChain) update() { } } } +// SendTxArgs represents the arguments to sumbit a new transaction into the transaction pool. +type BadBlockArgs struct { + Hash common.Hash `json:"hash"` + Header *types.Header `json:"header"` +} +// BadBlocks returns a list of the last 'bad blocks' that the client has seen on the network +func (bc *BlockChain) BadBlocks() ([] BadBlockArgs, error) { + headers := make([]BadBlockArgs, 0, bc.badBlocks.Len()) + for _, hash := range bc.badBlocks.Keys() { + if hdr, exist := bc.badBlocks.Peek(hash); exist { + headers = append(headers, BadBlockArgs{ hdr.(*types.Header).Hash(), hdr.(*types.Header)}) + } + } + return headers, nil +} +func (bc *BlockChain) addBadBlock(block *types.Block){ + bc.badBlocks.Add(block.Header().Hash(), block.Header()) +} // reportBlock logs a bad block error. func (bc *BlockChain) reportBlock(block *types.Block, receipts types.Receipts, err error) { + bc.addBadBlock(block) if glog.V(logger.Error) { var receiptString string for _, receipt := range receipts { diff --git a/eth/api.go b/eth/api.go index 07df0b79e3..6d855c8e75 100644 --- a/eth/api.go +++ b/eth/api.go @@ -566,3 +566,10 @@ func (api *PrivateDebugAPI) Preimage(ctx context.Context, hash common.Hash) (hex db := core.PreimageTable(api.eth.ChainDb()) return db.Get(hash.Bytes()) } + + +// 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 +func (api *PrivateDebugAPI) GetBadBlocks(ctx context.Context) ([] core.BadBlockArgs, error) { + return api.eth.BlockChain().BadBlocks() +} diff --git a/internal/web3ext/web3ext.go b/internal/web3ext/web3ext.go index edbe45fa34..c0386c3b4c 100644 --- a/internal/web3ext/web3ext.go +++ b/internal/web3ext/web3ext.go @@ -294,7 +294,12 @@ web3._extend({ call: 'debug_preimage', params: 1, inputFormatter: [null] - }) + }), + new web3._extend.Method({ + name: 'getBadBlocks', + call: 'debug_getBadBlocks', + params: 0, + }), ], properties: [] });