From 2a7830d442ddda447957413ba25c05733e405fe2 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Fri, 5 Aug 2022 18:22:19 +0800 Subject: [PATCH] itest: refactor `testMaxHtlcPathfind` --- lntest/itest/list_on_test.go | 4 + lntest/itest/lnd_max_htlcs_test.go | 207 +++++++++----------------- lntest/itest/lnd_test_list_on_test.go | 4 - 3 files changed, 74 insertions(+), 141 deletions(-) diff --git a/lntest/itest/list_on_test.go b/lntest/itest/list_on_test.go index 2bb5dcee6..7671663ec 100644 --- a/lntest/itest/list_on_test.go +++ b/lntest/itest/list_on_test.go @@ -251,4 +251,8 @@ var allTestCasesTemp = []*lntemp.TestCase{ Name: "wumbo channels", TestFunc: testWumboChannels, }, + { + Name: "max htlc pathfind", + TestFunc: testMaxHtlcPathfind, + }, } diff --git a/lntest/itest/lnd_max_htlcs_test.go b/lntest/itest/lnd_max_htlcs_test.go index 9f5218cac..d457e452f 100644 --- a/lntest/itest/lnd_max_htlcs_test.go +++ b/lntest/itest/lnd_max_htlcs_test.go @@ -1,13 +1,11 @@ package itest import ( - "context" - "testing" - "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc/invoicesrpc" "github.com/lightningnetwork/lnd/lnrpc/routerrpc" - "github.com/lightningnetwork/lnd/lntest" + "github.com/lightningnetwork/lnd/lntemp" + "github.com/lightningnetwork/lnd/lntemp/node" "github.com/lightningnetwork/lnd/lntypes" "github.com/stretchr/testify/require" ) @@ -16,118 +14,69 @@ import ( // channel where we have already reached the limit of the number of htlcs that // we may add to the remote party's commitment. This test asserts that we do // not attempt to use the full channel at all in our pathfinding. -func testMaxHtlcPathfind(net *lntest.NetworkHarness, t *harnessTest) { - ctxb := context.Background() - +func testMaxHtlcPathfind(ht *lntemp.HarnessTest) { // Setup a channel between Alice and Bob where Alice will only allow // Bob to add a maximum of 5 htlcs to her commitment. maxHtlcs := 5 - chanPoint := openChannelAndAssert( - t, net, net.Alice, net.Bob, - lntest.OpenChannelParams{ + alice, bob := ht.Alice, ht.Bob + chanPoint := ht.OpenChannel( + alice, bob, lntemp.OpenChannelParams{ Amt: 1000000, PushAmt: 800000, RemoteMaxHtlcs: uint16(maxHtlcs), }, ) - // Wait for Alice and Bob to receive the channel edge from the - // funding manager. - err := net.Alice.WaitForNetworkChannelOpen(chanPoint) - require.NoError(t.t, err, "alice does not have open channel") - - err = net.Bob.WaitForNetworkChannelOpen(chanPoint) - require.NoError(t.t, err, "bob does not have open channel") - // Alice and bob should have one channel open with each other now. - assertNodeNumChannels(t, net.Alice, 1) - assertNodeNumChannels(t, net.Bob, 1) + ht.AssertNodeNumChannels(alice, 1) + ht.AssertNodeNumChannels(bob, 1) // Send our maximum number of htlcs from Bob -> Alice so that we get // to a point where Alice won't accept any more htlcs on the channel. subscriptions := make([]*holdSubscription, maxHtlcs) - cancelCtxs := make([]func(), maxHtlcs) for i := 0; i < maxHtlcs; i++ { - subCtx, cancel := context.WithTimeout(ctxb, defaultTimeout) - cancelCtxs[i] = cancel - - subscriptions[i] = acceptHoldInvoice( - subCtx, t.t, i, net.Bob, net.Alice, - ) + subscriptions[i] = acceptHoldInvoice(ht, i, bob, alice) } - // Cancel all of our subscriptions on exit. - defer func() { - for _, cancel := range cancelCtxs { - cancel() - } - }() - - err = assertNumActiveHtlcs([]*lntest.HarnessNode{ - net.Alice, net.Bob, - }, maxHtlcs) - require.NoError(t.t, err, "htlcs not active") + ht.AssertNumActiveHtlcs(alice, maxHtlcs) + ht.AssertNumActiveHtlcs(bob, maxHtlcs) // Now we send a payment from Alice -> Bob to sanity check that our // commitment limit is not applied in the opposite direction. - subCtx, cancel := context.WithTimeout(ctxb, defaultTimeout) - defer cancel() - aliceBobSub := acceptHoldInvoice( - subCtx, t.t, maxHtlcs, net.Alice, net.Bob, - ) - err = assertNumActiveHtlcs([]*lntest.HarnessNode{ - net.Alice, net.Bob, - }, maxHtlcs+1) - require.NoError(t.t, err, "htlcs not active") + aliceBobSub := acceptHoldInvoice(ht, maxHtlcs, alice, bob) + ht.AssertNumActiveHtlcs(alice, maxHtlcs+1) + ht.AssertNumActiveHtlcs(bob, maxHtlcs+1) // Now, we're going to try to send another payment from Bob -> Alice. // We've hit our max remote htlcs, so we expect this payment to spin // out dramatically with pathfinding. - ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) - payment, err := net.Bob.RouterClient.SendPaymentV2( - ctxt, &routerrpc.SendPaymentRequest{ - Amt: 1000, - Dest: net.Alice.PubKey[:], - TimeoutSeconds: 60, - FeeLimitSat: 1000000, - MaxParts: 10, - Amp: true, - }, - ) - require.NoError(t.t, err, "send payment failed") - - update, err := payment.Recv() - require.NoError(t.t, err, "no payment in flight update") - require.Equal(t.t, lnrpc.Payment_IN_FLIGHT, update.Status, - "payment not inflight") - - update, err = payment.Recv() - require.NoError(t.t, err, "no payment failed update") - require.Equal(t.t, lnrpc.Payment_FAILED, update.Status) - require.Len(t.t, update.Htlcs, 0, "expected no htlcs dispatched") + sendReq := &routerrpc.SendPaymentRequest{ + Amt: 1000, + Dest: alice.PubKey[:], + TimeoutSeconds: 60, + FeeLimitSat: 1000000, + MaxParts: 10, + Amp: true, + } + ht.SendPaymentAndAssertStatus(bob, sendReq, lnrpc.Payment_FAILED) // Now that we're done, we cancel all our pending htlcs so that we // can cleanup the channel with a coop close. for _, sub := range subscriptions { - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - sub.cancel(ctxt, t.t) + sub.cancel(ht) } + aliceBobSub.cancel(ht) - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - aliceBobSub.cancel(ctxt, t.t) + ht.AssertNumActiveHtlcs(alice, 0) + ht.AssertNumActiveHtlcs(bob, 0) - err = assertNumActiveHtlcs([]*lntest.HarnessNode{ - net.Alice, net.Bob, - }, 0) - require.NoError(t.t, err, "expected all htlcs canceled") - - closeChannelAndAssert(t, net, net.Alice, chanPoint, false) + ht.CloseChannel(alice, chanPoint) } type holdSubscription struct { - recipient invoicesrpc.InvoicesClient + recipient *node.HarnessNode hash lntypes.Hash invSubscription invoicesrpc.Invoices_SubscribeSingleInvoiceClient paymentSubscription routerrpc.Router_SendPaymentV2Client @@ -135,89 +84,73 @@ type holdSubscription struct { // cancel updates a hold invoice to cancel from the recipient and consumes // updates from the payer until it has reached a final, failed state. -func (h *holdSubscription) cancel(ctx context.Context, t *testing.T) { - _, err := h.recipient.CancelInvoice(ctx, &invoicesrpc.CancelInvoiceMsg{ - PaymentHash: h.hash[:], - }) - require.NoError(t, err, "invoice cancel failed") +func (h *holdSubscription) cancel(ht *lntemp.HarnessTest) { + h.recipient.RPC.CancelInvoice(h.hash[:]) - invUpdate, err := h.invSubscription.Recv() - require.NoError(t, err, "cancel invoice subscribe failed") - require.Equal(t, lnrpc.Invoice_CANCELED, invUpdate.State, + invUpdate := ht.ReceiveSingleInvoice(h.invSubscription) + require.Equal(ht, lnrpc.Invoice_CANCELED, invUpdate.State, "expected invoice canceled") // We expect one in flight update when our htlc is canceled back, and // another when we fail the payment as a whole. - payUpdate, err := h.paymentSubscription.Recv() - require.NoError(t, err, "cancel payment subscribe failed") - require.Len(t, payUpdate.Htlcs, 1) - require.Equal(t, lnrpc.Payment_IN_FLIGHT, payUpdate.Status) + payUpdate := ht.AssertPaymentStatusFromStream( + h.paymentSubscription, lnrpc.Payment_IN_FLIGHT, + ) + require.Len(ht, payUpdate.Htlcs, 1) - payUpdate, err = h.paymentSubscription.Recv() - require.NoError(t, err, "cancel payment subscribe failed") - require.Equal(t, lnrpc.Payment_FAILED, payUpdate.Status, + payUpdate = ht.AssertPaymentStatusFromStream( + h.paymentSubscription, lnrpc.Payment_FAILED, + ) + require.Equal(ht, lnrpc.Payment_FAILED, payUpdate.Status, "expected payment failed") - require.Equal(t, lnrpc.PaymentFailureReason_FAILURE_REASON_INCORRECT_PAYMENT_DETAILS, + require.Equal(ht, lnrpc.PaymentFailureReason_FAILURE_REASON_INCORRECT_PAYMENT_DETAILS, //nolint:lll payUpdate.FailureReason, "expected unknown details") } // acceptHoldInvoice adds a hold invoice to the recipient node, pays it from // the sender and asserts that we have reached the accepted state where htlcs // are locked in for the payment. -func acceptHoldInvoice(ctx context.Context, t *testing.T, idx int, sender, - receiver *lntest.HarnessNode) *holdSubscription { +func acceptHoldInvoice(ht *lntemp.HarnessTest, idx int, sender, + receiver *node.HarnessNode) *holdSubscription { hash := [lntypes.HashSize]byte{byte(idx + 1)} - invoice, err := receiver.AddHoldInvoice( - ctx, &invoicesrpc.AddHoldInvoiceRequest{ - ValueMsat: 10000, - Hash: hash[:], - }, - ) - require.NoError(t, err, "couldn't add invoice") + req := &invoicesrpc.AddHoldInvoiceRequest{ + ValueMsat: 10000, + Hash: hash[:], + } + invoice := receiver.RPC.AddHoldInvoice(req) - invStream, err := receiver.InvoicesClient.SubscribeSingleInvoice( - ctx, &invoicesrpc.SubscribeSingleInvoiceRequest{ - RHash: hash[:], - }, - ) - require.NoError(t, err, "could not subscribe to invoice") + invStream := receiver.RPC.SubscribeSingleInvoice(hash[:]) + inv := ht.ReceiveSingleInvoice(invStream) + require.Equal(ht, lnrpc.Invoice_OPEN, inv.State, "expect open") - inv, err := invStream.Recv() - require.NoError(t, err, "invoice open stream failed") - require.Equal(t, lnrpc.Invoice_OPEN, inv.State, - "expected open") - - payStream, err := sender.RouterClient.SendPaymentV2( - ctx, &routerrpc.SendPaymentRequest{ - PaymentRequest: invoice.PaymentRequest, - TimeoutSeconds: 60, - FeeLimitSat: 1000000, - }, - ) - require.NoError(t, err, "send payment failed") + sendReq := &routerrpc.SendPaymentRequest{ + PaymentRequest: invoice.PaymentRequest, + TimeoutSeconds: 60, + FeeLimitSat: 1000000, + } + payStream := sender.RPC.SendPayment(sendReq) // Finally, assert that we progress to an accepted state. We expect // the payer to get one update for the creation of the payment, and // another when a htlc is dispatched. - payment, err := payStream.Recv() - require.NoError(t, err, "payment in flight stream failed") - require.Equal(t, lnrpc.Payment_IN_FLIGHT, payment.Status) - require.Len(t, payment.Htlcs, 0) + payment := ht.AssertPaymentStatusFromStream( + payStream, lnrpc.Payment_IN_FLIGHT, + ) + require.Empty(ht, payment.Htlcs) - payment, err = payStream.Recv() - require.NoError(t, err, "payment in flight stream failed") - require.Equal(t, lnrpc.Payment_IN_FLIGHT, payment.Status) - require.Len(t, payment.Htlcs, 1) + payment = ht.AssertPaymentStatusFromStream( + payStream, lnrpc.Payment_IN_FLIGHT, + ) + require.Len(ht, payment.Htlcs, 1) - inv, err = invStream.Recv() - require.NoError(t, err, "invoice accepted stream failed") - require.Equal(t, lnrpc.Invoice_ACCEPTED, inv.State, - "expected accepted invoice") + inv = ht.ReceiveSingleInvoice(invStream) + require.Equal(ht, lnrpc.Invoice_ACCEPTED, inv.State, + "expected accepted") return &holdSubscription{ - recipient: receiver.InvoicesClient, + recipient: receiver, hash: hash, invSubscription: invStream, paymentSubscription: payStream, diff --git a/lntest/itest/lnd_test_list_on_test.go b/lntest/itest/lnd_test_list_on_test.go index dea3d20ef..74010eb0a 100644 --- a/lntest/itest/lnd_test_list_on_test.go +++ b/lntest/itest/lnd_test_list_on_test.go @@ -194,10 +194,6 @@ var allTestCases = []*testCase{ name: "wallet import pubkey", test: testWalletImportPubKey, }, - { - name: "max htlc pathfind", - test: testMaxHtlcPathfind, - }, { name: "rpc middleware interceptor", test: testRPCMiddlewareInterceptor,