OSDN Git Service

Rollback pr2, rollback 的时候,更新 wallet 的状态, 改内核的下一个版本发 (#493)
authoripqhjjybj <250657661@qq.com>
Wed, 19 Feb 2020 10:09:43 +0000 (18:09 +0800)
committerGitHub <noreply@github.com>
Wed, 19 Feb 2020 10:09:43 +0000 (18:09 +0800)
* add rollback_func

* add wallet rollback

* update wallet finished

* add new wallet rollback flag

* fix one flag

* new design of new wallet

* update one comment

* rollback status from one wallet best hash start

* change two func name

* fix one test

* change rollback func return info

* remove ugly code

* fix ugly code

* remove ugly code

cmd/vapord/commands/rollback_node.go [new file with mode: 0644]
node/node.go
test/wallet_test_util.go
wallet/wallet.go

diff --git a/cmd/vapord/commands/rollback_node.go b/cmd/vapord/commands/rollback_node.go
new file mode 100644 (file)
index 0000000..ff1f878
--- /dev/null
@@ -0,0 +1,38 @@
+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)
+}
index b352ae2..1ecb0e4 100644 (file)
@@ -59,13 +59,7 @@ type Node struct {
 
 // 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")
@@ -79,12 +73,6 @@ func NewNode(config *cfg.Config) *Node {
                "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))
@@ -128,6 +116,10 @@ func NewNode(config *cfg.Config) *Node {
                        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()
@@ -170,6 +162,69 @@ func NewNode(config *cfg.Config) *Node {
        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)
index f633f57..a3c1e19 100644 (file)
@@ -251,6 +251,11 @@ func (cfg *walletTestConfig) Run() error {
        if err != nil {
                return err
        }
+
+       if err = wallet.Run(); err != nil {
+               return err
+       }
+
        ctx := &walletTestContext{
                Wallet: wallet,
                Chain:  chain,
index 739e949..e22c44e 100644 (file)
@@ -80,16 +80,22 @@ func NewWallet(store WalletStore, account *account.Manager, asset *asset.Registr
                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.
@@ -307,6 +313,22 @@ func (w *Wallet) DeleteAccount(accountID string) (err error) {
        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()