walletrpc+btcwallet: no custom account with various key scopes

Currently, a user can create a custom account with various key scopes.
This is not a desired behaviour.
This commit is contained in:
Torakushi 2023-02-17 18:06:19 +01:00
parent dd5ed71669
commit 77d3f00c3b
No known key found for this signature in database
GPG Key ID: 19C7D027EAB8B169
4 changed files with 70 additions and 0 deletions

View File

@ -1447,6 +1447,9 @@ var importAccountCommand = cli.Command{
The address type can usually be inferred from the key's version, but may
be required for certain keys to map them into the proper scope.
If an account with the same name already exists (even with a different
key scope), an error will be returned.
For BIP-0044 keys, an address type must be specified as we intend to not
support importing BIP-0044 keys into the wallet using the legacy
pay-to-pubkey-hash (P2PKH) scheme. A nested witness address type will

View File

@ -2,6 +2,7 @@ package itest
import (
"bytes"
"fmt"
"testing"
"time"
@ -468,6 +469,10 @@ func testWalletImportAccount(ht *lntest.HarnessTest) {
name string
addrType walletrpc.AddressType
}{
{
name: "standard BIP-0044",
addrType: walletrpc.AddressType_WITNESS_PUBKEY_HASH,
},
{
name: "standard BIP-0049",
addrType: walletrpc.
@ -550,6 +555,34 @@ func runWalletImportAccountScenario(ht *lntest.HarnessTest,
}
dave.RPC.ImportAccount(importReq)
// Try to import an account with the same name but with a different
// key scope. It should return an error.
otherAddrType := walletrpc.AddressType_TAPROOT_PUBKEY
if addrType == walletrpc.AddressType_TAPROOT_PUBKEY {
otherAddrType--
}
listReq = &walletrpc.ListAccountsRequest{
Name: "default",
AddressType: otherAddrType,
}
listResp = carol.RPC.ListAccounts(listReq)
require.Len(ht, listResp.Accounts, 1)
carolAccountOtherAddrType := listResp.Accounts[0]
errAccountExists := fmt.Sprintf(
"account '%s' already exists", importedAccount,
)
importReq = &walletrpc.ImportAccountRequest{
Name: importedAccount,
ExtendedPublicKey: carolAccountOtherAddrType.ExtendedPublicKey,
AddressType: otherAddrType,
}
err := dave.RPC.ImportAccountAssertErr(importReq)
require.ErrorContains(ht, err, errAccountExists)
// We'll generate an address for Carol from Dave's node to receive some
// funds.
externalAddr := newExternalAddr(

View File

@ -235,6 +235,20 @@ func (h *HarnessRPC) ImportAccount(
return resp
}
// ImportAccountAssertErr makes the ImportAccount RPC call and asserts an error
// is returned. It then returns the error.
func (h *HarnessRPC) ImportAccountAssertErr(
req *walletrpc.ImportAccountRequest) error {
ctxt, cancel := context.WithTimeout(h.runCtx, DefaultTimeout)
defer cancel()
_, err := h.WalletKit.ImportAccount(ctxt, req)
require.Error(h, err)
return err
}
// ImportPublicKey makes a RPC call to the node's WalletKitClient and asserts.
//
//nolint:lll

View File

@ -843,6 +843,10 @@ func (b *BtcWallet) ListAddresses(name string,
// The address type can usually be inferred from the key's version, but may be
// required for certain keys to map them into the proper scope.
//
// For custom accounts, we will first check if there is no account with the same
// name (even with a different key scope). No custom account should have various
// key scopes as it will result in non-deterministic behaviour.
//
// For BIP-0044 keys, an address type must be specified as we intend to not
// support importing BIP-0044 keys into the wallet using the legacy
// pay-to-pubkey-hash (P2PKH) scheme. A nested witness address type will force
@ -860,6 +864,22 @@ func (b *BtcWallet) ImportAccount(name string, accountPubKey *hdkeychain.Extende
dryRun bool) (*waddrmgr.AccountProperties, []btcutil.Address,
[]btcutil.Address, error) {
// For custom accounts, we first check if there is no existing account
// with the same name.
if name != lnwallet.DefaultAccountName &&
name != waddrmgr.ImportedAddrAccountName {
_, err := b.ListAccounts(name, nil)
if err == nil {
return nil, nil, nil,
fmt.Errorf("account '%s' already exists",
name)
}
if !waddrmgr.IsError(err, waddrmgr.ErrAccountNotFound) {
return nil, nil, nil, err
}
}
if !dryRun {
accountProps, err := b.wallet.ImportAccount(
name, accountPubKey, masterKeyFingerprint, addrType,