itest: switch over to routerrpc.SendPaymentV2

This commit is contained in:
Joost Jager 2020-03-31 12:44:18 +02:00
parent ca9c58aec9
commit e201ed8106
No known key found for this signature in database
GPG Key ID: A61B9D4C393C59C7
13 changed files with 464 additions and 410 deletions

@ -4,7 +4,6 @@ package itest
import ( import (
"context" "context"
"encoding/hex"
"strings" "strings"
"time" "time"
@ -177,24 +176,18 @@ out:
// TODO(roasbeef): return failure response rather than failing entire // TODO(roasbeef): return failure response rather than failing entire
// stream on payment error. // stream on payment error.
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
sendReq := &lnrpc.SendRequest{ sendReq := &routerrpc.SendPaymentRequest{
PaymentHashString: hex.EncodeToString(makeFakePayHash(t)), PaymentHash: makeFakePayHash(t),
DestString: hex.EncodeToString(carol.PubKey[:]), Dest: carol.PubKey[:],
Amt: payAmt, Amt: payAmt,
FinalCltvDelta: int32(carolPayReq.CltvExpiry), FinalCltvDelta: int32(carolPayReq.CltvExpiry),
TimeoutSeconds: 60,
FeeLimitMsat: noFeeLimitMsat,
} }
resp, err := net.Alice.SendPaymentSync(ctxt, sendReq) sendAndAssertFailure(
if err != nil { t, net.Alice,
t.Fatalf("unable to send payment: %v", err) sendReq, lnrpc.PaymentFailureReason_FAILURE_REASON_INCORRECT_PAYMENT_DETAILS,
} )
// The payment should have resulted in an error since we sent it with the
// wrong payment hash.
if resp.PaymentError == "" {
t.Fatalf("payment should have been rejected due to invalid " +
"payment hash")
}
assertLastHTLCError( assertLastHTLCError(
t, net.Alice, t, net.Alice,
lnrpc.Failure_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS, lnrpc.Failure_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS,
@ -219,25 +212,18 @@ out:
// Next, we'll test the case of a recognized payHash but, an incorrect // Next, we'll test the case of a recognized payHash but, an incorrect
// value on the extended HTLC. // value on the extended HTLC.
htlcAmt := lnwire.NewMSatFromSatoshis(1000) htlcAmt := lnwire.NewMSatFromSatoshis(1000)
sendReq = &lnrpc.SendRequest{ sendReq = &routerrpc.SendPaymentRequest{
PaymentHashString: hex.EncodeToString(carolInvoice.RHash), PaymentHash: carolInvoice.RHash,
DestString: hex.EncodeToString(carol.PubKey[:]), Dest: carol.PubKey[:],
Amt: int64(htlcAmt.ToSatoshis()), // 10k satoshis are expected. Amt: int64(htlcAmt.ToSatoshis()), // 10k satoshis are expected.
FinalCltvDelta: int32(carolPayReq.CltvExpiry), FinalCltvDelta: int32(carolPayReq.CltvExpiry),
TimeoutSeconds: 60,
FeeLimitMsat: noFeeLimitMsat,
} }
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) sendAndAssertFailure(
resp, err = net.Alice.SendPaymentSync(ctxt, sendReq) t, net.Alice,
if err != nil { sendReq, lnrpc.PaymentFailureReason_FAILURE_REASON_INCORRECT_PAYMENT_DETAILS,
t.Fatalf("unable to send payment: %v", err) )
}
// The payment should fail with an error since we sent 1k satoshis isn't of
// 10k as was requested.
if resp.PaymentError == "" {
t.Fatalf("payment should have been rejected due to wrong " +
"HTLC amount")
}
assertLastHTLCError( assertLastHTLCError(
t, net.Alice, t, net.Alice,
lnrpc.Failure_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS, lnrpc.Failure_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS,
@ -262,14 +248,7 @@ out:
// Next we'll test an error that occurs mid-route due to an outgoing // Next we'll test an error that occurs mid-route due to an outgoing
// link having insufficient capacity. In order to do so, we'll first // link having insufficient capacity. In order to do so, we'll first
// need to unbalance the link connecting Bob<->Carol. // need to unbalance the link connecting Bob<->Carol.
ctx, cancel := context.WithCancel(ctxb) //
defer cancel()
bobPayStream, err := net.Bob.SendPayment(ctx)
if err != nil {
t.Fatalf("unable to create payment stream: %v", err)
}
// To do so, we'll push most of the funds in the channel over to // To do so, we'll push most of the funds in the channel over to
// Alice's side, leaving on 10k satoshis of available balance for bob. // Alice's side, leaving on 10k satoshis of available balance for bob.
// There's a max payment amount, so we'll have to do this // There's a max payment amount, so we'll have to do this
@ -294,17 +273,14 @@ out:
if err != nil { if err != nil {
t.Fatalf("unable to generate carol invoice: %v", err) t.Fatalf("unable to generate carol invoice: %v", err)
} }
if err := bobPayStream.Send(&lnrpc.SendRequest{ sendAndAssertSuccess(
PaymentRequest: carolInvoice2.PaymentRequest, t, net.Bob,
}); err != nil { &routerrpc.SendPaymentRequest{
t.Fatalf("unable to send payment: %v", err) PaymentRequest: carolInvoice2.PaymentRequest,
} TimeoutSeconds: 60,
FeeLimitMsat: noFeeLimitMsat,
if resp, err := bobPayStream.Recv(); err != nil { },
t.Fatalf("payment stream has been closed: %v", err) )
} else if resp.PaymentError != "" {
t.Fatalf("bob's payment failed: %v", resp.PaymentError)
}
// For each send bob makes, we need to check that bob has a // For each send bob makes, we need to check that bob has a
// forward and settle event for his send, and carol has a // forward and settle event for his send, and carol has a
@ -331,19 +307,15 @@ out:
t.Fatalf("unable to generate carol invoice: %v", err) t.Fatalf("unable to generate carol invoice: %v", err)
} }
sendReq = &lnrpc.SendRequest{ sendReq = &routerrpc.SendPaymentRequest{
PaymentRequest: carolInvoice3.PaymentRequest, PaymentRequest: carolInvoice3.PaymentRequest,
TimeoutSeconds: 60,
FeeLimitMsat: noFeeLimitMsat,
} }
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) sendAndAssertFailure(
resp, err = net.Alice.SendPaymentSync(ctxt, sendReq) t, net.Alice,
if err != nil { sendReq, lnrpc.PaymentFailureReason_FAILURE_REASON_NO_ROUTE,
t.Fatalf("unable to send payment: %v", err) )
}
if resp.PaymentError == "" {
t.Fatalf("payment should fail due to insufficient "+
"capacity: %v", err)
}
assertLastHTLCError( assertLastHTLCError(
t, net.Alice, lnrpc.Failure_TEMPORARY_CHANNEL_FAILURE, t, net.Alice, lnrpc.Failure_TEMPORARY_CHANNEL_FAILURE,
) )
@ -382,19 +354,15 @@ out:
t.Fatalf("unable to reset mission control: %v", err) t.Fatalf("unable to reset mission control: %v", err)
} }
sendReq = &lnrpc.SendRequest{ sendAndAssertFailure(
PaymentRequest: carolInvoice.PaymentRequest, t, net.Alice,
} &routerrpc.SendPaymentRequest{
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) PaymentRequest: carolInvoice.PaymentRequest,
resp, err = net.Alice.SendPaymentSync(ctxt, sendReq) TimeoutSeconds: 60,
if err != nil { FeeLimitMsat: noFeeLimitMsat,
t.Fatalf("unable to send payment: %v", err) },
} lnrpc.PaymentFailureReason_FAILURE_REASON_NO_ROUTE,
)
if resp.PaymentError == "" {
t.Fatalf("payment should have failed")
}
assertLastHTLCError(t, net.Alice, lnrpc.Failure_UNKNOWN_NEXT_PEER) assertLastHTLCError(t, net.Alice, lnrpc.Failure_UNKNOWN_NEXT_PEER)
// Alice should have a forwarding event and subsequent fail. // Alice should have a forwarding event and subsequent fail.

