lntemp+itest: refactor testSingleHopSendToRoute
This commit is contained in:
5 files changed
+116
-216
No files matched your search
@@ -2014,3 +2014,31 @@ func (h *HarnessTest) AssertChannelCommitHeight(hn *node.HarnessNode,
|
|||||||
|
|
||||||
require.NoError(h, err, "timeout while waiting for commit height")
|
require.NoError(h, err, "timeout while waiting for commit height")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AssertNumInvoices asserts that the number of invoices made within the test
|
||||||
|
// scope is as expected.
|
||||||
|
func (h *HarnessTest) AssertNumInvoices(hn *node.HarnessNode,
|
||||||
|
num int) []*lnrpc.Invoice {
|
||||||
|
|
||||||
|
have := hn.State.Invoice.Total
|
||||||
|
req := &lnrpc.ListInvoiceRequest{
|
||||||
|
NumMaxInvoices: math.MaxUint64,
|
||||||
|
IndexOffset: hn.State.Invoice.LastIndexOffset,
|
||||||
|
}
|
||||||
|
|
||||||
|
var invoices []*lnrpc.Invoice
|
||||||
|
err := wait.NoError(func() error {
|
||||||
|
resp := hn.RPC.ListInvoices(req)
|
||||||
|
|
||||||
|
invoices = resp.Invoices
|
||||||
|
if len(invoices) == num {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return errNumNotMatched(hn.Name(), "num of invoices",
|
||||||
|
num, len(invoices), have+len(invoices), have)
|
||||||
|
}, DefaultTimeout)
|
||||||
|
require.NoError(h, err, "timeout checking num of invoices")
|
||||||
|
|
||||||
|
return invoices
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package rpc
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -92,3 +93,16 @@ func (h *HarnessRPC) ResetMissionControl() {
|
|||||||
_, err := h.Router.ResetMissionControl(ctxt, req)
|
_, err := h.Router.ResetMissionControl(ctxt, req)
|
||||||
h.NoError(err, "ResetMissionControl")
|
h.NoError(err, "ResetMissionControl")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SendToRouteV2 makes a RPC call to SendToRouteV2 and asserts.
|
||||||
|
func (h *HarnessRPC) SendToRouteV2(
|
||||||
|
req *routerrpc.SendToRouteRequest) *lnrpc.HTLCAttempt {
|
||||||
|
|
||||||
|
ctxt, cancel := context.WithTimeout(h.runCtx, DefaultTimeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
resp, err := h.Router.SendToRouteV2(ctxt, req)
|
||||||
|
h.NoError(err, "SendToRouteV2")
|
||||||
|
|
||||||
|
return resp
|
||||||
|
}
|
||||||
@@ -305,7 +305,12 @@ var allTestCasesTemp = []*lntemp.TestCase{
|
|||||||
TestFunc: testRevokedCloseRetributionRemoteHodl,
|
TestFunc: testRevokedCloseRetributionRemoteHodl,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "revoked uncooperative close retribution altruist watchtower",
|
Name: "revoked uncooperative close retribution altruist " +
|
||||||
|
"watchtower",
|
||||||
TestFunc: testRevokedCloseRetributionAltruistWatchtower,
|
TestFunc: testRevokedCloseRetributionAltruistWatchtower,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "single-hop send to route",
|
||||||
|
TestFunc: testSingleHopSendToRoute,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
package itest
|
package itest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -14,6 +13,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/chainreg"
|
"github.com/lightningnetwork/lnd/chainreg"
|
||||||
"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/lntemp"
|
||||||
"github.com/lightningnetwork/lnd/lntest"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
@@ -68,23 +68,18 @@ var singleHopSendToRouteCases = []singleHopSendToRouteCase{
|
|||||||
// by feeding the route back into the various SendToRoute RPC methods. Here we
|
// by feeding the route back into the various SendToRoute RPC methods. Here we
|
||||||
// test all three SendToRoute endpoints, forcing each to perform both a regular
|
// test all three SendToRoute endpoints, forcing each to perform both a regular
|
||||||
// payment and an MPP payment.
|
// payment and an MPP payment.
|
||||||
func testSingleHopSendToRoute(net *lntest.NetworkHarness, t *harnessTest) {
|
func testSingleHopSendToRoute(ht *lntemp.HarnessTest) {
|
||||||
for _, test := range singleHopSendToRouteCases {
|
for _, test := range singleHopSendToRouteCases {
|
||||||
test := test
|
test := test
|
||||||
|
|
||||||
t.t.Run(test.name, func(t1 *testing.T) {
|
ht.Run(test.name, func(t1 *testing.T) {
|
||||||
ht := newHarnessTest(t1, t.lndHarness)
|
st := ht.Subtest(t1)
|
||||||
ht.RunTestCase(&testCase{
|
testSingleHopSendToRouteCase(st, test)
|
||||||
name: test.name,
|
|
||||||
test: func(_ *lntest.NetworkHarness, tt *harnessTest) {
|
|
||||||
testSingleHopSendToRouteCase(net, tt, test)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testSingleHopSendToRouteCase(net *lntest.NetworkHarness, t *harnessTest,
|
func testSingleHopSendToRouteCase(ht *lntemp.HarnessTest,
|
||||||
test singleHopSendToRouteCase) {
|
test singleHopSendToRouteCase) {
|
||||||
|
|
||||||
const chanAmt = btcutil.Amount(100000)
|
const chanAmt = btcutil.Amount(100000)
|
||||||
@@ -92,96 +87,41 @@ func testSingleHopSendToRouteCase(net *lntest.NetworkHarness, t *harnessTest,
|
|||||||
const numPayments = 5
|
const numPayments = 5
|
||||||
const amountPaid = int64(numPayments * paymentAmtSat)
|
const amountPaid = int64(numPayments * paymentAmtSat)
|
||||||
|
|
||||||
ctxb := context.Background()
|
|
||||||
var networkChans []*lnrpc.ChannelPoint
|
|
||||||
|
|
||||||
// Create Carol and Dave, then establish a channel between them. Carol
|
// Create Carol and Dave, then establish a channel between them. Carol
|
||||||
// is the sole funder of the channel with 100k satoshis. The network
|
// is the sole funder of the channel with 100k satoshis. The network
|
||||||
// topology should look like:
|
// topology should look like:
|
||||||
// Carol -> 100k -> Dave
|
// Carol -> 100k -> Dave
|
||||||
carol := net.NewNode(t.t, "Carol", nil)
|
carol := ht.NewNode("Carol", nil)
|
||||||
defer shutdownAndAssert(net, t, carol)
|
dave := ht.NewNode("Dave", nil)
|
||||||
|
|
||||||
dave := net.NewNode(t.t, "Dave", nil)
|
ht.ConnectNodes(carol, dave)
|
||||||
defer shutdownAndAssert(net, t, dave)
|
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
|
||||||
|
|
||||||
net.ConnectNodes(t.t, carol, dave)
|
|
||||||
net.SendCoins(t.t, btcutil.SatoshiPerBitcoin, carol)
|
|
||||||
|
|
||||||
// Open a channel with 100k satoshis between Carol and Dave with Carol
|
// Open a channel with 100k satoshis between Carol and Dave with Carol
|
||||||
// being the sole funder of the channel.
|
// being the sole funder of the channel.
|
||||||
chanPointCarol := openChannelAndAssert(
|
chanPointCarol := ht.OpenChannel(
|
||||||
t, net, carol, dave,
|
carol, dave, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||||
lntest.OpenChannelParams{
|
|
||||||
Amt: chanAmt,
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
networkChans = append(networkChans, chanPointCarol)
|
defer ht.CloseChannel(carol, chanPointCarol)
|
||||||
|
|
||||||
carolChanTXID, err := lnrpc.GetChanPointFundingTxid(chanPointCarol)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to get txid: %v", err)
|
|
||||||
}
|
|
||||||
carolFundPoint := wire.OutPoint{
|
|
||||||
Hash: *carolChanTXID,
|
|
||||||
Index: chanPointCarol.OutputIndex,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for all nodes to have seen all channels.
|
|
||||||
nodes := []*lntest.HarnessNode{carol, dave}
|
|
||||||
for _, chanPoint := range networkChans {
|
|
||||||
for _, node := range nodes {
|
|
||||||
txid, err := lnrpc.GetChanPointFundingTxid(chanPoint)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to get txid: %v", err)
|
|
||||||
}
|
|
||||||
point := wire.OutPoint{
|
|
||||||
Hash: *txid,
|
|
||||||
Index: chanPoint.OutputIndex,
|
|
||||||
}
|
|
||||||
|
|
||||||
err = node.WaitForNetworkChannelOpen(chanPoint)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("%s(%d): timeout waiting for "+
|
|
||||||
"channel(%s) open: %v", node.Name(),
|
|
||||||
node.NodeID, point, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create invoices for Dave, which expect a payment from Carol.
|
// Create invoices for Dave, which expect a payment from Carol.
|
||||||
payReqs, rHashes, _, err := createPayReqs(
|
payReqs, rHashes, _ := ht.CreatePayReqs(
|
||||||
dave, paymentAmtSat, numPayments,
|
dave, paymentAmtSat, numPayments,
|
||||||
)
|
)
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to create pay reqs: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reconstruct payment addresses.
|
// Reconstruct payment addresses.
|
||||||
var payAddrs [][]byte
|
var payAddrs [][]byte
|
||||||
for _, payReq := range payReqs {
|
for _, payReq := range payReqs {
|
||||||
ctx, _ := context.WithTimeout(
|
resp := dave.RPC.DecodePayReq(payReq)
|
||||||
context.Background(), defaultTimeout,
|
|
||||||
)
|
|
||||||
resp, err := dave.DecodePayReq(
|
|
||||||
ctx,
|
|
||||||
&lnrpc.PayReqString{PayReq: payReq},
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("decode pay req: %v", err)
|
|
||||||
}
|
|
||||||
payAddrs = append(payAddrs, resp.PaymentAddr)
|
payAddrs = append(payAddrs, resp.PaymentAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assert Carol and Dave are synced to the chain before proceeding, to
|
// Assert Carol and Dave are synced to the chain before proceeding, to
|
||||||
// ensure the queried route will have a valid final CLTV once the HTLC
|
// ensure the queried route will have a valid final CLTV once the HTLC
|
||||||
// reaches Dave.
|
// reaches Dave.
|
||||||
_, minerHeight, err := net.Miner.Client.GetBestBlock()
|
_, minerHeight := ht.Miner.GetBestBlock()
|
||||||
if err != nil {
|
ht.WaitForNodeBlockHeight(carol, minerHeight)
|
||||||
t.Fatalf("unable to get best height: %v", err)
|
ht.WaitForNodeBlockHeight(dave, minerHeight)
|
||||||
}
|
|
||||||
require.NoError(t.t, waitForNodeBlockHeight(carol, minerHeight))
|
|
||||||
require.NoError(t.t, waitForNodeBlockHeight(dave, minerHeight))
|
|
||||||
|
|
||||||
// Query for routes to pay from Carol to Dave using the default CLTV
|
// Query for routes to pay from Carol to Dave using the default CLTV
|
||||||
// config.
|
// config.
|
||||||
@@ -189,12 +129,7 @@ func testSingleHopSendToRouteCase(net *lntest.NetworkHarness, t *harnessTest,
|
|||||||
PubKey: dave.PubKeyStr,
|
PubKey: dave.PubKeyStr,
|
||||||
Amt: paymentAmtSat,
|
Amt: paymentAmtSat,
|
||||||
}
|
}
|
||||||
ctxt, _ := context.WithTimeout(ctxb, defaultTimeout)
|
routes := carol.RPC.QueryRoutes(routesReq)
|
||||||
routes, err := carol.QueryRoutes(ctxt, routesReq)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to get route from %s: %v",
|
|
||||||
carol.Name(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// There should only be one route to try, so take the first item.
|
// There should only be one route to try, so take the first item.
|
||||||
r := routes.Routes[0]
|
r := routes.Routes[0]
|
||||||
@@ -222,27 +157,14 @@ func testSingleHopSendToRouteCase(net *lntest.NetworkHarness, t *harnessTest,
|
|||||||
PaymentHash: rHash,
|
PaymentHash: rHash,
|
||||||
Route: r,
|
Route: r,
|
||||||
}
|
}
|
||||||
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
|
resp := carol.RPC.SendToRouteSync(sendReq)
|
||||||
resp, err := carol.SendToRouteSync(
|
require.Emptyf(ht, resp.PaymentError,
|
||||||
ctxt, sendReq,
|
"received payment error from %s: %v",
|
||||||
)
|
carol.Name(), resp.PaymentError)
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to send to route for "+
|
|
||||||
"%s: %v", carol.Name(), err)
|
|
||||||
}
|
|
||||||
if resp.PaymentError != "" {
|
|
||||||
t.Fatalf("received payment error from %s: %v",
|
|
||||||
carol.Name(), resp.PaymentError)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sendToRouteStream := func() {
|
sendToRouteStream := func() {
|
||||||
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
|
alicePayStream := carol.RPC.SendToRoute()
|
||||||
alicePayStream, err := carol.SendToRoute(ctxt) // nolint:staticcheck
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to create payment stream for "+
|
|
||||||
"carol: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, rHash := range rHashes {
|
for i, rHash := range rHashes {
|
||||||
setMPPFields(i)
|
setMPPFields(i)
|
||||||
@@ -252,19 +174,13 @@ func testSingleHopSendToRouteCase(net *lntest.NetworkHarness, t *harnessTest,
|
|||||||
Route: routes.Routes[0],
|
Route: routes.Routes[0],
|
||||||
}
|
}
|
||||||
err := alicePayStream.Send(sendReq)
|
err := alicePayStream.Send(sendReq)
|
||||||
|
require.NoError(ht, err, "unable to send payment")
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to send payment: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := alicePayStream.Recv()
|
resp, err := alicePayStream.Recv()
|
||||||
if err != nil {
|
require.NoError(ht, err, "unable to receive stream")
|
||||||
t.Fatalf("unable to send payment: %v", err)
|
require.Emptyf(ht, resp.PaymentError,
|
||||||
}
|
"received payment error from %s: %v",
|
||||||
if resp.PaymentError != "" {
|
carol.Name(), resp.PaymentError)
|
||||||
t.Fatalf("received payment error: %v",
|
|
||||||
resp.PaymentError)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sendToRouteRouterRPC := func() {
|
sendToRouteRouterRPC := func() {
|
||||||
@@ -275,23 +191,14 @@ func testSingleHopSendToRouteCase(net *lntest.NetworkHarness, t *harnessTest,
|
|||||||
PaymentHash: rHash,
|
PaymentHash: rHash,
|
||||||
Route: r,
|
Route: r,
|
||||||
}
|
}
|
||||||
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
|
resp := carol.RPC.SendToRouteV2(sendReq)
|
||||||
resp, err := carol.RouterClient.SendToRouteV2(
|
require.Nilf(ht, resp.Failure, "received payment "+
|
||||||
ctxt, sendReq,
|
"error from %s", carol.Name())
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to send to route for "+
|
|
||||||
"%s: %v", carol.Name(), err)
|
|
||||||
}
|
|
||||||
if resp.Failure != nil {
|
|
||||||
t.Fatalf("received payment error from %s: %v",
|
|
||||||
carol.Name(), resp.Failure)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Using Carol as the node as the source, send the payments
|
// Using Carol as the node as the source, send the payments
|
||||||
// synchronously via the the routerrpc's SendToRoute, or via the main RPC
|
// synchronously via the routerrpc's SendToRoute, or via the main RPC
|
||||||
// server's SendToRoute streaming or sync calls.
|
// server's SendToRoute streaming or sync calls.
|
||||||
switch {
|
switch {
|
||||||
case !test.routerrpc && test.streaming:
|
case !test.routerrpc && test.streaming:
|
||||||
@@ -301,118 +208,70 @@ func testSingleHopSendToRouteCase(net *lntest.NetworkHarness, t *harnessTest,
|
|||||||
case test.routerrpc && !test.streaming:
|
case test.routerrpc && !test.streaming:
|
||||||
sendToRouteRouterRPC()
|
sendToRouteRouterRPC()
|
||||||
default:
|
default:
|
||||||
t.Fatalf("routerrpc does not support streaming send_to_route")
|
require.Fail(ht, "routerrpc does not support "+
|
||||||
|
"streaming send_to_route")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that the payment's from Carol's PoV have the correct payment
|
// Verify that the payment's from Carol's PoV have the correct payment
|
||||||
// hash and amount.
|
// hash and amount.
|
||||||
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
|
payments := ht.AssertNumPayments(carol, numPayments)
|
||||||
paymentsResp, err := carol.ListPayments(
|
|
||||||
ctxt, &lnrpc.ListPaymentsRequest{},
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("error when obtaining %s payments: %v",
|
|
||||||
carol.Name(), err)
|
|
||||||
}
|
|
||||||
if len(paymentsResp.Payments) != numPayments {
|
|
||||||
t.Fatalf("incorrect number of payments, got %v, want %v",
|
|
||||||
len(paymentsResp.Payments), numPayments)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, p := range paymentsResp.Payments {
|
for i, p := range payments {
|
||||||
// Assert that the payment hashes for each payment match up.
|
// Assert that the payment hashes for each payment match up.
|
||||||
rHashHex := hex.EncodeToString(rHashes[i])
|
rHashHex := hex.EncodeToString(rHashes[i])
|
||||||
if p.PaymentHash != rHashHex {
|
require.Equalf(ht, rHashHex, p.PaymentHash,
|
||||||
t.Fatalf("incorrect payment hash for payment %d, "+
|
"incorrect payment hash for payment %d", i)
|
||||||
"want: %s got: %s",
|
|
||||||
i, rHashHex, p.PaymentHash)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert that each payment has no invoice since the payment was
|
// Assert that each payment has no invoice since the payment
|
||||||
// completed using SendToRoute.
|
// was completed using SendToRoute.
|
||||||
if p.PaymentRequest != "" {
|
require.Emptyf(ht, p.PaymentRequest,
|
||||||
t.Fatalf("incorrect payment request for payment: %d, "+
|
"incorrect payment request for payment: %d", i)
|
||||||
"want: \"\", got: %s",
|
|
||||||
i, p.PaymentRequest)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert the payment amount is correct.
|
// Assert the payment amount is correct.
|
||||||
if p.ValueSat != paymentAmtSat {
|
require.EqualValues(ht, paymentAmtSat, p.ValueSat,
|
||||||
t.Fatalf("incorrect payment amt for payment %d, "+
|
"incorrect payment amt for payment %d, ", i)
|
||||||
"want: %d, got: %d",
|
|
||||||
i, paymentAmtSat, p.ValueSat)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert exactly one htlc was made.
|
// Assert exactly one htlc was made.
|
||||||
if len(p.Htlcs) != 1 {
|
require.Lenf(ht, p.Htlcs, 1,
|
||||||
t.Fatalf("expected 1 htlc for payment %d, got: %d",
|
"expected 1 htlc for payment %d", i)
|
||||||
i, len(p.Htlcs))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert the htlc's route is populated.
|
// Assert the htlc's route is populated.
|
||||||
htlc := p.Htlcs[0]
|
htlc := p.Htlcs[0]
|
||||||
if htlc.Route == nil {
|
require.NotNilf(ht, htlc.Route,
|
||||||
t.Fatalf("expected route for payment %d", i)
|
"expected route for payment %d", i)
|
||||||
}
|
|
||||||
|
|
||||||
// Assert the hop has exactly one hop.
|
// Assert the hop has exactly one hop.
|
||||||
if len(htlc.Route.Hops) != 1 {
|
require.Lenf(ht, htlc.Route.Hops, 1,
|
||||||
t.Fatalf("expected 1 hop for payment %d, got: %d",
|
"expected 1 hop for payment %d", i)
|
||||||
i, len(htlc.Route.Hops))
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this is an MPP test, assert the MPP record's fields are
|
// If this is an MPP test, assert the MPP record's fields are
|
||||||
// properly populated. Otherwise the hop should not have an MPP
|
// properly populated. Otherwise the hop should not have an MPP
|
||||||
// record.
|
// record.
|
||||||
hop := htlc.Route.Hops[0]
|
hop := htlc.Route.Hops[0]
|
||||||
if hop.MppRecord == nil {
|
require.NotNilf(ht, hop.MppRecord,
|
||||||
t.Fatalf("expected mpp record for mpp payment")
|
"expected mpp record for mpp payment %d", i)
|
||||||
}
|
|
||||||
|
|
||||||
if hop.MppRecord.TotalAmtMsat != paymentAmtSat*1000 {
|
require.EqualValues(ht, paymentAmtSat*1000,
|
||||||
t.Fatalf("incorrect mpp total msat for payment %d "+
|
hop.MppRecord.TotalAmtMsat,
|
||||||
"want: %d, got: %d",
|
"incorrect mpp total msat for payment %d", i)
|
||||||
i, paymentAmtSat*1000,
|
|
||||||
hop.MppRecord.TotalAmtMsat)
|
|
||||||
}
|
|
||||||
|
|
||||||
expAddr := payAddrs[i]
|
expAddr := payAddrs[i]
|
||||||
if !bytes.Equal(hop.MppRecord.PaymentAddr, expAddr) {
|
require.Equal(ht, expAddr, hop.MppRecord.PaymentAddr,
|
||||||
t.Fatalf("incorrect mpp payment addr for payment %d "+
|
"incorrect mpp payment addr for payment %d ", i)
|
||||||
"want: %x, got: %x",
|
|
||||||
i, expAddr, hop.MppRecord.PaymentAddr)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that the invoices's from Dave's PoV have the correct payment
|
// Verify that the invoices's from Dave's PoV have the correct payment
|
||||||
// hash and amount.
|
// hash and amount.
|
||||||
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
|
invoices := ht.AssertNumInvoices(dave, numPayments)
|
||||||
invoicesResp, err := dave.ListInvoices(
|
|
||||||
ctxt, &lnrpc.ListInvoiceRequest{},
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("error when obtaining %s payments: %v",
|
|
||||||
dave.Name(), err)
|
|
||||||
}
|
|
||||||
if len(invoicesResp.Invoices) != numPayments {
|
|
||||||
t.Fatalf("incorrect number of invoices, got %v, want %v",
|
|
||||||
len(invoicesResp.Invoices), numPayments)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, inv := range invoicesResp.Invoices {
|
for i, inv := range invoices {
|
||||||
// Assert that the payment hashes match up.
|
// Assert that the payment hashes match up.
|
||||||
if !bytes.Equal(inv.RHash, rHashes[i]) {
|
require.Equal(ht, rHashes[i], inv.RHash,
|
||||||
t.Fatalf("incorrect payment hash for invoice %d, "+
|
"incorrect payment hash for invoice %d", i)
|
||||||
"want: %x got: %x",
|
|
||||||
i, rHashes[i], inv.RHash)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert that the amount paid to the invoice is correct.
|
// Assert that the amount paid to the invoice is correct.
|
||||||
if inv.AmtPaidSat != paymentAmtSat {
|
require.EqualValues(ht, paymentAmtSat, inv.AmtPaidSat,
|
||||||
t.Fatalf("incorrect payment amt for invoice %d, "+
|
"incorrect payment amt for invoice %d, ", i)
|
||||||
"want: %d, got %d",
|
|
||||||
i, paymentAmtSat, inv.AmtPaidSat)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// At this point all the channels within our proto network should be
|
// At this point all the channels within our proto network should be
|
||||||
@@ -420,12 +279,10 @@ func testSingleHopSendToRouteCase(net *lntest.NetworkHarness, t *harnessTest,
|
|||||||
// payment flow generated above. The order of asserts corresponds to
|
// payment flow generated above. The order of asserts corresponds to
|
||||||
// increasing of time is needed to embed the HTLC in commitment
|
// increasing of time is needed to embed the HTLC in commitment
|
||||||
// transaction, in channel Carol->Dave, order is Dave and then Carol.
|
// transaction, in channel Carol->Dave, order is Dave and then Carol.
|
||||||
assertAmountPaid(t, "Carol(local) => Dave(remote)", dave,
|
ht.AssertAmountPaid("Carol(local) => Dave(remote)", dave,
|
||||||
carolFundPoint, int64(0), amountPaid)
|
chanPointCarol, int64(0), amountPaid)
|
||||||
assertAmountPaid(t, "Carol(local) => Dave(remote)", carol,
|
ht.AssertAmountPaid("Carol(local) => Dave(remote)", carol,
|
||||||
carolFundPoint, amountPaid, int64(0))
|
chanPointCarol, amountPaid, int64(0))
|
||||||
|
|
||||||
closeChannelAndAssert(t, net, carol, chanPointCarol, false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// testMultiHopSendToRoute tests that payments are properly processed
|
// testMultiHopSendToRoute tests that payments are properly processed
|
||||||
|
|||||||
@@ -8,10 +8,6 @@ var allTestCases = []*testCase{
|
|||||||
name: "single hop invoice",
|
name: "single hop invoice",
|
||||||
test: testSingleHopInvoice,
|
test: testSingleHopInvoice,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "single-hop send to route",
|
|
||||||
test: testSingleHopSendToRoute,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "multi-hop send to route",
|
name: "multi-hop send to route",
|
||||||
test: testMultiHopSendToRoute,
|
test: testMultiHopSendToRoute,
|
||||||
|
|||||||
Reference in new issue
Block a user