itest: refactor testSendMultiPathPayment

This commit is contained in:
yyforyongyu 2022-08-10 11:34:59 +08:00
parent 1f1123523e
commit 4292c05e04
No known key found for this signature in database
GPG Key ID: 9BCD95C4FF296868
4 changed files with 56 additions and 76 deletions

View File

@ -389,4 +389,8 @@ var allTestCasesTemp = []*lntemp.TestCase{
Name: "sendtoroute multi path payment", Name: "sendtoroute multi path payment",
TestFunc: testSendToRouteMultiPath, TestFunc: testSendToRouteMultiPath,
}, },
{
Name: "send multi path payment",
TestFunc: testSendMultiPathPayment,
},
} }

View File

@ -439,6 +439,15 @@ func (m *mppTestScenario) closeChannels() {
return return
} }
// TODO(yy): remove the sleep once the following bug is fixed. When the
// payment is reported as settled by Alice, it's expected the
// commitment dance is finished and all subsequent states have been
// updated. Yet we'd receive the error `cannot co-op close channel with
// active htlcs` or `link failed to shutdown` if we close the channel.
// We need to investigate the order of settling the payments and
// updating commitments to understand and fix .
time.Sleep(2 * time.Second)
// Close all channels without mining the closing transactions. // Close all channels without mining the closing transactions.
m.ht.CloseChannelAssertPending(m.alice, m.channelPoints[0], false) m.ht.CloseChannelAssertPending(m.alice, m.channelPoints[0], false)
m.ht.CloseChannelAssertPending(m.alice, m.channelPoints[1], false) m.ht.CloseChannelAssertPending(m.alice, m.channelPoints[1], false)

View File

