waddrmgr/scoped_manager: add nextAddresses cache update to db tx's OnCommit()
This commit makes nextAddresses add a function to the transactions OnCommit handler used to update the cache on successful database transaction commit. Before this we would risk the cache and database of get out of sync if the database transaction failed or was aborted after the cache was updated.
This commit is contained in:
parent
3378be750b
commit
918d9c2f88
1 changed files with 33 additions and 20 deletions
|
@ -818,33 +818,46 @@ func (s *ScopedKeyManager) nextAddresses(ns walletdb.ReadWriteBucket,
|
|||
}
|
||||
}
|
||||
|
||||
// Finally update the next address tracking and add the addresses to
|
||||
// the cache after the newly generated addresses have been successfully
|
||||
// added to the db.
|
||||
managedAddresses := make([]ManagedAddress, 0, len(addressInfo))
|
||||
for _, info := range addressInfo {
|
||||
ma := info.managedAddr
|
||||
s.addrs[addrKey(ma.Address().ScriptAddress())] = ma
|
||||
|
||||
// Add the new managed address to the list of addresses that
|
||||
// need their private keys derived when the address manager is
|
||||
// next unlocked.
|
||||
if s.rootManager.IsLocked() && !s.rootManager.WatchOnly() {
|
||||
s.deriveOnUnlock = append(s.deriveOnUnlock, info)
|
||||
}
|
||||
|
||||
managedAddresses = append(managedAddresses, ma)
|
||||
}
|
||||
|
||||
// Set the last address and next address for tracking.
|
||||
ma := addressInfo[len(addressInfo)-1].managedAddr
|
||||
if internal {
|
||||
acctInfo.nextInternalIndex = nextIndex
|
||||
acctInfo.lastInternalAddr = ma
|
||||
} else {
|
||||
acctInfo.nextExternalIndex = nextIndex
|
||||
acctInfo.lastExternalAddr = ma
|
||||
// Finally, create a closure that will update the next address tracking
|
||||
// and add the addresses to the cache after the newly generated
|
||||
// addresses have been successfully committed to the db.
|
||||
onCommit := func() {
|
||||
// Since this closure will be called when the DB transaction
|
||||
// gets committed, we won't longer be holding the manager's
|
||||
// mutex at that point. We must therefore re-acquire it before
|
||||
// continuing.
|
||||
s.mtx.Lock()
|
||||
defer s.mtx.Unlock()
|
||||
|
||||
for _, info := range addressInfo {
|
||||
ma := info.managedAddr
|
||||
s.addrs[addrKey(ma.Address().ScriptAddress())] = ma
|
||||
|
||||
// Add the new managed address to the list of addresses
|
||||
// that need their private keys derived when the
|
||||
// address manager is next unlocked.
|
||||
if s.rootManager.IsLocked() && !s.rootManager.WatchOnly() {
|
||||
s.deriveOnUnlock = append(s.deriveOnUnlock, info)
|
||||
}
|
||||
}
|
||||
|
||||
// Set the last address and next address for tracking.
|
||||
ma := addressInfo[len(addressInfo)-1].managedAddr
|
||||
if internal {
|
||||
acctInfo.nextInternalIndex = nextIndex
|
||||
acctInfo.lastInternalAddr = ma
|
||||
} else {
|
||||
acctInfo.nextExternalIndex = nextIndex
|
||||
acctInfo.lastExternalAddr = ma
|
||||
}
|
||||
}
|
||||
ns.Tx().OnCommit(onCommit)
|
||||
|
||||
return managedAddresses, nil
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue