itest: test backup restore of script enforced lease channel type

This commit is contained in:
Wilmer Paulino 2021-07-26 13:03:41 -07:00 committed by Olaoluwa Osuntokun
parent 0b0dd65c93
commit e891dd0fd3
No known key found for this signature in database
GPG Key ID: 3BBD59E99B280306
3 changed files with 148 additions and 52 deletions

View File

@ -1109,7 +1109,7 @@ func assertNumPendingChannels(t *harnessTest, node *lntest.HarnessNode,
func assertDLPExecuted(net *lntest.NetworkHarness, t *harnessTest,
carol *lntest.HarnessNode, carolStartingBalance int64,
dave *lntest.HarnessNode, daveStartingBalance int64,
anchors bool) {
commitType lnrpc.CommitmentType) {
// Increase the fee estimate so that the following force close tx will
// be cpfp'ed.
@ -1124,7 +1124,7 @@ func assertDLPExecuted(net *lntest.NetworkHarness, t *harnessTest,
// Upon reconnection, the nodes should detect that Dave is out of sync.
// Carol should force close the channel using her latest commitment.
expectedTxes := 1
if anchors {
if commitTypeHasAnchors(commitType) {
expectedTxes = 2
}
_, err := waitForNTxsInMempool(
@ -1151,13 +1151,6 @@ func assertDLPExecuted(net *lntest.NetworkHarness, t *harnessTest,
// Generate a single block, which should confirm the closing tx.
_ = mineBlocks(t, net, 1, expectedTxes)[0]
// Dave should sweep his funds immediately, as they are not timelocked.
// We also expect Dave to sweep his anchor, if present.
_, err = waitForNTxsInMempool(
net.Miner.Client, expectedTxes, minerMempoolTimeout,
)
require.NoError(t.t, err, "unable to find Dave's sweep tx in mempool")
// Dave should consider the channel pending force close (since he is
// waiting for his sweep to confirm).
assertNumPendingChannels(t, dave, 0, 1)
@ -1166,11 +1159,93 @@ func assertDLPExecuted(net *lntest.NetworkHarness, t *harnessTest,
// before she can sweep her outputs.
assertNumPendingChannels(t, carol, 0, 1)
// Mine the sweep tx.
_ = mineBlocks(t, net, 1, expectedTxes)[0]
if commitType == lnrpc.CommitmentType_SCRIPT_ENFORCED_LEASE {
// Dave should sweep his anchor only, since he still has the
// lease CLTV constraint on his commitment output.
_, err = waitForNTxsInMempool(
net.Miner.Client, 1, minerMempoolTimeout,
)
require.NoError(t.t, err, "unable to find Dave's anchor sweep "+
"tx in mempool")
// Now Dave should consider the channel fully closed.
assertNumPendingChannels(t, dave, 0, 0)
// Mine Dave's anchor sweep tx.
_ = mineBlocks(t, net, 1, 1)[0]
// After Carol's output matures, she should also reclaim her
// funds.
//
// The commit sweep resolver publishes the sweep tx at
// defaultCSV-1 and we already mined one block after the
// commitmment was published, so take that into account.
mineBlocks(t, net, defaultCSV-1-1, 0)
carolSweep, err := waitForTxInMempool(
net.Miner.Client, minerMempoolTimeout,
)
require.NoError(t.t, err, "unable to find Carol's sweep tx in "+
"mempool")
block := mineBlocks(t, net, 1, 1)[0]
assertTxInBlock(t, block, carolSweep)
// Now the channel should be fully closed also from Carol's POV.
assertNumPendingChannels(t, carol, 0, 0)
// We'll now mine the remaining blocks to prompt Dave to sweep
// his CLTV-constrained output.
ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout)
defer cancel()
resp, err := dave.PendingChannels(
ctxt, &lnrpc.PendingChannelsRequest{},
)
require.NoError(t.t, err)
blocksTilMaturity :=
resp.PendingForceClosingChannels[0].BlocksTilMaturity
require.Positive(t.t, blocksTilMaturity)
mineBlocks(t, net, uint32(blocksTilMaturity), 0)
daveSweep, err := waitForTxInMempool(
net.Miner.Client, minerMempoolTimeout,
)
require.NoError(t.t, err, "unable to find Dave's sweep tx in "+
"mempool")
block = mineBlocks(t, net, 1, 1)[0]
assertTxInBlock(t, block, daveSweep)
// Now Dave should consider the channel fully closed.
assertNumPendingChannels(t, dave, 0, 0)
} else {
// Dave should sweep his funds immediately, as they are not
// timelocked. We also expect Dave to sweep his anchor, if
// present.
_, err = waitForNTxsInMempool(
net.Miner.Client, expectedTxes, minerMempoolTimeout,
)
require.NoError(t.t, err, "unable to find Dave's sweep tx in "+
"mempool")
// Mine the sweep tx.
_ = mineBlocks(t, net, 1, expectedTxes)[0]
// Now Dave should consider the channel fully closed.
assertNumPendingChannels(t, dave, 0, 0)
// After Carol's output matures, she should also reclaim her
// funds.
//
// The commit sweep resolver publishes the sweep tx at
// defaultCSV-1 and we already mined one block after the
// commitmment was published, so take that into account.
mineBlocks(t, net, defaultCSV-1-1, 0)
carolSweep, err := waitForTxInMempool(
net.Miner.Client, minerMempoolTimeout,
)
require.NoError(t.t, err, "unable to find Carol's sweep tx in "+
"mempool")
block := mineBlocks(t, net, 1, 1)[0]
assertTxInBlock(t, block, carolSweep)
// Now the channel should be fully closed also from Carol's POV.
assertNumPendingChannels(t, carol, 0, 0)
}
// We query Dave's balance to make sure it increased after the channel
// closed. This checks that he was able to sweep the funds he had in
@ -1185,22 +1260,6 @@ func assertDLPExecuted(net *lntest.NetworkHarness, t *harnessTest,
t.t, daveBalance, daveStartingBalance, "balance not increased",
)
// After the Carol's output matures, she should also reclaim her funds.
//
// The commit sweep resolver publishes the sweep tx at defaultCSV-1 and
// we already mined one block after the commitment was published, so
// take that into account.
mineBlocks(t, net, defaultCSV-1-1, 0)
carolSweep, err := waitForTxInMempool(
net.Miner.Client, minerMempoolTimeout,
)
require.NoError(t.t, err, "unable to find Carol's sweep tx in mempool")
block := mineBlocks(t, net, 1, 1)[0]
assertTxInBlock(t, block, carolSweep)
// Now the channel should be fully closed also from Carol's POV.
assertNumPendingChannels(t, carol, 0, 0)
// Make sure Carol got her balance back.
err = wait.NoError(func() error {
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)

View File

@ -337,10 +337,37 @@ func testChannelBackupRestore(net *lntest.NetworkHarness, t *harnessTest) {
// Restore the backup from the on-disk file, using the RPC
// interface, for anchor commitment channels.
{
name: "restore from backup file anchors",
initiator: true,
private: false,
anchorCommit: true,
name: "restore from backup file anchors",
initiator: true,
private: false,
commitmentType: lnrpc.CommitmentType_ANCHORS,
restoreMethod: func(oldNode *lntest.HarnessNode,
backupFilePath string,
mnemonic []string) (nodeRestorer, error) {
// Read the entire Multi backup stored within
// this node's channels.backup file.
multi, err := ioutil.ReadFile(backupFilePath)
if err != nil {
return nil, err
}
// Now that we have Dave's backup file, we'll
// create a new nodeRestorer that will restore
// using the on-disk channels.backup.
return chanRestoreViaRPC(
net, password, mnemonic, multi, oldNode,
)
},
},
// Restore the backup from the on-disk file, using the RPC
// interface, for script-enforced leased channels.
{
name: "restore from backup file script enforced lease",
initiator: true,
private: false,
commitmentType: lnrpc.CommitmentType_SCRIPT_ENFORCED_LEASE,
restoreMethod: func(oldNode *lntest.HarnessNode,
backupFilePath string,
mnemonic []string) (nodeRestorer, error) {
@ -399,7 +426,7 @@ func testChannelBackupRestore(net *lntest.NetworkHarness, t *harnessTest) {
"anchors",
initiator: true,
private: false,
anchorCommit: true,
commitmentType: lnrpc.CommitmentType_ANCHORS,
localForceClose: true,
restoreMethod: func(oldNode *lntest.HarnessNode,
backupFilePath string,
@ -814,9 +841,9 @@ type chanRestoreTestCase struct {
// confirmed or not.
unconfirmed bool
// anchorCommit is true, then the new anchor commitment type will be
// used for the channels created in the test.
anchorCommit bool
// commitmentType specifies the commitment type that should be used for
// the channel from Dave to Carol.
commitmentType lnrpc.CommitmentType
// legacyRevocation signals if a channel with the legacy revocation
// producer format should also be created before restoring.
@ -854,11 +881,9 @@ func testChanRestoreScenario(t *harnessTest, net *lntest.NetworkHarness,
"--minbackoff=50ms",
"--maxbackoff=1s",
}
if testCase.anchorCommit {
anchorNodeArgs := nodeArgsForCommitType(
lnrpc.CommitmentType_ANCHORS,
)
nodeArgs = append(nodeArgs, anchorNodeArgs...)
if testCase.commitmentType != lnrpc.CommitmentType_UNKNOWN_COMMITMENT_TYPE {
args := nodeArgsForCommitType(testCase.commitmentType)
nodeArgs = append(nodeArgs, args...)
}
// First, we'll create a brand new node we'll use within the test. If
@ -884,7 +909,7 @@ func testChanRestoreScenario(t *harnessTest, net *lntest.NetworkHarness,
// For the anchor output case we need two UTXOs for Carol so she can
// sweep both the local and remote anchor.
if testCase.anchorCommit {
if commitTypeHasAnchors(testCase.commitmentType) {
net.SendCoins(t.t, btcutil.SatoshiPerBitcoin, carol)
}
@ -936,12 +961,23 @@ func testChanRestoreScenario(t *harnessTest, net *lntest.NetworkHarness,
)
default:
var fundingShim *lnrpc.FundingShim
if testCase.commitmentType == lnrpc.CommitmentType_SCRIPT_ENFORCED_LEASE {
_, minerHeight, err := net.Miner.Client.GetBestBlock()
require.NoError(t.t, err)
thawHeight := uint32(minerHeight + 144)
fundingShim, _, _ = deriveFundingShim(
net, t, from, to, chanAmt, thawHeight, true,
)
}
chanPoint = openChannelAndAssert(
t, net, from, to,
lntest.OpenChannelParams{
Amt: chanAmt,
PushAmt: pushAmt,
Private: testCase.private,
t, net, from, to, lntest.OpenChannelParams{
Amt: chanAmt,
PushAmt: pushAmt,
Private: testCase.private,
FundingShim: fundingShim,
CommitmentType: testCase.commitmentType,
},
)
@ -1086,7 +1122,8 @@ func testChanRestoreScenario(t *harnessTest, net *lntest.NetworkHarness,
assertTimeLockSwept(
net, t, carol, carolStartingBalance, dave,
daveStartingBalance, testCase.anchorCommit,
daveStartingBalance,
commitTypeHasAnchors(testCase.commitmentType),
)
return
@ -1167,7 +1204,7 @@ func testChanRestoreScenario(t *harnessTest, net *lntest.NetworkHarness,
require.NoError(t.t, err)
numUTXOs := 1
if testCase.anchorCommit {
if commitTypeHasAnchors(testCase.commitmentType) {
numUTXOs = 2
}
assertNumUTXOs(t.t, carol, numUTXOs)
@ -1183,7 +1220,7 @@ func testChanRestoreScenario(t *harnessTest, net *lntest.NetworkHarness,
// end of the protocol.
assertDLPExecuted(
net, t, carol, carolStartingBalance, dave, daveStartingBalance,
testCase.anchorCommit,
testCase.commitmentType,
)
}

View File

@ -1014,7 +1014,7 @@ func testDataLossProtection(net *lntest.NetworkHarness, t *harnessTest) {
// on chain, and both of them properly carry out the DLP protocol.
assertDLPExecuted(
net, t, carol, carolStartingBalance, dave, daveStartingBalance,
false,
lnrpc.CommitmentType_STATIC_REMOTE_KEY,
)
// As a second part of this test, we will test the scenario where a