wallet: move DB access from rescan ntfns into correct goroutine
This commit is contained in:
parent
81a9bb67c1
commit
8e2c741f88
2 changed files with 51 additions and 96 deletions
|
@ -33,6 +33,47 @@ func (w *Wallet) handleChainNotifications() {
|
|||
}
|
||||
}
|
||||
|
||||
catchUpHashes := func(w *Wallet, client chain.Interface,
|
||||
height int32) error {
|
||||
// TODO(aakselrod): There's a race conditon here, which
|
||||
// happens when a reorg occurs between the
|
||||
// rescanProgress notification and the last GetBlockHash
|
||||
// call. The solution when using btcd is to make btcd
|
||||
// send blockconnected notifications with each block
|
||||
// the way Neutrino does, and get rid of the loop. The
|
||||
// other alternative is to check the final hash and,
|
||||
// if it doesn't match the original hash returned by
|
||||
// the notification, to roll back and restart the
|
||||
// rescan.
|
||||
log.Infof("Catching up block hashes to height %d, this"+
|
||||
" might take a while", height)
|
||||
err := walletdb.Update(w.db, func(tx walletdb.ReadWriteTx) error {
|
||||
ns := tx.ReadWriteBucket(waddrmgrNamespaceKey)
|
||||
startBlock := w.Manager.SyncedTo()
|
||||
for i := startBlock.Height + 1; i <= height; i++ {
|
||||
hash, err := client.GetBlockHash(int64(i))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bs := waddrmgr.BlockStamp{
|
||||
Height: i,
|
||||
Hash: *hash,
|
||||
}
|
||||
err = w.Manager.SetSyncedTo(ns, &bs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("Failed to update address manager "+
|
||||
"sync state for height %d: %v", height, err)
|
||||
}
|
||||
log.Info("Done catching up block hashes")
|
||||
return err
|
||||
}
|
||||
|
||||
for n := range chainClient.Notifications() {
|
||||
var notificationName string
|
||||
var err error
|
||||
|
@ -72,9 +113,16 @@ func (w *Wallet) handleChainNotifications() {
|
|||
}
|
||||
notificationName = "filteredblockconnected"
|
||||
|
||||
// The following are handled by the wallet's rescan
|
||||
// goroutines, so just pass them there.
|
||||
case *chain.RescanProgress, *chain.RescanFinished:
|
||||
// The following require some database maintenance, but also
|
||||
// need to be reported to the wallet's rescan goroutine.
|
||||
case *chain.RescanProgress:
|
||||
err = catchUpHashes(w, chainClient, n.Height)
|
||||
notificationName = "rescanprogress"
|
||||
w.rescanNotifications <- n
|
||||
case *chain.RescanFinished:
|
||||
err = catchUpHashes(w, chainClient, n.Height)
|
||||
notificationName = "rescanprogress"
|
||||
w.SetChainSynced(true)
|
||||
w.rescanNotifications <- n
|
||||
}
|
||||
if err != nil {
|
||||
|
|
|
@ -9,7 +9,6 @@ import (
|
|||
"github.com/roasbeef/btcutil"
|
||||
"github.com/roasbeef/btcwallet/chain"
|
||||
"github.com/roasbeef/btcwallet/waddrmgr"
|
||||
"github.com/roasbeef/btcwallet/walletdb"
|
||||
"github.com/roasbeef/btcwallet/wtxmgr"
|
||||
)
|
||||
|
||||
|
@ -175,51 +174,6 @@ out:
|
|||
log.Infof("Rescanned through block %v (height %d)",
|
||||
n.Hash, n.Height)
|
||||
|
||||
client := w.ChainClient()
|
||||
// Since btcd rescans don't send blockconnected
|
||||
// notifications, we need to cycle through all of the
|
||||
// rescanned blocks and write the hashes to the
|
||||
// database. Neutrino rescans do send the notifications,
|
||||
// which means this loop won't actually cycle.
|
||||
//
|
||||
// TODO(aakselrod): There's a race conditon here, which
|
||||
// happens when a reorg occurs between the
|
||||
// rescanProgress notification and the last GetBlockHash
|
||||
// call. The solution when using btcd is to make btcd
|
||||
// send blockconnected notifications with each block
|
||||
// the way Neutrino does, and get rid of the loop. The
|
||||
// other alternative is to check the final hash and,
|
||||
// if it doesn't match the original hash returned by
|
||||
// the notification, to roll back and restart the
|
||||
// rescan.
|
||||
log.Infof("Catching up block hashes to height %d, this"+
|
||||
" might take a while", n.Height)
|
||||
err := walletdb.Update(w.db, func(tx walletdb.ReadWriteTx) error {
|
||||
ns := tx.ReadWriteBucket(waddrmgrNamespaceKey)
|
||||
startBlock := w.Manager.SyncedTo()
|
||||
for i := startBlock.Height + 1; i <= n.Height; i++ {
|
||||
hash, err := client.GetBlockHash(int64(i))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bs := waddrmgr.BlockStamp{
|
||||
Height: i,
|
||||
Hash: *hash,
|
||||
}
|
||||
err = w.Manager.SetSyncedTo(ns, &bs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("Failed to update address manager "+
|
||||
"sync state for hash %v (height %d): %v",
|
||||
n.Hash, n.Height, err)
|
||||
}
|
||||
log.Info("Done catching up block hashes")
|
||||
|
||||
case msg := <-w.rescanFinished:
|
||||
n := msg.Notification
|
||||
addrs := msg.Addresses
|
||||
|
@ -228,53 +182,6 @@ out:
|
|||
"%s, height %d)", len(addrs), noun, n.Hash,
|
||||
n.Height)
|
||||
|
||||
client := w.ChainClient()
|
||||
// Since btcd rescans don't send blockconnected
|
||||
// notifications, we need to cycle through all of the
|
||||
// rescanned blocks and write the hashes to the
|
||||
// database. Neutrino rescans do send the notifications,
|
||||
// which means this loop won't actually cycle.
|
||||
//
|
||||
// TODO(aakselrod): There's a race conditon here, which
|
||||
// happens when a reorg occurs between the
|
||||
// rescanFinished notification and the last GetBlockHash
|
||||
// call. The solution when using btcd is to make btcd
|
||||
// send blockconnected notifications with each block
|
||||
// the way Neutrino does, and get rid of the loop. The
|
||||
// other alternative is to check the final hash and,
|
||||
// if it doesn't match the original hash returned by
|
||||
// the notification, to roll back and restart the
|
||||
// rescan.
|
||||
log.Infof("Catching up block hashes to height %d, this"+
|
||||
" might take a while", n.Height)
|
||||
err := walletdb.Update(w.db, func(tx walletdb.ReadWriteTx) error {
|
||||
ns := tx.ReadWriteBucket(waddrmgrNamespaceKey)
|
||||
startBlock := w.Manager.SyncedTo()
|
||||
for i := startBlock.Height + 1; i <= n.Height; i++ {
|
||||
hash, err := client.GetBlockHash(int64(i))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bs := waddrmgr.BlockStamp{
|
||||
Height: i,
|
||||
Hash: *hash,
|
||||
}
|
||||
err = w.Manager.SetSyncedTo(ns, &bs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("Failed to update address manager "+
|
||||
"sync state for hash %v (height %d): %v",
|
||||
n.Hash, n.Height, err)
|
||||
continue
|
||||
}
|
||||
|
||||
w.SetChainSynced(true)
|
||||
log.Info("Done catching up block hashes")
|
||||
go w.resendUnminedTxs()
|
||||
|
||||
case <-quit:
|
||||
|
|
Loading…
Add table
Reference in a new issue