itest: test imported address in coop close

Make sure that an address imported to LND via ImportTapscript or ImportPublicKey
can be used as a delivery address in coop close.

New test cases:
 - P2TR address imported with ImportTapscript
 - P2TR address imported with ImportPublicKey
 - P2WPKH address imported with ImportPublicKey

Safeguard against https://github.com/lightninglabs/loop/issues/923
This commit is contained in:
Boris Nagaev
2025-04-22 11:03:18 -03:00
parent 6451ce495a
commit c9b5974341

View File

@@ -4,7 +4,9 @@ import (
"fmt"
"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/txscript"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/wait"
"github.com/stretchr/testify/require"
@@ -15,7 +17,7 @@ var coopCloseWithExternalTestCases = []*lntest.TestCase{
Name: "set P2WPKH delivery address at open",
TestFunc: func(ht *lntest.HarnessTest) {
testCoopCloseWithExternalDelivery(
ht, true,
ht, true, false, false,
lnrpc.AddressType_UNUSED_WITNESS_PUBKEY_HASH,
)
},
@@ -24,7 +26,7 @@ var coopCloseWithExternalTestCases = []*lntest.TestCase{
Name: "set P2WPKH delivery address at close",
TestFunc: func(ht *lntest.HarnessTest) {
testCoopCloseWithExternalDelivery(
ht, false,
ht, false, false, false,
lnrpc.AddressType_UNUSED_WITNESS_PUBKEY_HASH,
)
},
@@ -33,7 +35,7 @@ var coopCloseWithExternalTestCases = []*lntest.TestCase{
Name: "set P2TR delivery address at open",
TestFunc: func(ht *lntest.HarnessTest) {
testCoopCloseWithExternalDelivery(
ht, true,
ht, true, false, false,
lnrpc.AddressType_UNUSED_TAPROOT_PUBKEY,
)
},
@@ -42,7 +44,61 @@ var coopCloseWithExternalTestCases = []*lntest.TestCase{
Name: "set P2TR delivery address at close",
TestFunc: func(ht *lntest.HarnessTest) {
testCoopCloseWithExternalDelivery(
ht, false,
ht, false, false, false,
lnrpc.AddressType_UNUSED_TAPROOT_PUBKEY,
)
},
},
{
Name: "set imported P2TR address (ImportTapscript) at open",
TestFunc: func(ht *lntest.HarnessTest) {
testCoopCloseWithExternalDelivery(
ht, true, true, false,
lnrpc.AddressType_UNUSED_TAPROOT_PUBKEY,
)
},
},
{
Name: "set imported P2TR address (ImportTapscript) at close",
TestFunc: func(ht *lntest.HarnessTest) {
testCoopCloseWithExternalDelivery(
ht, false, true, false,
lnrpc.AddressType_UNUSED_TAPROOT_PUBKEY,
)
},
},
{
Name: "set imported P2WPKH address at open",
TestFunc: func(ht *lntest.HarnessTest) {
testCoopCloseWithExternalDelivery(
ht, true, false, true,
lnrpc.AddressType_UNUSED_WITNESS_PUBKEY_HASH,
)
},
},
{
Name: "set imported P2WPKH address at close",
TestFunc: func(ht *lntest.HarnessTest) {
testCoopCloseWithExternalDelivery(
ht, false, false, true,
lnrpc.AddressType_UNUSED_WITNESS_PUBKEY_HASH,
)
},
},
{
Name: "set imported P2TR address (ImportPublicKey) at open",
TestFunc: func(ht *lntest.HarnessTest) {
testCoopCloseWithExternalDelivery(
ht, true, false, true,
lnrpc.AddressType_UNUSED_TAPROOT_PUBKEY,
)
},
},
{
Name: "set imported P2TR address (ImportPublicKey) at close",
TestFunc: func(ht *lntest.HarnessTest) {
testCoopCloseWithExternalDelivery(
ht, false, false, true,
lnrpc.AddressType_UNUSED_TAPROOT_PUBKEY,
)
},
@@ -53,20 +109,102 @@ var coopCloseWithExternalTestCases = []*lntest.TestCase{
// balance irrespective of whether the delivery address is in LND's wallet or
// not. Some users set this value to be an address in a different wallet and
// this should not affect our ability to accurately report the settled balance.
//
// If importTapscript is set, it imports a Taproot script and internal key to
// Alice's LND using ImportTapscript to make sure it doesn't interfere with
// delivery address. If importPubkey is set, the address is imported using
// ImportPublicKey.
func testCoopCloseWithExternalDelivery(ht *lntest.HarnessTest,
upfrontShutdown bool, deliveryAddressType lnrpc.AddressType) {
upfrontShutdown, importTapscript, importPubkey bool,
deliveryAddressType lnrpc.AddressType) {
alice := ht.NewNodeWithCoins("Alice", nil)
bob := ht.NewNodeWithCoins("bob", nil)
ht.ConnectNodes(alice, bob)
// Make fake taproot internal public key (equal to the final).
// This is only used if importTapscript or importPubkey is set.
taprootPubkey := [32]byte{1, 2, 3}
if upfrontShutdown {
// Make new address for second sub-test not to import
// the same address twice causing an error.
taprootPubkey[3] = 1
}
pkScriptBytes := append(
[]byte{txscript.OP_1, txscript.OP_DATA_32},
taprootPubkey[:]...,
)
pkScript, err := txscript.ParsePkScript(pkScriptBytes)
require.NoError(ht, err)
taprootAddress, err := pkScript.Address(harnessNetParams)
require.NoError(ht, err)
var addr string
switch {
// Use ImportTapscript.
case importTapscript:
addr = taprootAddress.String()
// Import the taproot address to LND.
req := &walletrpc.ImportTapscriptRequest{
InternalPublicKey: taprootPubkey[:],
Script: &walletrpc.ImportTapscriptRequest_FullKeyOnly{
FullKeyOnly: true,
},
}
res := alice.RPC.ImportTapscript(req)
require.Equal(ht, addr, res.P2TrAddress)
// Use ImportPublicKey.
case importPubkey:
var (
address btcutil.Address
pubKey []byte
addressType walletrpc.AddressType
)
switch deliveryAddressType {
case lnrpc.AddressType_UNUSED_WITNESS_PUBKEY_HASH:
// Make fake public key hash.
pk := [33]byte{2, 3, 4}
if upfrontShutdown {
// Make new address for second sub-test.
pk[1]++
}
address, err = btcutil.NewAddressWitnessPubKeyHash(
btcutil.Hash160(pk[:]), harnessNetParams,
)
require.NoError(ht, err)
pubKey = pk[:]
addressType = walletrpc.AddressType_WITNESS_PUBKEY_HASH
case lnrpc.AddressType_UNUSED_TAPROOT_PUBKEY:
address = taprootAddress
pubKey = taprootPubkey[:]
addressType = walletrpc.AddressType_TAPROOT_PUBKEY
default:
ht.Fatalf("not allowed address type: %v",
deliveryAddressType)
}
addr = address.String()
// Import the address to LND.
alice.RPC.ImportPublicKey(&walletrpc.ImportPublicKeyRequest{
PublicKey: pubKey,
AddressType: addressType,
})
// Here we generate a final delivery address in bob's wallet but set by
// alice. We do this to ensure that the address is not in alice's LND
// wallet. We already correctly track settled balances when the address
// is in the LND wallet.
addr := bob.RPC.NewAddress(&lnrpc.NewAddressRequest{
Type: deliveryAddressType,
})
default:
res := bob.RPC.NewAddress(&lnrpc.NewAddressRequest{
Type: deliveryAddressType,
})
addr = res.Address
}
// Prepare for channel open.
openParams := lntest.OpenChannelParams{
@@ -76,7 +214,7 @@ func testCoopCloseWithExternalDelivery(ht *lntest.HarnessTest,
// If we are testing the case where we set it on open then we'll set the
// upfront shutdown script in the channel open parameters.
if upfrontShutdown {
openParams.CloseAddress = addr.Address
openParams.CloseAddress = addr
}
// Open the channel!
@@ -91,14 +229,14 @@ func testCoopCloseWithExternalDelivery(ht *lntest.HarnessTest,
// If we are testing the case where we set the delivery address on
// channel close then we will set it in the channel close parameters.
if !upfrontShutdown {
closeParams.DeliveryAddress = addr.Address
closeParams.DeliveryAddress = addr
}
// Close the channel!
closeClient := alice.RPC.CloseChannel(&closeParams)
// Assert that we got a channel update when we get a closing txid.
_, err := closeClient.Recv()
_, err = closeClient.Recv()
require.NoError(ht, err)
// Mine the closing transaction.