core, eth, internal: Added debug_getBadBlocks()
method (#3654)
* 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, api: go format + docs * core/blockchain: Documentation, fix minor nitpick * core: fix failing blockchain test
This commit is contained in:
parent
4ece9c6cb0
commit
72dcd3c58b
@ -60,6 +60,7 @@ const (
|
|||||||
// must be bumped when consensus algorithm is changed, this forces the upgradedb
|
// 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)
|
// command to be run (forces the blocks to be imported again using the new algorithm)
|
||||||
BlockChainVersion = 3
|
BlockChainVersion = 3
|
||||||
|
badBlockLimit = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
// BlockChain represents the canonical chain given a database with a genesis
|
// BlockChain represents the canonical chain given a database with a genesis
|
||||||
@ -108,6 +109,8 @@ type BlockChain struct {
|
|||||||
processor Processor // block processor interface
|
processor Processor // block processor interface
|
||||||
validator Validator // block and state validator interface
|
validator Validator // block and state validator interface
|
||||||
vmConfig vm.Config
|
vmConfig vm.Config
|
||||||
|
|
||||||
|
badBlocks *lru.Cache // Bad block cache
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBlockChain returns a fully initialised block chain using information
|
// 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)
|
bodyRLPCache, _ := lru.New(bodyCacheLimit)
|
||||||
blockCache, _ := lru.New(blockCacheLimit)
|
blockCache, _ := lru.New(blockCacheLimit)
|
||||||
futureBlocks, _ := lru.New(maxFutureBlocks)
|
futureBlocks, _ := lru.New(maxFutureBlocks)
|
||||||
|
badBlocks, _ := lru.New(badBlockLimit)
|
||||||
|
|
||||||
bc := &BlockChain{
|
bc := &BlockChain{
|
||||||
config: config,
|
config: config,
|
||||||
@ -130,6 +134,7 @@ func NewBlockChain(chainDb ethdb.Database, config *params.ChainConfig, pow pow.P
|
|||||||
futureBlocks: futureBlocks,
|
futureBlocks: futureBlocks,
|
||||||
pow: pow,
|
pow: pow,
|
||||||
vmConfig: vmConfig,
|
vmConfig: vmConfig,
|
||||||
|
badBlocks: badBlocks,
|
||||||
}
|
}
|
||||||
bc.SetValidator(NewBlockValidator(config, bc, pow))
|
bc.SetValidator(NewBlockValidator(config, bc, pow))
|
||||||
bc.SetProcessor(NewStateProcessor(config, bc))
|
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")
|
glog.V(logger.Debug).Infoln("Premature abort during block chain processing")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
bstart := time.Now()
|
bstart := time.Now()
|
||||||
// Wait for block i's nonce to be verified before processing
|
// Wait for block i's nonce to be verified before processing
|
||||||
// its state transition.
|
// its state transition.
|
||||||
@ -1242,8 +1246,32 @@ func (self *BlockChain) update() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BadBlockArgs represents the entries in the list returned when bad blocks are queried.
|
||||||
|
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 {
|
||||||
|
header := hdr.(*types.Header)
|
||||||
|
headers = append(headers, BadBlockArgs{header.Hash(), header})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return headers, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// addBadBlock adds a bad block to the bad-block LRU cache
|
||||||
|
func (bc *BlockChain) addBadBlock(block *types.Block) {
|
||||||
|
bc.badBlocks.Add(block.Header().Hash(), block.Header())
|
||||||
|
}
|
||||||
|
|
||||||
// reportBlock logs a bad block error.
|
// reportBlock logs a bad block error.
|
||||||
func (bc *BlockChain) reportBlock(block *types.Block, receipts types.Receipts, err error) {
|
func (bc *BlockChain) reportBlock(block *types.Block, receipts types.Receipts, err error) {
|
||||||
|
bc.addBadBlock(block)
|
||||||
if glog.V(logger.Error) {
|
if glog.V(logger.Error) {
|
||||||
var receiptString string
|
var receiptString string
|
||||||
for _, receipt := range receipts {
|
for _, receipt := range receipts {
|
||||||
|
@ -485,6 +485,7 @@ func chm(genesis *types.Block, db ethdb.Database) *BlockChain {
|
|||||||
bc.bodyRLPCache, _ = lru.New(100)
|
bc.bodyRLPCache, _ = lru.New(100)
|
||||||
bc.blockCache, _ = lru.New(100)
|
bc.blockCache, _ = lru.New(100)
|
||||||
bc.futureBlocks, _ = lru.New(100)
|
bc.futureBlocks, _ = lru.New(100)
|
||||||
|
bc.badBlocks, _ = lru.New(10)
|
||||||
bc.SetValidator(bproc{})
|
bc.SetValidator(bproc{})
|
||||||
bc.SetProcessor(bproc{})
|
bc.SetProcessor(bproc{})
|
||||||
bc.ResetWithGenesisBlock(genesis)
|
bc.ResetWithGenesisBlock(genesis)
|
||||||
|
@ -566,3 +566,9 @@ func (api *PrivateDebugAPI) Preimage(ctx context.Context, hash common.Hash) (hex
|
|||||||
db := core.PreimageTable(api.eth.ChainDb())
|
db := core.PreimageTable(api.eth.ChainDb())
|
||||||
return db.Get(hash.Bytes())
|
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()
|
||||||
|
}
|
||||||
|
@ -294,7 +294,12 @@ web3._extend({
|
|||||||
call: 'debug_preimage',
|
call: 'debug_preimage',
|
||||||
params: 1,
|
params: 1,
|
||||||
inputFormatter: [null]
|
inputFormatter: [null]
|
||||||
})
|
}),
|
||||||
|
new web3._extend.Method({
|
||||||
|
name: 'getBadBlocks',
|
||||||
|
call: 'debug_getBadBlocks',
|
||||||
|
params: 0,
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
properties: []
|
properties: []
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user