btcwallet: fix non-deterministic behaviour in ListAccounts

In theory, it should be only one custom account with a given name. However,
due to a lack of check, users could have created custom accounts with various
key scopes. In that case, ListAccounts has to list all these accounts.
This commit is contained in:
Torakushi 2023-02-27 17:34:11 +01:00
parent cf1f44ab10
commit 2ef5ea9742
No known key found for this signature in database
GPG Key ID: 19C7D027EAB8B169

View File

@ -636,17 +636,36 @@ func (b *BtcWallet) ListAccounts(name string,
break break
} }
// Otherwise, we'll retrieve the single account that's mapped by // In theory, there should be only one custom account for the
// the given name. // given name. However, due to a lack of check, users could
scope, acctNum, err := b.wallet.LookupAccount(name) // create custom accounts with various key scopes. This
if err != nil { // behaviour has been fixed but, we return all potential custom
return nil, err // accounts with the given name.
for _, scope := range waddrmgr.DefaultKeyScopes {
a, err := b.wallet.AccountPropertiesByName(
scope, name,
)
switch {
case waddrmgr.IsError(err, waddrmgr.ErrAccountNotFound):
continue
// In the specific case of a wallet initialized only by
// importing account xpubs (watch only wallets), it is
// possible that some keyscopes will be 'unknown' by the
// wallet (depending on the xpubs given to initialize
// it). If the keyscope is not found, just skip it.
case waddrmgr.IsError(err, waddrmgr.ErrScopeNotFound):
continue
case err != nil:
return nil, err
}
res = append(res, a)
} }
account, err := b.wallet.AccountProperties(scope, acctNum) if len(res) == 0 {
if err != nil { return nil, newAccountNotFoundError(name)
return nil, err
} }
res = append(res, account)
// Only the key scope filter was provided, so we'll return all accounts // Only the key scope filter was provided, so we'll return all accounts
// matching it. // matching it.
@ -690,6 +709,18 @@ func (b *BtcWallet) ListAccounts(name string,
return res, nil return res, nil
} }
// newAccountNotFoundError returns an error indicating that the manager didn't
// find the specific account. This error is used to be compatible with the old
// 'LookupAccount' behaviour previously used.
func newAccountNotFoundError(name string) error {
str := fmt.Sprintf("account name '%s' not found", name)
return waddrmgr.ManagerError{
ErrorCode: waddrmgr.ErrAccountNotFound,
Description: str,
}
}
// RequiredReserve returns the minimum amount of satoshis that should be // RequiredReserve returns the minimum amount of satoshis that should be
// kept in the wallet in order to fee bump anchor channels if necessary. // kept in the wallet in order to fee bump anchor channels if necessary.
// The value scales with the number of public anchor channels but is // The value scales with the number of public anchor channels but is