core, eth, internal, les, light: consistent error handling

This commit is contained in:
htkao 2019-02-19 21:40:53 -08:00
parent d3ccedc767
commit c4e7c83d38
8 changed files with 35 additions and 23 deletions

View file

@ -195,7 +195,9 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
// make sure the headerByNumber (if present) is in our current canonical chain // make sure the headerByNumber (if present) is in our current canonical chain
if headerByNumber != nil && headerByNumber.Hash() == header.Hash() { if headerByNumber != nil && headerByNumber.Hash() == header.Hash() {
log.Error("Found bad hash, rewinding chain", "number", header.Number, "hash", header.ParentHash) log.Error("Found bad hash, rewinding chain", "number", header.Number, "hash", header.ParentHash)
bc.SetHead(header.Number.Uint64() - 1) if err := bc.SetHead(header.Number.Uint64() - 1); err != nil {
return nil, err
}
log.Error("Chain rewind was successful, resuming normal operation") log.Error("Chain rewind was successful, resuming normal operation")
} }
} }

View file

@ -51,9 +51,9 @@ func (b *EthAPIBackend) CurrentBlock() *types.Block {
return b.eth.blockchain.CurrentBlock() return b.eth.blockchain.CurrentBlock()
} }
func (b *EthAPIBackend) SetHead(number uint64) { func (b *EthAPIBackend) SetHead(number uint64) error {
b.eth.protocolManager.downloader.Cancel() b.eth.protocolManager.downloader.Cancel()
b.eth.blockchain.SetHead(number) return b.eth.blockchain.SetHead(number)
} }
func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) { func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) {

View file

@ -171,7 +171,9 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
// Rewind the chain in case of an incompatible config upgrade. // Rewind the chain in case of an incompatible config upgrade.
if compat, ok := genesisErr.(*params.ConfigCompatError); ok { if compat, ok := genesisErr.(*params.ConfigCompatError); ok {
log.Warn("Rewinding chain to upgrade configuration", "err", compat) log.Warn("Rewinding chain to upgrade configuration", "err", compat)
eth.blockchain.SetHead(compat.RewindTo) if err := eth.blockchain.SetHead(compat.RewindTo); err != nil {
return nil, err
}
rawdb.WriteChainConfig(chainDb, genesisHash, chainConfig) rawdb.WriteChainConfig(chainDb, genesisHash, chainConfig)
} }
eth.bloomIndexer.Start(eth.blockchain) eth.bloomIndexer.Start(eth.blockchain)
@ -315,8 +317,8 @@ func (s *Ethereum) APIs() []rpc.API {
}...) }...)
} }
func (s *Ethereum) ResetWithGenesisBlock(gb *types.Block) { func (s *Ethereum) ResetWithGenesisBlock(gb *types.Block) error {
s.blockchain.ResetWithGenesisBlock(gb) return s.blockchain.ResetWithGenesisBlock(gb)
} }
func (s *Ethereum) Etherbase() (eb common.Address, err error) { func (s *Ethereum) Etherbase() (eb common.Address, err error) {

View file

@ -1574,8 +1574,8 @@ func (api *PrivateDebugAPI) ChaindbCompact() error {
} }
// SetHead rewinds the head of the blockchain to a previous block. // SetHead rewinds the head of the blockchain to a previous block.
func (api *PrivateDebugAPI) SetHead(number hexutil.Uint64) { func (api *PrivateDebugAPI) SetHead(number hexutil.Uint64) error {
api.b.SetHead(uint64(number)) return api.b.SetHead(uint64(number))
} }
// PublicNetAPI offers network related RPC methods // PublicNetAPI offers network related RPC methods

View file

@ -46,7 +46,7 @@ type Backend interface {
AccountManager() *accounts.Manager AccountManager() *accounts.Manager
// BlockChain API // BlockChain API
SetHead(number uint64) SetHead(number uint64) error
HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error)
BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Block, error) BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Block, error)
StateAndHeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*state.StateDB, *types.Header, error) StateAndHeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*state.StateDB, *types.Header, error)

View file