@ -217,7 +217,9 @@ func testMultiHopPayments(net *lntest.NetworkHarness, t *harnessTest) {
// Using Carol as the source, pay to the 5 invoices from Bob created // Using Carol as the source, pay to the 5 invoices from Bob created
// above. // above.
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
err = completePaymentRequests(ctxt, carol, payReqs, true) err = completePaymentRequests(
ctxt, carol, carol.RouterClient, payReqs, true,
)
if err != nil { if err != nil {
t.Fatalf("unable to send payments: %v", err) t.Fatalf("unable to send payments: %v", err)
} }

@ -13,6 +13,7 @@ import (
"github.com/lightningnetwork/lnd/lncfg" "github.com/lightningnetwork/lnd/lncfg"
"github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc" "github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"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/lntypes" "github.com/lightningnetwork/lnd/lntypes"
@ -62,13 +63,14 @@ func testMultiHopHtlcLocalChainClaim(net *lntest.NetworkHarness, t *harnessTest,
ctx, cancel := context.WithCancel(ctxb) ctx, cancel := context.WithCancel(ctxb)
defer cancel() defer cancel()
alicePayStream, err := alice.SendPayment(ctx) _, err = alice.RouterClient.SendPaymentV2(
if err != nil { ctx,
t.Fatalf("unable to create payment stream for alice: %v", err) &routerrpc.SendPaymentRequest{
} PaymentRequest: carolInvoice.PaymentRequest,
err = alicePayStream.Send(&lnrpc.SendRequest{ TimeoutSeconds: 60,
PaymentRequest: carolInvoice.PaymentRequest, FeeLimitMsat: noFeeLimitMsat,
}) },
)
if err != nil { if err != nil {
t.Fatalf("unable to send payment: %v", err) t.Fatalf("unable to send payment: %v", err)
} }

@ -14,6 +14,7 @@ import (
"github.com/lightningnetwork/lnd" "github.com/lightningnetwork/lnd"
"github.com/lightningnetwork/lnd/lncfg" "github.com/lightningnetwork/lnd/lncfg"
"github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lntest" "github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/wait" "github.com/lightningnetwork/lnd/lntest/wait"
) )
@ -52,31 +53,38 @@ func testMultiHopHtlcLocalTimeout(net *lntest.NetworkHarness, t *harnessTest,
ctx, cancel := context.WithCancel(ctxb) ctx, cancel := context.WithCancel(ctxb)
defer cancel() defer cancel()
alicePayStream, err := alice.SendPayment(ctx)
if err != nil {
t.Fatalf("unable to create payment stream for alice: %v", err)
}
// We'll create two random payment hashes unknown to carol, then send // We'll create two random payment hashes unknown to carol, then send
// each of them by manually specifying the HTLC details. // each of them by manually specifying the HTLC details.
carolPubKey := carol.PubKey[:] carolPubKey := carol.PubKey[:]
dustPayHash := makeFakePayHash(t) dustPayHash := makeFakePayHash(t)
payHash := makeFakePayHash(t) payHash := makeFakePayHash(t)
err = alicePayStream.Send(&lnrpc.SendRequest{
Dest: carolPubKey, _, err := alice.RouterClient.SendPaymentV2(
Amt: int64(dustHtlcAmt), ctx,
PaymentHash: dustPayHash, &routerrpc.SendPaymentRequest{
FinalCltvDelta: finalCltvDelta, Dest: carolPubKey,
}) Amt: int64(dustHtlcAmt),
PaymentHash: dustPayHash,
FinalCltvDelta: finalCltvDelta,
TimeoutSeconds: 60,
FeeLimitMsat: noFeeLimitMsat,
},
)
if err != nil { if err != nil {
t.Fatalf("unable to send alice htlc: %v", err) t.Fatalf("unable to send alice htlc: %v", err)
} }
err = alicePayStream.Send(&lnrpc.SendRequest{
Dest: carolPubKey, _, err = alice.RouterClient.SendPaymentV2(
Amt: int64(htlcAmt), ctx,
PaymentHash: payHash, &routerrpc.SendPaymentRequest{
FinalCltvDelta: finalCltvDelta, Dest: carolPubKey,
}) Amt: int64(htlcAmt),
PaymentHash: payHash,
FinalCltvDelta: finalCltvDelta,
TimeoutSeconds: 60,
FeeLimitMsat: noFeeLimitMsat,
},
)
if err != nil { if err != nil {
t.Fatalf("unable to send alice htlc: %v", err) t.Fatalf("unable to send alice htlc: %v", err)
} }

@ -13,6 +13,7 @@ import (
"github.com/lightningnetwork/lnd/lncfg" "github.com/lightningnetwork/lnd/lncfg"
"github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc" "github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"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/lntypes" "github.com/lightningnetwork/lnd/lntypes"
@ -64,13 +65,14 @@ func testMultiHopReceiverChainClaim(net *lntest.NetworkHarness, t *harnessTest,
ctx, cancel := context.WithCancel(ctxb) ctx, cancel := context.WithCancel(ctxb)
defer cancel() defer cancel()
alicePayStream, err := alice.SendPayment(ctx) _, err = alice.RouterClient.SendPaymentV2(
if err != nil { ctx,
t.Fatalf("unable to create payment stream for alice: %v", err) &routerrpc.SendPaymentRequest{
} PaymentRequest: carolInvoice.PaymentRequest,
err = alicePayStream.Send(&lnrpc.SendRequest{ TimeoutSeconds: 60,
PaymentRequest: carolInvoice.PaymentRequest, FeeLimitMsat: noFeeLimitMsat,
}) },
)
if err != nil { if err != nil {
t.Fatalf("unable to send payment: %v", err) t.Fatalf("unable to send payment: %v", err)
} }

@ -13,6 +13,7 @@ import (
"github.com/lightningnetwork/lnd/lncfg" "github.com/lightningnetwork/lnd/lncfg"
"github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc" "github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"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/lntypes" "github.com/lightningnetwork/lnd/lntypes"
@ -62,13 +63,14 @@ func testMultiHopHtlcRemoteChainClaim(net *lntest.NetworkHarness, t *harnessTest
ctx, cancel := context.WithCancel(ctxb) ctx, cancel := context.WithCancel(ctxb)
defer cancel() defer cancel()
alicePayStream, err := alice.SendPayment(ctx) _, err = alice.RouterClient.SendPaymentV2(
if err != nil { ctx,
t.Fatalf("unable to create payment stream for alice: %v", err) &routerrpc.SendPaymentRequest{
} PaymentRequest: carolInvoice.PaymentRequest,
err = alicePayStream.Send(&lnrpc.SendRequest{ TimeoutSeconds: 60,
PaymentRequest: carolInvoice.PaymentRequest, FeeLimitMsat: noFeeLimitMsat,
}) },
)
if err != nil { if err != nil {
t.Fatalf("unable to send payment: %v", err) t.Fatalf("unable to send payment: %v", err)
} }

@ -10,6 +10,7 @@ import (
"github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil"
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lntest" "github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/wait" "github.com/lightningnetwork/lnd/lntest/wait"
) )
@ -44,20 +45,20 @@ func testMultiHopLocalForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness,
ctx, cancel := context.WithCancel(ctxb) ctx, cancel := context.WithCancel(ctxb)
defer cancel() defer cancel()
alicePayStream, err := alice.SendPayment(ctx)
if err != nil {
t.Fatalf("unable to create payment stream for alice: %v", err)
}
// We'll now send a single HTLC across our multi-hop network. // We'll now send a single HTLC across our multi-hop network.
carolPubKey := carol.PubKey[:] carolPubKey := carol.PubKey[:]
payHash := makeFakePayHash(t) payHash := makeFakePayHash(t)
err = alicePayStream.Send(&lnrpc.SendRequest{ _, err := alice.RouterClient.SendPaymentV2(
Dest: carolPubKey, ctx,
Amt: int64(htlcAmt), &routerrpc.SendPaymentRequest{
PaymentHash: payHash, Dest: carolPubKey,
FinalCltvDelta: finalCltvDelta, Amt: int64(htlcAmt),
}) PaymentHash: payHash,
FinalCltvDelta: finalCltvDelta,
TimeoutSeconds: 60,
FeeLimitMsat: noFeeLimitMsat,
},
)
if err != nil { if err != nil {
t.Fatalf("unable to send alice htlc: %v", err) t.Fatalf("unable to send alice htlc: %v", err)
} }

@ -10,6 +10,7 @@ import (
"github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil"
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lntest" "github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/wait" "github.com/lightningnetwork/lnd/lntest/wait"
) )
@ -45,20 +46,20 @@ func testMultiHopRemoteForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness,
ctx, cancel := context.WithCancel(ctxb) ctx, cancel := context.WithCancel(ctxb)
defer cancel() defer cancel()
alicePayStream, err := alice.SendPayment(ctx)
if err != nil {
t.Fatalf("unable to create payment stream for alice: %v", err)
}
// We'll now send a single HTLC across our multi-hop network. // We'll now send a single HTLC across our multi-hop network.
carolPubKey := carol.PubKey[:] carolPubKey := carol.PubKey[:]
payHash := makeFakePayHash(t) payHash := makeFakePayHash(t)
err = alicePayStream.Send(&lnrpc.SendRequest{ _, err := alice.RouterClient.SendPaymentV2(
Dest: carolPubKey, ctx,
Amt: int64(htlcAmt), &routerrpc.SendPaymentRequest{
PaymentHash: payHash, Dest: carolPubKey,
FinalCltvDelta: finalCltvDelta, Amt: int64(htlcAmt),
}) PaymentHash: payHash,
FinalCltvDelta: finalCltvDelta,
TimeoutSeconds: 60,
FeeLimitMsat: noFeeLimitMsat,
},
)
if err != nil { if err != nil {
t.Fatalf("unable to send alice htlc: %v", err) t.Fatalf("unable to send alice htlc: %v", err)
} }

@ -74,7 +74,7 @@ func testSendMultiPathPayment(net *lntest.NetworkHarness, t *harnessTest) {
t, net.Alice, t, net.Alice,
&routerrpc.SendPaymentRequest{ &routerrpc.SendPaymentRequest{
PaymentRequest: payReq, PaymentRequest: payReq,
MaxParts: 10, MaxParts: 10,
TimeoutSeconds: 60, TimeoutSeconds: 60,
FeeLimitMsat: noFeeLimitMsat, FeeLimitMsat: noFeeLimitMsat,
}, },

@ -5,11 +5,13 @@ package itest
import ( import (
"bytes" "bytes"
"context" "context"
"encoding/hex"
"time" "time"
"github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil"
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"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/lntypes" "github.com/lightningnetwork/lnd/lntypes"
@ -62,21 +64,17 @@ func testSingleHopInvoice(net *lntest.NetworkHarness, t *harnessTest) {
// With the invoice for Bob added, send a payment towards Alice paying // With the invoice for Bob added, send a payment towards Alice paying
// to the above generated invoice. // to the above generated invoice.
sendReq := &lnrpc.SendRequest{ resp := sendAndAssertSuccess(
PaymentRequest: invoiceResp.PaymentRequest, t, net.Alice,
} &routerrpc.SendPaymentRequest{
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) PaymentRequest: invoiceResp.PaymentRequest,
resp, err := net.Alice.SendPaymentSync(ctxt, sendReq) TimeoutSeconds: 60,
if err != nil { FeeLimitMsat: noFeeLimitMsat,
t.Fatalf("unable to send payment: %v", err) },
} )
if hex.EncodeToString(preimage) != resp.PaymentPreimage {
// Ensure we obtain the proper preimage in the response.
if resp.PaymentError != "" {
t.Fatalf("error when attempting recv: %v", resp.PaymentError)
} else if !bytes.Equal(preimage, resp.PaymentPreimage) {
t.Fatalf("preimage mismatch: expected %v, got %v", preimage, t.Fatalf("preimage mismatch: expected %v, got %v", preimage,
resp.GetPaymentPreimage()) resp.PaymentPreimage)
} }
// Bob's invoice should now be found and marked as settled. // Bob's invoice should now be found and marked as settled.
@ -118,17 +116,14 @@ func testSingleHopInvoice(net *lntest.NetworkHarness, t *harnessTest) {
// Next send another payment, but this time using a zpay32 encoded // Next send another payment, but this time using a zpay32 encoded
// invoice rather than manually specifying the payment details. // invoice rather than manually specifying the payment details.
sendReq = &lnrpc.SendRequest{ sendAndAssertSuccess(
PaymentRequest: invoiceResp.PaymentRequest, t, net.Alice,
} &routerrpc.SendPaymentRequest{
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) PaymentRequest: invoiceResp.PaymentRequest,
resp, err = net.Alice.SendPaymentSync(ctxt, sendReq) TimeoutSeconds: 60,
if err != nil { FeeLimitMsat: noFeeLimitMsat,
t.Fatalf("unable to send payment: %v", err) },
} )
if resp.PaymentError != "" {
t.Fatalf("error when attempting recv: %v", resp.PaymentError)
}
// The second payment should also have succeeded, with the balances // The second payment should also have succeeded, with the balances
// being update accordingly. // being update accordingly.
@ -144,23 +139,20 @@ func testSingleHopInvoice(net *lntest.NetworkHarness, t *harnessTest) {
keySendPreimage := lntypes.Preimage{3, 4, 5, 11} keySendPreimage := lntypes.Preimage{3, 4, 5, 11}
keySendHash := keySendPreimage.Hash() keySendHash := keySendPreimage.Hash()
sendReq = &lnrpc.SendRequest{ sendAndAssertSuccess(
Dest: net.Bob.PubKey[:], t, net.Alice,
Amt: paymentAmt, &routerrpc.SendPaymentRequest{
FinalCltvDelta: 40, Dest: net.Bob.PubKey[:],
PaymentHash: keySendHash[:], Amt: paymentAmt,
DestCustomRecords: map[uint64][]byte{ FinalCltvDelta: 40,
record.KeySendType: keySendPreimage[:], PaymentHash: keySendHash[:],
DestCustomRecords: map[uint64][]byte{
record.KeySendType: keySendPreimage[:],
},
TimeoutSeconds: 60,
FeeLimitMsat: noFeeLimitMsat,
}, },
} )
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
resp, err = net.Alice.SendPaymentSync(ctxt, sendReq)
if err != nil {
t.Fatalf("unable to send payment: %v", err)
}
if resp.PaymentError != "" {
t.Fatalf("error when attempting recv: %v", resp.PaymentError)
}
// The keysend payment should also have succeeded, with the balances // The keysend payment should also have succeeded, with the balances
// being update accordingly. // being update accordingly.

@ -647,7 +647,8 @@ func shutdownAndAssert(net *lntest.NetworkHarness, t *harnessTest,
// payment requests. If the awaitResponse parameter is true, this function // payment requests. If the awaitResponse parameter is true, this function
// does not return until all payments successfully complete without errors. // does not return until all payments successfully complete without errors.
func completePaymentRequests(ctx context.Context, client lnrpc.LightningClient, func completePaymentRequests(ctx context.Context, client lnrpc.LightningClient,
paymentRequests []string, awaitResponse bool) error { routerClient routerrpc.RouterClient, paymentRequests []string,
awaitResponse bool) error {
// We start by getting the current state of the client's channels. This // We start by getting the current state of the client's channels. This
// is needed to ensure the payments actually have been committed before // is needed to ensure the payments actually have been committed before
@ -659,36 +660,54 @@ func completePaymentRequests(ctx context.Context, client lnrpc.LightningClient,
return err return err
} }
ctxc, cancel := context.WithCancel(ctx) // send sends a payment and returns an error if it doesn't succeeded.
defer cancel() send := func(payReq string) error {
ctxc, cancel := context.WithCancel(ctx)
defer cancel()
payStream, err := client.SendPayment(ctxc) payStream, err := routerClient.SendPaymentV2(
if err != nil { ctxc,
return err &routerrpc.SendPaymentRequest{
} PaymentRequest: payReq,
TimeoutSeconds: 60,
for _, payReq := range paymentRequests { FeeLimitMsat: noFeeLimitMsat,
sendReq := &lnrpc.SendRequest{ },
PaymentRequest: payReq, )
}
err := payStream.Send(sendReq)
if err != nil { if err != nil {
return err return err
} }
resp, err := getPaymentResult(payStream)
if err != nil {
return err
}
if resp.Status != lnrpc.Payment_SUCCEEDED {
return errors.New(resp.FailureReason)
}
return nil
} }
// Launch all payments simultaneously.
results := make(chan error)
for _, payReq := range paymentRequests {
payReqCopy := payReq
go func() {
err := send(payReqCopy)
if awaitResponse {
results <- err
}
}()
}
// If awaiting a response, verify that all payments succeeded.
if awaitResponse { if awaitResponse {
for range paymentRequests { for range paymentRequests {
resp, err := payStream.Recv() err := <-results
if err != nil { if err != nil {
return err return err
} }
if resp.PaymentError != "" {
return fmt.Errorf("received payment error: %v",
resp.PaymentError)
}
} }
return nil return nil
} }
@ -1530,17 +1549,14 @@ func testPaymentFollowingChannelOpen(net *lntest.NetworkHarness, t *harnessTest)
// Send payment to Bob so that a channel update to disk will be // Send payment to Bob so that a channel update to disk will be
// executed. // executed.
ctxt, cancel = context.WithTimeout(ctxb, defaultTimeout) sendAndAssertSuccess(
defer cancel() t, net.Alice,
_, err = net.Alice.SendPaymentSync( &routerrpc.SendPaymentRequest{
ctxt,
&lnrpc.SendRequest{
PaymentRequest: bobPayReqs[0], PaymentRequest: bobPayReqs[0],
TimeoutSeconds: 60,
FeeLimitSat: 1000000,
}, },
) )
if err != nil {
t.Fatalf("unable to create payment stream for alice: %v", err)
}
// At this point we want to make sure the channel is opened and not // At this point we want to make sure the channel is opened and not
// pending. // pending.
@ -1968,15 +1984,15 @@ func testUpdateChannelPolicy(net *lntest.NetworkHarness, t *harnessTest) {
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
err = completePaymentRequests( err = completePaymentRequests(
ctxt, net.Alice, []string{resp.PaymentRequest}, true, ctxt, net.Alice, net.Alice.RouterClient,
[]string{resp.PaymentRequest}, true,
) )
// Alice knows about the channel policy of Carol and should therefore // Alice knows about the channel policy of Carol and should therefore
// not be able to find a path during routing. // not be able to find a path during routing.
expErr := channeldb.FailureReasonNoRoute.Error() expErr := lnrpc.PaymentFailureReason_FAILURE_REASON_NO_ROUTE
if err == nil || if err.Error() != expErr.String() {
!strings.Contains(err.Error(), expErr) { t.Fatalf("expected %v, instead got %v", expErr, err)
t.Fatalf("expected payment to fail, instead got %v", err)
} }
// Now we try to send a payment over the channel with a value too low // Now we try to send a payment over the channel with a value too low
@ -2141,7 +2157,8 @@ func testUpdateChannelPolicy(net *lntest.NetworkHarness, t *harnessTest) {
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
err = completePaymentRequests( err = completePaymentRequests(
ctxt, net.Alice, []string{resp.PaymentRequest}, true, ctxt, net.Alice, net.Alice.RouterClient,
[]string{resp.PaymentRequest}, true,
) )
if err != nil { if err != nil {
t.Fatalf("unable to send payment: %v", err) t.Fatalf("unable to send payment: %v", err)
@ -2949,27 +2966,26 @@ func testChannelUnsettledBalance(net *lntest.NetworkHarness, t *harnessTest) {
numInvoices = 6 numInvoices = 6
) )
// Create a paystream from Alice to Carol to enable Alice to make // Simulateneously send numInvoices payments from Alice to Carol.
// a series of payments.
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
alicePayStream, err := net.Alice.SendPayment(ctxt)
if err != nil {
t.Fatalf("unable to create payment stream for alice: %v", err)
}
// Send payments from Alice to Carol a number of numInvoices
// times.
carolPubKey := carol.PubKey[:] carolPubKey := carol.PubKey[:]
errChan := make(chan error)
for i := 0; i < numInvoices; i++ { for i := 0; i < numInvoices; i++ {
err = alicePayStream.Send(&lnrpc.SendRequest{ go func() {
Dest: carolPubKey, ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
Amt: int64(payAmt), _, err := net.Alice.RouterClient.SendPaymentV2(ctxt,
PaymentHash: makeFakePayHash(t), &routerrpc.SendPaymentRequest{
FinalCltvDelta: lnd.DefaultBitcoinTimeLockDelta, Dest: carolPubKey,
}) Amt: int64(payAmt),
if err != nil { PaymentHash: makeFakePayHash(t),
t.Fatalf("unable to send alice htlc: %v", err) FinalCltvDelta: lnd.DefaultBitcoinTimeLockDelta,
} TimeoutSeconds: 60,
FeeLimitMsat: noFeeLimitMsat,
})
if err != nil {
errChan <- err
}
}()
} }
// Test that the UnsettledBalance for both Alice and Carol // Test that the UnsettledBalance for both Alice and Carol
@ -3013,6 +3029,13 @@ func testChannelUnsettledBalance(net *lntest.NetworkHarness, t *harnessTest) {
t.Fatalf("unsettled balace error: %v", unsettledErr) t.Fatalf("unsettled balace error: %v", unsettledErr)
} }
// Check for payment errors.
select {
case err := <-errChan:
t.Fatalf("payment error: %v", err)
default:
}
// Force and assert the channel closure. // Force and assert the channel closure.
ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout)
closeChannelAndAssert(ctxt, t, net, net.Alice, chanPointAlice, true) closeChannelAndAssert(ctxt, t, net, net.Alice, chanPointAlice, true)
@ -3283,22 +3306,22 @@ func channelForceClosureTest(net *lntest.NetworkHarness, t *harnessTest,
// Send payments from Alice to Carol, since Carol is htlchodl mode, the // Send payments from Alice to Carol, since Carol is htlchodl mode, the
// htlc outputs should be left unsettled, and should be swept by the // htlc outputs should be left unsettled, and should be swept by the
// utxo nursery. // utxo nursery.
ctx, cancel := context.WithCancel(ctxb)
defer cancel()
alicePayStream, err := alice.SendPayment(ctx)
if err != nil {
t.Fatalf("unable to create payment stream for alice: %v", err)
}
carolPubKey := carol.PubKey[:] carolPubKey := carol.PubKey[:]
for i := 0; i < numInvoices; i++ { for i := 0; i < numInvoices; i++ {
err = alicePayStream.Send(&lnrpc.SendRequest{ ctx, cancel := context.WithCancel(ctxb)
Dest: carolPubKey, defer cancel()
Amt: int64(paymentAmt),
PaymentHash: makeFakePayHash(t), _, err := alice.RouterClient.SendPaymentV2(
FinalCltvDelta: lnd.DefaultBitcoinTimeLockDelta, ctx,
}) &routerrpc.SendPaymentRequest{
Dest: carolPubKey,
Amt: int64(paymentAmt),
PaymentHash: makeFakePayHash(t),
FinalCltvDelta: lnd.DefaultBitcoinTimeLockDelta,
TimeoutSeconds: 60,
FeeLimitMsat: noFeeLimitMsat,
},
)
if err != nil { if err != nil {
t.Fatalf("unable to send alice htlc: %v", err) t.Fatalf("unable to send alice htlc: %v", err)
} }
@ -4255,17 +4278,18 @@ func testSphinxReplayPersistence(net *lntest.NetworkHarness, t *harnessTest) {
ctx, cancel := context.WithCancel(ctxb) ctx, cancel := context.WithCancel(ctxb)
defer cancel() defer cancel()
payStream, err := fred.SendPayment(ctx) payStream, err := fred.RouterClient.SendPaymentV2(
ctx,
&routerrpc.SendPaymentRequest{
PaymentRequest: invoiceResp.PaymentRequest,
TimeoutSeconds: 60,
FeeLimitMsat: noFeeLimitMsat,
},
)
if err != nil { if err != nil {
t.Fatalf("unable to open payment stream: %v", err) t.Fatalf("unable to open payment stream: %v", err)
} }
sendReq := &lnrpc.SendRequest{PaymentRequest: invoiceResp.PaymentRequest}
err = payStream.Send(sendReq)
if err != nil {
t.Fatalf("unable to send payment: %v", err)
}
time.Sleep(200 * time.Millisecond) time.Sleep(200 * time.Millisecond)
// Dave's invoice should not be marked as settled. // Dave's invoice should not be marked as settled.
@ -4303,14 +4327,14 @@ func testSphinxReplayPersistence(net *lntest.NetworkHarness, t *harnessTest) {
// pending payment. Even though he still holds the original settle, if // pending payment. Even though he still holds the original settle, if
// he does fail, it is almost certainly caused by the sphinx replay // he does fail, it is almost certainly caused by the sphinx replay
// protection, as it is the only validation we do in hodl mode. // protection, as it is the only validation we do in hodl mode.
resp, err := payStream.Recv() result, err := getPaymentResult(payStream)
if err != nil { if err != nil {
t.Fatalf("unable to receive payment response: %v", err) t.Fatalf("unable to receive payment response: %v", err)
} }
// Assert that Fred receives the expected failure after Carol sent a // Assert that Fred receives the expected failure after Carol sent a
// duplicate packet that fails due to sphinx replay detection. // duplicate packet that fails due to sphinx replay detection.
if resp.PaymentError == "" { if result.Status == lnrpc.Payment_SUCCEEDED {
t.Fatalf("expected payment error") t.Fatalf("expected payment error")
} }
assertLastHTLCError(t, fred, lnrpc.Failure_INVALID_ONION_KEY) assertLastHTLCError(t, fred, lnrpc.Failure_INVALID_ONION_KEY)
@ -4395,17 +4419,14 @@ func testListPayments(net *lntest.NetworkHarness, t *harnessTest) {
// With the invoice for Bob added, send a payment towards Alice paying // With the invoice for Bob added, send a payment towards Alice paying
// to the above generated invoice. // to the above generated invoice.
sendReq := &lnrpc.SendRequest{ sendAndAssertSuccess(
PaymentRequest: invoiceResp.PaymentRequest, t, net.Alice,
} &routerrpc.SendPaymentRequest{
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) PaymentRequest: invoiceResp.PaymentRequest,
resp, err := net.Alice.SendPaymentSync(ctxt, sendReq) TimeoutSeconds: 60,
if err != nil { FeeLimitSat: 1000000,
t.Fatalf("unable to send payment: %v", err) },
} )
if resp.PaymentError != "" {
t.Fatalf("error when attempting recv: %v", resp.PaymentError)
}
// Grab Alice's list of payments, she should show the existence of // Grab Alice's list of payments, she should show the existence of
// exactly one payment. // exactly one payment.
@ -5647,7 +5668,9 @@ func testPrivateChannels(net *lntest.NetworkHarness, t *harnessTest) {
// Let Carol pay the invoices. // Let Carol pay the invoices.
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
err = completePaymentRequests(ctxt, carol, payReqs, true) err = completePaymentRequests(
ctxt, carol, carol.RouterClient, payReqs, true,
)
if err != nil { if err != nil {
t.Fatalf("unable to send payments: %v", err) t.Fatalf("unable to send payments: %v", err)
} }
@ -5703,7 +5726,9 @@ func testPrivateChannels(net *lntest.NetworkHarness, t *harnessTest) {
// Let Bob pay the invoices. // Let Bob pay the invoices.
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
err = completePaymentRequests(ctxt, net.Alice, payReqs, true) err = completePaymentRequests(
ctxt, net.Alice, net.Alice.RouterClient, payReqs, true,
)
if err != nil { if err != nil {
t.Fatalf("unable to send payments: %v", err) t.Fatalf("unable to send payments: %v", err)
} }
@ -6179,7 +6204,9 @@ func testMultiHopOverPrivateChannels(net *lntest.NetworkHarness, t *harnessTest)
// Let Alice pay the invoice. // Let Alice pay the invoice.
payReqs := []string{resp.PaymentRequest} payReqs := []string{resp.PaymentRequest}
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
err = completePaymentRequests(ctxt, net.Alice, payReqs, true) err = completePaymentRequests(
ctxt, net.Alice, net.Alice.RouterClient, payReqs, true,
)
if err != nil { if err != nil {
t.Fatalf("unable to send payments from alice to dave: %v", err) t.Fatalf("unable to send payments from alice to dave: %v", err)
} }
@ -6315,18 +6342,25 @@ func testInvoiceSubscriptions(net *lntest.NetworkHarness, t *harnessTest) {
// With the assertion above set up, send a payment from Alice to Bob // With the assertion above set up, send a payment from Alice to Bob
// which should finalize and settle the invoice. // which should finalize and settle the invoice.
sendReq := &lnrpc.SendRequest{ sendReq := &routerrpc.SendPaymentRequest{
PaymentRequest: invoiceResp.PaymentRequest, PaymentRequest: invoiceResp.PaymentRequest,
TimeoutSeconds: 60,
FeeLimitMsat: noFeeLimitMsat,
} }
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
resp, err := net.Alice.SendPaymentSync(ctxt, sendReq) stream, err := net.Alice.RouterClient.SendPaymentV2(ctxt, sendReq)
if err != nil { if err != nil {
close(quit) close(quit)
t.Fatalf("unable to send payment: %v", err) t.Fatalf("unable to send payment: %v", err)
} }
if resp.PaymentError != "" { result, err := getPaymentResult(stream)
if err != nil {
close(quit) close(quit)
t.Fatalf("error when attempting recv: %v", resp.PaymentError) t.Fatalf("cannot get payment result: %v", err)
}
if result.Status != lnrpc.Payment_SUCCEEDED {
close(quit)
t.Fatalf("error when attempting recv: %v", result.Status)
} }
select { select {
@ -6390,7 +6424,7 @@ func testInvoiceSubscriptions(net *lntest.NetworkHarness, t *harnessTest) {
// can test that all settled invoices are properly notified. // can test that all settled invoices are properly notified.
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
err = completePaymentRequests( err = completePaymentRequests(
ctxt, net.Alice, payReqs, true, ctxt, net.Alice, net.Alice.RouterClient, payReqs, true,
) )
if err != nil { if err != nil {
t.Fatalf("unable to send payment: %v", err) t.Fatalf("unable to send payment: %v", err)
@ -6970,7 +7004,9 @@ func testFailingChannel(net *lntest.NetworkHarness, t *harnessTest) {
// Send the payment from Alice to Carol. We expect Carol to attempt to // Send the payment from Alice to Carol. We expect Carol to attempt to
// settle this payment with the wrong preimage. // settle this payment with the wrong preimage.
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
err = completePaymentRequests(ctxt, net.Alice, carolPayReqs, false) err = completePaymentRequests(
ctxt, net.Alice, net.Alice.RouterClient, carolPayReqs, false,
)
if err != nil { if err != nil {
t.Fatalf("unable to send payments: %v", err) t.Fatalf("unable to send payments: %v", err)
} }
@ -7442,8 +7478,10 @@ func testRevokedCloseRetribution(net *lntest.NetworkHarness, t *harnessTest) {
// Send payments from Carol to Bob using 3 of Bob's payment hashes // Send payments from Carol to Bob using 3 of Bob's payment hashes
// generated above. // generated above.
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
err = completePaymentRequests(ctxt, carol, bobPayReqs[:numInvoices/2], err = completePaymentRequests(
true) ctxt, carol, carol.RouterClient, bobPayReqs[:numInvoices/2],
true,
)
if err != nil { if err != nil {
t.Fatalf("unable to send payments: %v", err) t.Fatalf("unable to send payments: %v", err)
} }
@ -7496,8 +7534,10 @@ func testRevokedCloseRetribution(net *lntest.NetworkHarness, t *harnessTest) {
// Finally, send payments from Carol to Bob, consuming Bob's remaining // Finally, send payments from Carol to Bob, consuming Bob's remaining
// payment hashes. // payment hashes.
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
err = completePaymentRequests(ctxt, carol, bobPayReqs[numInvoices/2:], err = completePaymentRequests(
true) ctxt, carol, carol.RouterClient, bobPayReqs[numInvoices/2:],
true,
)
if err != nil { if err != nil {
t.Fatalf("unable to send payments: %v", err) t.Fatalf("unable to send payments: %v", err)
} }
@ -7749,7 +7789,9 @@ func testRevokedCloseRetributionZeroValueRemoteOutput(net *lntest.NetworkHarness
// Finally, send payments from Dave to Carol, consuming Carol's remaining // Finally, send payments from Dave to Carol, consuming Carol's remaining
// payment hashes. // payment hashes.
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
err = completePaymentRequests(ctxt, dave, carolPayReqs, false) err = completePaymentRequests(
ctxt, dave, dave.RouterClient, carolPayReqs, false,
)
if err != nil { if err != nil {
t.Fatalf("unable to send payments: %v", err) t.Fatalf("unable to send payments: %v", err)
} }
@ -8002,7 +8044,8 @@ func testRevokedCloseRetributionRemoteHodl(net *lntest.NetworkHarness,
// generated above. // generated above.
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
err = completePaymentRequests( err = completePaymentRequests(
ctxt, dave, carolPayReqs[:numInvoices/2], false, ctxt, dave, dave.RouterClient, carolPayReqs[:numInvoices/2],
false,
) )
if err != nil { if err != nil {
t.Fatalf("unable to send payments: %v", err) t.Fatalf("unable to send payments: %v", err)
@ -8022,7 +8065,8 @@ func testRevokedCloseRetributionRemoteHodl(net *lntest.NetworkHarness,
// generated above. // generated above.
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
err = completePaymentRequests( err = completePaymentRequests(
ctxt, carol, davePayReqs[:numInvoices/2], false, ctxt, carol, carol.RouterClient, davePayReqs[:numInvoices/2],
false,
) )
if err != nil { if err != nil {
t.Fatalf("unable to send payments: %v", err) t.Fatalf("unable to send payments: %v", err)
@ -8070,7 +8114,8 @@ func testRevokedCloseRetributionRemoteHodl(net *lntest.NetworkHarness,
// remaining payment hashes. // remaining payment hashes.
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
err = completePaymentRequests( err = completePaymentRequests(
ctxt, dave, carolPayReqs[numInvoices/2:], false, ctxt, dave, dave.RouterClient, carolPayReqs[numInvoices/2:],
false,
) )
if err != nil { if err != nil {
t.Fatalf("unable to send payments: %v", err) t.Fatalf("unable to send payments: %v", err)
@ -8469,7 +8514,9 @@ func testRevokedCloseRetributionAltruistWatchtower(net *lntest.NetworkHarness,
// Finally, send payments from Dave to Carol, consuming Carol's remaining // Finally, send payments from Dave to Carol, consuming Carol's remaining
// payment hashes. // payment hashes.
err = completePaymentRequests(ctxb, dave, carolPayReqs, false) err = completePaymentRequests(
ctxb, dave, dave.RouterClient, carolPayReqs, false,
)
if err != nil { if err != nil {
t.Fatalf("unable to send payments: %v", err) t.Fatalf("unable to send payments: %v", err)
} }
@ -8930,8 +8977,10 @@ func testDataLossProtection(net *lntest.NetworkHarness, t *harnessTest) {
// Send payments from Carol using 3 of the payment hashes // Send payments from Carol using 3 of the payment hashes
// generated above. // generated above.
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
err = completePaymentRequests(ctxt, carol, err = completePaymentRequests(
payReqs[:numInvoices/2], true) ctxt, carol, carol.RouterClient,
payReqs[:numInvoices/2], true,
)
if err != nil { if err != nil {
t.Fatalf("unable to send payments: %v", err) t.Fatalf("unable to send payments: %v", err)
} }
@ -8985,8 +9034,10 @@ func testDataLossProtection(net *lntest.NetworkHarness, t *harnessTest) {
// Finally, send more payments from , using the remaining // Finally, send more payments from , using the remaining
// payment hashes. // payment hashes.
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
err = completePaymentRequests(ctxt, carol, err = completePaymentRequests(
payReqs[numInvoices/2:], true) ctxt, carol, carol.RouterClient,
payReqs[numInvoices/2:], true,
)
if err != nil { if err != nil {
t.Fatalf("unable to send payments: %v", err) t.Fatalf("unable to send payments: %v", err)
} }
@ -9290,7 +9341,8 @@ func testRejectHTLC(net *lntest.NetworkHarness, t *harnessTest) {
// Alice pays Carols invoice. // Alice pays Carols invoice.
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
err = completePaymentRequests( err = completePaymentRequests(
ctxt, net.Alice, []string{resp.PaymentRequest}, true, ctxt, net.Alice, net.Alice.RouterClient,
[]string{resp.PaymentRequest}, true,
) )
if err != nil { if err != nil {
t.Fatalf("unable to send payments from alice to carol: %v", err) t.Fatalf("unable to send payments from alice to carol: %v", err)
@ -9315,7 +9367,8 @@ func testRejectHTLC(net *lntest.NetworkHarness, t *harnessTest) {
// Carol pays Bobs invoice. // Carol pays Bobs invoice.
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
err = completePaymentRequests( err = completePaymentRequests(
ctxt, carol, []string{resp.PaymentRequest}, true, ctxt, carol, carol.RouterClient,
[]string{resp.PaymentRequest}, true,
) )
if err != nil { if err != nil {
t.Fatalf("unable to send payments from carol to bob: %v", err) t.Fatalf("unable to send payments from carol to bob: %v", err)
@ -9343,7 +9396,8 @@ func testRejectHTLC(net *lntest.NetworkHarness, t *harnessTest) {
// --rejecthtlc. // --rejecthtlc.
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
err = completePaymentRequests( err = completePaymentRequests(
ctxt, net.Alice, []string{resp.PaymentRequest}, true, ctxt, net.Alice, net.Alice.RouterClient,
[]string{resp.PaymentRequest}, true,
) )
if err == nil { if err == nil {
t.Fatalf( t.Fatalf(
@ -9887,33 +9941,45 @@ func testAsyncPayments(net *lntest.NetworkHarness, t *harnessTest) {
"timeout: %v", err) "timeout: %v", err)
} }
// Open up a payment stream to Alice that we'll use to send payment to // Simultaneously send payments from Alice to Bob using of Bob's payment
// Bob. We also create a small helper function to send payments to Bob, // hashes generated above.
// consuming the payment hashes we generated above.
ctxt, _ = context.WithTimeout(ctxb, lntest.AsyncBenchmarkTimeout)
alicePayStream, err := net.Alice.SendPayment(ctxt)
if err != nil {
t.Fatalf("unable to create payment stream for alice: %v", err)
}
// Send payments from Alice to Bob using of Bob's payment hashes
// generated above.
now := time.Now() now := time.Now()
errChan := make(chan error)
statusChan := make(chan *lnrpc.Payment)
for i := 0; i < numInvoices; i++ { for i := 0; i < numInvoices; i++ {
sendReq := &lnrpc.SendRequest{ payReq := bobPayReqs[i]
PaymentRequest: bobPayReqs[i], go func() {
} ctxt, _ = context.WithTimeout(ctxb, lntest.AsyncBenchmarkTimeout)
stream, err := net.Alice.RouterClient.SendPaymentV2(
ctxt,
&routerrpc.SendPaymentRequest{
PaymentRequest: payReq,
TimeoutSeconds: 60,
FeeLimitMsat: noFeeLimitMsat,
},
)
if err != nil {
errChan <- err
}
result, err := getPaymentResult(stream)
if err != nil {
errChan <- err
}
if err := alicePayStream.Send(sendReq); err != nil { statusChan <- result
t.Fatalf("unable to send payment: "+ }()
"stream has been closed: %v", err)
}
} }
// Wait until all the payments have settled. // Wait until all the payments have settled.
for i := 0; i < numInvoices; i++ { for i := 0; i < numInvoices; i++ {
if _, err := alicePayStream.Recv(); err != nil { select {
t.Fatalf("payment stream have been closed: %v", err) case result := <-statusChan:
if result.Status == lnrpc.Payment_SUCCEEDED {
continue
}
case err := <-errChan:
t.Fatalf("payment error: %v", err)
} }
} }
@ -10058,90 +10124,51 @@ func testBidirectionalAsyncPayments(net *lntest.NetworkHarness, t *harnessTest)
t.Fatalf("unable to reset mc for alice: %v", err) t.Fatalf("unable to reset mc for alice: %v", err)
} }
// Open up a payment streams to Alice and to Bob, that we'll use to
// send payment between nodes.
ctx, cancel := context.WithTimeout(ctxb, lntest.AsyncBenchmarkTimeout)
defer cancel()
alicePayStream, err := net.Alice.SendPayment(ctx)
if err != nil {
t.Fatalf("unable to create payment stream for alice: %v", err)
}
ctx, cancel = context.WithTimeout(ctxb, lntest.AsyncBenchmarkTimeout)
defer cancel()
bobPayStream, err := net.Bob.SendPayment(ctx)
if err != nil {
t.Fatalf("unable to create payment stream for bob: %v", err)
}
// Send payments from Alice to Bob and from Bob to Alice in async // Send payments from Alice to Bob and from Bob to Alice in async
// manner. // manner.
for i := 0; i < numInvoices; i++ { errChan := make(chan error)
aliceSendReq := &lnrpc.SendRequest{ statusChan := make(chan *lnrpc.Payment)
PaymentRequest: bobPayReqs[i],
}
bobSendReq := &lnrpc.SendRequest{ send := func(node *lntest.HarnessNode, payReq string) {
PaymentRequest: alicePayReqs[i], go func() {
} ctxt, _ = context.WithTimeout(
ctxb, lntest.AsyncBenchmarkTimeout,
)
stream, err := node.RouterClient.SendPaymentV2(
ctxt,
&routerrpc.SendPaymentRequest{
PaymentRequest: payReq,
TimeoutSeconds: 60,
FeeLimitMsat: noFeeLimitMsat,
},
)
if err != nil {
errChan <- err
}
result, err := getPaymentResult(stream)
if err != nil {
errChan <- err
}
if err := alicePayStream.Send(aliceSendReq); err != nil { statusChan <- result
t.Fatalf("unable to send payment: "+ }()
"%v", err)
}
if err := bobPayStream.Send(bobSendReq); err != nil {
t.Fatalf("unable to send payment: "+
"%v", err)
}
} }
errChan := make(chan error) for i := 0; i < numInvoices; i++ {
go func() { send(net.Bob, alicePayReqs[i])
for i := 0; i < numInvoices; i++ { send(net.Alice, bobPayReqs[i])
if resp, err := alicePayStream.Recv(); err != nil { }
errChan <- errors.Errorf("payment stream has"+
" been closed: %v", err)
return
} else if resp.PaymentError != "" {
errChan <- errors.Errorf("unable to send "+
"payment from alice to bob: %v",
resp.PaymentError)
return
}
}
errChan <- nil
}()
go func() { // Expect all payments to succeed.
for i := 0; i < numInvoices; i++ { for i := 0; i < 2*numInvoices; i++ {
if resp, err := bobPayStream.Recv(); err != nil {
errChan <- errors.Errorf("payment stream has"+
" been closed: %v", err)
return
} else if resp.PaymentError != "" {
errChan <- errors.Errorf("unable to send "+
"payment from bob to alice: %v",
resp.PaymentError)
return
}
}
errChan <- nil
}()
// Wait for Alice and Bob receive their payments, and throw and error
// if something goes wrong.
for i := 0; i < 2; i++ {
select { select {
case err := <-errChan: case result := <-statusChan:
if err != nil { if result.Status != lnrpc.Payment_SUCCEEDED {
t.Fatalf(err.Error()) t.Fatalf("payment error: %v", result.Status)
} }
case <-time.After(lntest.AsyncBenchmarkTimeout):
t.Fatalf("waiting for payments to finish too long "+ case err := <-errChan:
"(%v)", lntest.AsyncBenchmarkTimeout) t.Fatalf("payment error: %v", err)
} }
} }
@ -10504,7 +10531,9 @@ func testSwitchCircuitPersistence(net *lntest.NetworkHarness, t *harnessTest) {
// Using Carol as the source, pay to the 5 invoices from Bob created // Using Carol as the source, pay to the 5 invoices from Bob created
// above. // above.
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
err = completePaymentRequests(ctxt, net.Bob, payReqs, false) err = completePaymentRequests(
ctxt, net.Bob, net.Bob.RouterClient, payReqs, false,
)
if err != nil { if err != nil {
t.Fatalf("unable to send payments: %v", err) t.Fatalf("unable to send payments: %v", err)
} }
@ -10630,7 +10659,9 @@ func testSwitchCircuitPersistence(net *lntest.NetworkHarness, t *harnessTest) {
// Using Carol as the source, pay to the 5 invoices from Bob created // Using Carol as the source, pay to the 5 invoices from Bob created
// above. // above.
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
err = completePaymentRequests(ctxt, net.Bob, payReqs, true) err = completePaymentRequests(
ctxt, net.Bob, net.Bob.RouterClient, payReqs, true,
)
if err != nil { if err != nil {
t.Fatalf("unable to send payments: %v", err) t.Fatalf("unable to send payments: %v", err)
} }
@ -10827,7 +10858,9 @@ func testSwitchOfflineDelivery(net *lntest.NetworkHarness, t *harnessTest) {
// Using Carol as the source, pay to the 5 invoices from Bob created // Using Carol as the source, pay to the 5 invoices from Bob created
// above. // above.
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
err = completePaymentRequests(ctxt, net.Bob, payReqs, false) err = completePaymentRequests(
ctxt, net.Bob, net.Bob.RouterClient, payReqs, false,
)
if err != nil { if err != nil {
t.Fatalf("unable to send payments: %v", err) t.Fatalf("unable to send payments: %v", err)
} }
@ -10959,7 +10992,9 @@ func testSwitchOfflineDelivery(net *lntest.NetworkHarness, t *harnessTest) {
// Using Carol as the source, pay to the 5 invoices from Bob created // Using Carol as the source, pay to the 5 invoices from Bob created
// above. // above.
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
err = completePaymentRequests(ctxt, net.Bob, payReqs, true) err = completePaymentRequests(
ctxt, net.Bob, net.Bob.RouterClient, payReqs, true,
)
if err != nil { if err != nil {
t.Fatalf("unable to send payments: %v", err) t.Fatalf("unable to send payments: %v", err)
} }
@ -11156,7 +11191,9 @@ func testSwitchOfflineDeliveryPersistence(net *lntest.NetworkHarness, t *harness
// Using Carol as the source, pay to the 5 invoices from Bob created // Using Carol as the source, pay to the 5 invoices from Bob created
// above. // above.
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
err = completePaymentRequests(ctxt, net.Bob, payReqs, false) err = completePaymentRequests(
ctxt, net.Bob, net.Bob.RouterClient, payReqs, false,
)
if err != nil { if err != nil {
t.Fatalf("unable to send payments: %v", err) t.Fatalf("unable to send payments: %v", err)
} }
@ -11295,7 +11332,9 @@ func testSwitchOfflineDeliveryPersistence(net *lntest.NetworkHarness, t *harness
// Using Carol as the source, pay to the 5 invoices from Bob created // Using Carol as the source, pay to the 5 invoices from Bob created
// above. // above.
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
err = completePaymentRequests(ctxt, net.Bob, payReqs, true) err = completePaymentRequests(
ctxt, net.Bob, net.Bob.RouterClient, payReqs, true,
)
if err != nil { if err != nil {
t.Fatalf("unable to send payments: %v", err) t.Fatalf("unable to send payments: %v", err)
} }
@ -11490,7 +11529,9 @@ func testSwitchOfflineDeliveryOutgoingOffline(
// Using Carol as the source, pay to the 5 invoices from Bob created // Using Carol as the source, pay to the 5 invoices from Bob created
// above. // above.
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
err = completePaymentRequests(ctxt, net.Bob, payReqs, false) err = completePaymentRequests(
ctxt, net.Bob, net.Bob.RouterClient, payReqs, false,
)
if err != nil { if err != nil {
t.Fatalf("unable to send payments: %v", err) t.Fatalf("unable to send payments: %v", err)
} }
@ -12038,21 +12079,21 @@ func testRouteFeeCutoff(net *lntest.NetworkHarness, t *harnessTest) {
t.Fatalf("unable to create invoice: %v", err) t.Fatalf("unable to create invoice: %v", err)
} }
sendReq := &lnrpc.SendRequest{ sendReq := &routerrpc.SendPaymentRequest{
PaymentRequest: invoiceResp.PaymentRequest, PaymentRequest: invoiceResp.PaymentRequest,
FeeLimit: feeLimit, TimeoutSeconds: 60,
FeeLimitMsat: noFeeLimitMsat,
} }
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) switch limit := feeLimit.Limit.(type) {
paymentResp, err := net.Alice.SendPaymentSync(ctxt, sendReq) case *lnrpc.FeeLimit_Fixed:
if err != nil { sendReq.FeeLimitMsat = 1000 * limit.Fixed
t.Fatalf("unable to send payment: %v", err) case *lnrpc.FeeLimit_Percent:
} sendReq.FeeLimitMsat = 1000 * paymentAmt * limit.Percent / 100
if paymentResp.PaymentError != "" {
t.Fatalf("unable to send payment: %v",
paymentResp.PaymentError)
} }
checkRoute(paymentResp.PaymentRoute) result := sendAndAssertSuccess(t, net.Alice, sendReq)
checkRoute(result.Htlcs[0].Route)
} }
// We'll start off using percentages first. Since the fee along the // We'll start off using percentages first. Since the fee along the
@ -13179,8 +13220,8 @@ func testChanRestoreScenario(t *harnessTest, net *lntest.NetworkHarness,
ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) ctxt, _ := context.WithTimeout(ctxb, defaultTimeout)
err = completePaymentRequests( err = completePaymentRequests(
ctxt, from, []string{invoiceResp.PaymentRequest}, ctxt, from, from.RouterClient,
true, []string{invoiceResp.PaymentRequest}, true,
) )
if err != nil { if err != nil {
t.Fatalf("unable to complete payments: %v", err) t.Fatalf("unable to complete payments: %v", err)
@ -14208,7 +14249,8 @@ func testExternalFundingChanPoint(net *lntest.NetworkHarness, t *harnessTest) {
} }
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
err = completePaymentRequests( err = completePaymentRequests(
ctxt, carol, []string{resp.PaymentRequest}, true, ctxt, carol, carol.RouterClient, []string{resp.PaymentRequest},
true,
) )
if err != nil { if err != nil {
t.Fatalf("unable to make payments between Carol and Dave") t.Fatalf("unable to make payments between Carol and Dave")
@ -14259,6 +14301,37 @@ func sendAndAssertSuccess(t *harnessTest, node *lntest.HarnessNode,
return result return result
} }
// sendAndAssertFailure sends the given payment requests and asserts that the
// payment fails with the expected reason.
func sendAndAssertFailure(t *harnessTest, node *lntest.HarnessNode,
req *routerrpc.SendPaymentRequest,
failureReason lnrpc.PaymentFailureReason) *lnrpc.Payment {
ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout)
defer cancel()
stream, err := node.RouterClient.SendPaymentV2(ctx, req)
if err != nil {
t.Fatalf("unable to send payment: %v", err)
}
result, err := getPaymentResult(stream)
if err != nil {
t.Fatalf("unable to get payment result: %v", err)
}
if result.Status != lnrpc.Payment_FAILED {
t.Fatalf("payment was expected to fail, but succeeded")
}
if result.FailureReason != failureReason {
t.Fatalf("payment should have been rejected due to "+
"%v, but got %v", failureReason, result.Status)
}
return result
}
// getPaymentResult reads a final result from the stream and returns it. // getPaymentResult reads a final result from the stream and returns it.
func getPaymentResult(stream routerrpc.Router_SendPaymentV2Client) ( func getPaymentResult(stream routerrpc.Router_SendPaymentV2Client) (
*lnrpc.Payment, error) { *lnrpc.Payment, error) {

@ -31,6 +31,7 @@
<time> [ERR] CRTR: Payment with hash <hex> failed: error <time> [ERR] CRTR: Payment with hash <hex> failed: error
<time> [ERR] CRTR: Payment with hash <hex> failed: incorrect_payment_details <time> [ERR] CRTR: Payment with hash <hex> failed: incorrect_payment_details
<time> [ERR] CRTR: Payment with hash <hex> failed: insufficient_balance <time> [ERR] CRTR: Payment with hash <hex> failed: insufficient_balance
<time> [ERR] CRTR: Payment with hash <hex> failed: no_route
<time> [ERR] CRTR: Payment with hash <hex> failed: router shutting down <time> [ERR] CRTR: Payment with hash <hex> failed: router shutting down
<time> [ERR] CRTR: Resuming payment with hash <hex> failed: error. <time> [ERR] CRTR: Resuming payment with hash <hex> failed: error.
<time> [ERR] CRTR: Resuming payment with hash <hex> failed: incorrect_payment_details. <time> [ERR] CRTR: Resuming payment with hash <hex> failed: incorrect_payment_details.

@ -7,6 +7,7 @@ import (
"context" "context"
"crypto/rand" "crypto/rand"
"fmt" "fmt"
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil"
"github.com/btcsuite/btcutil/psbt" "github.com/btcsuite/btcutil/psbt"
@ -219,7 +220,8 @@ func testPsbtChanFunding(net *lntest.NetworkHarness, t *harnessTest) {
} }
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
err = completePaymentRequests( err = completePaymentRequests(
ctxt, carol, []string{resp.PaymentRequest}, true, ctxt, carol, carol.RouterClient, []string{resp.PaymentRequest},
true,
) )
if err != nil { if err != nil {
t.Fatalf("unable to make payments between Carol and Dave") t.Fatalf("unable to make payments between Carol and Dave")