diff --git a/cmd/geth/main.go b/cmd/geth/main.go index c46343a606..a7d3a73efb 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -39,6 +39,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/logger" + "github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/rpc/codec" "github.com/ethereum/go-ethereum/rpc/comms" @@ -68,6 +69,15 @@ func init() { app.Action = run app.HideVersion = true // we have a command to print the version app.Commands = []cli.Command{ + { + Action: blockRecovery, + Name: "recover", + Usage: "attempts to recover a corrupted database by setting a new block head by number", + Description: ` +The recover commands will attempt to read out the last +block based on that. +`, + }, blocktestCommand, importCommand, exportCommand, @@ -439,6 +449,20 @@ func unlockAccount(ctx *cli.Context, am *accounts.Manager, account string) (pass return } +func blockRecovery(ctx *cli.Context) { + num := ctx.Args().First() + if len(ctx.Args()) < 1 { + glog.Fatal("recover requires block number") + } + + cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx) + ethereum, err := eth.New(cfg) + if err != nil { + utils.Fatalf("%v", err) + } + ethereum.ChainManager().Recover(common.String2Big(num).Uint64()) +} + func startEth(ctx *cli.Context, eth *eth.Ethereum) { // Start Ethereum itself diff --git a/core/chain_manager.go b/core/chain_manager.go index c89aae3f08..247b5fdb31 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -238,6 +238,16 @@ func (self *ChainManager) setTransState(statedb *state.StateDB) { self.transState = statedb } +func (bc *ChainManager) Recover(num uint64) { + block := bc.GetBlockByNumber(num) + if block != nil { + bc.insert(block) + glog.Infof("Recovery succesful. New HEAD %x\n", block.Hash()) + } else { + glog.Fatalln("Recovery failed") + } +} + func (bc *ChainManager) recover() bool { data, _ := bc.blockDb.Get([]byte("checkpoint")) if len(data) != 0 { @@ -261,8 +271,6 @@ func (bc *ChainManager) setLastState() { if len(data) != 0 { block := bc.GetBlock(common.BytesToHash(data)) if block != nil { - bc.blockDb.Put([]byte("checkpoint"), block.Hash().Bytes()) - bc.currentBlock = block bc.lastBlockHash = block.Hash() } else {