From 69cb45e3e7a64c29b40e5c35b40d0f85a19169b2 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Fri, 2 Nov 2018 18:43:15 -0700 Subject: [PATCH] wallet/wallet: use new migration logic for waddrmgr and wtxmgr In this commit, we modify the wallet to use the new migration logic provided by the recently introduced migration package. Additionally, we'll also perform all of our upgrades within the same database transaction to guarantee fault-tolerance of the wallet. --- wallet/wallet.go | 79 ++++++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 43 deletions(-) diff --git a/wallet/wallet.go b/wallet/wallet.go index f069e7a..b15157c 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -23,8 +23,6 @@ import ( "github.com/btcsuite/btcd/rpcclient" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/davecgh/go-spew/spew" - "github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil/hdkeychain" "github.com/btcsuite/btcwallet/chain" @@ -32,7 +30,9 @@ import ( "github.com/btcsuite/btcwallet/wallet/txauthor" "github.com/btcsuite/btcwallet/wallet/txrules" "github.com/btcsuite/btcwallet/walletdb" + "github.com/btcsuite/btcwallet/walletdb/migration" "github.com/btcsuite/btcwallet/wtxmgr" + "github.com/davecgh/go-spew/spew" ) const ( @@ -3375,58 +3375,49 @@ func Create(db walletdb.DB, pubPass, privPass, seed []byte, params *chaincfg.Par func Open(db walletdb.DB, pubPass []byte, cbs *waddrmgr.OpenCallbacks, params *chaincfg.Params, recoveryWindow uint32) (*Wallet, error) { - err := walletdb.View(db, func(tx walletdb.ReadTx) error { - waddrmgrBucket := tx.ReadBucket(waddrmgrNamespaceKey) - if waddrmgrBucket == nil { + var ( + addrMgr *waddrmgr.Manager + txMgr *wtxmgr.Store + ) + + // Before attempting to open the wallet, we'll check if there are any + // database upgrades for us to proceed. We'll also create our references + // to the address and transaction managers, as they are backed by the + // database. + err := walletdb.Update(db, func(tx walletdb.ReadWriteTx) error { + addrMgrBucket := tx.ReadWriteBucket(waddrmgrNamespaceKey) + if addrMgrBucket == nil { return errors.New("missing address manager namespace") } - wtxmgrBucket := tx.ReadBucket(wtxmgrNamespaceKey) - if wtxmgrBucket == nil { + txMgrBucket := tx.ReadWriteBucket(wtxmgrNamespaceKey) + if txMgrBucket == nil { return errors.New("missing transaction manager namespace") } + + addrMgrUpgrader := waddrmgr.NewMigrationManager(addrMgrBucket) + txMgrUpgrader := wtxmgr.NewMigrationManager(txMgrBucket) + err := migration.Upgrade(txMgrUpgrader, addrMgrUpgrader) + if err != nil { + return err + } + + addrMgr, err = waddrmgr.Open(addrMgrBucket, pubPass, params) + if err != nil { + return err + } + txMgr, err = wtxmgr.Open(txMgrBucket, params) + if err != nil { + return err + } + return nil }) if err != nil { return nil, err } - // Perform upgrades as necessary. Each upgrade is done under its own - // transaction, which is managed by each package itself, so the entire - // DB is passed instead of passing already opened write transaction. - // - // This will need to change later when upgrades in one package depend on - // data in another (such as removing chain synchronization from address - // manager). - err = waddrmgr.DoUpgrades(db, waddrmgrNamespaceKey, pubPass, params, cbs) - if err != nil { - return nil, err - } - err = wtxmgr.DoUpgrades(db, wtxmgrNamespaceKey) - if err != nil { - return nil, err - } - - // Open database abstraction instances - var ( - addrMgr *waddrmgr.Manager - txMgr *wtxmgr.Store - ) - err = walletdb.View(db, func(tx walletdb.ReadTx) error { - addrmgrNs := tx.ReadBucket(waddrmgrNamespaceKey) - txmgrNs := tx.ReadBucket(wtxmgrNamespaceKey) - var err error - addrMgr, err = waddrmgr.Open(addrmgrNs, pubPass, params) - if err != nil { - return err - } - txMgr, err = wtxmgr.Open(txmgrNs, params) - return err - }) - if err != nil { - return nil, err - } - log.Infof("Opened wallet") // TODO: log balance? last sync height? + w := &Wallet{ publicPassphrase: pubPass, db: db, @@ -3449,9 +3440,11 @@ func Open(db walletdb.DB, pubPass []byte, cbs *waddrmgr.OpenCallbacks, chainParams: params, quit: make(chan struct{}), } + w.NtfnServer = newNotificationServer(w) w.TxStore.NotifyUnspent = func(hash *chainhash.Hash, index uint32) { w.NtfnServer.notifyUnspentOutput(0, hash, index) } + return w, nil }