wallet: ensure timestamp is always set when calling waddrmgr.SetSyncedTo

This commit is contained in:
Olaoluwa Osuntokun 2018-03-10 16:38:54 -08:00
parent 0dcd36bf59
commit 5eaecee2c9
2 changed files with 40 additions and 5 deletions

View file

@ -49,15 +49,23 @@ func (w *Wallet) handleChainNotifications() {
" might take a while", height) " might take a while", height)
err := walletdb.Update(w.db, func(tx walletdb.ReadWriteTx) error { err := walletdb.Update(w.db, func(tx walletdb.ReadWriteTx) error {
ns := tx.ReadWriteBucket(waddrmgrNamespaceKey) ns := tx.ReadWriteBucket(waddrmgrNamespaceKey)
startBlock := w.Manager.SyncedTo() startBlock := w.Manager.SyncedTo()
for i := startBlock.Height + 1; i <= height; i++ { for i := startBlock.Height + 1; i <= height; i++ {
hash, err := client.GetBlockHash(int64(i)) hash, err := client.GetBlockHash(int64(i))
if err != nil { if err != nil {
return err return err
} }
header, err := chainClient.GetBlockHeader(hash)
if err != nil {
return err
}
bs := waddrmgr.BlockStamp{ bs := waddrmgr.BlockStamp{
Height: i, Height: i,
Hash: *hash, Hash: *hash,
Timestamp: header.Timestamp,
} }
err = w.Manager.SetSyncedTo(ns, &bs) err = w.Manager.SetSyncedTo(ns, &bs)
if err != nil { if err != nil {
@ -70,6 +78,7 @@ func (w *Wallet) handleChainNotifications() {
log.Errorf("Failed to update address manager "+ log.Errorf("Failed to update address manager "+
"sync state for height %d: %v", height, err) "sync state for height %d: %v", height, err)
} }
log.Info("Done catching up block hashes") log.Info("Done catching up block hashes")
return err return err
} }

View file

@ -355,29 +355,35 @@ func (w *Wallet) syncWithChain() error {
if err != nil { if err != nil {
return err return err
} }
checkHeight := bestHeight checkHeight := bestHeight
if len(w.chainParams.Checkpoints) > 0 { if len(w.chainParams.Checkpoints) > 0 {
checkHeight = w.chainParams.Checkpoints[len( checkHeight = w.chainParams.Checkpoints[len(
w.chainParams.Checkpoints)-1].Height w.chainParams.Checkpoints)-1].Height
} }
logHeight := checkHeight logHeight := checkHeight
if bestHeight > logHeight { if bestHeight > logHeight {
logHeight = bestHeight logHeight = bestHeight
} }
log.Infof("Catching up block hashes to height %d, this will "+ log.Infof("Catching up block hashes to height %d, this will "+
"take a while...", logHeight) "take a while...", logHeight)
// Initialize the first database transaction. // Initialize the first database transaction.
tx, err := w.db.BeginReadWriteTx() tx, err := w.db.BeginReadWriteTx()
if err != nil { if err != nil {
return err return err
} }
ns := tx.ReadWriteBucket(waddrmgrNamespaceKey) ns := tx.ReadWriteBucket(waddrmgrNamespaceKey)
for height := int32(1); height <= bestHeight; height++ { for height := int32(1); height <= bestHeight; height++ {
hash, err := chainClient.GetBlockHash(int64(height)) hash, err := chainClient.GetBlockHash(int64(height))
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
return err return err
} }
// If we've found the best height the backend knows // If we've found the best height the backend knows
// about, but we haven't reached the last checkpoint, we // about, but we haven't reached the last checkpoint, we
// know the backend is still synchronizing. We can give // know the backend is still synchronizing. We can give
@ -392,6 +398,7 @@ func (w *Wallet) syncWithChain() error {
tx.Rollback() tx.Rollback()
return err return err
} }
// If we're using the Neutrino backend, we can // If we're using the Neutrino backend, we can
// check if it's current or not. If it's not and // check if it's current or not. If it's not and
// we've exceeded the original checkHeight, we // we've exceeded the original checkHeight, we
@ -408,14 +415,22 @@ func (w *Wallet) syncWithChain() error {
} }
} }
} }
header, err := chainClient.GetBlockHeader(hash)
if err != nil {
return err
}
err = w.Manager.SetSyncedTo(ns, &waddrmgr.BlockStamp{ err = w.Manager.SetSyncedTo(ns, &waddrmgr.BlockStamp{
Hash: *hash, Hash: *hash,
Height: height, Height: height,
Timestamp: header.Timestamp,
}) })
if err != nil { if err != nil {
tx.Rollback() tx.Rollback()
return err return err
} }
// Every 10K blocks, commit and start a new database TX. // Every 10K blocks, commit and start a new database TX.
if height%10000 == 0 { if height%10000 == 0 {
err = tx.Commit() err = tx.Commit()
@ -423,14 +438,18 @@ func (w *Wallet) syncWithChain() error {
tx.Rollback() tx.Rollback()
return err return err
} }
log.Infof("Caught up to height %d", height) log.Infof("Caught up to height %d", height)
tx, err = w.db.BeginReadWriteTx() tx, err = w.db.BeginReadWriteTx()
if err != nil { if err != nil {
return err return err
} }
ns = tx.ReadWriteBucket(waddrmgrNamespaceKey) ns = tx.ReadWriteBucket(waddrmgrNamespaceKey)
} }
} }
// Commit (or roll back) the final database transaction. // Commit (or roll back) the final database transaction.
err = tx.Commit() err = tx.Commit()
if err != nil { if err != nil {
@ -470,8 +489,15 @@ func (w *Wallet) syncWithChain() error {
if err != nil { if err != nil {
return err return err
} }
header, err := chainClient.GetBlockHeader(hash)
if err != nil {
return err
}
rollbackStamp.Hash = *chainHash rollbackStamp.Hash = *chainHash
rollbackStamp.Height = height rollbackStamp.Height = height
rollbackStamp.Timestamp = header.Timestamp
if bytes.Equal(hash[:], chainHash[:]) { if bytes.Equal(hash[:], chainHash[:]) {
break break
} }
@ -1986,9 +2012,9 @@ func (w *Wallet) ImportPrivateKey(scope waddrmgr.KeyScope, wif *btcutil.WIF,
Height: 0, Height: 0,
} }
} else { } else {
header, err := w.chainClient.GetBlockHeader(&bs.Hash)
// Only update the new birthday time from default value if we // Only update the new birthday time from default value if we
// actually have timestamp info in the header. // actually have timestamp info in the header.
header, err := w.chainClient.GetBlockHeader(&bs.Hash)
if err == nil { if err == nil {
newBirthday = header.Timestamp newBirthday = header.Timestamp
} }