github.com/decred/dcrlnd@v0.7.6/lntest/itest/lnd_amp_test.go (about)

     1  package itest
     2  
     3  import (
     4  	"context"
     5  	"crypto/rand"
     6  	"encoding/hex"
     7  	"sort"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/decred/dcrd/dcrutil/v4"
    12  	"github.com/decred/dcrlnd/amp"
    13  	"github.com/decred/dcrlnd/chainreg"
    14  	"github.com/decred/dcrlnd/lnrpc"
    15  	"github.com/decred/dcrlnd/lnrpc/invoicesrpc"
    16  	"github.com/decred/dcrlnd/lnrpc/routerrpc"
    17  	"github.com/decred/dcrlnd/lntest"
    18  	"github.com/decred/dcrlnd/lntypes"
    19  	"github.com/stretchr/testify/require"
    20  )
    21  
    22  // testSendPaymentAMPInvoice tests that we can send an AMP payment to a
    23  // specified AMP invoice using SendPaymentV2.
    24  func testSendPaymentAMPInvoice(net *lntest.NetworkHarness, t *harnessTest) {
    25  	t.t.Run("native payaddr", func(t *testing.T) {
    26  		tt := newHarnessTest(t, net)
    27  		testSendPaymentAMPInvoiceCase(net, tt, false)
    28  	})
    29  	t.t.Run("external payaddr", func(t *testing.T) {
    30  		tt := newHarnessTest(t, net)
    31  		testSendPaymentAMPInvoiceCase(net, tt, true)
    32  	})
    33  }
    34  
    35  func testSendPaymentAMPInvoiceCase(net *lntest.NetworkHarness, t *harnessTest,
    36  	useExternalPayAddr bool) {
    37  
    38  	ctxb := context.Background()
    39  
    40  	ctx := newMppTestContext(t, net)
    41  	defer ctx.shutdownNodes()
    42  
    43  	// Subscribe to bob's invoices. Do this early in the test to make sure
    44  	// that the subscription has actually been completed when we add an
    45  	// invoice. Otherwise the notification will be missed.
    46  	req := &lnrpc.InvoiceSubscription{}
    47  	ctxc, cancelSubscription := context.WithCancel(ctxb)
    48  	bobInvoiceSubscription, err := ctx.bob.SubscribeInvoices(ctxc, req)
    49  	require.NoError(t.t, err)
    50  	defer cancelSubscription()
    51  
    52  	const paymentAmt = dcrutil.Amount(300000)
    53  
    54  	// Set up a network with three different paths Alice <-> Bob. Channel
    55  	// capacities are set such that the payment can only succeed if (at
    56  	// least) three paths are used.
    57  	//
    58  	//              _ Eve _
    59  	//             /       \
    60  	// Alice -- Carol ---- Bob
    61  	//      \              /
    62  	//       \__ Dave ____/
    63  	//
    64  	ctx.openChannel(ctx.carol, ctx.bob, 135000)
    65  	ctx.openChannel(ctx.alice, ctx.carol, 235000)
    66  	ctx.openChannel(ctx.dave, ctx.bob, 135000)
    67  	ctx.openChannel(ctx.alice, ctx.dave, 135000)
    68  	ctx.openChannel(ctx.eve, ctx.bob, 135000)
    69  	ctx.openChannel(ctx.carol, ctx.eve, 135000)
    70  
    71  	defer ctx.closeChannels()
    72  
    73  	ctx.waitForChannels()
    74  
    75  	addInvoiceResp, err := ctx.bob.AddInvoice(context.Background(), &lnrpc.Invoice{
    76  		Value: int64(paymentAmt),
    77  		IsAmp: true,
    78  	})
    79  	require.NoError(t.t, err)
    80  
    81  	// Ensure we get a notification of the invoice being added by Bob.
    82  	rpcInvoice, err := bobInvoiceSubscription.Recv()
    83  	require.NoError(t.t, err)
    84  
    85  	require.False(t.t, rpcInvoice.Settled) // nolint:staticcheck
    86  	require.Equal(t.t, lnrpc.Invoice_OPEN, rpcInvoice.State)
    87  	require.Equal(t.t, int64(0), rpcInvoice.AmtPaidAtoms)
    88  	require.Equal(t.t, int64(0), rpcInvoice.AmtPaidMAtoms)
    89  
    90  	require.Equal(t.t, 0, len(rpcInvoice.Htlcs))
    91  
    92  	// Increase Dave's fee to make the test deterministic. Otherwise it
    93  	// would be unpredictable whether pathfinding would go through Charlie
    94  	// or Dave for the first shard.
    95  	_, err = ctx.dave.UpdateChannelPolicy(
    96  		context.Background(),
    97  		&lnrpc.PolicyUpdateRequest{
    98  			Scope:         &lnrpc.PolicyUpdateRequest_Global{Global: true},
    99  			BaseFeeMAtoms: 500000,
   100  			FeeRate:       0.001,
   101  			TimeLockDelta: 40,
   102  		},
   103  	)
   104  	if err != nil {
   105  		t.Fatalf("dave policy update: %v", err)
   106  	}
   107  
   108  	// Generate an external payment address when attempting to pseudo-reuse
   109  	// an AMP invoice. When using an external payment address, we'll also
   110  	// expect an extra invoice to appear in the ListInvoices response, since
   111  	// a new invoice will be JIT inserted under a different payment address
   112  	// than the one in the invoice.
   113  	var (
   114  		expNumInvoices  = 1
   115  		externalPayAddr []byte
   116  	)
   117  	if useExternalPayAddr {
   118  		expNumInvoices = 2
   119  		externalPayAddr = make([]byte, 32)
   120  		_, err = rand.Read(externalPayAddr)
   121  		require.NoError(t.t, err)
   122  	}
   123  
   124  	payment := sendAndAssertSuccess(
   125  		t, ctx.alice, &routerrpc.SendPaymentRequest{
   126  			PaymentRequest: addInvoiceResp.PaymentRequest,
   127  			PaymentAddr:    externalPayAddr,
   128  			TimeoutSeconds: 60,
   129  			FeeLimitMAtoms: noFeeLimitMAtoms,
   130  		},
   131  	)
   132  
   133  	// Check that Alice split the payment in at least three shards. Because
   134  	// the hand-off of the htlc to the link is asynchronous (via a mailbox),
   135  	// there is some non-determinism in the process. Depending on whether
   136  	// the new pathfinding round is started before or after the htlc is
   137  	// locked into the channel, different sharding may occur. Therefore we
   138  	// can only check if the number of shards isn't below the theoretical
   139  	// minimum.
   140  	succeeded := 0
   141  	for _, htlc := range payment.Htlcs {
   142  		if htlc.Status == lnrpc.HTLCAttempt_SUCCEEDED {
   143  			succeeded++
   144  		}
   145  	}
   146  
   147  	const minExpectedShards = 3
   148  	if succeeded < minExpectedShards {
   149  		t.Fatalf("expected at least %v shards, but got %v",
   150  			minExpectedShards, succeeded)
   151  	}
   152  
   153  	// When an external payment address is supplied, we'll get an extra
   154  	// notification for the JIT inserted invoice, since it differs from the
   155  	// original.
   156  	if useExternalPayAddr {
   157  		_, err = bobInvoiceSubscription.Recv()
   158  		require.NoError(t.t, err)
   159  	}
   160  
   161  	// There should now be a settle event for the invoice.
   162  	rpcInvoice, err = bobInvoiceSubscription.Recv()
   163  	require.NoError(t.t, err)
   164  
   165  	// Also fetch Bob's invoice from ListInvoices and assert it is equal to
   166  	// the one recevied via the subscription.
   167  	invoiceResp, err := ctx.bob.ListInvoices(
   168  		ctxb, &lnrpc.ListInvoiceRequest{},
   169  	)
   170  	require.NoError(t.t, err)
   171  	require.Equal(t.t, expNumInvoices, len(invoiceResp.Invoices))
   172  	assertInvoiceEqual(t.t, rpcInvoice, invoiceResp.Invoices[expNumInvoices-1])
   173  
   174  	// Assert that the invoice is settled for the total payment amount and
   175  	// has the correct payment address.
   176  	require.True(t.t, rpcInvoice.Settled) // nolint:staticcheck
   177  	require.Equal(t.t, lnrpc.Invoice_SETTLED, rpcInvoice.State)
   178  	require.Equal(t.t, int64(paymentAmt), rpcInvoice.AmtPaidAtoms)
   179  	require.Equal(t.t, int64(paymentAmt*1000), rpcInvoice.AmtPaidMAtoms)
   180  
   181  	// Finally, assert that the same set id is recorded for each htlc, and
   182  	// that the preimage hash pair is valid.
   183  	var setID []byte
   184  	require.Equal(t.t, succeeded, len(rpcInvoice.Htlcs))
   185  	for _, htlc := range rpcInvoice.Htlcs {
   186  		require.NotNil(t.t, htlc.Amp)
   187  		if setID == nil {
   188  			setID = make([]byte, 32)
   189  			copy(setID, htlc.Amp.SetId)
   190  		}
   191  		require.Equal(t.t, setID, htlc.Amp.SetId)
   192  
   193  		// Parse the child hash and child preimage, and assert they are
   194  		// well-formed.
   195  		childHash, err := lntypes.MakeHash(htlc.Amp.Hash)
   196  		require.NoError(t.t, err)
   197  		childPreimage, err := lntypes.MakePreimage(htlc.Amp.Preimage)
   198  		require.NoError(t.t, err)
   199  
   200  		// Assert that the preimage actually matches the hashes.
   201  		validPreimage := childPreimage.Matches(childHash)
   202  		require.True(t.t, validPreimage)
   203  	}
   204  
   205  	// The set ID we extract above should be shown in the final settled
   206  	// state.
   207  	ampState := rpcInvoice.AmpInvoiceState[hex.EncodeToString(setID)]
   208  	require.Equal(t.t, lnrpc.InvoiceHTLCState_SETTLED, ampState.State)
   209  }
   210  
   211  // testSendPaymentAMPInvoiceRepeat tests that it's possible to pay an AMP
   212  // invoice multiple times by having the client generate a new setID each time.
   213  func testSendPaymentAMPInvoiceRepeat(net *lntest.NetworkHarness,
   214  	t *harnessTest) {
   215  
   216  	// In this basic test, we'll only need two nodes as we want to
   217  	// primarily test the recurring payment feature. So we'll re-use the
   218  	carol := net.NewNode(t.t, "Carol", nil)
   219  	defer shutdownAndAssert(net, t, carol)
   220  
   221  	// Send Carol enough coins to be able to open a channel to Dave.
   222  	net.SendCoins(t.t, dcrutil.AtomsPerCoin, carol)
   223  
   224  	dave := net.NewNode(t.t, "Dave", nil)
   225  	defer shutdownAndAssert(net, t, dave)
   226  
   227  	// Before we start the test, we'll ensure both sides are connected to
   228  	// the funding flow can properly be executed.
   229  	net.EnsureConnected(t.t, carol, dave)
   230  
   231  	// Set up an invoice subscription so we can be notified when Dave
   232  	// receives his repeated payments.
   233  	req := &lnrpc.InvoiceSubscription{}
   234  	ctxb := context.Background()
   235  	ctxc, cancelSubscription := context.WithCancel(ctxb)
   236  	invSubscription, err := dave.SubscribeInvoices(ctxc, req)
   237  	require.NoError(t.t, err)
   238  	defer cancelSubscription()
   239  
   240  	// Establish a channel between Carol and Dave.
   241  	chanAmt := dcrutil.Amount(100_000)
   242  	chanPoint := openChannelAndAssert(
   243  		t, net, carol, dave,
   244  		lntest.OpenChannelParams{
   245  			Amt: chanAmt,
   246  		},
   247  	)
   248  	err = carol.WaitForNetworkChannelOpen(chanPoint)
   249  	require.NoError(t.t, err, "carol didn't report channel")
   250  	err = dave.WaitForNetworkChannelOpen(chanPoint)
   251  	require.NoError(t.t, err, "dave didn't report channel")
   252  
   253  	// Create an AMP invoice of a trivial amount, that we'll pay repeatedly
   254  	// in this integration test.
   255  	paymentAmt := 10000
   256  	addInvoiceResp, err := dave.AddInvoice(ctxb, &lnrpc.Invoice{
   257  		Value: int64(paymentAmt),
   258  		IsAmp: true,
   259  	})
   260  	require.NoError(t.t, err)
   261  
   262  	// We should get an initial notification that the HTLC has been added.
   263  	rpcInvoice, err := invSubscription.Recv()
   264  	require.NoError(t.t, err)
   265  	require.False(t.t, rpcInvoice.Settled) // nolint:staticcheck
   266  	require.Equal(t.t, lnrpc.Invoice_OPEN, rpcInvoice.State)
   267  	require.Equal(t.t, int64(0), rpcInvoice.AmtPaidAtoms)
   268  	require.Equal(t.t, int64(0), rpcInvoice.AmtPaidMAtoms)
   269  
   270  	require.Equal(t.t, 0, len(rpcInvoice.Htlcs))
   271  
   272  	// Now we'll use Carol to pay the invoice that Dave created.
   273  	_ = sendAndAssertSuccess(
   274  		t, carol, &routerrpc.SendPaymentRequest{
   275  			PaymentRequest: addInvoiceResp.PaymentRequest,
   276  			TimeoutSeconds: 60,
   277  			FeeLimitMAtoms: noFeeLimitMAtoms,
   278  		},
   279  	)
   280  
   281  	// Dave should get a notification that the invoice has been settled.
   282  	invoiceNtfn, err := invSubscription.Recv()
   283  	require.NoError(t.t, err)
   284  
   285  	// The notification should signal that the invoice is now settled, and
   286  	// should also include the set ID, and show the proper amount paid.
   287  	require.True(t.t, invoiceNtfn.Settled) // nolint:staticcheck
   288  	require.Equal(t.t, lnrpc.Invoice_SETTLED, invoiceNtfn.State)
   289  	require.Equal(t.t, paymentAmt, int(invoiceNtfn.AmtPaidAtoms))
   290  	require.Equal(t.t, 1, len(invoiceNtfn.AmpInvoiceState))
   291  	var firstSetID []byte
   292  	for setIDStr, ampState := range invoiceNtfn.AmpInvoiceState {
   293  		firstSetID, _ = hex.DecodeString(setIDStr)
   294  		require.Equal(t.t, lnrpc.InvoiceHTLCState_SETTLED, ampState.State)
   295  	}
   296  
   297  	// Pay the invoice again, we should get another notification that Dave
   298  	// has received another payment.
   299  	_ = sendAndAssertSuccess(
   300  		t, carol, &routerrpc.SendPaymentRequest{
   301  			PaymentRequest: addInvoiceResp.PaymentRequest,
   302  			TimeoutSeconds: 60,
   303  			FeeLimitMAtoms: noFeeLimitMAtoms,
   304  		},
   305  	)
   306  
   307  	// Dave should get another notification.
   308  	invoiceNtfn, err = invSubscription.Recv()
   309  	require.NoError(t.t, err)
   310  
   311  	// The invoice should still be shown as settled, and also include the
   312  	// information about this newly generated setID, showing 2x the amount
   313  	// paid.
   314  	require.True(t.t, invoiceNtfn.Settled) // nolint:staticcheck
   315  	require.Equal(t.t, paymentAmt*2, int(invoiceNtfn.AmtPaidAtoms))
   316  
   317  	var secondSetID []byte
   318  	for setIDStr, ampState := range invoiceNtfn.AmpInvoiceState {
   319  		secondSetID, _ = hex.DecodeString(setIDStr)
   320  		require.Equal(t.t, lnrpc.InvoiceHTLCState_SETTLED, ampState.State)
   321  	}
   322  
   323  	// The returned invoice should only include a single HTLC since we
   324  	// return the "projected" sub-invoice for a given setID.
   325  	require.Equal(t.t, 1, len(invoiceNtfn.Htlcs))
   326  
   327  	// However the AMP state index should show that there've been two
   328  	// repeated payments to this invoice so far.
   329  	require.Equal(t.t, 2, len(invoiceNtfn.AmpInvoiceState))
   330  
   331  	// Now we'll look up the invoice using the new LookupInvoice2 RPC call
   332  	// by the set ID of each of the invoices.
   333  	subInvoice1, err := dave.LookupInvoiceV2(ctxb, &invoicesrpc.LookupInvoiceMsg{
   334  		InvoiceRef: &invoicesrpc.LookupInvoiceMsg_SetId{
   335  			SetId: firstSetID,
   336  		},
   337  		LookupModifier: invoicesrpc.LookupModifier_HTLC_SET_ONLY,
   338  	})
   339  	require.Nil(t.t, err)
   340  	subInvoice2, err := dave.LookupInvoiceV2(ctxb, &invoicesrpc.LookupInvoiceMsg{
   341  		InvoiceRef: &invoicesrpc.LookupInvoiceMsg_SetId{
   342  			SetId: secondSetID,
   343  		},
   344  		LookupModifier: invoicesrpc.LookupModifier_HTLC_SET_ONLY,
   345  	})
   346  	require.Nil(t.t, err)
   347  
   348  	// Each invoice should only show a single HTLC present, as we passed
   349  	// the HTLC set only modifier.
   350  	require.Equal(t.t, 1, len(subInvoice1.Htlcs))
   351  	require.Equal(t.t, 1, len(subInvoice2.Htlcs))
   352  
   353  	// If we look up the same invoice, by its payment address, but now with
   354  	// the HTLC blank modifier, then none of them should be returned.
   355  	rootInvoice, err := dave.LookupInvoiceV2(ctxb, &invoicesrpc.LookupInvoiceMsg{
   356  		InvoiceRef: &invoicesrpc.LookupInvoiceMsg_PaymentAddr{
   357  			PaymentAddr: addInvoiceResp.PaymentAddr,
   358  		},
   359  		LookupModifier: invoicesrpc.LookupModifier_HTLC_SET_BLANK,
   360  	})
   361  	require.Nil(t.t, err)
   362  	require.Equal(t.t, 0, len(rootInvoice.Htlcs))
   363  
   364  	// If we look up the same invoice, by its payment address, but without
   365  	// that modified, then we should get all the relevant HTLCs.
   366  	rootInvoice, err = dave.LookupInvoiceV2(ctxb,
   367  		&invoicesrpc.LookupInvoiceMsg{
   368  			InvoiceRef: &invoicesrpc.LookupInvoiceMsg_PaymentAddr{
   369  				PaymentAddr: addInvoiceResp.PaymentAddr,
   370  			},
   371  		})
   372  	require.Nil(t.t, err)
   373  	require.Equal(t.t, 2, len(rootInvoice.Htlcs))
   374  
   375  	// Finally, we'll test that if we subscribe for notifications of
   376  	// settled invoices, we get a backlog, which includes the invoice we
   377  	// settled last (since you can only fetch from index 1 onwards), and
   378  	// only the relevant set of HTLCs.
   379  	req = &lnrpc.InvoiceSubscription{
   380  		SettleIndex: 1,
   381  	}
   382  	ctxc, cancelSubscription2 := context.WithCancel(ctxb)
   383  	invSub2, err := dave.SubscribeInvoices(ctxc, req)
   384  	require.NoError(t.t, err)
   385  	defer cancelSubscription2()
   386  
   387  	// The first invoice we get back should match the state of the invoice
   388  	// after our second payment: amt updated, but only a single HTLC shown
   389  	// through.
   390  	backlogInv, _ := invSub2.Recv()
   391  	require.Equal(t.t, 1, len(backlogInv.Htlcs))
   392  	require.Equal(t.t, 2, len(backlogInv.AmpInvoiceState))
   393  	require.True(t.t, backlogInv.Settled) // nolint:staticcheck
   394  	require.Equal(t.t, paymentAmt*2, int(backlogInv.AmtPaidAtoms))
   395  }
   396  
   397  // testSendPaymentAMP tests that we can send an AMP payment to a specified
   398  // destination using SendPaymentV2.
   399  func testSendPaymentAMP(net *lntest.NetworkHarness, t *harnessTest) {
   400  	ctxb := context.Background()
   401  
   402  	ctx := newMppTestContext(t, net)
   403  	defer ctx.shutdownNodes()
   404  
   405  	const paymentAmt = dcrutil.Amount(300000)
   406  
   407  	// Set up a network with three different paths Alice <-> Bob. Channel
   408  	// capacities are set such that the payment can only succeed if (at
   409  	// least) three paths are used.
   410  	//
   411  	//              _ Eve _
   412  	//             /       \
   413  	// Alice -- Carol ---- Bob
   414  	//      \              /
   415  	//       \__ Dave ____/
   416  	//
   417  	ctx.openChannel(ctx.carol, ctx.bob, 135000)
   418  	ctx.openChannel(ctx.alice, ctx.carol, 235000)
   419  	ctx.openChannel(ctx.dave, ctx.bob, 135000)
   420  	ctx.openChannel(ctx.alice, ctx.dave, 135000)
   421  	ctx.openChannel(ctx.eve, ctx.bob, 135000)
   422  	ctx.openChannel(ctx.carol, ctx.eve, 135000)
   423  
   424  	defer ctx.closeChannels()
   425  
   426  	ctx.waitForChannels()
   427  
   428  	// Increase Dave's fee to make the test deterministic. Otherwise it
   429  	// would be unpredictable whether pathfinding would go through Charlie
   430  	// or Dave for the first shard.
   431  	_, err := ctx.dave.UpdateChannelPolicy(
   432  		context.Background(),
   433  		&lnrpc.PolicyUpdateRequest{
   434  			Scope:         &lnrpc.PolicyUpdateRequest_Global{Global: true},
   435  			BaseFeeMAtoms: 500000,
   436  			FeeRate:       0.001,
   437  			TimeLockDelta: 40,
   438  		},
   439  	)
   440  	if err != nil {
   441  		t.Fatalf("dave policy update: %v", err)
   442  	}
   443  
   444  	payment := sendAndAssertSuccess(
   445  		t, ctx.alice, &routerrpc.SendPaymentRequest{
   446  			Dest:           ctx.bob.PubKey[:],
   447  			Amt:            int64(paymentAmt),
   448  			FinalCltvDelta: chainreg.DefaultDecredTimeLockDelta,
   449  			TimeoutSeconds: 60,
   450  			FeeLimitMAtoms: noFeeLimitMAtoms,
   451  			Amp:            true,
   452  		},
   453  	)
   454  
   455  	// Check that Alice split the payment in at least three shards. Because
   456  	// the hand-off of the htlc to the link is asynchronous (via a mailbox),
   457  	// there is some non-determinism in the process. Depending on whether
   458  	// the new pathfinding round is started before or after the htlc is
   459  	// locked into the channel, different sharding may occur. Therefore we
   460  	// can only check if the number of shards isn't below the theoretical
   461  	// minimum.
   462  	succeeded := 0
   463  	for _, htlc := range payment.Htlcs {
   464  		if htlc.Status == lnrpc.HTLCAttempt_SUCCEEDED {
   465  			succeeded++
   466  		}
   467  	}
   468  
   469  	const minExpectedShards = 3
   470  	if succeeded < minExpectedShards {
   471  		t.Fatalf("expected at least %v shards, but got %v",
   472  			minExpectedShards, succeeded)
   473  	}
   474  
   475  	// Fetch Bob's invoices.
   476  	invoiceResp, err := ctx.bob.ListInvoices(
   477  		ctxb, &lnrpc.ListInvoiceRequest{},
   478  	)
   479  	require.NoError(t.t, err)
   480  
   481  	// There should only be one invoice.
   482  	require.Equal(t.t, 1, len(invoiceResp.Invoices))
   483  	rpcInvoice := invoiceResp.Invoices[0]
   484  
   485  	// Assert that the invoice is settled for the total payment amount and
   486  	// has the correct payment address.
   487  	require.True(t.t, rpcInvoice.Settled)
   488  	require.Equal(t.t, lnrpc.Invoice_SETTLED, rpcInvoice.State)
   489  	require.Equal(t.t, int64(paymentAmt), rpcInvoice.AmtPaidAtoms)
   490  	require.Equal(t.t, int64(paymentAmt*1000), rpcInvoice.AmtPaidMAtoms)
   491  
   492  	// Finally, assert that the same set id is recorded for each htlc, and
   493  	// that the preimage hash pair is valid.
   494  	var setID []byte
   495  	require.Equal(t.t, succeeded, len(rpcInvoice.Htlcs))
   496  	for _, htlc := range rpcInvoice.Htlcs {
   497  		require.NotNil(t.t, htlc.Amp)
   498  		if setID == nil {
   499  			setID = make([]byte, 32)
   500  			copy(setID, htlc.Amp.SetId)
   501  		}
   502  		require.Equal(t.t, setID, htlc.Amp.SetId)
   503  
   504  		// Parse the child hash and child preimage, and assert they are
   505  		// well-formed.
   506  		childHash, err := lntypes.MakeHash(htlc.Amp.Hash)
   507  		require.NoError(t.t, err)
   508  		childPreimage, err := lntypes.MakePreimage(htlc.Amp.Preimage)
   509  		require.NoError(t.t, err)
   510  
   511  		// Assert that the preimage actually matches the hashes.
   512  		validPreimage := childPreimage.Matches(childHash)
   513  		require.True(t.t, validPreimage)
   514  	}
   515  
   516  	// The set ID we extract above should be shown in the final settled
   517  	// state.
   518  	ampState := rpcInvoice.AmpInvoiceState[hex.EncodeToString(setID)]
   519  	require.Equal(t.t, lnrpc.InvoiceHTLCState_SETTLED, ampState.State)
   520  }
   521  
   522  func testSendToRouteAMP(net *lntest.NetworkHarness, t *harnessTest) {
   523  	ctxb := context.Background()
   524  
   525  	ctx := newMppTestContext(t, net)
   526  	defer ctx.shutdownNodes()
   527  
   528  	const (
   529  		paymentAmt = dcrutil.Amount(300000)
   530  		numShards  = 3
   531  		shardAmt   = paymentAmt / numShards
   532  		chanAmt    = shardAmt * 3 / 2
   533  	)
   534  
   535  	// Set up a network with three different paths Alice <-> Bob.
   536  	//              _ Eve _
   537  	//             /       \
   538  	// Alice -- Carol ---- Bob
   539  	//      \              /
   540  	//       \__ Dave ____/
   541  	//
   542  	ctx.openChannel(ctx.carol, ctx.bob, chanAmt)
   543  	ctx.openChannel(ctx.dave, ctx.bob, chanAmt)
   544  	ctx.openChannel(ctx.alice, ctx.dave, chanAmt)
   545  	ctx.openChannel(ctx.eve, ctx.bob, chanAmt)
   546  	ctx.openChannel(ctx.carol, ctx.eve, chanAmt)
   547  
   548  	// Since the channel Alice-> Carol will have to carry two
   549  	// shards, we make it larger.
   550  	ctx.openChannel(ctx.alice, ctx.carol, chanAmt+shardAmt)
   551  
   552  	defer ctx.closeChannels()
   553  
   554  	ctx.waitForChannels()
   555  
   556  	// Subscribe to bob's invoices.
   557  	req := &lnrpc.InvoiceSubscription{}
   558  	ctxc, cancelSubscription := context.WithCancel(ctxb)
   559  	bobInvoiceSubscription, err := ctx.bob.SubscribeInvoices(ctxc, req)
   560  	require.NoError(t.t, err)
   561  	defer cancelSubscription()
   562  
   563  	// We'll send shards along three routes from Alice.
   564  	sendRoutes := [numShards][]*lntest.HarnessNode{
   565  		{ctx.carol, ctx.bob},
   566  		{ctx.dave, ctx.bob},
   567  		{ctx.carol, ctx.eve, ctx.bob},
   568  	}
   569  
   570  	payAddr := make([]byte, 32)
   571  	_, err = rand.Read(payAddr)
   572  	require.NoError(t.t, err)
   573  
   574  	setID := make([]byte, 32)
   575  	_, err = rand.Read(setID)
   576  	require.NoError(t.t, err)
   577  
   578  	var sharer amp.Sharer
   579  	sharer, err = amp.NewSeedSharer()
   580  	require.NoError(t.t, err)
   581  
   582  	time.Sleep(time.Second)
   583  	ctx.alice.LogPrintf("======================== gonna start %s", shardAmt)
   584  
   585  	childPreimages := make(map[lntypes.Preimage]uint32)
   586  	responses := make(chan *lnrpc.HTLCAttempt, len(sendRoutes))
   587  
   588  	// Define a closure for sending each of the three shards.
   589  	sendShard := func(i int, hops []*lntest.HarnessNode) {
   590  		// Build a route for the specified hops.
   591  		r, err := ctx.buildRoute(ctxb, shardAmt, ctx.alice, hops)
   592  		if err != nil {
   593  			t.Fatalf("unable to build route: %v", err)
   594  		}
   595  
   596  		// Set the MPP records to indicate this is a payment shard.
   597  		hop := r.Hops[len(r.Hops)-1]
   598  		hop.TlvPayload = true
   599  		hop.MppRecord = &lnrpc.MPPRecord{
   600  			PaymentAddr:    payAddr,
   601  			TotalAmtMAtoms: int64(paymentAmt * 1000),
   602  		}
   603  
   604  		var child *amp.Child
   605  		if i < len(sendRoutes)-1 {
   606  			var left amp.Sharer
   607  			left, sharer, err = sharer.Split()
   608  			require.NoError(t.t, err)
   609  
   610  			child = left.Child(uint32(i))
   611  		} else {
   612  			child = sharer.Child(uint32(i))
   613  		}
   614  		childPreimages[child.Preimage] = child.Index
   615  
   616  		hop.AmpRecord = &lnrpc.AMPRecord{
   617  			RootShare:  child.Share[:],
   618  			SetId:      setID,
   619  			ChildIndex: child.Index,
   620  		}
   621  
   622  		// Send the shard.
   623  		sendReq := &routerrpc.SendToRouteRequest{
   624  			PaymentHash: child.Hash[:],
   625  			Route:       r,
   626  		}
   627  
   628  		// We'll send all shards in their own goroutine, since SendToRoute will
   629  		// block as long as the payment is in flight.
   630  		go func() {
   631  			ctxt, _ := context.WithTimeout(ctxb, defaultTimeout)
   632  			resp, err := ctx.alice.RouterClient.SendToRouteV2(ctxt, sendReq)
   633  			if err != nil {
   634  				t.Fatalf("unable to send payment: %v", err)
   635  			}
   636  
   637  			responses <- resp
   638  		}()
   639  	}
   640  
   641  	// Send the first shard, this cause Bob to JIT add an invoice.
   642  	sendShard(0, sendRoutes[0])
   643  
   644  	// Ensure we get a notification of the invoice being added by Bob.
   645  	rpcInvoice, err := bobInvoiceSubscription.Recv()
   646  	require.NoError(t.t, err)
   647  
   648  	require.False(t.t, rpcInvoice.Settled) // nolint:staticcheck
   649  	require.Equal(t.t, lnrpc.Invoice_OPEN, rpcInvoice.State)
   650  	require.Equal(t.t, int64(0), rpcInvoice.AmtPaidAtoms)
   651  	require.Equal(t.t, int64(0), rpcInvoice.AmtPaidMAtoms)
   652  	require.Equal(t.t, payAddr, rpcInvoice.PaymentAddr)
   653  
   654  	require.Equal(t.t, 0, len(rpcInvoice.Htlcs))
   655  
   656  	sendShard(1, sendRoutes[1])
   657  	sendShard(2, sendRoutes[2])
   658  
   659  	// Assert that all of the child preimages are unique.
   660  	require.Equal(t.t, len(sendRoutes), len(childPreimages))
   661  
   662  	// Make a copy of the childPreimages map for validating the resulting
   663  	// invoice.
   664  	childPreimagesCopy := make(map[lntypes.Preimage]uint32)
   665  	for preimage, childIndex := range childPreimages {
   666  		childPreimagesCopy[preimage] = childIndex
   667  	}
   668  
   669  	// Wait for all responses to be back, and check that they all
   670  	// succeeded.
   671  	for range sendRoutes {
   672  		var resp *lnrpc.HTLCAttempt
   673  		select {
   674  		case resp = <-responses:
   675  		case <-time.After(defaultTimeout):
   676  			t.Fatalf("response not received")
   677  		}
   678  
   679  		if resp.Failure != nil {
   680  			t.Fatalf("received payment failure : %v", resp.Failure)
   681  		}
   682  
   683  		preimage, err := lntypes.MakePreimage(resp.Preimage)
   684  		require.NoError(t.t, err)
   685  
   686  		// Assert that the response includes one of our child preimages.
   687  		_, ok := childPreimages[preimage]
   688  		require.True(t.t, ok)
   689  
   690  		// Remove this preimage from out set so that we ensure all
   691  		// responses have a unique child preimage.
   692  		delete(childPreimages, preimage)
   693  	}
   694  	childPreimages = childPreimagesCopy
   695  
   696  	// There should now be a settle event for the invoice.
   697  	rpcInvoice, err = bobInvoiceSubscription.Recv()
   698  	require.NoError(t.t, err)
   699  
   700  	// Also fetch Bob's invoice from ListInvoices and assert it is equal to
   701  	// the one recevied via the subscription.
   702  	invoiceResp, err := ctx.bob.ListInvoices(
   703  		ctxb, &lnrpc.ListInvoiceRequest{},
   704  	)
   705  	require.NoError(t.t, err)
   706  	require.Equal(t.t, 1, len(invoiceResp.Invoices))
   707  	assertInvoiceEqual(t.t, rpcInvoice, invoiceResp.Invoices[0])
   708  
   709  	// Assert that the invoice is settled for the total payment amount and
   710  	// has the correct payment address.
   711  	require.True(t.t, rpcInvoice.Settled)
   712  	require.Equal(t.t, lnrpc.Invoice_SETTLED, rpcInvoice.State)
   713  	require.Equal(t.t, int64(paymentAmt), rpcInvoice.AmtPaidAtoms)
   714  	require.Equal(t.t, int64(paymentAmt*1000), rpcInvoice.AmtPaidMAtoms)
   715  	require.Equal(t.t, payAddr, rpcInvoice.PaymentAddr)
   716  
   717  	// Finally, assert that the proper set id is recorded for each htlc, and
   718  	// that the preimage hash pair is valid.
   719  	require.Equal(t.t, numShards, len(rpcInvoice.Htlcs))
   720  	for _, htlc := range rpcInvoice.Htlcs {
   721  		require.NotNil(t.t, htlc.Amp)
   722  		require.Equal(t.t, setID, htlc.Amp.SetId)
   723  
   724  		// Parse the child hash and child preimage, and assert they are
   725  		// well-formed.
   726  		childHash, err := lntypes.MakeHash(htlc.Amp.Hash)
   727  		require.NoError(t.t, err)
   728  		childPreimage, err := lntypes.MakePreimage(htlc.Amp.Preimage)
   729  		require.NoError(t.t, err)
   730  
   731  		// Assert that the preimage actually matches the hashes.
   732  		validPreimage := childPreimage.Matches(childHash)
   733  		require.True(t.t, validPreimage)
   734  
   735  		// Assert that the HTLC includes one of our child preimages.
   736  		childIndex, ok := childPreimages[childPreimage]
   737  		require.True(t.t, ok)
   738  
   739  		// Assert that the correct child index is reflected.
   740  		require.Equal(t.t, childIndex, htlc.Amp.ChildIndex)
   741  
   742  		// Remove this preimage from our set so that we ensure all HTLCs
   743  		// have a unique child preimage.
   744  		delete(childPreimages, childPreimage)
   745  	}
   746  }
   747  
   748  // assertInvoiceEqual asserts that two lnrpc.Invoices are equivalent. A custom
   749  // comparison function is defined for these tests, since proto message returned
   750  // from unary and streaming RPCs (as of protobuf 1.23.0 and grpc 1.29.1) aren't
   751  // consistent with the private fields set on the messages. As a result, we avoid
   752  // using require.Equal and test only the actual data members.
   753  func assertInvoiceEqual(t *testing.T, a, b *lnrpc.Invoice) {
   754  	t.Helper()
   755  
   756  	// Ensure the HTLCs are sorted properly before attempting to compare.
   757  	sort.Slice(a.Htlcs, func(i, j int) bool {
   758  		return a.Htlcs[i].ChanId < a.Htlcs[j].ChanId
   759  	})
   760  	sort.Slice(b.Htlcs, func(i, j int) bool {
   761  		return b.Htlcs[i].ChanId < b.Htlcs[j].ChanId
   762  	})
   763  
   764  	require.Equal(t, a.Memo, b.Memo)
   765  	require.Equal(t, a.RPreimage, b.RPreimage)
   766  	require.Equal(t, a.RHash, b.RHash)
   767  	require.Equal(t, a.Value, b.Value)
   768  	require.Equal(t, a.ValueMAtoms, b.ValueMAtoms)
   769  	require.Equal(t, a.CreationDate, b.CreationDate)
   770  	require.Equal(t, a.SettleDate, b.SettleDate)
   771  	require.Equal(t, a.PaymentRequest, b.PaymentRequest)
   772  	require.Equal(t, a.DescriptionHash, b.DescriptionHash)
   773  	require.Equal(t, a.Expiry, b.Expiry)
   774  	require.Equal(t, a.FallbackAddr, b.FallbackAddr)
   775  	require.Equal(t, a.CltvExpiry, b.CltvExpiry)
   776  	require.Equal(t, a.RouteHints, b.RouteHints)
   777  	require.Equal(t, a.Private, b.Private)
   778  	require.Equal(t, a.AddIndex, b.AddIndex)
   779  	require.Equal(t, a.SettleIndex, b.SettleIndex)
   780  	require.Equal(t, a.AmtPaidAtoms, b.AmtPaidAtoms)
   781  	require.Equal(t, a.AmtPaidMAtoms, b.AmtPaidMAtoms)
   782  	require.Equal(t, a.State, b.State)
   783  	require.Equal(t, a.Features, b.Features)
   784  	require.Equal(t, a.IsKeysend, b.IsKeysend)
   785  	require.Equal(t, a.PaymentAddr, b.PaymentAddr)
   786  	require.Equal(t, a.IsAmp, b.IsAmp)
   787  
   788  	require.Equal(t, len(a.Htlcs), len(b.Htlcs))
   789  	for i := range a.Htlcs {
   790  		htlcA, htlcB := a.Htlcs[i], b.Htlcs[i]
   791  		require.Equal(t, htlcA.ChanId, htlcB.ChanId)
   792  		require.Equal(t, htlcA.HtlcIndex, htlcB.HtlcIndex)
   793  		require.Equal(t, htlcA.AmtMAtoms, htlcB.AmtMAtoms)
   794  		require.Equal(t, htlcA.AcceptHeight, htlcB.AcceptHeight)
   795  		require.Equal(t, htlcA.AcceptTime, htlcB.AcceptTime)
   796  		require.Equal(t, htlcA.ResolveTime, htlcB.ResolveTime)
   797  		require.Equal(t, htlcA.ExpiryHeight, htlcB.ExpiryHeight)
   798  		require.Equal(t, htlcA.State, htlcB.State)
   799  		require.Equal(t, htlcA.CustomRecords, htlcB.CustomRecords)
   800  		require.Equal(t, htlcA.MppTotalAmtMAtoms, htlcB.MppTotalAmtMAtoms)
   801  		require.Equal(t, htlcA.Amp, htlcB.Amp)
   802  	}
   803  }