From 17efcdba2fc05889b8157f436d44b120e5fb01b1 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Tue, 14 May 2019 13:18:58 -0700 Subject: [PATCH] wallet: wait until chain backend is current to begin wallet sync This serves as groundwork for only storing up to MaxReorgDepth blocks upon initial sync. To do so, we want to make sure the chain backend considers itself current so that we can only fetch the latest MaxReorgDepth blocks from it. --- wallet/wallet.go | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/wallet/wallet.go b/wallet/wallet.go index 9622bee..5fad970 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -327,7 +327,22 @@ func (w *Wallet) activeData(dbtx walletdb.ReadTx) ([]btcutil.Address, []wtxmgr.C // finished. The birthday block can be passed in, if set, to ensure we can // properly detect if it gets rolled back. func (w *Wallet) syncWithChain(birthdayStamp *waddrmgr.BlockStamp) error { - // To start, if we've yet to find our birthday stamp, we'll do so now. + chainClient, err := w.requireChainClient() + if err != nil { + return err + } + + // We'll wait until the backend is synced to ensure we get the latest + // MaxReorgDepth blocks to store. We don't do this for development + // environments as we can't guarantee a lively chain. + if !w.isDevEnv() { + log.Debug("Waiting for chain backend to sync to tip") + if err := w.waitUntilBackendSynced(chainClient); err != nil { + return err + } + log.Debug("Chain backend synced to tip!") + } + if birthdayStamp == nil { var err error birthdayStamp, err = w.syncToBirthday() @@ -357,11 +372,6 @@ func (w *Wallet) syncWithChain(birthdayStamp *waddrmgr.BlockStamp) error { // before catching up with the rescan. rollback := false rollbackStamp := w.Manager.SyncedTo() - chainClient, err := w.requireChainClient() - if err != nil { - return err - } - err = walletdb.Update(w.db, func(tx walletdb.ReadWriteTx) error { addrmgrNs := tx.ReadWriteBucket(waddrmgrNamespaceKey) txmgrNs := tx.ReadWriteBucket(wtxmgrNamespaceKey) @@ -467,6 +477,26 @@ func (w *Wallet) isDevEnv() bool { return true } +// waitUntilBackendSynced blocks until the chain backend considers itself +// "current". +func (w *Wallet) waitUntilBackendSynced(chainClient chain.Interface) error { + // We'll poll every second to determine if our chain considers itself + // "current". + t := time.NewTicker(time.Second) + defer t.Stop() + + for { + select { + case <-t.C: + if chainClient.IsCurrent() { + return nil + } + case <-w.quitChan(): + return ErrWalletShuttingDown + } + } +} + // scanChain is a helper method that scans the chain from the starting height // until the tip of the chain. The onBlock callback can be used to perform // certain operations for every block that we process as we scan the chain.