@ -1,22 +1,19 @@
package itest package itest
import ( import (
"context"
"encoding/hex" "encoding/hex"
"github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/btcutil"
"github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc" "github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lntest" "github.com/lightningnetwork/lnd/lntemp"
"github.com/stretchr/testify/require"
) )
// testSendMultiPathPayment tests that we are able to successfully route a // testSendMultiPathPayment tests that we are able to successfully route a
// payment using multiple shards across different paths. // payment using multiple shards across different paths.
func testSendMultiPathPayment(net *lntest.NetworkHarness, t *harnessTest) { func testSendMultiPathPayment(ht *lntemp.HarnessTest) {
ctxb := context.Background() mts := newMppTestScenario(ht)
ctx := newMppTestContext(t, net)
defer ctx.shutdownNodes()
const paymentAmt = btcutil.Amount(300000) const paymentAmt = btcutil.Amount(300000)
@ -30,57 +27,45 @@ func testSendMultiPathPayment(net *lntest.NetworkHarness, t *harnessTest) {
// \ / // \ /
// \__ Dave ____/ // \__ Dave ____/
// //
ctx.openChannel(ctx.carol, ctx.bob, 135000) req := &mppOpenChannelRequest{
ctx.openChannel(ctx.alice, ctx.carol, 235000) amtAliceCarol: 235000,
ctx.openChannel(ctx.dave, ctx.bob, 135000) amtAliceDave: 135000,
ctx.openChannel(ctx.alice, ctx.dave, 135000) amtCarolBob: 135000,
ctx.openChannel(ctx.eve, ctx.bob, 135000) amtCarolEve: 135000,
ctx.openChannel(ctx.carol, ctx.eve, 135000) amtDaveBob: 135000,
amtEveBob: 135000,
defer ctx.closeChannels() }
mts.openChannels(req)
ctx.waitForChannels() chanPointAliceDave := mts.channelPoints[1]
// Increase Dave's fee to make the test deterministic. Otherwise it // Increase Dave's fee to make the test deterministic. Otherwise it
// would be unpredictable whether pathfinding would go through Charlie // would be unpredictable whether pathfinding would go through Charlie
// or Dave for the first shard. // or Dave for the first shard.
_, err := ctx.dave.UpdateChannelPolicy( expectedPolicy := mts.updateDaveGlobalPolicy()
context.Background(),
&lnrpc.PolicyUpdateRequest{ // Make sure Alice has heard it.
Scope: &lnrpc.PolicyUpdateRequest_Global{Global: true}, ht.AssertChannelPolicyUpdate(
BaseFeeMsat: 500000, mts.alice, mts.dave, expectedPolicy, chanPointAliceDave, false,
FeeRate: 0.001,
TimeLockDelta: 40,
},
) )
if err != nil {
t.Fatalf("dave policy update: %v", err)
}
// Our first test will be Alice paying Bob using a SendPayment call. // Our first test will be Alice paying Bob using a SendPayment call.
// Let Bob create an invoice for Alice to pay. // Let Bob create an invoice for Alice to pay.
payReqs, rHashes, invoices, err := createPayReqs( payReqs, rHashes, invoices := ht.CreatePayReqs(mts.bob, paymentAmt, 1)
ctx.bob, paymentAmt, 1,
)
if err != nil {
t.Fatalf("unable to create pay reqs: %v", err)
}
rHash := rHashes[0] rHash := rHashes[0]
payReq := payReqs[0] payReq := payReqs[0]
payment := sendAndAssertSuccess( sendReq := &routerrpc.SendPaymentRequest{
t, ctx.alice, &routerrpc.SendPaymentRequest{ PaymentRequest: payReq,
PaymentRequest: payReq, MaxParts: 10,
MaxParts: 10, TimeoutSeconds: 60,
TimeoutSeconds: 60, FeeLimitMsat: noFeeLimitMsat,
FeeLimitMsat: noFeeLimitMsat, }
}, payment := ht.SendPaymentAssertSettled(mts.alice, sendReq)
)
// Make sure we got the preimage. // Make sure we got the preimage.
if payment.PaymentPreimage != hex.EncodeToString(invoices[0].RPreimage) { require.Equal(ht, hex.EncodeToString(invoices[0].RPreimage),
t.Fatalf("preimage doesn't match") payment.PaymentPreimage, "preimage doesn't match")
}
// Check that Alice split the payment in at least three shards. Because // Check that Alice split the payment in at least three shards. Because
// the hand-off of the htlc to the link is asynchronous (via a mailbox), // the hand-off of the htlc to the link is asynchronous (via a mailbox),
@ -97,32 +82,17 @@ func testSendMultiPathPayment(net *lntest.NetworkHarness, t *harnessTest) {
} }
const minExpectedShards = 3 const minExpectedShards = 3
if succeeded < minExpectedShards { require.GreaterOrEqual(ht, succeeded, minExpectedShards,
t.Fatalf("expected at least %v shards, but got %v", "expected shards not reached")
minExpectedShards, succeeded)
}
// Make sure Bob show the invoice as settled for the full // Make sure Bob show the invoice as settled for the full amount.
// amount. inv := mts.bob.RPC.LookupInvoice(rHash)
ctxt, _ := context.WithTimeout(ctxb, defaultTimeout)
inv, err := ctx.bob.LookupInvoice(
ctxt, &lnrpc.PaymentHash{
RHash: rHash,
},
)
if err != nil {
t.Fatalf("error when obtaining invoice: %v", err)
}
if inv.AmtPaidSat != int64(paymentAmt) { require.EqualValues(ht, paymentAmt, inv.AmtPaidSat,
t.Fatalf("incorrect payment amt for invoice"+ "incorrect payment amt")
"want: %d, got %d",
paymentAmt, inv.AmtPaidSat)
}
if inv.State != lnrpc.Invoice_SETTLED { require.Equal(ht, lnrpc.Invoice_SETTLED, inv.State,
t.Fatalf("Invoice not settled: %v", inv.State) "Invoice not settled")
}
settled := 0 settled := 0
for _, htlc := range inv.Htlcs { for _, htlc := range inv.Htlcs {
@ -130,8 +100,9 @@ func testSendMultiPathPayment(net *lntest.NetworkHarness, t *harnessTest) {
settled++ settled++
} }
} }
if settled != succeeded { require.Equal(ht, succeeded, settled,
t.Fatalf("expected invoice to be settled "+ "num of HTLCs wrong")
"with %v HTLCs, had %v", succeeded, settled)
} // Finally, close all channels.
mts.closeChannels()
} }

View File

@ -56,10 +56,6 @@ var allTestCases = []*testCase{
name: "sendpayment amp invoice repeat", name: "sendpayment amp invoice repeat",
test: testSendPaymentAMPInvoiceRepeat, test: testSendPaymentAMPInvoiceRepeat,
}, },
{
name: "send multi path payment",
test: testSendMultiPathPayment,
},
{ {
name: "forward interceptor", name: "forward interceptor",
test: testForwardInterceptorBasic, test: testForwardInterceptorBasic,