Skip to content

Commit

Permalink
waddrmgr: use atomic bool instead of mutex for WatchOnly()
Browse files Browse the repository at this point in the history
  • Loading branch information
aakselrod committed Nov 25, 2024
1 parent 5838215 commit 3f4b45a
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 25 deletions.
36 changes: 13 additions & 23 deletions waddrmgr/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"crypto/sha512"
"fmt"
"sync"
"sync/atomic"
"time"

"github.com/btcsuite/btcd/btcutil"
Expand Down Expand Up @@ -345,7 +346,7 @@ type Manager struct {
internalAddrSchemas map[AddressType][]KeyScope

syncState syncState
watchingOnly bool
watchingOnly atomic.Bool
birthday time.Time
locked bool
closed bool
Expand Down Expand Up @@ -392,18 +393,7 @@ type Manager struct {
// WatchOnly returns true if the root manager is in watch only mode, and false
// otherwise.
func (m *Manager) WatchOnly() bool {
m.mtx.RLock()
defer m.mtx.RUnlock()

return m.watchOnly()
}

// watchOnly returns true if the root manager is in watch only mode, and false
// otherwise.
//
// NOTE: This method requires the Manager's lock to be held.
func (m *Manager) watchOnly() bool {
return m.watchingOnly
return m.watchingOnly.Load()
}

// IsWatchOnlyAccount determines if the account with the given key scope is set
Expand Down Expand Up @@ -489,7 +479,7 @@ func (m *Manager) Close() {
}

// Attempt to clear private key material from memory.
if !m.watchingOnly && !m.locked {
if !m.WatchOnly() && !m.locked {
m.lock()
}

Expand Down Expand Up @@ -517,7 +507,7 @@ func (m *Manager) NewScopedKeyManager(ns walletdb.ReadWriteBucket,
defer m.mtx.Unlock()

var rootPriv *hdkeychain.ExtendedKey
if !m.watchingOnly {
if !m.WatchOnly() {
// If the manager is locked, then we can't create a new scoped
// manager.
if m.locked {
Expand Down Expand Up @@ -588,7 +578,7 @@ func (m *Manager) NewScopedKeyManager(ns walletdb.ReadWriteBucket,
return nil, err
}

if !m.watchingOnly {
if !m.WatchOnly() {
// With the database state created, we'll now derive the
// cointype key using the master HD private key, then encrypt
// it along with the first account using our crypto keys.
Expand Down Expand Up @@ -888,7 +878,7 @@ func (m *Manager) ChangePassphrase(ns walletdb.ReadWriteBucket, oldPassphrase,
newPassphrase []byte, private bool, config *ScryptOptions) error {

// No private passphrase to change for a watching-only address manager.
if private && m.watchingOnly {
if private && m.WatchOnly() {
return managerError(ErrWatchingOnly, errWatchingOnly, nil)
}

Expand Down Expand Up @@ -1053,7 +1043,7 @@ func (m *Manager) ConvertToWatchingOnly(ns walletdb.ReadWriteBucket) error {
defer m.mtx.Unlock()

// Exit now if the manager is already watching-only.
if m.watchingOnly {
if m.WatchOnly() {
return nil
}

Expand Down Expand Up @@ -1118,7 +1108,7 @@ func (m *Manager) ConvertToWatchingOnly(ns walletdb.ReadWriteBucket) error {
m.masterKeyPriv = nil

// Mark the manager watching-only.
m.watchingOnly = true
m.watchingOnly.Store(true)
return nil

}
Expand Down Expand Up @@ -1149,7 +1139,7 @@ func (m *Manager) isLocked() bool {
// manager.
func (m *Manager) Lock() error {
// A watching-only address manager can't be locked.
if m.watchingOnly {
if m.WatchOnly() {
return managerError(ErrWatchingOnly, errWatchingOnly, nil)
}

Expand All @@ -1175,7 +1165,7 @@ func (m *Manager) Lock() error {
// manager.
func (m *Manager) Unlock(ns walletdb.ReadBucket, passphrase []byte) error {
// A watching-only address manager can't be unlocked.
if m.watchingOnly {
if m.WatchOnly() {
return managerError(ErrWatchingOnly, errWatchingOnly, nil)
}

Expand Down Expand Up @@ -1330,7 +1320,7 @@ func (m *Manager) LookupAccount(ns walletdb.ReadBucket, name string) (KeyScope,
func (m *Manager) selectCryptoKey(keyType CryptoKeyType) (EncryptorDecryptor, error) {
if keyType == CKTPrivate || keyType == CKTScript {
// The manager must be unlocked to work with the private keys.
if m.locked || m.watchingOnly {
if m.locked || m.WatchOnly() {
return nil, managerError(ErrLocked, errLocked, nil)
}
}
Expand Down Expand Up @@ -1412,8 +1402,8 @@ func newManager(chainParams *chaincfg.Params, masterKeyPub *snacl.SecretKey,
scopedManagers: scopedManagers,
externalAddrSchemas: make(map[AddressType][]KeyScope),
internalAddrSchemas: make(map[AddressType][]KeyScope),
watchingOnly: watchingOnly,
}
m.watchingOnly.Store(watchingOnly)

for _, sMgr := range m.scopedManagers {
externalType := sMgr.AddrSchema().ExternalAddrType
Expand Down
4 changes: 2 additions & 2 deletions waddrmgr/scoped_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ func (s *ScopedKeyManager) loadAccountInfo(ns walletdb.ReadBucket,

// The wallet will only contain private keys for default accounts if the
// wallet's not set up as watch-only and it's been unlocked.
watchOnly := s.rootManager.watchOnly()
watchOnly := s.rootManager.WatchOnly()
hasPrivateKey := !s.rootManager.isLocked() && !watchOnly

// Create the new account info with the known information. The rest of
Expand Down Expand Up @@ -777,7 +777,7 @@ func (s *ScopedKeyManager) chainAddressRowToManaged(ns walletdb.ReadBucket,

// Since the manger's mutex is assumed to held when invoking this
// function, we use the internal isLocked to avoid a deadlock.
private := !s.rootManager.isLocked() && !s.rootManager.watchOnly()
private := !s.rootManager.isLocked() && !s.rootManager.WatchOnly()

addressKey, acctKey, masterKeyFingerprint, err := s.deriveKeyFromPath(
ns, row.account, row.branch, row.index, private,
Expand Down

0 comments on commit 3f4b45a

Please sign in to comment.