@ -51,9 +51,9 @@ func (b *LesApiBackend) CurrentBlock() *types.Block {
return types.NewBlockWithHeader(b.eth.BlockChain().CurrentHeader()) return types.NewBlockWithHeader(b.eth.BlockChain().CurrentHeader())
} }
func (b *LesApiBackend) SetHead(number uint64) { func (b *LesApiBackend) SetHead(number uint64) error {
b.eth.protocolManager.downloader.Cancel() b.eth.protocolManager.downloader.Cancel()
b.eth.blockchain.SetHead(number) return b.eth.blockchain.SetHead(number)
} }
func (b *LesApiBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) { func (b *LesApiBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) {

View file

@ -135,7 +135,9 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
// Rewind the chain in case of an incompatible config upgrade. // Rewind the chain in case of an incompatible config upgrade.
if compat, ok := genesisErr.(*params.ConfigCompatError); ok { if compat, ok := genesisErr.(*params.ConfigCompatError); ok {
log.Warn("Rewinding chain to upgrade configuration", "err", compat) log.Warn("Rewinding chain to upgrade configuration", "err", compat)
leth.blockchain.SetHead(compat.RewindTo) if err := leth.blockchain.SetHead(compat.RewindTo); err != nil {
return nil, err
}
rawdb.WriteChainConfig(chainDb, genesisHash, chainConfig) rawdb.WriteChainConfig(chainDb, genesisHash, chainConfig)
} }
@ -238,8 +240,8 @@ func (s *LightEthereum) APIs() []rpc.API {
}...) }...)
} }
func (s *LightEthereum) ResetWithGenesisBlock(gb *types.Block) { func (s *LightEthereum) ResetWithGenesisBlock(gb *types.Block) error {
s.blockchain.ResetWithGenesisBlock(gb) return s.blockchain.ResetWithGenesisBlock(gb)
} }
func (s *LightEthereum) BlockChain() *light.LightChain { return s.blockchain } func (s *LightEthereum) BlockChain() *light.LightChain { return s.blockchain }

View file

@ -109,7 +109,9 @@ func NewLightChain(odr OdrBackend, config *params.ChainConfig, engine consensus.
for hash := range core.BadHashes { for hash := range core.BadHashes {
if header := bc.GetHeaderByHash(hash); header != nil { if header := bc.GetHeaderByHash(hash); header != nil {
log.Error("Found bad hash, rewinding chain", "number", header.Number, "hash", header.ParentHash) log.Error("Found bad hash, rewinding chain", "number", header.Number, "hash", header.ParentHash)
bc.SetHead(header.Number.Uint64() - 1) if err := bc.SetHead(header.Number.Uint64() - 1); err != nil {
return nil, err
}
log.Error("Chain rewind was successful, resuming normal operation") log.Error("Chain rewind was successful, resuming normal operation")
} }
} }
@ -146,7 +148,9 @@ func (lc *LightChain) Odr() OdrBackend {
func (lc *LightChain) loadLastState() error { func (lc *LightChain) loadLastState() error {
if head := rawdb.ReadHeadHeaderHash(lc.chainDb); head == (common.Hash{}) { if head := rawdb.ReadHeadHeaderHash(lc.chainDb); head == (common.Hash{}) {
// Corrupt or empty database, init from scratch // Corrupt or empty database, init from scratch
lc.Reset() if err := lc.Reset(); err != nil {
return err
}
} else { } else {
if header := lc.GetHeaderByHash(head); header != nil { if header := lc.GetHeaderByHash(head); header != nil {
lc.hc.SetCurrentHeader(header) lc.hc.SetCurrentHeader(header)
@ -163,12 +167,12 @@ func (lc *LightChain) loadLastState() error {
// SetHead rewinds the local chain to a new head. Everything above the new // SetHead rewinds the local chain to a new head. Everything above the new
// head will be deleted and the new one set. // head will be deleted and the new one set.
func (lc *LightChain) SetHead(head uint64) { func (lc *LightChain) SetHead(head uint64) error {
lc.chainmu.Lock() lc.chainmu.Lock()
defer lc.chainmu.Unlock() defer lc.chainmu.Unlock()
lc.hc.SetHead(head, nil) lc.hc.SetHead(head, nil)
lc.loadLastState() return lc.loadLastState()
} }
// GasLimit returns the gas limit of the current HEAD block. // GasLimit returns the gas limit of the current HEAD block.
@ -177,16 +181,17 @@ func (lc *LightChain) GasLimit() uint64 {
} }
// Reset purges the entire blockchain, restoring it to its genesis state. // Reset purges the entire blockchain, restoring it to its genesis state.
func (lc *LightChain) Reset() { func (lc *LightChain) Reset() error {
lc.ResetWithGenesisBlock(lc.genesisBlock) return lc.ResetWithGenesisBlock(lc.genesisBlock)
} }
// ResetWithGenesisBlock purges the entire blockchain, restoring it to the // ResetWithGenesisBlock purges the entire blockchain, restoring it to the
// specified genesis state. // specified genesis state.
func (lc *LightChain) ResetWithGenesisBlock(genesis *types.Block) { func (lc *LightChain) ResetWithGenesisBlock(genesis *types.Block) error {
// Dump the entire block chain and purge the caches // Dump the entire block chain and purge the caches
lc.SetHead(0) if err := lc.SetHead(0); err != nil {
return err
}
lc.chainmu.Lock() lc.chainmu.Lock()
defer lc.chainmu.Unlock() defer lc.chainmu.Unlock()
@ -197,6 +202,7 @@ func (lc *LightChain) ResetWithGenesisBlock(genesis *types.Block) {
lc.genesisBlock = genesis lc.genesisBlock = genesis
lc.hc.SetGenesis(lc.genesisBlock.Header()) lc.hc.SetGenesis(lc.genesisBlock.Header())
lc.hc.SetCurrentHeader(lc.genesisBlock.Header()) lc.hc.SetCurrentHeader(lc.genesisBlock.Header())
return nil
} }
// Accessors // Accessors