diff --git a/core/blockchain.go b/core/blockchain.go index b6605e66c9..a04c712a7c 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -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 if headerByNumber != nil && headerByNumber.Hash() == header.Hash() { 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") } } diff --git a/eth/api_backend.go b/eth/api_backend.go index a48815e0db..08439d9a58 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -51,9 +51,9 @@ func (b *EthAPIBackend) CurrentBlock() *types.Block { 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.blockchain.SetHead(number) + return b.eth.blockchain.SetHead(number) } func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) { diff --git a/eth/backend.go b/eth/backend.go index 6a136182ab..762c2406e3 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -171,7 +171,9 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { // Rewind the chain in case of an incompatible config upgrade. if compat, ok := genesisErr.(*params.ConfigCompatError); ok { 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) } eth.bloomIndexer.Start(eth.blockchain) @@ -315,8 +317,8 @@ func (s *Ethereum) APIs() []rpc.API { }...) } -func (s *Ethereum) ResetWithGenesisBlock(gb *types.Block) { - s.blockchain.ResetWithGenesisBlock(gb) +func (s *Ethereum) ResetWithGenesisBlock(gb *types.Block) error { + return s.blockchain.ResetWithGenesisBlock(gb) } func (s *Ethereum) Etherbase() (eb common.Address, err error) { diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 4d5ef27da1..97b61748b5 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1574,8 +1574,8 @@ func (api *PrivateDebugAPI) ChaindbCompact() error { } // SetHead rewinds the head of the blockchain to a previous block. -func (api *PrivateDebugAPI) SetHead(number hexutil.Uint64) { - api.b.SetHead(uint64(number)) +func (api *PrivateDebugAPI) SetHead(number hexutil.Uint64) error { + return api.b.SetHead(uint64(number)) } // PublicNetAPI offers network related RPC methods diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go index e23ee03b15..425275d45e 100644 --- a/internal/ethapi/backend.go +++ b/internal/ethapi/backend.go @@ -46,7 +46,7 @@ type Backend interface { AccountManager() *accounts.Manager // BlockChain API - SetHead(number uint64) + SetHead(number uint64) error HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Block, error) StateAndHeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*state.StateDB, *types.Header, error) diff --git a/les/api_backend.go b/les/api_backend.go index 7531396235..1456cfd02c 100644 --- a/les/api_backend.go +++ b/les/api_backend.go @@ -51,9 +51,9 @@ func (b *LesApiBackend) CurrentBlock() *types.Block { 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.blockchain.SetHead(number) + return b.eth.blockchain.SetHead(number) } func (b *LesApiBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) { diff --git a/les/backend.go b/les/backend.go index cd99f8f813..c2b4e4eca6 100644 --- a/les/backend.go +++ b/les/backend.go @@ -135,7 +135,9 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) { // Rewind the chain in case of an incompatible config upgrade. if compat, ok := genesisErr.(*params.ConfigCompatError); ok { 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) } @@ -238,8 +240,8 @@ func (s *LightEthereum) APIs() []rpc.API { }...) } -func (s *LightEthereum) ResetWithGenesisBlock(gb *types.Block) { - s.blockchain.ResetWithGenesisBlock(gb) +func (s *LightEthereum) ResetWithGenesisBlock(gb *types.Block) error { + return s.blockchain.ResetWithGenesisBlock(gb) } func (s *LightEthereum) BlockChain() *light.LightChain { return s.blockchain } diff --git a/light/lightchain.go b/light/lightchain.go index 5019622c79..b3e9b5f5f1 100644 --- a/light/lightchain.go +++ b/light/lightchain.go @@ -109,7 +109,9 @@ func NewLightChain(odr OdrBackend, config *params.ChainConfig, engine consensus. for hash := range core.BadHashes { if header := bc.GetHeaderByHash(hash); header != nil { 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") } } @@ -146,7 +148,9 @@ func (lc *LightChain) Odr() OdrBackend { func (lc *LightChain) loadLastState() error { if head := rawdb.ReadHeadHeaderHash(lc.chainDb); head == (common.Hash{}) { // Corrupt or empty database, init from scratch - lc.Reset() + if err := lc.Reset(); err != nil { + return err + } } else { if header := lc.GetHeaderByHash(head); header != nil { 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 // 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() defer lc.chainmu.Unlock() lc.hc.SetHead(head, nil) - lc.loadLastState() + return lc.loadLastState() } // 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. -func (lc *LightChain) Reset() { - lc.ResetWithGenesisBlock(lc.genesisBlock) +func (lc *LightChain) Reset() error { + return lc.ResetWithGenesisBlock(lc.genesisBlock) } // ResetWithGenesisBlock purges the entire blockchain, restoring it to the // 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 - lc.SetHead(0) - + if err := lc.SetHead(0); err != nil { + return err + } lc.chainmu.Lock() defer lc.chainmu.Unlock() @@ -197,6 +202,7 @@ func (lc *LightChain) ResetWithGenesisBlock(genesis *types.Block) { lc.genesisBlock = genesis lc.hc.SetGenesis(lc.genesisBlock.Header()) lc.hc.SetCurrentHeader(lc.genesisBlock.Header()) + return nil } // Accessors