itest: add SendPayment AMP itest

This commit is contained in:
Johan T. Halseth 2021-03-31 13:26:15 +02:00
parent a2a61a104f
commit 13c00127da
No known key found for this signature in database
GPG Key ID: 15BAADA29DA20D26
2 changed files with 129 additions and 0 deletions

@ -7,6 +7,7 @@ import (
"github.com/btcsuite/btcutil"
"github.com/lightningnetwork/lnd/amp"
"github.com/lightningnetwork/lnd/chainreg"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lntest"
@ -14,6 +15,129 @@ import (
"github.com/stretchr/testify/require"
)
// testSendPaymentAMP tests that we can send an AMP payment to a specified
// destination using SendPaymentV2.
func testSendPaymentAMP(net *lntest.NetworkHarness, t *harnessTest) {
ctxb := context.Background()
ctx := newMppTestContext(t, net)
defer ctx.shutdownNodes()
const paymentAmt = btcutil.Amount(300000)
// Set up a network with three different paths Alice <-> Bob. Channel
// capacities are set such that the payment can only succeed if (at
// least) three paths are used.
//
// _ Eve _
// / \
// Alice -- Carol ---- Bob
// \ /
// \__ Dave ____/
//
ctx.openChannel(ctx.carol, ctx.bob, 135000)
ctx.openChannel(ctx.alice, ctx.carol, 235000)
ctx.openChannel(ctx.dave, ctx.bob, 135000)
ctx.openChannel(ctx.alice, ctx.dave, 135000)
ctx.openChannel(ctx.eve, ctx.bob, 135000)
ctx.openChannel(ctx.carol, ctx.eve, 135000)
defer ctx.closeChannels()
ctx.waitForChannels()
// Increase Dave's fee to make the test deterministic. Otherwise it
// would be unpredictable whether pathfinding would go through Charlie
// or Dave for the first shard.
_, err := ctx.dave.UpdateChannelPolicy(
context.Background(),
&lnrpc.PolicyUpdateRequest{
Scope: &lnrpc.PolicyUpdateRequest_Global{Global: true},
BaseFeeMsat: 500000,
FeeRate: 0.001,
TimeLockDelta: 40,
},
)
if err != nil {
t.Fatalf("dave policy update: %v", err)
}
ctxt, _ := context.WithTimeout(context.Background(), 4*defaultTimeout)
payment := sendAndAssertSuccess(
ctxt, t, net.Alice,
&routerrpc.SendPaymentRequest{
Dest: net.Bob.PubKey[:],
Amt: int64(paymentAmt),
FinalCltvDelta: chainreg.DefaultBitcoinTimeLockDelta,
MaxParts: 10,
TimeoutSeconds: 60,
FeeLimitMsat: noFeeLimitMsat,
Amp: true,
},
)
// 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),
// there is some non-determinism in the process. Depending on whether
// the new pathfinding round is started before or after the htlc is
// locked into the channel, different sharding may occur. Therefore we
// can only check if the number of shards isn't below the theoretical
// minimum.
succeeded := 0
for _, htlc := range payment.Htlcs {
if htlc.Status == lnrpc.HTLCAttempt_SUCCEEDED {
succeeded++
}
}
const minExpectedShards = 3
if succeeded < minExpectedShards {
t.Fatalf("expected at least %v shards, but got %v",
minExpectedShards, succeeded)
}
// Fetch Bob's invoices.
invoiceResp, err := net.Bob.ListInvoices(
ctxb, &lnrpc.ListInvoiceRequest{},
)
require.NoError(t.t, err)
// There should only be one invoice.
require.Equal(t.t, 1, len(invoiceResp.Invoices))
rpcInvoice := invoiceResp.Invoices[0]
// Assert that the invoice is settled for the total payment amount and
// has the correct payment address.
require.True(t.t, rpcInvoice.Settled)
require.Equal(t.t, lnrpc.Invoice_SETTLED, rpcInvoice.State)
require.Equal(t.t, int64(paymentAmt), rpcInvoice.AmtPaidSat)
require.Equal(t.t, int64(paymentAmt*1000), rpcInvoice.AmtPaidMsat)
// Finally, assert that the same set id is recorded for each htlc, and
// that the preimage hash pair is valid.
var setID []byte
require.Equal(t.t, succeeded, len(rpcInvoice.Htlcs))
for _, htlc := range rpcInvoice.Htlcs {
require.NotNil(t.t, htlc.Amp)
if setID == nil {
setID = make([]byte, 32)
copy(setID, htlc.Amp.SetId)
}
require.Equal(t.t, setID, htlc.Amp.SetId)
// Parse the child hash and child preimage, and assert they are
// well-formed.
childHash, err := lntypes.MakeHash(htlc.Amp.Hash)
require.NoError(t.t, err)
childPreimage, err := lntypes.MakePreimage(htlc.Amp.Preimage)
require.NoError(t.t, err)
// Assert that the preimage actually matches the hashes.
validPreimage := childPreimage.Matches(childHash)
require.True(t.t, validPreimage)
}
}
func testSendToRouteAMP(net *lntest.NetworkHarness, t *harnessTest) {
ctxb := context.Background()

@ -274,6 +274,11 @@ var allTestCases = []*testCase{
name: "sendtoroute amp",
test: testSendToRouteAMP,
},
{
name: "sendpayment amp",
test: testSendPaymentAMP,
},
{
name: "send multi path payment",
test: testSendMultiPathPayment,