--- /dev/null
+package commands
+
+import (
+ "strconv"
+
+ log "github.com/sirupsen/logrus"
+ "github.com/spf13/cobra"
+
+ "github.com/bytom/vapor/node"
+)
+
+var rollbackCmd = &cobra.Command{
+ Use: "rollback",
+ Short: "Rollback chain to target height!",
+ Args: cobra.ExactArgs(1),
+ Run: func(cmd *cobra.Command, args []string) {
+ setLogLevel(config.LogLevel)
+
+ height, err := strconv.ParseInt(args[0], 10, 64)
+ if err != nil {
+ log.WithFields(log.Fields{"module": logModule, "err": err}).Fatal("failed to parse int")
+ }
+
+ if height < 0 {
+ log.WithFields(log.Fields{"module": logModule}).Fatal("height should >= 0")
+ }
+
+ if err = node.Rollback(config, uint64(height)); err != nil {
+ log.WithFields(log.Fields{"module": logModule, "err": err}).Fatal("failed to rollback")
+ }
+
+ log.WithFields(log.Fields{"module": logModule}).Infof("success to rollback height of %d", height)
+ },
+}
+
+func init() {
+ RootCmd.AddCommand(rollbackCmd)
+}
// NewNode create bytom node
func NewNode(config *cfg.Config) *Node {
- if err := lockDataDirectory(config); err != nil {
- cmn.Exit("Error: " + err.Error())
- }
-
- if err := cfg.LoadFederationFile(config.FederationFile(), config); err != nil {
- cmn.Exit(cmn.Fmt("Failed to load federated information:[%s]", err.Error()))
- }
+ initNodeConfig(config)
if err := vaporLog.InitLogFile(config); err != nil {
log.WithField("err", err).Fatalln("InitLogFile failed")
"fed_controlprogram": hex.EncodeToString(cfg.FederationWScript(config)),
}).Info()
- if err := consensus.InitActiveNetParams(config.ChainID); err != nil {
- log.Fatalf("Failed to init ActiveNetParams:[%s]", err.Error())
- }
-
- initCommonConfig(config)
-
// Get store
if config.DBBackend != "memdb" && config.DBBackend != "leveldb" {
cmn.Exit(cmn.Fmt("Param db_backend [%v] is invalid, use leveldb or memdb", config.DBBackend))
log.WithFields(log.Fields{"module": logModule, "error": err}).Error("init NewWallet")
}
+ if err = wallet.Run(); err != nil {
+ log.WithFields(log.Fields{"module": logModule, "error": err}).Error("init NewWallet work running thread")
+ }
+
// trigger rescan wallet
if config.Wallet.Rescan {
wallet.RescanBlocks()
return node
}
+// Rollback rollback chain from one height to targetHeight
+func Rollback(config *cfg.Config, targetHeight uint64) error {
+ if err := initNodeConfig(config); err != nil {
+ return err
+ }
+
+ // Get store
+ if config.DBBackend != "leveldb" {
+ return errors.New("Param db_backend is invalid, use leveldb")
+ }
+
+ coreDB := dbm.NewDB("core", config.DBBackend, config.DBDir())
+ store := database.NewStore(coreDB)
+
+ dispatcher := event.NewDispatcher()
+ movCore := mov.NewMovCore(config.DBBackend, config.DBDir(), consensus.ActiveNetParams.MovStartHeight)
+ txPool := protocol.NewTxPool(store, []protocol.DustFilterer{movCore}, dispatcher)
+ chain, err := protocol.NewChain(store, txPool, []protocol.Protocoler{movCore}, dispatcher)
+ if err != nil {
+ return err
+ }
+
+ hsm, err := pseudohsm.New(config.KeysDir())
+ if err != nil {
+ return err
+ }
+
+ walletDB := dbm.NewDB("wallet", config.DBBackend, config.DBDir())
+ walletStore := database.NewWalletStore(walletDB)
+ accountStore := database.NewAccountStore(walletDB)
+ accounts := account.NewManager(accountStore, chain)
+ assets := asset.NewRegistry(walletDB, chain)
+ wallet, err := w.NewWallet(walletStore, accounts, assets, hsm, chain, dispatcher, config.Wallet.TxIndex)
+ if err != nil {
+ return err
+ }
+
+ if err := wallet.Rollback(targetHeight); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func initNodeConfig(config *cfg.Config) error {
+ if err := lockDataDirectory(config); err != nil {
+ log.WithField("err", err).Info("Error: " + err.Error())
+ return err
+ }
+
+ if err := cfg.LoadFederationFile(config.FederationFile(), config); err != nil {
+ log.WithField("err", err).Info("Failed to load federated information")
+ return err
+ }
+
+ if err := consensus.InitActiveNetParams(config.ChainID); err != nil {
+ log.Fatalf("Failed to init ActiveNetParams:[%s]", err.Error())
+ }
+
+ cfg.CommonConfig = config
+ return nil
+}
+
// find whether config xpubs equal genesis block xpubs
func checkConfig(chain *protocol.Chain, config *cfg.Config) error {
fedpegScript := cfg.FederationWScript(config)
return nil, err
}
+ return w, nil
+}
+
+// Run go to run some wallet recorvery and clean tx thread
+func (w *Wallet) Run() error {
var err error
w.TxMsgSub, err = w.EventDispatcher.Subscribe(protocol.TxMsgEvent{})
if err != nil {
- return nil, err
+ return err
}
go w.walletUpdater()
go w.delUnconfirmedTx()
go w.MemPoolTxQueryLoop()
- return w, nil
+
+ return nil
}
// MemPoolTxQueryLoop constantly pass a transaction accepted by mempool to the wallet.
return nil
}
+// Rollback wallet to target height
+func (w *Wallet) Rollback(targetHeight uint64) error {
+ for w.Status.WorkHeight > targetHeight {
+ block, err := w.Chain.GetBlockByHash(&w.Status.WorkHash)
+ if err != nil {
+ return err
+ }
+
+ if err = w.DetachBlock(block); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
func (w *Wallet) UpdateAccountAlias(accountID string, newAlias string) (err error) {
w.rw.Lock()
defer w.rw.Unlock()