github.com/decred/dcrlnd@v0.7.6/lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go (about)

     1  package itest
     2  
     3  import (
     4  	"context"
     5  	"time"
     6  
     7  	"github.com/decred/dcrd/wire"
     8  	"github.com/decred/dcrlnd/lncfg"
     9  	"github.com/decred/dcrlnd/lnrpc"
    10  	"github.com/decred/dcrlnd/lnrpc/invoicesrpc"
    11  	"github.com/decred/dcrlnd/lnrpc/routerrpc"
    12  	"github.com/decred/dcrlnd/lntest"
    13  	"github.com/decred/dcrlnd/lntest/wait"
    14  	"github.com/decred/dcrlnd/lntypes"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  // testMultiHopReceiverChainClaim tests that in the multi-hop setting, if the
    19  // receiver of an HTLC knows the preimage, but wasn't able to settle the HTLC
    20  // off-chain, then it goes on chain to claim the HTLC uing the HTLC success
    21  // transaction. In this scenario, the node that sent the outgoing HTLC should
    22  // extract the preimage from the sweep transaction, and finish settling the
    23  // HTLC backwards into the route.
    24  func testMultiHopReceiverChainClaim(net *lntest.NetworkHarness, t *harnessTest,
    25  	alice, bob *lntest.HarnessNode, c lnrpc.CommitmentType) {
    26  
    27  	ctxb := context.Background()
    28  
    29  	// First, we'll create a three hop network: Alice -> Bob -> Carol, with
    30  	// Carol refusing to actually settle or directly cancel any HTLC's
    31  	// self.
    32  	aliceChanPoint, bobChanPoint, carol := createThreeHopNetwork(
    33  		t, net, alice, bob, false, c,
    34  	)
    35  
    36  	// Clean up carol's node when the test finishes.
    37  	defer shutdownAndAssert(net, t, carol)
    38  
    39  	// With the network active, we'll now add a new hodl invoice at Carol's
    40  	// end. Make sure the cltv expiry delta is large enough, otherwise Bob
    41  	// won't send out the outgoing htlc.
    42  
    43  	const invoiceAmt = 100000
    44  	preimage := lntypes.Preimage{1, 2, 4}
    45  	payHash := preimage.Hash()
    46  	invoiceReq := &invoicesrpc.AddHoldInvoiceRequest{
    47  		Value:      invoiceAmt,
    48  		CltvExpiry: 40,
    49  		Hash:       payHash[:],
    50  	}
    51  	ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout)
    52  	defer cancel()
    53  	carolInvoice, err := carol.AddHoldInvoice(ctxt, invoiceReq)
    54  	require.NoError(t.t, err)
    55  
    56  	// Now that we've created the invoice, we'll send a single payment from
    57  	// Alice to Carol. We won't wait for the response however, as Carol
    58  	// will not immediately settle the payment.
    59  	ctx, cancel := context.WithCancel(ctxb)
    60  	defer cancel()
    61  
    62  	_, err = alice.RouterClient.SendPaymentV2(
    63  		ctx, &routerrpc.SendPaymentRequest{
    64  			PaymentRequest: carolInvoice.PaymentRequest,
    65  			TimeoutSeconds: 60,
    66  			FeeLimitMAtoms: noFeeLimitMAtoms,
    67  		},
    68  	)
    69  	require.NoError(t.t, err)
    70  
    71  	// At this point, all 3 nodes should now have an active channel with
    72  	// the created HTLC pending on all of them.
    73  	nodes := []*lntest.HarnessNode{alice, bob, carol}
    74  	err = wait.NoError(func() error {
    75  		return assertActiveHtlcs(nodes, payHash[:])
    76  	}, defaultTimeout)
    77  	require.NoError(t.t, err)
    78  
    79  	// Wait for carol to mark invoice as accepted. There is a small gap to
    80  	// bridge between adding the htlc to the channel and executing the exit
    81  	// hop logic.
    82  	waitForInvoiceAccepted(t, carol, payHash)
    83  
    84  	restartBob, err := net.SuspendNode(bob)
    85  	require.NoError(t.t, err)
    86  
    87  	// Settle invoice. This will just mark the invoice as settled, as there
    88  	// is no link anymore to remove the htlc from the commitment tx. For
    89  	// this test, it is important to actually settle and not leave the
    90  	// invoice in the accepted state, because without a known preimage, the
    91  	// channel arbitrator won't go to chain.
    92  	ctx, cancel = context.WithTimeout(ctxb, defaultTimeout)
    93  	defer cancel()
    94  	_, err = carol.SettleInvoice(ctx, &invoicesrpc.SettleInvoiceMsg{
    95  		Preimage: preimage[:],
    96  	})
    97  	require.NoError(t.t, err)
    98  
    99  	// Increase the fee estimate so that the following force close tx will
   100  	// be cpfp'ed.
   101  	net.SetFeeEstimate(30000)
   102  
   103  	// Now we'll mine enough blocks to prompt carol to actually go to the
   104  	// chain in order to sweep her HTLC since the value is high enough.
   105  	// TODO(roasbeef): modify once go to chain policy changes
   106  	numBlocks := padCLTV(uint32(
   107  		invoiceReq.CltvExpiry - lncfg.DefaultIncomingBroadcastDelta,
   108  	))
   109  	_, err = net.Generate(numBlocks)
   110  	require.NoError(t.t, err)
   111  
   112  	// At this point, Carol should broadcast her active commitment
   113  	// transaction in order to go to the chain and sweep her HTLC. If there
   114  	// are anchors, Carol also sweeps hers.
   115  	expectedTxes := 1
   116  	hasAnchors := commitTypeHasAnchors(c)
   117  	if hasAnchors {
   118  		expectedTxes = 2
   119  	}
   120  	_, err = getNTxsFromMempool(
   121  		net.Miner.Node, expectedTxes, minerMempoolTimeout,
   122  	)
   123  	require.NoError(t.t, err)
   124  
   125  	bobFundingTxid, err := lnrpc.GetChanPointFundingTxid(bobChanPoint)
   126  	require.NoError(t.t, err)
   127  
   128  	carolFundingPoint := wire.OutPoint{
   129  		Hash:  *bobFundingTxid,
   130  		Index: bobChanPoint.OutputIndex,
   131  	}
   132  
   133  	// The commitment transaction should be spending from the funding
   134  	// transaction.
   135  	closingTx := getSpendingTxInMempool(
   136  		t, net.Miner.Node, minerMempoolTimeout, carolFundingPoint,
   137  	)
   138  	closingTxid := closingTx.TxHash()
   139  
   140  	// Confirm the commitment.
   141  	mineBlocks(t, net, 1, expectedTxes)
   142  
   143  	// Restart bob again.
   144  	err = restartBob()
   145  	require.NoError(t.t, err)
   146  
   147  	// After the force close transaction is mined, a series of transactions
   148  	// should be broadcast by Bob and Carol. When Bob notices Carol's second
   149  	// level transaction in the mempool, he will extract the preimage and
   150  	// settle the HTLC back off-chain.
   151  	switch c {
   152  	// Carol should broadcast her second level HTLC transaction and Bob
   153  	// should broadcast a sweep tx to sweep his output in the channel with
   154  	// Carol.
   155  	case lnrpc.CommitmentType_LEGACY:
   156  		expectedTxes = 2
   157  
   158  	// Carol should broadcast her second level HTLC transaction and Bob
   159  	// should broadcast a sweep tx to sweep his output in the channel with
   160  	// Carol, and another sweep tx to sweep his anchor output.
   161  	case lnrpc.CommitmentType_ANCHORS:
   162  		expectedTxes = 3
   163  
   164  	// Carol should broadcast her second level HTLC transaction and Bob
   165  	// should broadcast a sweep tx to sweep his anchor output. Bob's commit
   166  	// output can't be swept yet as he's incurring an additional CLTV from
   167  	// being the channel initiator of a script-enforced leased channel.
   168  	case lnrpc.CommitmentType_SCRIPT_ENFORCED_LEASE:
   169  		expectedTxes = 2
   170  
   171  	default:
   172  		t.Fatalf("unhandled commitment type %v", c)
   173  	}
   174  	txes, err := getNTxsFromMempool(net.Miner.Node,
   175  		expectedTxes, minerMempoolTimeout)
   176  	require.NoError(t.t, err)
   177  
   178  	// All transactions should be spending from the commitment transaction.
   179  	assertAllTxesSpendFrom(t, txes, closingTxid)
   180  
   181  	// We'll now mine an additional block which should confirm both the
   182  	// second layer transactions.
   183  	_, err = net.Generate(1)
   184  	require.NoError(t.t, err)
   185  
   186  	// Wait for Carol to process the block before performing the next
   187  	// checks.
   188  	time.Sleep(time.Second * 4)
   189  
   190  	// TODO(roasbeef): assert bob pending state as well
   191  
   192  	// Carol's pending channel report should now show two outputs under
   193  	// limbo: her commitment output, as well as the second-layer claim
   194  	// output.
   195  	pendingChansRequest := &lnrpc.PendingChannelsRequest{}
   196  	ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
   197  	pendingChanResp, err := carol.PendingChannels(ctxt, pendingChansRequest)
   198  	require.NoError(t.t, err)
   199  
   200  	require.NotZero(t.t, len(pendingChanResp.PendingForceClosingChannels))
   201  	forceCloseChan := pendingChanResp.PendingForceClosingChannels[0]
   202  	require.NotZero(t.t, forceCloseChan.LimboBalance)
   203  
   204  	// The pending HTLC carol has should also now be in stage 2.
   205  	require.Len(t.t, forceCloseChan.PendingHtlcs, 1)
   206  	require.Equal(t.t, uint32(2), forceCloseChan.PendingHtlcs[0].Stage)
   207  
   208  	// Once the second-level transaction confirmed, Bob should have
   209  	// extracted the preimage from the chain, and sent it back to Alice,
   210  	// clearing the HTLC off-chain.
   211  	nodes = []*lntest.HarnessNode{alice}
   212  	err = wait.NoError(func() error {
   213  		return assertNumActiveHtlcs(nodes, 0)
   214  	}, defaultTimeout)
   215  	require.NoError(t.t, err)
   216  
   217  	// If we mine 4 additional blocks, then Carol can sweep the second level
   218  	// HTLC output.
   219  	_, err = net.Generate(defaultCSV)
   220  	require.NoError(t.t, err)
   221  
   222  	// We should have a new transaction in the mempool.
   223  	_, err = waitForTxInMempool(net.Miner.Node, minerMempoolTimeout)
   224  	require.NoError(t.t, err)
   225  
   226  	// Finally, if we mine an additional block to confirm these two sweep
   227  	// transactions, Carol should not show a pending channel in her report
   228  	// afterwards.
   229  	_, err = net.Generate(1)
   230  	require.NoError(t.t, err)
   231  	err = waitForNumChannelPendingForceClose(carol, 0, nil)
   232  	require.NoError(t.t, err)
   233  
   234  	// The invoice should show as settled for Carol, indicating that it was
   235  	// swept on-chain.
   236  	invoicesReq := &lnrpc.ListInvoiceRequest{}
   237  	invoicesResp, err := carol.ListInvoices(ctxb, invoicesReq)
   238  	require.NoError(t.t, err)
   239  	require.Len(t.t, invoicesResp.Invoices, 1)
   240  	invoice := invoicesResp.Invoices[0]
   241  	require.Equal(t.t, lnrpc.Invoice_SETTLED, invoice.State)
   242  	require.Equal(t.t, int64(invoiceAmt), invoice.AmtPaidAtoms)
   243  
   244  	// Finally, check that the Alice's payment is correctly marked
   245  	// succeeded.
   246  	err = checkPaymentStatus(alice, preimage, lnrpc.Payment_SUCCEEDED)
   247  	require.NoError(t.t, err)
   248  
   249  	if c == lnrpc.CommitmentType_SCRIPT_ENFORCED_LEASE {
   250  		// Bob still has his commit output to sweep to since he incurred
   251  		// an additional CLTV from being the channel initiator of a
   252  		// script-enforced leased channel, regardless of whether he
   253  		// forced closed the channel or not.
   254  		ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
   255  		pendingChanResp, err := bob.PendingChannels(
   256  			ctxt, &lnrpc.PendingChannelsRequest{},
   257  		)
   258  		require.NoError(t.t, err)
   259  
   260  		require.Len(t.t, pendingChanResp.PendingForceClosingChannels, 1)
   261  		forceCloseChan := pendingChanResp.PendingForceClosingChannels[0]
   262  		require.Positive(t.t, forceCloseChan.LimboBalance)
   263  		require.Positive(t.t, forceCloseChan.BlocksTilMaturity)
   264  
   265  		// TODO: Bob still shows a pending HTLC at this point when he
   266  		// shouldn't, as he already extracted the preimage from Carol's
   267  		// claim.
   268  		// require.Len(t.t, forceCloseChan.PendingHtlcs, 0)
   269  
   270  		// Mine enough blocks for Bob's commit output's CLTV to expire
   271  		// and sweep it.
   272  		_ = mineBlocks(t, net, uint32(forceCloseChan.BlocksTilMaturity), 0)
   273  		commitOutpoint := wire.OutPoint{Hash: closingTxid, Index: 3}
   274  		assertSpendingTxInMempool(
   275  			t, net.Miner.Node, minerMempoolTimeout, commitOutpoint,
   276  		)
   277  		_, err = net.Generate(1)
   278  		require.NoError(t.t, err)
   279  	}
   280  
   281  	err = waitForNumChannelPendingForceClose(bob, 0, nil)
   282  	require.NoError(t.t, err)
   283  
   284  	// We'll close out the channel between Alice and Bob, then shutdown
   285  	// carol to conclude the test.
   286  	closeChannelAndAssertType(t, net, alice, aliceChanPoint, false, false)
   287  }