mirror of
https://github.com/aljazceru/breez-lnd.git
synced 2025-12-17 06:04:20 +01:00
multi: create and list all default internal accounts
This commit is contained in:
@@ -105,6 +105,21 @@ const (
|
|||||||
KeyFamilyTowerID KeyFamily = 9
|
KeyFamilyTowerID KeyFamily = 9
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// VersionZeroKeyFamilies is a slice of all the known key families for first
|
||||||
|
// version of the key derivation schema defined in this package.
|
||||||
|
var VersionZeroKeyFamilies = []KeyFamily{
|
||||||
|
KeyFamilyMultiSig,
|
||||||
|
KeyFamilyRevocationBase,
|
||||||
|
KeyFamilyHtlcBase,
|
||||||
|
KeyFamilyPaymentBase,
|
||||||
|
KeyFamilyDelayBase,
|
||||||
|
KeyFamilyRevocationRoot,
|
||||||
|
KeyFamilyNodeKey,
|
||||||
|
KeyFamilyStaticBackup,
|
||||||
|
KeyFamilyTowerSession,
|
||||||
|
KeyFamilyTowerID,
|
||||||
|
}
|
||||||
|
|
||||||
// KeyLocator is a two-tuple that can be used to derive *any* key that has ever
|
// KeyLocator is a two-tuple that can be used to derive *any* key that has ever
|
||||||
// been used under the key derivation mechanisms described in this file.
|
// been used under the key derivation mechanisms described in this file.
|
||||||
// Version 0 of our key derivation schema uses the following BIP43-like
|
// Version 0 of our key derivation schema uses the following BIP43-like
|
||||||
|
|||||||
@@ -16,25 +16,11 @@ import (
|
|||||||
"github.com/btcsuite/btcwallet/wallet"
|
"github.com/btcsuite/btcwallet/wallet"
|
||||||
"github.com/btcsuite/btcwallet/walletdb"
|
"github.com/btcsuite/btcwallet/walletdb"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
_ "github.com/btcsuite/btcwallet/walletdb/bdb" // Required in order to create the default database.
|
_ "github.com/btcsuite/btcwallet/walletdb/bdb" // Required in order to create the default database.
|
||||||
)
|
)
|
||||||
|
|
||||||
// versionZeroKeyFamilies is a slice of all the known key families for first
|
|
||||||
// version of the key derivation schema defined in this package.
|
|
||||||
var versionZeroKeyFamilies = []KeyFamily{
|
|
||||||
KeyFamilyMultiSig,
|
|
||||||
KeyFamilyRevocationBase,
|
|
||||||
KeyFamilyHtlcBase,
|
|
||||||
KeyFamilyPaymentBase,
|
|
||||||
KeyFamilyDelayBase,
|
|
||||||
KeyFamilyRevocationRoot,
|
|
||||||
KeyFamilyNodeKey,
|
|
||||||
KeyFamilyStaticBackup,
|
|
||||||
KeyFamilyTowerSession,
|
|
||||||
KeyFamilyTowerID,
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
testHDSeed = chainhash.Hash{
|
testHDSeed = chainhash.Hash{
|
||||||
0xb7, 0x94, 0x38, 0x5f, 0x2d, 0x1e, 0xf7, 0xab,
|
0xb7, 0x94, 0x38, 0x5f, 0x2d, 0x1e, 0xf7, 0xab,
|
||||||
@@ -139,9 +125,7 @@ func TestKeyRingDerivation(t *testing.T) {
|
|||||||
cleanUp, wallet, err := createTestBtcWallet(
|
cleanUp, wallet, err := createTestBtcWallet(
|
||||||
CoinTypeBitcoin,
|
CoinTypeBitcoin,
|
||||||
)
|
)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatalf("unable to create wallet: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
keyRing := NewBtcWalletKeyRing(wallet, CoinTypeBitcoin)
|
keyRing := NewBtcWalletKeyRing(wallet, CoinTypeBitcoin)
|
||||||
|
|
||||||
@@ -151,9 +135,7 @@ func TestKeyRingDerivation(t *testing.T) {
|
|||||||
cleanUp, wallet, err := createTestBtcWallet(
|
cleanUp, wallet, err := createTestBtcWallet(
|
||||||
CoinTypeLitecoin,
|
CoinTypeLitecoin,
|
||||||
)
|
)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatalf("unable to create wallet: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
keyRing := NewBtcWalletKeyRing(wallet, CoinTypeLitecoin)
|
keyRing := NewBtcWalletKeyRing(wallet, CoinTypeLitecoin)
|
||||||
|
|
||||||
@@ -163,9 +145,7 @@ func TestKeyRingDerivation(t *testing.T) {
|
|||||||
cleanUp, wallet, err := createTestBtcWallet(
|
cleanUp, wallet, err := createTestBtcWallet(
|
||||||
CoinTypeTestnet,
|
CoinTypeTestnet,
|
||||||
)
|
)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatalf("unable to create wallet: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
keyRing := NewBtcWalletKeyRing(wallet, CoinTypeTestnet)
|
keyRing := NewBtcWalletKeyRing(wallet, CoinTypeTestnet)
|
||||||
|
|
||||||
@@ -189,14 +169,11 @@ func TestKeyRingDerivation(t *testing.T) {
|
|||||||
success := t.Run(fmt.Sprintf("%v", keyRingName), func(t *testing.T) {
|
success := t.Run(fmt.Sprintf("%v", keyRingName), func(t *testing.T) {
|
||||||
// First, we'll ensure that we're able to derive keys
|
// First, we'll ensure that we're able to derive keys
|
||||||
// from each of the known key families.
|
// from each of the known key families.
|
||||||
for _, keyFam := range versionZeroKeyFamilies {
|
for _, keyFam := range VersionZeroKeyFamilies {
|
||||||
// First, we'll ensure that we can derive the
|
// First, we'll ensure that we can derive the
|
||||||
// *next* key in the keychain.
|
// *next* key in the keychain.
|
||||||
keyDesc, err := keyRing.DeriveNextKey(keyFam)
|
keyDesc, err := keyRing.DeriveNextKey(keyFam)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatalf("unable to derive next for "+
|
|
||||||
"keyFam=%v: %v", keyFam, err)
|
|
||||||
}
|
|
||||||
assertEqualKeyLocator(t,
|
assertEqualKeyLocator(t,
|
||||||
KeyLocator{
|
KeyLocator{
|
||||||
Family: keyFam,
|
Family: keyFam,
|
||||||
@@ -212,10 +189,7 @@ func TestKeyRingDerivation(t *testing.T) {
|
|||||||
Index: 0,
|
Index: 0,
|
||||||
}
|
}
|
||||||
firstKeyDesc, err := keyRing.DeriveKey(keyLoc)
|
firstKeyDesc, err := keyRing.DeriveKey(keyLoc)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatalf("unable to derive first key for "+
|
|
||||||
"keyFam=%v: %v", keyFam, err)
|
|
||||||
}
|
|
||||||
if !keyDesc.PubKey.IsEqual(firstKeyDesc.PubKey) {
|
if !keyDesc.PubKey.IsEqual(firstKeyDesc.PubKey) {
|
||||||
t.Fatalf("mismatched keys: expected %x, "+
|
t.Fatalf("mismatched keys: expected %x, "+
|
||||||
"got %x",
|
"got %x",
|
||||||
@@ -240,10 +214,7 @@ func TestKeyRingDerivation(t *testing.T) {
|
|||||||
Index: uint32(i),
|
Index: uint32(i),
|
||||||
}
|
}
|
||||||
keyDesc, err := keyRing.DeriveKey(keyLoc)
|
keyDesc, err := keyRing.DeriveKey(keyLoc)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatalf("unable to derive first key for "+
|
|
||||||
"keyFam=%v: %v", keyFam, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure that the key locator matches
|
// Ensure that the key locator matches
|
||||||
// up as well.
|
// up as well.
|
||||||
@@ -260,11 +231,7 @@ func TestKeyRingDerivation(t *testing.T) {
|
|||||||
Index: randKeyIndex,
|
Index: randKeyIndex,
|
||||||
}
|
}
|
||||||
keyDesc, err = keyRing.DeriveKey(keyLoc)
|
keyDesc, err = keyRing.DeriveKey(keyLoc)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatalf("unable to derive key_index=%v "+
|
|
||||||
"for keyFam=%v: %v",
|
|
||||||
randKeyIndex, keyFam, err)
|
|
||||||
}
|
|
||||||
assertEqualKeyLocator(
|
assertEqualKeyLocator(
|
||||||
t, keyLoc, keyDesc.KeyLocator,
|
t, keyLoc, keyDesc.KeyLocator,
|
||||||
)
|
)
|
||||||
@@ -293,9 +260,7 @@ func TestSecretKeyRingDerivation(t *testing.T) {
|
|||||||
cleanUp, wallet, err := createTestBtcWallet(
|
cleanUp, wallet, err := createTestBtcWallet(
|
||||||
CoinTypeBitcoin,
|
CoinTypeBitcoin,
|
||||||
)
|
)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatalf("unable to create wallet: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
keyRing := NewBtcWalletKeyRing(wallet, CoinTypeBitcoin)
|
keyRing := NewBtcWalletKeyRing(wallet, CoinTypeBitcoin)
|
||||||
|
|
||||||
@@ -305,9 +270,7 @@ func TestSecretKeyRingDerivation(t *testing.T) {
|
|||||||
cleanUp, wallet, err := createTestBtcWallet(
|
cleanUp, wallet, err := createTestBtcWallet(
|
||||||
CoinTypeLitecoin,
|
CoinTypeLitecoin,
|
||||||
)
|
)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatalf("unable to create wallet: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
keyRing := NewBtcWalletKeyRing(wallet, CoinTypeLitecoin)
|
keyRing := NewBtcWalletKeyRing(wallet, CoinTypeLitecoin)
|
||||||
|
|
||||||
@@ -317,9 +280,7 @@ func TestSecretKeyRingDerivation(t *testing.T) {
|
|||||||
cleanUp, wallet, err := createTestBtcWallet(
|
cleanUp, wallet, err := createTestBtcWallet(
|
||||||
CoinTypeTestnet,
|
CoinTypeTestnet,
|
||||||
)
|
)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
t.Fatalf("unable to create wallet: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
keyRing := NewBtcWalletKeyRing(wallet, CoinTypeTestnet)
|
keyRing := NewBtcWalletKeyRing(wallet, CoinTypeTestnet)
|
||||||
|
|
||||||
@@ -342,7 +303,7 @@ func TestSecretKeyRingDerivation(t *testing.T) {
|
|||||||
// For, each key family, we'll ensure that we're able
|
// For, each key family, we'll ensure that we're able
|
||||||
// to obtain the private key of a randomly select child
|
// to obtain the private key of a randomly select child
|
||||||
// index within the key family.
|
// index within the key family.
|
||||||
for _, keyFam := range versionZeroKeyFamilies {
|
for _, keyFam := range VersionZeroKeyFamilies {
|
||||||
randKeyIndex := uint32(rand.Int31())
|
randKeyIndex := uint32(rand.Int31())
|
||||||
keyLoc := KeyLocator{
|
keyLoc := KeyLocator{
|
||||||
Family: keyFam,
|
Family: keyFam,
|
||||||
|
|||||||
@@ -310,6 +310,14 @@ func (r *ServerShell) CreateSubServer(configRegistry lnrpc.SubServerConfigDispat
|
|||||||
return subServer, macPermissions, nil
|
return subServer, macPermissions, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// internalScope returns the internal key scope.
|
||||||
|
func (w *WalletKit) internalScope() waddrmgr.KeyScope {
|
||||||
|
return waddrmgr.KeyScope{
|
||||||
|
Purpose: keychain.BIP0043Purpose,
|
||||||
|
Coin: w.cfg.ChainParams.HDCoinType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ListUnspent returns useful information about each unspent output owned by the
|
// ListUnspent returns useful information about each unspent output owned by the
|
||||||
// wallet, as reported by the underlying `ListUnspentWitness`; the information
|
// wallet, as reported by the underlying `ListUnspentWitness`; the information
|
||||||
// returned is: outpoint, amount in satoshis, address, address type,
|
// returned is: outpoint, amount in satoshis, address, address type,
|
||||||
@@ -1245,7 +1253,9 @@ func (w *WalletKit) FinalizePsbt(_ context.Context,
|
|||||||
|
|
||||||
// marshalWalletAccount converts the properties of an account into its RPC
|
// marshalWalletAccount converts the properties of an account into its RPC
|
||||||
// representation.
|
// representation.
|
||||||
func marshalWalletAccount(account *waddrmgr.AccountProperties) (*Account, error) {
|
func marshalWalletAccount(internalScope waddrmgr.KeyScope,
|
||||||
|
account *waddrmgr.AccountProperties) (*Account, error) {
|
||||||
|
|
||||||
var addrType AddressType
|
var addrType AddressType
|
||||||
switch account.KeyScope {
|
switch account.KeyScope {
|
||||||
case waddrmgr.KeyScopeBIP0049Plus:
|
case waddrmgr.KeyScopeBIP0049Plus:
|
||||||
@@ -1259,6 +1269,10 @@ func marshalWalletAccount(account *waddrmgr.AccountProperties) (*Account, error)
|
|||||||
switch *account.AddrSchema {
|
switch *account.AddrSchema {
|
||||||
case waddrmgr.KeyScopeBIP0049AddrSchema:
|
case waddrmgr.KeyScopeBIP0049AddrSchema:
|
||||||
addrType = AddressType_NESTED_WITNESS_PUBKEY_HASH
|
addrType = AddressType_NESTED_WITNESS_PUBKEY_HASH
|
||||||
|
|
||||||
|
case waddrmgr.ScopeAddrMap[waddrmgr.KeyScopeBIP0049Plus]:
|
||||||
|
addrType = AddressType_HYBRID_NESTED_WITNESS_PUBKEY_HASH
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unsupported address schema %v",
|
return nil, fmt.Errorf("unsupported address schema %v",
|
||||||
*account.AddrSchema)
|
*account.AddrSchema)
|
||||||
@@ -1267,6 +1281,9 @@ func marshalWalletAccount(account *waddrmgr.AccountProperties) (*Account, error)
|
|||||||
case waddrmgr.KeyScopeBIP0084:
|
case waddrmgr.KeyScopeBIP0084:
|
||||||
addrType = AddressType_WITNESS_PUBKEY_HASH
|
addrType = AddressType_WITNESS_PUBKEY_HASH
|
||||||
|
|
||||||
|
case internalScope:
|
||||||
|
addrType = AddressType_WITNESS_PUBKEY_HASH
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("account %v has unsupported "+
|
return nil, fmt.Errorf("account %v has unsupported "+
|
||||||
"key scope %v", account.AccountName, account.KeyScope)
|
"key scope %v", account.AccountName, account.KeyScope)
|
||||||
@@ -1340,7 +1357,9 @@ func (w *WalletKit) ListAccounts(ctx context.Context,
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
rpcAccount, err := marshalWalletAccount(account)
|
rpcAccount, err := marshalWalletAccount(
|
||||||
|
w.internalScope(), account,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -1431,7 +1450,7 @@ func (w *WalletKit) ImportAccount(ctx context.Context,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
rpcAccount, err := marshalWalletAccount(accountProps)
|
rpcAccount, err := marshalWalletAccount(w.internalScope(), accountProps)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -299,7 +299,7 @@ func (b *BtcWallet) Start() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := b.wallet.Manager.FetchScopedKeyManager(b.chainKeyScope)
|
scope, err := b.wallet.Manager.FetchScopedKeyManager(b.chainKeyScope)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// If the scope hasn't yet been created (it wouldn't been
|
// If the scope hasn't yet been created (it wouldn't been
|
||||||
// loaded by default if it was), then we'll manually create the
|
// loaded by default if it was), then we'll manually create the
|
||||||
@@ -307,7 +307,7 @@ func (b *BtcWallet) Start() error {
|
|||||||
err := walletdb.Update(b.db, func(tx walletdb.ReadWriteTx) error {
|
err := walletdb.Update(b.db, func(tx walletdb.ReadWriteTx) error {
|
||||||
addrmgrNs := tx.ReadWriteBucket(waddrmgrNamespaceKey)
|
addrmgrNs := tx.ReadWriteBucket(waddrmgrNamespaceKey)
|
||||||
|
|
||||||
_, err := b.wallet.Manager.NewScopedKeyManager(
|
scope, err = b.wallet.Manager.NewScopedKeyManager(
|
||||||
addrmgrNs, b.chainKeyScope, lightningAddrSchema,
|
addrmgrNs, b.chainKeyScope, lightningAddrSchema,
|
||||||
)
|
)
|
||||||
return err
|
return err
|
||||||
@@ -317,6 +317,43 @@ func (b *BtcWallet) Start() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now that the wallet is unlocked, we'll go ahead and make sure we
|
||||||
|
// create accounts for all the key families we're going to use. This
|
||||||
|
// will make it possible to list all the account/family xpubs in the
|
||||||
|
// wallet list RPC.
|
||||||
|
err = walletdb.Update(b.db, func(tx walletdb.ReadWriteTx) error {
|
||||||
|
addrmgrNs := tx.ReadWriteBucket(waddrmgrNamespaceKey)
|
||||||
|
|
||||||
|
for _, keyFam := range keychain.VersionZeroKeyFamilies {
|
||||||
|
// If this is the multi-sig key family, then we can
|
||||||
|
// return early as this is the default account that's
|
||||||
|
// created.
|
||||||
|
if keyFam == keychain.KeyFamilyMultiSig {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, we'll check if the account already exists,
|
||||||
|
// if so, we can once again bail early.
|
||||||
|
_, err := scope.AccountName(addrmgrNs, uint32(keyFam))
|
||||||
|
if err == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we reach this point, then the account hasn't yet
|
||||||
|
// been created, so we'll need to create it before we
|
||||||
|
// can proceed.
|
||||||
|
err = scope.NewRawAccount(addrmgrNs, uint32(keyFam))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Establish an RPC connection in addition to starting the goroutines
|
// Establish an RPC connection in addition to starting the goroutines
|
||||||
// in the underlying wallet.
|
// in the underlying wallet.
|
||||||
if err := b.chain.Start(); err != nil {
|
if err := b.chain.Start(); err != nil {
|
||||||
@@ -556,6 +593,18 @@ func (b *BtcWallet) ListAccounts(name string,
|
|||||||
account := account
|
account := account
|
||||||
res = append(res, &account.AccountProperties)
|
res = append(res, &account.AccountProperties)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
accounts, err = b.wallet.Accounts(waddrmgr.KeyScope{
|
||||||
|
Purpose: keychain.BIP0043Purpose,
|
||||||
|
Coin: b.cfg.CoinType,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, account := range accounts.Accounts {
|
||||||
|
account := account
|
||||||
|
res = append(res, &account.AccountProperties)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
|
|||||||
@@ -3019,6 +3019,13 @@ func (r *rpcServer) WalletBalance(ctx context.Context,
|
|||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// There now also are the accounts for the internal channel
|
||||||
|
// related keys. We skip those as they'll never have any direct
|
||||||
|
// balance.
|
||||||
|
if account.KeyScope.Purpose == keychain.BIP0043Purpose {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// Get total balance, from txs that have >= 0 confirmations.
|
// Get total balance, from txs that have >= 0 confirmations.
|
||||||
totalBal, err := r.server.cc.Wallet.ConfirmedBalance(
|
totalBal, err := r.server.cc.Wallet.ConfirmedBalance(
|
||||||
0, account.AccountName,
|
0, account.AccountName,
|
||||||
|
|||||||
Reference in New Issue
Block a user