itest: extend relevant itests to cover taproot chans final

This commit is contained in:
Olaoluwa Osuntokun 2025-10-29 18:31:27 -07:00
parent d86b84001f
commit 5bbfdc6267
9 changed files with 600 additions and 25 deletions

View file

@ -193,7 +193,8 @@ func newChanRestoreScenario(ht *lntest.HarnessTest, ct lnrpc.CommitmentType,
// If the commitment type is taproot, then the channel must also be
// private.
var privateChan bool
if ct == lnrpc.CommitmentType_SIMPLE_TAPROOT {
if ct == lnrpc.CommitmentType_SIMPLE_TAPROOT ||
ct == lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL {
privateChan = true
}
@ -639,7 +640,8 @@ func runChanRestoreScenarioCommitTypes(ht *lntest.HarnessTest,
// If this was a zero conf taproot channel, then since it's private,
// we'll need to mine an extra block (framework won't mine extra blocks
// otherwise).
if ct == lnrpc.CommitmentType_SIMPLE_TAPROOT && zeroConf {
if (ct == lnrpc.CommitmentType_SIMPLE_TAPROOT ||
ct == lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL) && zeroConf {
ht.MineBlocksAndAssertNumTxes(1, 1)
}

View file

@ -26,6 +26,10 @@ var channelForceCloseTestCases = []*lntest.TestCase{
Name: "simple taproot",
TestFunc: testChannelForceClosureSimpleTaproot,
},
{
Name: "simple taproot final",
TestFunc: testChannelForceClosureSimpleTaprootFinal,
},
{
Name: "anchor restart",
TestFunc: testChannelForceClosureAnchorRestart,
@ -34,6 +38,10 @@ var channelForceCloseTestCases = []*lntest.TestCase{
Name: "simple taproot restart",
TestFunc: testChannelForceClosureSimpleTaprootRestart,
},
{
Name: "simple taproot final restart",
TestFunc: testChannelForceClosureSimpleTaprootFinalRestart,
},
{
Name: "wrong preimage",
@ -87,6 +95,31 @@ func testChannelForceClosureSimpleTaproot(ht *lntest.HarnessTest) {
runChannelForceClosureTest(ht, cfgs, openChannelParams)
}
// testChannelForceClosureSimpleTaprootFinal runs `runChannelForceClosureTest`
// with production simple taproot channels.
func testChannelForceClosureSimpleTaprootFinal(ht *lntest.HarnessTest) {
// Create a simple network: Alice -> Carol, using production simple
// taproot channels.
//
// Prepare params.
openChannelParams := lntest.OpenChannelParams{
Amt: chanAmt,
PushAmt: pushAmt,
// If the channel is a taproot channel, then we'll need to
// create a private channel.
//
// TODO(roasbeef): lift after G175
CommitmentType: lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL,
Private: true,
}
cfg := node.CfgSimpleTaproot
cfgCarol := append([]string{"--hodl.exit-settle"}, cfg...)
cfgs := [][]string{cfg, cfgCarol}
runChannelForceClosureTest(ht, cfgs, openChannelParams)
}
// runChannelForceClosureTest performs a test to exercise the behavior of
// "force" closing a channel or unilaterally broadcasting the latest local
// commitment state on-chain. The test creates a new channel between Alice and
@ -675,6 +708,31 @@ func testChannelForceClosureSimpleTaprootRestart(ht *lntest.HarnessTest) {
runChannelForceClosureTestRestart(ht, cfgs, openChannelParams)
}
// testChannelForceClosureSimpleTaprootFinalRestart runs
// `runChannelForceClosureTestRestart` with production simple taproot channels.
func testChannelForceClosureSimpleTaprootFinalRestart(ht *lntest.HarnessTest) {
// Create a simple network: Alice -> Carol, using production simple
// taproot channels.
//
// Prepare params.
openChannelParams := lntest.OpenChannelParams{
Amt: chanAmt,
PushAmt: pushAmt,
// If the channel is a taproot channel, then we'll need to
// create a private channel.
//
// TODO(roasbeef): lift after G175
CommitmentType: lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL,
Private: true,
}
cfg := node.CfgSimpleTaproot
cfgCarol := append([]string{"--hodl.exit-settle"}, cfg...)
cfgs := [][]string{cfg, cfgCarol}
runChannelForceClosureTestRestart(ht, cfgs, openChannelParams)
}
// runChannelForceClosureTestRestart performs a test to exercise the behavior of
// "force" closing a channel or unilaterally broadcasting the latest local
// commitment state on-chain. The test creates a new channel between Alice and

View file

@ -33,6 +33,10 @@ var basicFundingTestCases = []*lntest.TestCase{
Name: "basic flow simple taproot",
TestFunc: testBasicChannelFundingSimpleTaproot,
},
{
Name: "basic flow simple taproot final",
TestFunc: testBasicChannelFundingSimpleTaprootFinal,
},
}
// allFundingTypes defines the channel types to test for the basic funding
@ -41,6 +45,7 @@ var allFundingTypes = []lnrpc.CommitmentType{
lnrpc.CommitmentType_STATIC_REMOTE_KEY,
lnrpc.CommitmentType_ANCHORS,
lnrpc.CommitmentType_SIMPLE_TAPROOT,
lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL,
}
// testBasicChannelFundingStaticRemote performs a test exercising expected
@ -130,6 +135,35 @@ func testBasicChannelFundingSimpleTaproot(ht *lntest.HarnessTest) {
}
}
// testBasicChannelFundingSimpleTaprootFinal performs a test exercising expected
// behavior from a basic funding workflow. The test creates a new channel
// between Carol and Dave, with Carol using the production simple taproot
// commitment type, and Dave using allFundingTypes.
func testBasicChannelFundingSimpleTaprootFinal(ht *lntest.HarnessTest) {
carolCommitType := lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL
// We'll test all possible combinations of the feature bit presence
// that both nodes can signal for this new channel type. We'll make a
// new Carol+Dave for each test instance as well.
for _, daveCommitType := range allFundingTypes {
cc := carolCommitType
dc := daveCommitType
testName := fmt.Sprintf(
"carol_commit=%v,dave_commit=%v", cc, dc,
)
success := ht.Run(testName, func(t *testing.T) {
st := ht.Subtest(t)
runBasicFundingTest(st, cc, dc)
})
if !success {
break
}
}
}
// runBasicFundingTest is a helper function that takes Carol and Dave's
// commitment types and test the funding flow.
func runBasicFundingTest(ht *lntest.HarnessTest, carolCommitType,
@ -158,14 +192,17 @@ func runBasicFundingTest(ht *lntest.HarnessTest, carolCommitType,
// private, otherwise it'll be rejected by Dave.
//
// TODO(roasbeef): lift after gossip 1.75
if carolCommitType == lnrpc.CommitmentType_SIMPLE_TAPROOT {
if carolCommitType == lnrpc.CommitmentType_SIMPLE_TAPROOT ||
carolCommitType == lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL {
privateChan = true
}
// If carol wants taproot, but dave wants something else, then we'll
// assert that the channel negotiation attempt fails.
// If carol wants taproot, but dave wants something else (excluding
// SIMPLE_TAPROOT_FINAL which is allowed via cross-type negotiation),
// then we'll assert that the channel negotiation attempt fails.
if carolCommitType == lnrpc.CommitmentType_SIMPLE_TAPROOT &&
daveCommitType != lnrpc.CommitmentType_SIMPLE_TAPROOT {
daveCommitType != lnrpc.CommitmentType_SIMPLE_TAPROOT &&
daveCommitType != lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL {
expectedErr := fmt.Errorf("requested channel type " +
"not supported")
@ -181,6 +218,12 @@ func runBasicFundingTest(ht *lntest.HarnessTest, carolCommitType,
return
}
// NOTE: With both staging and final feature bits advertised by default,
// cross-type negotiation (e.g., Carol wants FINAL, Dave prefers
// STAGING) will succeed because explicit channel_type takes precedence.
// The channel will be created with Carol's requested type (FINAL) since
// Dave advertises support for it.
carolChan, daveChan := basicChannelFundingTest(
ht, carol, dave, nil, privateChan, &carolCommitType,
)
@ -196,6 +239,9 @@ func runBasicFundingTest(ht *lntest.HarnessTest, carolCommitType,
expType := carolCommitType
switch daveCommitType {
// Dave supports production taproot, type will be what Carol supports.
case lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL:
// Dave supports taproot, type will be what Carol supports.
case lnrpc.CommitmentType_SIMPLE_TAPROOT:
@ -206,6 +252,9 @@ func runBasicFundingTest(ht *lntest.HarnessTest, carolCommitType,
if expType == lnrpc.CommitmentType_SIMPLE_TAPROOT {
expType = lnrpc.CommitmentType_ANCHORS
}
if expType == lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL {
expType = lnrpc.CommitmentType_ANCHORS
}
// Dave only supports tweakless, channel will be downgraded to this
// type if Carol supports anchors.
@ -215,6 +264,8 @@ func runBasicFundingTest(ht *lntest.HarnessTest, carolCommitType,
expType = lnrpc.CommitmentType_STATIC_REMOTE_KEY
case lnrpc.CommitmentType_SIMPLE_TAPROOT:
expType = lnrpc.CommitmentType_STATIC_REMOTE_KEY
case lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL:
expType = lnrpc.CommitmentType_STATIC_REMOTE_KEY
}
// Dave only supports legacy type, channel will be downgraded to this
@ -240,6 +291,9 @@ func runBasicFundingTest(ht *lntest.HarnessTest, carolCommitType,
case expType == lnrpc.CommitmentType_SIMPLE_TAPROOT &&
chansCommitType == lnrpc.CommitmentType_SIMPLE_TAPROOT:
case expType == lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL &&
chansCommitType == lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL:
default:
ht.Fatalf("expected nodes to signal commit type %v, instead "+
"got %v", expType, chansCommitType)
@ -289,10 +343,13 @@ func basicChannelFundingTest(ht *lntest.HarnessTest,
// explicit commitment type. This allows us to continue supporting the
// existing min version comparison for implicit negotiation.
var commitTypeParam lnrpc.CommitmentType
if commitType != nil &&
*commitType == lnrpc.CommitmentType_SIMPLE_TAPROOT {
if commitType != nil {
switch *commitType {
case lnrpc.CommitmentType_SIMPLE_TAPROOT,
lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL:
commitTypeParam = *commitType
commitTypeParam = *commitType
}
}
// First establish a channel with a capacity of 0.5 BTC between Alice
@ -834,9 +891,38 @@ func runExternalFundingTaproot(ht *lntest.HarnessTest) {
// HTLCs.
ht.AssertInvoiceSettled(dave, resp.PaymentAddr)
// Mine past the thaw height so the channel can be cooperatively
// closed. With RBF cooperative close (auto-enabled for taproot
// channels), both sides enforce the thaw height check during
// shutdown negotiation.
ht.MineBlocks(int(thawHeight))
// Next we'll try but this time with Dave (the responder) as the
// initiator. This time the channel should be closed as normal.
ht.CloseChannel(dave, chanPoint2)
// initiator. With RBF close auto-enabled for taproot channels,
// both sides create competing closing txs. Only one makes it
// to the mempool (the other is rejected as a same-fee RBF).
// We skip the mempool check since the local tx may not be the
// one that made it in.
closeStream, _ := ht.CloseChannelAssertPending(
dave, chanPoint2, false,
lntest.WithSkipMempoolCheck(),
)
// Mine a block to confirm whichever closing tx is in the mempool.
ht.MineBlocksAndAssertNumTxes(1, 1)
// Consume updates until we get the final ChanClose event. The
// RBF close protocol may send multiple ClosePending updates
// (one per side's closing tx proposal) before the final close.
for {
event, err := ht.ReceiveCloseChannelUpdate(closeStream)
require.NoError(ht, err)
//nolint:ll
if _, ok := event.Update.(*lnrpc.CloseStatusUpdate_ChanClose); ok {
break
}
}
// Let's make sure we can abandon it.
carol.RPC.AbandonChannel(&lnrpc.AbandonChannelRequest{

View file

@ -47,6 +47,14 @@ var multiHopForceCloseTestCases = []*lntest.TestCase{
Name: "local claim outgoing htlc simple taproot zero conf",
TestFunc: testLocalClaimOutgoingHTLCSimpleTaprootZeroConf,
},
{
Name: "local claim outgoing htlc simple taproot final",
TestFunc: testLocalClaimOutgoingHTLCSimpleTaprootFinal,
},
{
Name: "local claim outgoing htlc simple taproot final zero conf",
TestFunc: testLocalClaimOutgoingHTLCSimpleTaprootFinalZeroConf,
},
{
Name: "local claim outgoing htlc leased",
TestFunc: testLocalClaimOutgoingHTLCLeased,
@ -71,6 +79,14 @@ var multiHopForceCloseTestCases = []*lntest.TestCase{
Name: "receiver preimage claim simple taproot zero conf",
TestFunc: testMultiHopReceiverPreimageClaimSimpleTaprootZeroConf,
},
{
Name: "receiver preimage claim simple taproot final",
TestFunc: testMultiHopReceiverPreimageClaimSimpleTaprootFinal,
},
{
Name: "receiver preimage claim simple taproot final zero conf",
TestFunc: testMultiHopReceiverPreimageClaimSimpleTaprootFinalZeroConf,
},
{
Name: "receiver preimage claim leased",
TestFunc: testMultiHopReceiverPreimageClaimLeased,
@ -95,6 +111,14 @@ var multiHopForceCloseTestCases = []*lntest.TestCase{
Name: "local force close before timeout simple taproot zero conf",
TestFunc: testLocalForceCloseBeforeTimeoutSimpleTaprootZeroConf,
},
{
Name: "local force close before timeout simple taproot final",
TestFunc: testLocalForceCloseBeforeTimeoutSimpleTaprootFinal,
},
{
Name: "local force close before timeout simple taproot final zero conf",
TestFunc: testLocalForceCloseBeforeTimeoutSimpleTaprootFinalZeroConf,
},
{
Name: "local force close before timeout leased",
TestFunc: testLocalForceCloseBeforeTimeoutLeased,
@ -119,6 +143,14 @@ var multiHopForceCloseTestCases = []*lntest.TestCase{
Name: "remote force close before timeout simple taproot zero conf",
TestFunc: testRemoteForceCloseBeforeTimeoutSimpleTaprootZeroConf,
},
{
Name: "remote force close before timeout simple taproot final",
TestFunc: testRemoteForceCloseBeforeTimeoutSimpleTaprootFinal,
},
{
Name: "remote force close before timeout simple taproot final zero conf",
TestFunc: testRemoteForceCloseBeforeTimeoutSimpleTaprootFinalZeroConf,
},
{
Name: "remote force close before timeout leased",
TestFunc: testRemoteForceCloseBeforeTimeoutLeased,
@ -143,6 +175,14 @@ var multiHopForceCloseTestCases = []*lntest.TestCase{
Name: "local claim incoming htlc simple taproot zero conf",
TestFunc: testLocalClaimIncomingHTLCSimpleTaprootZeroConf,
},
{
Name: "local claim incoming htlc simple taproot final",
TestFunc: testLocalClaimIncomingHTLCSimpleTaprootFinal,
},
{
Name: "local claim incoming htlc simple taproot final zero conf",
TestFunc: testLocalClaimIncomingHTLCSimpleTaprootFinalZeroConf,
},
{
Name: "local claim incoming htlc leased",
TestFunc: testLocalClaimIncomingHTLCLeased,
@ -167,6 +207,14 @@ var multiHopForceCloseTestCases = []*lntest.TestCase{
Name: "local preimage claim simple taproot zero conf",
TestFunc: testLocalPreimageClaimSimpleTaprootZeroConf,
},
{
Name: "local preimage claim simple taproot final",
TestFunc: testLocalPreimageClaimSimpleTaprootFinal,
},
{
Name: "local preimage claim simple taproot final zero conf",
TestFunc: testLocalPreimageClaimSimpleTaprootFinalZeroConf,
},
{
Name: "local preimage claim leased",
TestFunc: testLocalPreimageClaimLeased,
@ -191,6 +239,14 @@ var multiHopForceCloseTestCases = []*lntest.TestCase{
Name: "htlc aggregation simple taproot zero conf",
TestFunc: testHtlcAggregaitonSimpleTaprootZeroConf,
},
{
Name: "htlc aggregation simple taproot final",
TestFunc: testHtlcAggregationSimpleTaprootFinal,
},
{
Name: "htlc aggregation simple taproot final zero conf",
TestFunc: testHtlcAggregationSimpleTaprootFinalZeroConf,
},
{
Name: "htlc aggregation leased",
TestFunc: testHtlcAggregaitonLeased,
@ -285,6 +341,53 @@ func testLocalClaimOutgoingHTLCSimpleTaprootZeroConf(ht *lntest.HarnessTest) {
runLocalClaimOutgoingHTLC(ht, cfgs, openChannelParams)
}
// testLocalClaimOutgoingHTLCSimpleTaprootFinal tests
// `runLocalClaimOutgoingHTLC` with production simple taproot channel.
func testLocalClaimOutgoingHTLCSimpleTaprootFinal(ht *lntest.HarnessTest) {
c := lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL
// Create a three hop network: Alice -> Bob -> Carol, using production
// simple taproot channels.
//
// Prepare params.
openChannelParams := lntest.OpenChannelParams{
Amt: chanAmt,
CommitmentType: c,
Private: true,
}
cfg := node.CfgSimpleTaproot
cfgCarol := append([]string{"--hodl.exit-settle"}, cfg...)
cfgs := [][]string{cfg, cfg, cfgCarol}
runLocalClaimOutgoingHTLC(ht, cfgs, openChannelParams)
}
// testLocalClaimOutgoingHTLCSimpleTaprootFinalZeroConf tests
// `runLocalClaimOutgoingHTLC` with zero-conf production simple taproot channel.
func testLocalClaimOutgoingHTLCSimpleTaprootFinalZeroConf(ht *lntest.HarnessTest) {
c := lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL
// Create a three hop network: Alice -> Bob -> Carol, using zero-conf
// production simple taproot channels.
//
// Prepare params.
openChannelParams := lntest.OpenChannelParams{
Amt: chanAmt,
ZeroConf: true,
CommitmentType: c,
Private: true,
}
// Prepare Carol's node config to enable zero-conf and leased channel.
cfg := node.CfgSimpleTaproot
cfg = append(cfg, node.CfgZeroConf...)
cfgCarol := append([]string{"--hodl.exit-settle"}, cfg...)
cfgs := [][]string{cfg, cfg, cfgCarol}
runLocalClaimOutgoingHTLC(ht, cfgs, openChannelParams)
}
// testLocalClaimOutgoingHTLCLeased tests `runLocalClaimOutgoingHTLC` with
// script enforced lease channel.
func testLocalClaimOutgoingHTLCLeased(ht *lntest.HarnessTest) {
@ -361,7 +464,8 @@ func runLocalClaimOutgoingHTLC(ht *lntest.HarnessTest,
// If this is a taproot channel, then we'll need to make some manual
// route hints so Alice can actually find a route.
var routeHints []*lnrpc.RouteHint
if params.CommitmentType == lnrpc.CommitmentType_SIMPLE_TAPROOT {
if params.CommitmentType == lnrpc.CommitmentType_SIMPLE_TAPROOT ||
params.CommitmentType == lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL {
routeHints = makeRouteHints(bob, carol, params.ZeroConf)
}
@ -623,6 +727,55 @@ func testMultiHopReceiverPreimageClaimSimpleTaprootZeroConf(
runMultiHopReceiverPreimageClaim(ht, cfgs, openChannelParams)
}
// testMultiHopReceiverPreimageClaimSimpleTaprootFinal tests
// `runMultiHopReceiverPreimageClaim` with production simple taproot channels.
func testMultiHopReceiverPreimageClaimSimpleTaprootFinal(ht *lntest.HarnessTest) {
c := lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL
// Create a three hop network: Alice -> Bob -> Carol, using production
// simple taproot channels.
//
// Prepare params.
openChannelParams := lntest.OpenChannelParams{
Amt: chanAmt,
CommitmentType: c,
Private: true,
}
cfg := node.CfgSimpleTaproot
cfgs := [][]string{cfg, cfg, cfg}
runMultiHopReceiverPreimageClaim(ht, cfgs, openChannelParams)
}
// testMultiHopReceiverPreimageClaimSimpleTaprootFinalZeroConf tests
// `runMultiHopReceiverPreimageClaim` with zero-conf production simple taproot
// channels.
func testMultiHopReceiverPreimageClaimSimpleTaprootFinalZeroConf(
ht *lntest.HarnessTest) {
c := lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL
// Create a three hop network: Alice -> Bob -> Carol, using zero-conf
// production simple taproot channels.
//
// Prepare params.
openChannelParams := lntest.OpenChannelParams{
Amt: chanAmt,
ZeroConf: true,
CommitmentType: c,
Private: true,
}
// Prepare Carol's node config to enable zero-conf and leased
// channel.
cfg := node.CfgSimpleTaproot
cfg = append(cfg, node.CfgZeroConf...)
cfgs := [][]string{cfg, cfg, cfg}
runMultiHopReceiverPreimageClaim(ht, cfgs, openChannelParams)
}
// testMultiHopReceiverPreimageClaimLeased tests
// `runMultiHopReceiverPreimageClaim` with script enforce lease channels.
func testMultiHopReceiverPreimageClaimLeased(ht *lntest.HarnessTest) {
@ -697,7 +850,8 @@ func runMultiHopReceiverPreimageClaim(ht *lntest.HarnessTest,
// If this is a taproot channel, then we'll need to make some manual
// route hints so Alice can actually find a route.
var routeHints []*lnrpc.RouteHint
if params.CommitmentType == lnrpc.CommitmentType_SIMPLE_TAPROOT {
if params.CommitmentType == lnrpc.CommitmentType_SIMPLE_TAPROOT ||
params.CommitmentType == lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL {
routeHints = makeRouteHints(bob, carol, params.ZeroConf)
}
@ -978,6 +1132,56 @@ func testLocalForceCloseBeforeTimeoutSimpleTaprootZeroConf(
runLocalForceCloseBeforeHtlcTimeout(ht, cfgs, params)
}
// testLocalForceCloseBeforeTimeoutSimpleTaprootFinal tests
// `runLocalForceCloseBeforeHtlcTimeout` with production simple taproot channel.
func testLocalForceCloseBeforeTimeoutSimpleTaprootFinal(ht *lntest.HarnessTest) {
c := lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL
// Create a three hop network: Alice -> Bob -> Carol, using production
// simple taproot channels.
//
// Prepare params.
params := lntest.OpenChannelParams{
Amt: chanAmt,
CommitmentType: c,
Private: true,
}
cfg := node.CfgSimpleTaproot
cfgCarol := append([]string{"--hodl.exit-settle"}, cfg...)
cfgs := [][]string{cfg, cfg, cfgCarol}
runLocalForceCloseBeforeHtlcTimeout(ht, cfgs, params)
}
// testLocalForceCloseBeforeTimeoutSimpleTaprootFinalZeroConf tests
// `runLocalForceCloseBeforeHtlcTimeout` with zero-conf production simple
// taproot channel.
func testLocalForceCloseBeforeTimeoutSimpleTaprootFinalZeroConf(
ht *lntest.HarnessTest) {
c := lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL
// Create a three hop network: Alice -> Bob -> Carol, using zero-conf
// production simple taproot channels.
//
// Prepare params.
params := lntest.OpenChannelParams{
Amt: chanAmt,
ZeroConf: true,
CommitmentType: c,
Private: true,
}
// Prepare Carol's node config to enable zero-conf and leased channel.
cfg := node.CfgSimpleTaproot
cfg = append(cfg, node.CfgZeroConf...)
cfgCarol := append([]string{"--hodl.exit-settle"}, cfg...)
cfgs := [][]string{cfg, cfg, cfgCarol}
runLocalForceCloseBeforeHtlcTimeout(ht, cfgs, params)
}
// testLocalForceCloseBeforeTimeoutLeased tests
// `runLocalForceCloseBeforeHtlcTimeout` with script enforced lease channel.
func testLocalForceCloseBeforeTimeoutLeased(ht *lntest.HarnessTest) {
@ -1047,7 +1251,8 @@ func runLocalForceCloseBeforeHtlcTimeout(ht *lntest.HarnessTest,
// If this is a taproot channel, then we'll need to make some manual
// route hints so Alice can actually find a route.
var routeHints []*lnrpc.RouteHint
if params.CommitmentType == lnrpc.CommitmentType_SIMPLE_TAPROOT {
if params.CommitmentType == lnrpc.CommitmentType_SIMPLE_TAPROOT ||
params.CommitmentType == lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL {
routeHints = makeRouteHints(bob, carol, params.ZeroConf)
}
@ -1317,6 +1522,56 @@ func testRemoteForceCloseBeforeTimeoutSimpleTaproot(ht *lntest.HarnessTest) {
runRemoteForceCloseBeforeHtlcTimeout(ht, cfgs, params)
}
// testRemoteForceCloseBeforeTimeoutSimpleTaprootFinal tests
// `runRemoteForceCloseBeforeHtlcTimeout` with production simple taproot channel.
func testRemoteForceCloseBeforeTimeoutSimpleTaprootFinal(ht *lntest.HarnessTest) {
c := lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL
// Create a three hop network: Alice -> Bob -> Carol, using production
// simple taproot channels.
//
// Prepare params.
params := lntest.OpenChannelParams{
Amt: chanAmt,
CommitmentType: c,
Private: true,
}
cfg := node.CfgSimpleTaproot
cfgCarol := append([]string{"--hodl.exit-settle"}, cfg...)
cfgs := [][]string{cfg, cfg, cfgCarol}
runRemoteForceCloseBeforeHtlcTimeout(ht, cfgs, params)
}
// testRemoteForceCloseBeforeTimeoutSimpleTaprootFinalZeroConf tests
// `runRemoteForceCloseBeforeHtlcTimeout` with zero-conf production simple
// taproot channel.
func testRemoteForceCloseBeforeTimeoutSimpleTaprootFinalZeroConf(
ht *lntest.HarnessTest) {
c := lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL
// Create a three hop network: Alice -> Bob -> Carol, using zero-conf
// production simple taproot channels.
//
// Prepare params.
params := lntest.OpenChannelParams{
Amt: chanAmt,
ZeroConf: true,
CommitmentType: c,
Private: true,
}
// Prepare Carol's node config to enable zero-conf and leased channel.
cfg := node.CfgSimpleTaproot
cfg = append(cfg, node.CfgZeroConf...)
cfgCarol := append([]string{"--hodl.exit-settle"}, cfg...)
cfgs := [][]string{cfg, cfg, cfgCarol}
runRemoteForceCloseBeforeHtlcTimeout(ht, cfgs, params)
}
// testRemoteForceCloseBeforeTimeoutLeasedZeroConf tests
// `runRemoteForceCloseBeforeHtlcTimeout` with zero-conf script enforced lease
// channel.
@ -1383,7 +1638,8 @@ func runRemoteForceCloseBeforeHtlcTimeout(ht *lntest.HarnessTest,
// If this is a taproot channel, then we'll need to make some manual
// route hints so Alice can actually find a route.
var routeHints []*lnrpc.RouteHint
if params.CommitmentType == lnrpc.CommitmentType_SIMPLE_TAPROOT {
if params.CommitmentType == lnrpc.CommitmentType_SIMPLE_TAPROOT ||
params.CommitmentType == lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL {
routeHints = makeRouteHints(bob, carol, params.ZeroConf)
}
@ -1614,6 +1870,52 @@ func testLocalClaimIncomingHTLCSimpleTaproot(ht *lntest.HarnessTest) {
runLocalClaimIncomingHTLC(ht, cfgs, params)
}
// testLocalClaimIncomingHTLCSimpleTaprootFinal tests
// `runLocalClaimIncomingHTLC` with production simple taproot channel.
func testLocalClaimIncomingHTLCSimpleTaprootFinal(ht *lntest.HarnessTest) {
c := lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL
// Create a three hop network: Alice -> Bob -> Carol, using production
// simple taproot channels.
//
// Prepare params.
params := lntest.OpenChannelParams{
Amt: chanAmt,
CommitmentType: c,
Private: true,
}
cfg := node.CfgSimpleTaproot
cfgs := [][]string{cfg, cfg, cfg}
runLocalClaimIncomingHTLC(ht, cfgs, params)
}
// testLocalClaimIncomingHTLCSimpleTaprootFinalZeroConf tests
// `runLocalClaimIncomingHTLC` with zero-conf production simple taproot channel.
func testLocalClaimIncomingHTLCSimpleTaprootFinalZeroConf(ht *lntest.HarnessTest) {
c := lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL
// Create a three hop network: Alice -> Bob -> Carol, using zero-conf
// production simple taproot channels.
//
// Prepare params.
params := lntest.OpenChannelParams{
Amt: chanAmt,
ZeroConf: true,
CommitmentType: c,
Private: true,
}
// Prepare Carol's node config to enable zero-conf and simple taproot
// channel.
cfg := node.CfgSimpleTaproot
cfg = append(cfg, node.CfgZeroConf...)
cfgs := [][]string{cfg, cfg, cfg}
runLocalClaimIncomingHTLC(ht, cfgs, params)
}
// runLocalClaimIncomingHTLC tests that in a multi-hop HTLC scenario, if we
// force close a channel with an incoming HTLC, and later find out the preimage
// via the witness beacon, we properly settle the HTLC on-chain using the HTLC
@ -1639,7 +1941,8 @@ func runLocalClaimIncomingHTLC(ht *lntest.HarnessTest,
// If this is a taproot channel, then we'll need to make some manual
// route hints so Alice can actually find a route.
var routeHints []*lnrpc.RouteHint
if params.CommitmentType == lnrpc.CommitmentType_SIMPLE_TAPROOT {
if params.CommitmentType == lnrpc.CommitmentType_SIMPLE_TAPROOT ||
params.CommitmentType == lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL {
routeHints = makeRouteHints(bob, carol, params.ZeroConf)
}
@ -2242,6 +2545,51 @@ func testLocalPreimageClaimSimpleTaproot(ht *lntest.HarnessTest) {
runLocalPreimageClaim(ht, cfgs, params)
}
// testLocalPreimageClaimSimpleTaprootFinal tests `runLocalPreimageClaim` with
// production simple taproot channel.
func testLocalPreimageClaimSimpleTaprootFinal(ht *lntest.HarnessTest) {
c := lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL
// Create a three hop network: Alice -> Bob -> Carol, using production
// simple taproot channels.
//
// Prepare params.
params := lntest.OpenChannelParams{
Amt: chanAmt,
CommitmentType: c,
Private: true,
}
cfg := node.CfgSimpleTaproot
cfgs := [][]string{cfg, cfg, cfg}
runLocalPreimageClaim(ht, cfgs, params)
}
// testLocalPreimageClaimSimpleTaprootFinalZeroConf tests
// `runLocalPreimageClaim` with zero-conf production simple taproot channel.
func testLocalPreimageClaimSimpleTaprootFinalZeroConf(ht *lntest.HarnessTest) {
c := lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL
// Create a three hop network: Alice -> Bob -> Carol, using zero-conf
// production simple taproot channels.
//
// Prepare params.
params := lntest.OpenChannelParams{
Amt: chanAmt,
ZeroConf: true,
CommitmentType: c,
Private: true,
}
// Prepare Carol's node config to enable zero-conf and leased channel.
cfg := node.CfgSimpleTaproot
cfg = append(cfg, node.CfgZeroConf...)
cfgs := [][]string{cfg, cfg, cfg}
runLocalPreimageClaim(ht, cfgs, params)
}
// runLocalPreimageClaim tests that in the multi-hop HTLC scenario, if the
// remote party goes to chain while we have an incoming HTLC, then when we
// found out the preimage via the witness beacon, we properly settle the HTLC
@ -2268,7 +2616,8 @@ func runLocalPreimageClaim(ht *lntest.HarnessTest,
// If this is a taproot channel, then we'll need to make some manual
// route hints so Alice can actually find a route.
var routeHints []*lnrpc.RouteHint
if params.CommitmentType == lnrpc.CommitmentType_SIMPLE_TAPROOT {
if params.CommitmentType == lnrpc.CommitmentType_SIMPLE_TAPROOT ||
params.CommitmentType == lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL {
routeHints = makeRouteHints(bob, carol, params.ZeroConf)
}
@ -2814,6 +3163,51 @@ func testHtlcAggregaitonSimpleTaproot(ht *lntest.HarnessTest) {
runHtlcAggregation(ht, cfgs, params)
}
// testHtlcAggregationSimpleTaprootFinal tests `runHtlcAggregation` with
// production simple taproot channel.
func testHtlcAggregationSimpleTaprootFinal(ht *lntest.HarnessTest) {
c := lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL
// Create a three hop network: Alice -> Bob -> Carol, using production
// simple taproot channels.
//
// Prepare params.
params := lntest.OpenChannelParams{
Amt: chanAmt,
CommitmentType: c,
Private: true,
}
cfg := node.CfgSimpleTaproot
cfgs := [][]string{cfg, cfg, cfg}
runHtlcAggregation(ht, cfgs, params)
}
// testHtlcAggregationSimpleTaprootFinalZeroConf tests `runHtlcAggregation`
// with zero-conf production simple taproot channel.
func testHtlcAggregationSimpleTaprootFinalZeroConf(ht *lntest.HarnessTest) {
c := lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL
// Create a three hop network: Alice -> Bob -> Carol, using zero-conf
// production simple taproot channels.
//
// Prepare params.
params := lntest.OpenChannelParams{
Amt: chanAmt,
ZeroConf: true,
CommitmentType: c,
Private: true,
}
// Prepare Carol's node config to enable zero-conf and leased channel.
cfg := node.CfgSimpleTaproot
cfg = append(cfg, node.CfgZeroConf...)
cfgs := [][]string{cfg, cfg, cfg}
runHtlcAggregation(ht, cfgs, params)
}
// testHtlcAggregaitonLeasedZeroConf tests `runHtlcAggregation` with zero-conf
// script enforced lease channel.
func testHtlcAggregaitonLeasedZeroConf(ht *lntest.HarnessTest) {
@ -2884,7 +3278,8 @@ func runHtlcAggregation(ht *lntest.HarnessTest,
aliceRouteHints []*lnrpc.RouteHint
)
if params.CommitmentType == lnrpc.CommitmentType_SIMPLE_TAPROOT {
if params.CommitmentType == lnrpc.CommitmentType_SIMPLE_TAPROOT ||
params.CommitmentType == lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL {
carolRouteHints = makeRouteHints(bob, carol, params.ZeroConf)
aliceRouteHints = makeRouteHints(bob, alice, params.ZeroConf)
}

View file

@ -709,7 +709,8 @@ func runAsyncPayments(ht *lntest.HarnessTest, alice, bob *node.HarnessNode,
if commitType != nil {
chanArgs.CommitmentType = *commitType
if *commitType == lnrpc.CommitmentType_SIMPLE_TAPROOT {
if *commitType == lnrpc.CommitmentType_SIMPLE_TAPROOT ||
*commitType == lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL {
chanArgs.Private = true
}
}

View file

@ -145,7 +145,8 @@ func runPsbtChanFundingWithNodes(ht *lntest.HarnessTest, carol,
// If this is a taproot channel, then we'll decode the PSBT to assert
// that an internal key is included.
if commitType == lnrpc.CommitmentType_SIMPLE_TAPROOT {
if commitType == lnrpc.CommitmentType_SIMPLE_TAPROOT ||
commitType == lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL {
decodedPSBT, err := psbt.NewFromRawBytes(
bytes.NewReader(tempPsbt), false,
)

View file

@ -47,6 +47,10 @@ var remoteSignerTestCases = []*lntest.TestCase{
Name: "funding async payments taproot",
TestFunc: testRemoteSignerAsyncPaymentsTaproot,
},
{
Name: "funding async payments taproot final",
TestFunc: testRemoteSignerAsyncPaymentsTaprootFinal,
},
{
Name: "shared key",
TestFunc: testRemoteSignerSharedKey,
@ -154,7 +158,8 @@ func prepareRemoteSignerTest(ht *lntest.HarnessTest, tc remoteSignerTestCase) (
}
var commitArgs []string
if tc.commitType == lnrpc.CommitmentType_SIMPLE_TAPROOT {
if tc.commitType == lnrpc.CommitmentType_SIMPLE_TAPROOT ||
tc.commitType == lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL {
commitArgs = lntest.NodeArgsForCommitType(
tc.commitType,
)
@ -307,6 +312,24 @@ func testRemoteSignerAsyncPaymentsTaproot(ht *lntest.HarnessTest) {
tc.fn(ht, watchOnly, carol)
}
func testRemoteSignerAsyncPaymentsTaprootFinal(ht *lntest.HarnessTest) {
tc := remoteSignerTestCase{
name: "async payments taproot final",
sendCoins: true,
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
commitType := lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL
runAsyncPayments(
tt, wo, carol, &commitType,
)
},
commitType: lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL,
}
_, watchOnly, carol := prepareRemoteSignerTest(ht, tc)
tc.fn(ht, watchOnly, carol)
}
func testRemoteSignerSharedKey(ht *lntest.HarnessTest) {
tc := remoteSignerTestCase{
name: "shared key",

View file

@ -52,7 +52,8 @@ func breachRetributionTestCase(ht *lntest.HarnessTest,
// In order to test Carol's response to an uncooperative channel
// closure by Bob, we'll first open up a channel between them with a
// 0.5 BTC value.
privateChan := commitType == lnrpc.CommitmentType_SIMPLE_TAPROOT
privateChan := commitType == lnrpc.CommitmentType_SIMPLE_TAPROOT ||
commitType == lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL
chanPoint := ht.OpenChannel(
carol, bob, lntest.OpenChannelParams{
CommitmentType: commitType,
@ -198,6 +199,7 @@ func breachRetributionTestCase(ht *lntest.HarnessTest,
func testRevokedCloseRetribution(ht *lntest.HarnessTest) {
for _, commitType := range []lnrpc.CommitmentType{
lnrpc.CommitmentType_SIMPLE_TAPROOT,
lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL,
} {
testName := fmt.Sprintf("%v", commitType.String())
ht.Run(testName, func(t *testing.T) {
@ -248,7 +250,8 @@ func revokedCloseRetributionZeroValueRemoteOutputCase(ht *lntest.HarnessTest,
// In order to test Dave's response to an uncooperative channel
// closure by Carol, we'll first open up a channel between them with a
// 0.5 BTC value.
privateChan := commitType == lnrpc.CommitmentType_SIMPLE_TAPROOT
privateChan := commitType == lnrpc.CommitmentType_SIMPLE_TAPROOT ||
commitType == lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL
chanPoint := ht.OpenChannel(
dave, carol, lntest.OpenChannelParams{
CommitmentType: commitType,
@ -381,6 +384,7 @@ func revokedCloseRetributionZeroValueRemoteOutputCase(ht *lntest.HarnessTest,
func testRevokedCloseRetributionZeroValueRemoteOutput(ht *lntest.HarnessTest) {
for _, commitType := range []lnrpc.CommitmentType{
lnrpc.CommitmentType_SIMPLE_TAPROOT,
lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL,
} {
testName := fmt.Sprintf("%v", commitType.String())
ht.Run(testName, func(t *testing.T) {
@ -435,7 +439,8 @@ func revokedCloseRetributionRemoteHodlCase(ht *lntest.HarnessTest,
// In order to test Dave's response to an uncooperative channel closure
// by Carol, we'll first open up a channel between them with a
// funding.MaxBtcFundingAmount (2^24) satoshis value.
privateChan := commitType == lnrpc.CommitmentType_SIMPLE_TAPROOT
privateChan := commitType == lnrpc.CommitmentType_SIMPLE_TAPROOT ||
commitType == lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL
chanPoint := ht.OpenChannel(
dave, carol, lntest.OpenChannelParams{
Amt: chanAmt,
@ -704,6 +709,7 @@ func revokedCloseRetributionRemoteHodlCase(ht *lntest.HarnessTest,
func testRevokedCloseRetributionRemoteHodl(ht *lntest.HarnessTest) {
for _, commitType := range []lnrpc.CommitmentType{
lnrpc.CommitmentType_SIMPLE_TAPROOT,
lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL,
} {
testName := fmt.Sprintf("%v", commitType.String())
ht.Run(testName, func(t *testing.T) {

View file

@ -1730,7 +1730,9 @@ func (h *HarnessTest) OpenChannelPsbt(srcNode, destNode *node.HarnessNode,
require.NoError(h, err)
switch p.CommitmentType {
case lnrpc.CommitmentType_SIMPLE_TAPROOT:
case lnrpc.CommitmentType_SIMPLE_TAPROOT,
lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL:
require.IsType(h, &btcutil.AddressTaproot{}, fundingAddr)
default:
@ -2586,6 +2588,7 @@ func (h *HarnessTest) DeriveFundingShim(alice, bob *node.HarnessNode,
)
if commitType == lnrpc.CommitmentType_SIMPLE_TAPROOT ||
commitType == lnrpc.CommitmentType_SIMPLE_TAPROOT_FINAL ||
commitType == lnrpc.CommitmentType_SIMPLE_TAPROOT_OVERLAY {
var carolKey, daveKey *btcec.PublicKey