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 }