wallet/wallet: commit birthday blockstamp upon initial sync/recovery

This commit is contained in:
Wilmer Paulino 2018-11-05 17:07:15 -08:00
parent 603e03de32
commit 71ead8e3b4
No known key found for this signature in database
GPG key ID: 6DF57B9F9514972F
2 changed files with 31 additions and 12 deletions

View file

@ -31,7 +31,7 @@ func (w *Wallet) handleChainNotifications() {
// some reason, however, the wallet will not be marked synced
// and many methods will error early since the wallet is known
// to be out of date.
err := w.syncWithChain()
err := w.syncWithChain(birthdayStamp)
if err != nil && !w.ShuttingDown() {
log.Warnf("Unable to synchronize wallet to chain: %v", err)
}

View file

@ -318,9 +318,10 @@ func (w *Wallet) activeData(dbtx walletdb.ReadTx) ([]btcutil.Address, []wtxmgr.C
}
// syncWithChain brings the wallet up to date with the current chain server
// connection. It creates a rescan request and blocks until the rescan has
// finished.
func (w *Wallet) syncWithChain() error {
// connection. It creates a rescan request and blocks until the rescan has
// 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 {
chainClient, err := w.requireChainClient()
if err != nil {
return err
@ -351,12 +352,6 @@ func (w *Wallet) syncWithChain() error {
isRecovery := w.recoveryWindow > 0
birthday := w.Manager.Birthday()
// If an initial sync is attempted, we will try and find the block stamp
// of the first block past our birthday. This will be fed into the
// rescan to ensure we catch transactions that are sent while performing
// the initial sync.
var birthdayStamp *waddrmgr.BlockStamp
// TODO(jrick): How should this handle a synced height earlier than
// the chain server best block?
@ -496,6 +491,19 @@ func (w *Wallet) syncWithChain() error {
Hash: *hash,
Timestamp: timestamp,
}
log.Debugf("Found birthday block: "+
"height=%d, hash=%v",
birthdayStamp.Height,
birthdayStamp.Hash)
err := w.Manager.SetBirthdayBlock(
ns, *birthdayStamp,
)
if err != nil {
tx.Rollback()
return err
}
}
// If we are in recovery mode and the check
@ -647,6 +655,18 @@ func (w *Wallet) syncWithChain() error {
// points at the new tip.
if birthdayStamp != nil && rollbackStamp.Height <= birthdayStamp.Height {
birthdayStamp = &rollbackStamp
log.Debugf("Found new birthday block after rollback: "+
"height=%d, hash=%v", birthdayStamp.Height,
birthdayStamp.Hash)
err := walletdb.Update(w.db, func(tx walletdb.ReadWriteTx) error {
ns := tx.ReadWriteBucket(waddrmgrNamespaceKey)
return w.Manager.SetBirthdayBlock(ns, *birthdayStamp)
})
if err != nil {
return nil
}
}
// Request notifications for connected and disconnected blocks.
@ -657,8 +677,7 @@ func (w *Wallet) syncWithChain() error {
// as well. I am leaning towards allowing off all rpcclient
// notification re-registrations, in which case the code here should be
// left as is.
err = chainClient.NotifyBlocks()
if err != nil {
if err := chainClient.NotifyBlocks(); err != nil {
return err
}