itest: test BIP-0086 Taproot account+pubkey import

This commit is contained in:
Oliver Gugger 2022-07-29 18:20:04 +02:00
parent 97dfc04117
commit 3a66a09d9d
No known key found for this signature in database
GPG Key ID: 8E4256593F177720

View File

@ -9,6 +9,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/btcsuite/btcd/btcec/v2/schnorr"
"github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/btcutil/hdkeychain" "github.com/btcsuite/btcd/btcutil/hdkeychain"
"github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/chaincfg/chainhash"
@ -31,7 +32,9 @@ const (
) )
// walletToLNAddrType maps walletrpc.AddressType to lnrpc.AddressType. // walletToLNAddrType maps walletrpc.AddressType to lnrpc.AddressType.
func walletToLNAddrType(t *testing.T, addrType walletrpc.AddressType) lnrpc.AddressType { func walletToLNAddrType(t *testing.T,
addrType walletrpc.AddressType) lnrpc.AddressType {
switch addrType { switch addrType {
case walletrpc.AddressType_NESTED_WITNESS_PUBKEY_HASH, case walletrpc.AddressType_NESTED_WITNESS_PUBKEY_HASH,
walletrpc.AddressType_HYBRID_NESTED_WITNESS_PUBKEY_HASH: walletrpc.AddressType_HYBRID_NESTED_WITNESS_PUBKEY_HASH:
@ -41,6 +44,9 @@ func walletToLNAddrType(t *testing.T, addrType walletrpc.AddressType) lnrpc.Addr
case walletrpc.AddressType_WITNESS_PUBKEY_HASH: case walletrpc.AddressType_WITNESS_PUBKEY_HASH:
return lnrpc.AddressType_WITNESS_PUBKEY_HASH return lnrpc.AddressType_WITNESS_PUBKEY_HASH
case walletrpc.AddressType_TAPROOT_PUBKEY:
return lnrpc.AddressType_TAPROOT_PUBKEY
default: default:
t.Fatalf("unhandled addr type %v", addrType) t.Fatalf("unhandled addr type %v", addrType)
return 0 return 0
@ -65,8 +71,6 @@ func newExternalAddr(t *testing.T, funder, signer *lntest.HarnessNode,
// Carol also needs to generate the address for the sake of this test to // Carol also needs to generate the address for the sake of this test to
// be able to sign the channel funding input. // be able to sign the channel funding input.
ctxt, cancel = context.WithTimeout(ctxb, defaultTimeout)
defer cancel()
signerResp, err := signer.NewAddress(ctxt, &lnrpc.NewAddressRequest{ signerResp, err := signer.NewAddress(ctxt, &lnrpc.NewAddressRequest{
Type: walletToLNAddrType(t, addrType), Type: walletToLNAddrType(t, addrType),
}) })
@ -96,6 +100,9 @@ func assertExternalAddrType(t *testing.T, addrStr string,
require.IsType(t, addr, &btcutil.AddressScriptHash{}) require.IsType(t, addr, &btcutil.AddressScriptHash{})
case walletrpc.AddressType_TAPROOT_PUBKEY:
require.IsType(t, addr, &btcutil.AddressTaproot{})
default: default:
t.Fatalf("unsupported account addr type %v", accountAddrType) t.Fatalf("unsupported account addr type %v", accountAddrType)
} }
@ -208,7 +215,9 @@ func psbtSendFromImportedAccount(t *harnessTest, srcNode, destNode,
ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout) ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout)
defer cancel() defer cancel()
balanceResp, err := srcNode.WalletBalance(ctxt, &lnrpc.WalletBalanceRequest{}) balanceResp, err := srcNode.WalletBalance(
ctxt, &lnrpc.WalletBalanceRequest{},
)
require.NoError(t.t, err) require.NoError(t.t, err)
require.Contains(t.t, balanceResp.AccountBalance, account) require.Contains(t.t, balanceResp.AccountBalance, account)
confBalance := balanceResp.AccountBalance[account].ConfirmedBalance confBalance := balanceResp.AccountBalance[account].ConfirmedBalance
@ -246,7 +255,9 @@ func psbtSendFromImportedAccount(t *harnessTest, srcNode, destNode,
finalizeReq := &walletrpc.FinalizePsbtRequest{ finalizeReq := &walletrpc.FinalizePsbtRequest{
FundedPsbt: fundResp.FundedPsbt, FundedPsbt: fundResp.FundedPsbt,
} }
finalizeResp, err := signer.WalletKitClient.FinalizePsbt(ctxt, finalizeReq) finalizeResp, err := signer.WalletKitClient.FinalizePsbt(
ctxt, finalizeReq,
)
require.NoError(t.t, err) require.NoError(t.t, err)
// With the PSBT signed, we can broadcast the resulting transaction. // With the PSBT signed, we can broadcast the resulting transaction.
@ -284,6 +295,18 @@ func psbtSendFromImportedAccount(t *harnessTest, srcNode, destNode,
expTxFee = 164 expTxFee = 164
expChangeScriptType = txscript.WitnessV0PubKeyHashTy expChangeScriptType = txscript.WitnessV0PubKeyHashTy
case walletrpc.AddressType_TAPROOT_PUBKEY:
if account != defaultImportedAccount {
expTxFee = 190
expChangeScriptType = txscript.WitnessV1TaprootTy
break
}
// Spends from the default imported account fall back to a P2WKH
// change. We'll want to change that, but in a separate PR.
expTxFee = 221
expChangeScriptType = txscript.WitnessV0PubKeyHashTy
default: default:
t.Fatalf("unsupported addr type %v", accountAddrType) t.Fatalf("unsupported addr type %v", accountAddrType)
} }
@ -322,7 +345,9 @@ func fundChanAndCloseFromImportedAccount(t *harnessTest, srcNode, destNode,
// on. // on.
ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout) ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout)
defer cancel() defer cancel()
balanceResp, err := srcNode.WalletBalance(ctxt, &lnrpc.WalletBalanceRequest{}) balanceResp, err := srcNode.WalletBalance(
ctxt, &lnrpc.WalletBalanceRequest{},
)
require.NoError(t.t, err) require.NoError(t.t, err)
require.Contains(t.t, balanceResp.AccountBalance, account) require.Contains(t.t, balanceResp.AccountBalance, account)
accountConfBalance := balanceResp. accountConfBalance := balanceResp.
@ -437,6 +462,18 @@ func fundChanAndCloseFromImportedAccount(t *harnessTest, srcNode, destNode,
expChanTxFee = 176 expChanTxFee = 176
expChangeScriptType = txscript.WitnessV0PubKeyHashTy expChangeScriptType = txscript.WitnessV0PubKeyHashTy
case walletrpc.AddressType_TAPROOT_PUBKEY:
if account != defaultImportedAccount {
expChanTxFee = 202
expChangeScriptType = txscript.WitnessV1TaprootTy
break
}
// Spends from the default imported account fall back to a P2WKH
// change. We'll want to change that, but in a separate PR.
expChanTxFee = 233
expChangeScriptType = txscript.WitnessV0PubKeyHashTy
default: default:
t.Fatalf("unsupported addr type %v", accountAddrType) t.Fatalf("unsupported addr type %v", accountAddrType)
} }
@ -563,6 +600,10 @@ func testWalletImportAccount(net *lntest.NetworkHarness, t *harnessTest) {
name: "standard BIP-0084", name: "standard BIP-0084",
addrType: walletrpc.AddressType_WITNESS_PUBKEY_HASH, addrType: walletrpc.AddressType_WITNESS_PUBKEY_HASH,
}, },
{
name: "standard BIP-0086",
addrType: walletrpc.AddressType_TAPROOT_PUBKEY,
},
} }
for _, tc := range testCases { for _, tc := range testCases {
@ -571,7 +612,9 @@ func testWalletImportAccount(net *lntest.NetworkHarness, t *harnessTest) {
ht := newHarnessTest(tt, net) ht := newHarnessTest(tt, net)
ht.RunTestCase(&testCase{ ht.RunTestCase(&testCase{
name: tc.name, name: tc.name,
test: func(net1 *lntest.NetworkHarness, t1 *harnessTest) { test: func(net1 *lntest.NetworkHarness,
t1 *harnessTest) {
testWalletImportAccountScenario( testWalletImportAccountScenario(
net, t, tc.addrType, net, t, tc.addrType,
) )
@ -669,7 +712,9 @@ func runWalletImportAccountScenario(net *lntest.NetworkHarness, t *harnessTest,
// some assertions we'll make later on. // some assertions we'll make later on.
ctxt, cancel = context.WithTimeout(ctxb, defaultTimeout) ctxt, cancel = context.WithTimeout(ctxb, defaultTimeout)
defer cancel() defer cancel()
balanceResp, err := dave.WalletBalance(ctxt, &lnrpc.WalletBalanceRequest{}) balanceResp, err := dave.WalletBalance(
ctxt, &lnrpc.WalletBalanceRequest{},
)
require.NoError(t.t, err) require.NoError(t.t, err)
require.Contains(t.t, balanceResp.AccountBalance, importedAccount) require.Contains(t.t, balanceResp.AccountBalance, importedAccount)
confBalance := balanceResp.AccountBalance[importedAccount].ConfirmedBalance confBalance := balanceResp.AccountBalance[importedAccount].ConfirmedBalance
@ -716,6 +761,10 @@ func testWalletImportPubKey(net *lntest.NetworkHarness, t *harnessTest) {
name: "BIP-0084", name: "BIP-0084",
addrType: walletrpc.AddressType_WITNESS_PUBKEY_HASH, addrType: walletrpc.AddressType_WITNESS_PUBKEY_HASH,
}, },
{
name: "BIP-0086",
addrType: walletrpc.AddressType_TAPROOT_PUBKEY,
},
} }
for _, tc := range testCases { for _, tc := range testCases {
@ -724,7 +773,9 @@ func testWalletImportPubKey(net *lntest.NetworkHarness, t *harnessTest) {
ht := newHarnessTest(tt, net) ht := newHarnessTest(tt, net)
ht.RunTestCase(&testCase{ ht.RunTestCase(&testCase{
name: tc.name, name: tc.name,
test: func(net1 *lntest.NetworkHarness, t1 *harnessTest) { test: func(net1 *lntest.NetworkHarness,
t1 *harnessTest) {
testWalletImportPubKeyScenario( testWalletImportPubKeyScenario(
net, t, tc.addrType, net, t, tc.addrType,
) )
@ -758,7 +809,9 @@ func testWalletImportPubKeyScenario(net *lntest.NetworkHarness, t *harnessTest,
// We'll define a helper closure that we'll use throughout the test to // We'll define a helper closure that we'll use throughout the test to
// generate a new address of the given type from Carol's perspective, // generate a new address of the given type from Carol's perspective,
// import it into Dave's wallet, and fund it. // import it into Dave's wallet, and fund it.
importPubKey := func(keyIndex uint32, prevConfBalance, prevUnconfBalance int64) { importPubKey := func(keyIndex uint32, prevConfBalance,
prevUnconfBalance int64) {
// Retrieve Carol's account public key for the corresponding // Retrieve Carol's account public key for the corresponding
// address type. // address type.
ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout) ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout)
@ -767,7 +820,9 @@ func testWalletImportPubKeyScenario(net *lntest.NetworkHarness, t *harnessTest,
Name: "default", Name: "default",
AddressType: addrType, AddressType: addrType,
} }
listResp, err := carol.WalletKitClient.ListAccounts(ctxt, listReq) listResp, err := carol.WalletKitClient.ListAccounts(
ctxt, listReq,
)
require.NoError(t.t, err) require.NoError(t.t, err)
require.Equal(t.t, len(listResp.Accounts), 1) require.Equal(t.t, len(listResp.Accounts), 1)
p2wkhAccount := listResp.Accounts[0] p2wkhAccount := listResp.Accounts[0]
@ -784,11 +839,19 @@ func testWalletImportPubKeyScenario(net *lntest.NetworkHarness, t *harnessTest,
externalAddrPubKey, err := externalAddrExtKey.ECPubKey() externalAddrPubKey, err := externalAddrExtKey.ECPubKey()
require.NoError(t.t, err) require.NoError(t.t, err)
// Serialize as 32-byte x-only pubkey for Taproot addresses.
serializedPubKey := externalAddrPubKey.SerializeCompressed()
if addrType == walletrpc.AddressType_TAPROOT_PUBKEY {
serializedPubKey = schnorr.SerializePubKey(
externalAddrPubKey,
)
}
// Import the public key into Dave. // Import the public key into Dave.
ctxt, cancel = context.WithTimeout(ctxb, defaultTimeout) ctxt, cancel = context.WithTimeout(ctxb, defaultTimeout)
defer cancel() defer cancel()
importReq := &walletrpc.ImportPublicKeyRequest{ importReq := &walletrpc.ImportPublicKeyRequest{
PublicKey: externalAddrPubKey.SerializeCompressed(), PublicKey: serializedPubKey,
AddressType: addrType, AddressType: addrType,
} }
_, err = dave.WalletKitClient.ImportPublicKey(ctxt, importReq) _, err = dave.WalletKitClient.ImportPublicKey(ctxt, importReq)
@ -798,9 +861,11 @@ func testWalletImportPubKeyScenario(net *lntest.NetworkHarness, t *harnessTest,
// required later when signing. // required later when signing.
ctxt, cancel = context.WithTimeout(ctxb, defaultTimeout) ctxt, cancel = context.WithTimeout(ctxb, defaultTimeout)
defer cancel() defer cancel()
carolAddrResp, err := carol.NewAddress(ctxt, &lnrpc.NewAddressRequest{ carolAddrResp, err := carol.NewAddress(
Type: walletToLNAddrType(t.t, addrType), ctxt, &lnrpc.NewAddressRequest{
}) Type: walletToLNAddrType(t.t, addrType),
},
)
require.NoError(t.t, err) require.NoError(t.t, err)
// Send coins to Carol's address and confirm them, making sure // Send coins to Carol's address and confirm them, making sure
@ -842,9 +907,13 @@ func testWalletImportPubKeyScenario(net *lntest.NetworkHarness, t *harnessTest,
// import into Dave again. // import into Dave again.
ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout) ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout)
defer cancel() defer cancel()
balanceResp, err := dave.WalletBalance(ctxt, &lnrpc.WalletBalanceRequest{}) balanceResp, err := dave.WalletBalance(
ctxt, &lnrpc.WalletBalanceRequest{},
)
require.NoError(t.t, err) require.NoError(t.t, err)
require.Contains(t.t, balanceResp.AccountBalance, defaultImportedAccount) require.Contains(
t.t, balanceResp.AccountBalance, defaultImportedAccount,
)
confBalance := balanceResp. confBalance := balanceResp.
AccountBalance[defaultImportedAccount].ConfirmedBalance AccountBalance[defaultImportedAccount].ConfirmedBalance
importPubKey(1, confBalance, 0) importPubKey(1, confBalance, 0)