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.
This commit is contained in:
Wilmer Paulino 2019-05-14 13:18:58 -07:00
parent 39f81c630b
commit 17efcdba2f
No known key found for this signature in database
GPG key ID: 6DF57B9F9514972F

View file

@ -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.