diff --git a/lntest/itest/lnd_multi-hop-error-propagation.go b/lntest/itest/lnd_multi-hop-error-propagation.go index d1689a99..70fb9525 100644 --- a/lntest/itest/lnd_multi-hop-error-propagation.go +++ b/lntest/itest/lnd_multi-hop-error-propagation.go @@ -4,7 +4,6 @@ package itest import ( "context" - "encoding/hex" "strings" "time" @@ -177,24 +176,18 @@ out: // TODO(roasbeef): return failure response rather than failing entire // stream on payment error. ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - sendReq := &lnrpc.SendRequest{ - PaymentHashString: hex.EncodeToString(makeFakePayHash(t)), - DestString: hex.EncodeToString(carol.PubKey[:]), - Amt: payAmt, - FinalCltvDelta: int32(carolPayReq.CltvExpiry), + sendReq := &routerrpc.SendPaymentRequest{ + PaymentHash: makeFakePayHash(t), + Dest: carol.PubKey[:], + Amt: payAmt, + FinalCltvDelta: int32(carolPayReq.CltvExpiry), + TimeoutSeconds: 60, + FeeLimitMsat: noFeeLimitMsat, } - resp, err := net.Alice.SendPaymentSync(ctxt, sendReq) - if err != nil { - t.Fatalf("unable to send payment: %v", err) - } - - // 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") - } - + sendAndAssertFailure( + t, net.Alice, + sendReq, lnrpc.PaymentFailureReason_FAILURE_REASON_INCORRECT_PAYMENT_DETAILS, + ) assertLastHTLCError( t, net.Alice, 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 // value on the extended HTLC. htlcAmt := lnwire.NewMSatFromSatoshis(1000) - sendReq = &lnrpc.SendRequest{ - PaymentHashString: hex.EncodeToString(carolInvoice.RHash), - DestString: hex.EncodeToString(carol.PubKey[:]), - Amt: int64(htlcAmt.ToSatoshis()), // 10k satoshis are expected. - FinalCltvDelta: int32(carolPayReq.CltvExpiry), + sendReq = &routerrpc.SendPaymentRequest{ + PaymentHash: carolInvoice.RHash, + Dest: carol.PubKey[:], + Amt: int64(htlcAmt.ToSatoshis()), // 10k satoshis are expected. + FinalCltvDelta: int32(carolPayReq.CltvExpiry), + 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) - } - - // 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") - } - + sendAndAssertFailure( + t, net.Alice, + sendReq, lnrpc.PaymentFailureReason_FAILURE_REASON_INCORRECT_PAYMENT_DETAILS, + ) assertLastHTLCError( t, net.Alice, 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 // link having insufficient capacity. In order to do so, we'll first // 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 // 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 @@ -294,17 +273,14 @@ out: if err != nil { t.Fatalf("unable to generate carol invoice: %v", err) } - if err := bobPayStream.Send(&lnrpc.SendRequest{ - PaymentRequest: carolInvoice2.PaymentRequest, - }); err != nil { - t.Fatalf("unable to send payment: %v", err) - } - - 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) - } + sendAndAssertSuccess( + t, net.Bob, + &routerrpc.SendPaymentRequest{ + PaymentRequest: carolInvoice2.PaymentRequest, + TimeoutSeconds: 60, + FeeLimitMsat: noFeeLimitMsat, + }, + ) // For each send bob makes, we need to check that bob 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) } - sendReq = &lnrpc.SendRequest{ + sendReq = &routerrpc.SendPaymentRequest{ PaymentRequest: carolInvoice3.PaymentRequest, + 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("payment should fail due to insufficient "+ - "capacity: %v", err) - } - + sendAndAssertFailure( + t, net.Alice, + sendReq, lnrpc.PaymentFailureReason_FAILURE_REASON_NO_ROUTE, + ) assertLastHTLCError( t, net.Alice, lnrpc.Failure_TEMPORARY_CHANNEL_FAILURE, ) @@ -382,19 +354,15 @@ out: t.Fatalf("unable to reset mission control: %v", err) } - sendReq = &lnrpc.SendRequest{ - PaymentRequest: carolInvoice.PaymentRequest, - } - 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("payment should have failed") - } - + sendAndAssertFailure( + t, net.Alice, + &routerrpc.SendPaymentRequest{ + PaymentRequest: carolInvoice.PaymentRequest, + TimeoutSeconds: 60, + FeeLimitMsat: noFeeLimitMsat, + }, + lnrpc.PaymentFailureReason_FAILURE_REASON_NO_ROUTE, + ) assertLastHTLCError(t, net.Alice, lnrpc.Failure_UNKNOWN_NEXT_PEER) // Alice should have a forwarding event and subsequent fail. diff --git a/lntest/itest/lnd_multi-hop-payments.go b/lntest/itest/lnd_multi-hop-payments.go index 39a48a08..fb9e79cb 100644 --- a/lntest/itest/lnd_multi-hop-payments.go +++ b/lntest/itest/lnd_multi-hop-payments.go @@ -217,7 +217,9 @@ func testMultiHopPayments(net *lntest.NetworkHarness, t *harnessTest) { // Using Carol as the source, pay to the 5 invoices from Bob created // above. ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - err = completePaymentRequests(ctxt, carol, payReqs, true) + err = completePaymentRequests( + ctxt, carol, carol.RouterClient, payReqs, true, + ) if err != nil { t.Fatalf("unable to send payments: %v", err) } diff --git a/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go b/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go index f63ef57d..0bab9b41 100644 --- a/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go @@ -13,6 +13,7 @@ import ( "github.com/lightningnetwork/lnd/lncfg" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc/invoicesrpc" + "github.com/lightningnetwork/lnd/lnrpc/routerrpc" "github.com/lightningnetwork/lnd/lntest" "github.com/lightningnetwork/lnd/lntest/wait" "github.com/lightningnetwork/lnd/lntypes" @@ -62,13 +63,14 @@ func testMultiHopHtlcLocalChainClaim(net *lntest.NetworkHarness, t *harnessTest, 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) - } - err = alicePayStream.Send(&lnrpc.SendRequest{ - PaymentRequest: carolInvoice.PaymentRequest, - }) + _, err = alice.RouterClient.SendPaymentV2( + ctx, + &routerrpc.SendPaymentRequest{ + PaymentRequest: carolInvoice.PaymentRequest, + TimeoutSeconds: 60, + FeeLimitMsat: noFeeLimitMsat, + }, + ) if err != nil { t.Fatalf("unable to send payment: %v", err) } diff --git a/lntest/itest/lnd_multi-hop_htlc_local_timeout_test.go b/lntest/itest/lnd_multi-hop_htlc_local_timeout_test.go index d751bca1..03320f08 100644 --- a/lntest/itest/lnd_multi-hop_htlc_local_timeout_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_local_timeout_test.go @@ -14,6 +14,7 @@ import ( "github.com/lightningnetwork/lnd" "github.com/lightningnetwork/lnd/lncfg" "github.com/lightningnetwork/lnd/lnrpc" + "github.com/lightningnetwork/lnd/lnrpc/routerrpc" "github.com/lightningnetwork/lnd/lntest" "github.com/lightningnetwork/lnd/lntest/wait" ) @@ -52,31 +53,38 @@ func testMultiHopHtlcLocalTimeout(net *lntest.NetworkHarness, t *harnessTest, 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) - } - // We'll create two random payment hashes unknown to carol, then send // each of them by manually specifying the HTLC details. carolPubKey := carol.PubKey[:] dustPayHash := makeFakePayHash(t) payHash := makeFakePayHash(t) - err = alicePayStream.Send(&lnrpc.SendRequest{ - Dest: carolPubKey, - Amt: int64(dustHtlcAmt), - PaymentHash: dustPayHash, - FinalCltvDelta: finalCltvDelta, - }) + + _, err := alice.RouterClient.SendPaymentV2( + ctx, + &routerrpc.SendPaymentRequest{ + Dest: carolPubKey, + Amt: int64(dustHtlcAmt), + PaymentHash: dustPayHash, + FinalCltvDelta: finalCltvDelta, + TimeoutSeconds: 60, + FeeLimitMsat: noFeeLimitMsat, + }, + ) if err != nil { t.Fatalf("unable to send alice htlc: %v", err) } - err = alicePayStream.Send(&lnrpc.SendRequest{ - Dest: carolPubKey, - Amt: int64(htlcAmt), - PaymentHash: payHash, - FinalCltvDelta: finalCltvDelta, - }) + + _, err = alice.RouterClient.SendPaymentV2( + ctx, + &routerrpc.SendPaymentRequest{ + Dest: carolPubKey, + Amt: int64(htlcAmt), + PaymentHash: payHash, + FinalCltvDelta: finalCltvDelta, + TimeoutSeconds: 60, + FeeLimitMsat: noFeeLimitMsat, + }, + ) if err != nil { t.Fatalf("unable to send alice htlc: %v", err) } diff --git a/lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go b/lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go index 8669383f..b157f4f0 100644 --- a/lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go @@ -13,6 +13,7 @@ import ( "github.com/lightningnetwork/lnd/lncfg" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc/invoicesrpc" + "github.com/lightningnetwork/lnd/lnrpc/routerrpc" "github.com/lightningnetwork/lnd/lntest" "github.com/lightningnetwork/lnd/lntest/wait" "github.com/lightningnetwork/lnd/lntypes" @@ -64,13 +65,14 @@ func testMultiHopReceiverChainClaim(net *lntest.NetworkHarness, t *harnessTest, 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) - } - err = alicePayStream.Send(&lnrpc.SendRequest{ - PaymentRequest: carolInvoice.PaymentRequest, - }) + _, err = alice.RouterClient.SendPaymentV2( + ctx, + &routerrpc.SendPaymentRequest{ + PaymentRequest: carolInvoice.PaymentRequest, + TimeoutSeconds: 60, + FeeLimitMsat: noFeeLimitMsat, + }, + ) if err != nil { t.Fatalf("unable to send payment: %v", err) } diff --git a/lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go b/lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go index e4f61b19..5ea1c4a1 100644 --- a/lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go @@ -13,6 +13,7 @@ import ( "github.com/lightningnetwork/lnd/lncfg" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc/invoicesrpc" + "github.com/lightningnetwork/lnd/lnrpc/routerrpc" "github.com/lightningnetwork/lnd/lntest" "github.com/lightningnetwork/lnd/lntest/wait" "github.com/lightningnetwork/lnd/lntypes" @@ -62,13 +63,14 @@ func testMultiHopHtlcRemoteChainClaim(net *lntest.NetworkHarness, t *harnessTest 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) - } - err = alicePayStream.Send(&lnrpc.SendRequest{ - PaymentRequest: carolInvoice.PaymentRequest, - }) + _, err = alice.RouterClient.SendPaymentV2( + ctx, + &routerrpc.SendPaymentRequest{ + PaymentRequest: carolInvoice.PaymentRequest, + TimeoutSeconds: 60, + FeeLimitMsat: noFeeLimitMsat, + }, + ) if err != nil { t.Fatalf("unable to send payment: %v", err) } diff --git a/lntest/itest/lnd_multi-hop_local_force_close_on_chain_htlc_timeout_test.go b/lntest/itest/lnd_multi-hop_local_force_close_on_chain_htlc_timeout_test.go index d51d2c3d..576295ec 100644 --- a/lntest/itest/lnd_multi-hop_local_force_close_on_chain_htlc_timeout_test.go +++ b/lntest/itest/lnd_multi-hop_local_force_close_on_chain_htlc_timeout_test.go @@ -10,6 +10,7 @@ import ( "github.com/btcsuite/btcutil" "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/lnrpc" + "github.com/lightningnetwork/lnd/lnrpc/routerrpc" "github.com/lightningnetwork/lnd/lntest" "github.com/lightningnetwork/lnd/lntest/wait" ) @@ -44,20 +45,20 @@ func testMultiHopLocalForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, 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) - } - // We'll now send a single HTLC across our multi-hop network. carolPubKey := carol.PubKey[:] payHash := makeFakePayHash(t) - err = alicePayStream.Send(&lnrpc.SendRequest{ - Dest: carolPubKey, - Amt: int64(htlcAmt), - PaymentHash: payHash, - FinalCltvDelta: finalCltvDelta, - }) + _, err := alice.RouterClient.SendPaymentV2( + ctx, + &routerrpc.SendPaymentRequest{ + Dest: carolPubKey, + Amt: int64(htlcAmt), + PaymentHash: payHash, + FinalCltvDelta: finalCltvDelta, + TimeoutSeconds: 60, + FeeLimitMsat: noFeeLimitMsat, + }, + ) if err != nil { t.Fatalf("unable to send alice htlc: %v", err) } diff --git a/lntest/itest/lnd_multi-hop_remote_force_close_on_chain_htlc_timeout_test.go b/lntest/itest/lnd_multi-hop_remote_force_close_on_chain_htlc_timeout_test.go index ebff9187..9d30a2dc 100644 --- a/lntest/itest/lnd_multi-hop_remote_force_close_on_chain_htlc_timeout_test.go +++ b/lntest/itest/lnd_multi-hop_remote_force_close_on_chain_htlc_timeout_test.go @@ -10,6 +10,7 @@ import ( "github.com/btcsuite/btcutil" "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/lnrpc" + "github.com/lightningnetwork/lnd/lnrpc/routerrpc" "github.com/lightningnetwork/lnd/lntest" "github.com/lightningnetwork/lnd/lntest/wait" ) @@ -45,20 +46,20 @@ func testMultiHopRemoteForceCloseOnChainHtlcTimeout(net *lntest.NetworkHarness, 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) - } - // We'll now send a single HTLC across our multi-hop network. carolPubKey := carol.PubKey[:] payHash := makeFakePayHash(t) - err = alicePayStream.Send(&lnrpc.SendRequest{ - Dest: carolPubKey, - Amt: int64(htlcAmt), - PaymentHash: payHash, - FinalCltvDelta: finalCltvDelta, - }) + _, err := alice.RouterClient.SendPaymentV2( + ctx, + &routerrpc.SendPaymentRequest{ + Dest: carolPubKey, + Amt: int64(htlcAmt), + PaymentHash: payHash, + FinalCltvDelta: finalCltvDelta, + TimeoutSeconds: 60, + FeeLimitMsat: noFeeLimitMsat, + }, + ) if err != nil { t.Fatalf("unable to send alice htlc: %v", err) } diff --git a/lntest/itest/lnd_send_multi_path_payment.go b/lntest/itest/lnd_send_multi_path_payment.go index 22732000..453f1676 100644 --- a/lntest/itest/lnd_send_multi_path_payment.go +++ b/lntest/itest/lnd_send_multi_path_payment.go @@ -74,7 +74,7 @@ func testSendMultiPathPayment(net *lntest.NetworkHarness, t *harnessTest) { t, net.Alice, &routerrpc.SendPaymentRequest{ PaymentRequest: payReq, - MaxParts: 10, + MaxParts: 10, TimeoutSeconds: 60, FeeLimitMsat: noFeeLimitMsat, }, diff --git a/lntest/itest/lnd_single_hop_invoice_test.go b/lntest/itest/lnd_single_hop_invoice_test.go index fa907d30..6f05841b 100644 --- a/lntest/itest/lnd_single_hop_invoice_test.go +++ b/lntest/itest/lnd_single_hop_invoice_test.go @@ -5,11 +5,13 @@ package itest import ( "bytes" "context" + "encoding/hex" "time" "github.com/btcsuite/btcutil" "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/lnrpc" + "github.com/lightningnetwork/lnd/lnrpc/routerrpc" "github.com/lightningnetwork/lnd/lntest" "github.com/lightningnetwork/lnd/lntest/wait" "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 // to the above generated invoice. - sendReq := &lnrpc.SendRequest{ - PaymentRequest: invoiceResp.PaymentRequest, - } - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - resp, err := net.Alice.SendPaymentSync(ctxt, sendReq) - if err != nil { - t.Fatalf("unable to send payment: %v", err) - } - - // 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) { + resp := sendAndAssertSuccess( + t, net.Alice, + &routerrpc.SendPaymentRequest{ + PaymentRequest: invoiceResp.PaymentRequest, + TimeoutSeconds: 60, + FeeLimitMsat: noFeeLimitMsat, + }, + ) + if hex.EncodeToString(preimage) != resp.PaymentPreimage { t.Fatalf("preimage mismatch: expected %v, got %v", preimage, - resp.GetPaymentPreimage()) + resp.PaymentPreimage) } // 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 // invoice rather than manually specifying the payment details. - sendReq = &lnrpc.SendRequest{ - PaymentRequest: invoiceResp.PaymentRequest, - } - 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) - } + sendAndAssertSuccess( + t, net.Alice, + &routerrpc.SendPaymentRequest{ + PaymentRequest: invoiceResp.PaymentRequest, + TimeoutSeconds: 60, + FeeLimitMsat: noFeeLimitMsat, + }, + ) // The second payment should also have succeeded, with the balances // being update accordingly. @@ -144,23 +139,20 @@ func testSingleHopInvoice(net *lntest.NetworkHarness, t *harnessTest) { keySendPreimage := lntypes.Preimage{3, 4, 5, 11} keySendHash := keySendPreimage.Hash() - sendReq = &lnrpc.SendRequest{ - Dest: net.Bob.PubKey[:], - Amt: paymentAmt, - FinalCltvDelta: 40, - PaymentHash: keySendHash[:], - DestCustomRecords: map[uint64][]byte{ - record.KeySendType: keySendPreimage[:], + sendAndAssertSuccess( + t, net.Alice, + &routerrpc.SendPaymentRequest{ + Dest: net.Bob.PubKey[:], + Amt: paymentAmt, + FinalCltvDelta: 40, + 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 // being update accordingly. diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index ac50aed7..7e5083f1 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -647,7 +647,8 @@ func shutdownAndAssert(net *lntest.NetworkHarness, t *harnessTest, // payment requests. If the awaitResponse parameter is true, this function // does not return until all payments successfully complete without errors. 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 // 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 } - ctxc, cancel := context.WithCancel(ctx) - defer cancel() + // send sends a payment and returns an error if it doesn't succeeded. + send := func(payReq string) error { + ctxc, cancel := context.WithCancel(ctx) + defer cancel() - payStream, err := client.SendPayment(ctxc) - if err != nil { - return err - } - - for _, payReq := range paymentRequests { - sendReq := &lnrpc.SendRequest{ - PaymentRequest: payReq, - } - err := payStream.Send(sendReq) + payStream, err := routerClient.SendPaymentV2( + ctxc, + &routerrpc.SendPaymentRequest{ + PaymentRequest: payReq, + TimeoutSeconds: 60, + FeeLimitMsat: noFeeLimitMsat, + }, + ) if err != nil { 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 { for range paymentRequests { - resp, err := payStream.Recv() + err := <-results if err != nil { return err } - if resp.PaymentError != "" { - return fmt.Errorf("received payment error: %v", - resp.PaymentError) - } } - 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 // executed. - ctxt, cancel = context.WithTimeout(ctxb, defaultTimeout) - defer cancel() - _, err = net.Alice.SendPaymentSync( - ctxt, - &lnrpc.SendRequest{ + sendAndAssertSuccess( + t, net.Alice, + &routerrpc.SendPaymentRequest{ 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 // pending. @@ -1968,15 +1984,15 @@ func testUpdateChannelPolicy(net *lntest.NetworkHarness, t *harnessTest) { ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) 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 // not be able to find a path during routing. - expErr := channeldb.FailureReasonNoRoute.Error() - if err == nil || - !strings.Contains(err.Error(), expErr) { - t.Fatalf("expected payment to fail, instead got %v", err) + expErr := lnrpc.PaymentFailureReason_FAILURE_REASON_NO_ROUTE + if err.Error() != expErr.String() { + t.Fatalf("expected %v, instead got %v", expErr, err) } // 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) err = completePaymentRequests( - ctxt, net.Alice, []string{resp.PaymentRequest}, true, + ctxt, net.Alice, net.Alice.RouterClient, + []string{resp.PaymentRequest}, true, ) if err != nil { t.Fatalf("unable to send payment: %v", err) @@ -2949,27 +2966,26 @@ func testChannelUnsettledBalance(net *lntest.NetworkHarness, t *harnessTest) { numInvoices = 6 ) - // Create a paystream from Alice to Carol to enable Alice to make - // 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. + // Simulateneously send numInvoices payments from Alice to Carol. carolPubKey := carol.PubKey[:] + errChan := make(chan error) for i := 0; i < numInvoices; i++ { - err = alicePayStream.Send(&lnrpc.SendRequest{ - Dest: carolPubKey, - Amt: int64(payAmt), - PaymentHash: makeFakePayHash(t), - FinalCltvDelta: lnd.DefaultBitcoinTimeLockDelta, - }) - if err != nil { - t.Fatalf("unable to send alice htlc: %v", err) - } + go func() { + ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) + _, err := net.Alice.RouterClient.SendPaymentV2(ctxt, + &routerrpc.SendPaymentRequest{ + Dest: carolPubKey, + Amt: int64(payAmt), + PaymentHash: makeFakePayHash(t), + FinalCltvDelta: lnd.DefaultBitcoinTimeLockDelta, + TimeoutSeconds: 60, + FeeLimitMsat: noFeeLimitMsat, + }) + + if err != nil { + errChan <- err + } + }() } // 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) } + // Check for payment errors. + select { + case err := <-errChan: + t.Fatalf("payment error: %v", err) + default: + } + // Force and assert the channel closure. ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) 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 // htlc outputs should be left unsettled, and should be swept by the // 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[:] for i := 0; i < numInvoices; i++ { - err = alicePayStream.Send(&lnrpc.SendRequest{ - Dest: carolPubKey, - Amt: int64(paymentAmt), - PaymentHash: makeFakePayHash(t), - FinalCltvDelta: lnd.DefaultBitcoinTimeLockDelta, - }) + ctx, cancel := context.WithCancel(ctxb) + defer cancel() + + _, err := alice.RouterClient.SendPaymentV2( + ctx, + &routerrpc.SendPaymentRequest{ + Dest: carolPubKey, + Amt: int64(paymentAmt), + PaymentHash: makeFakePayHash(t), + FinalCltvDelta: lnd.DefaultBitcoinTimeLockDelta, + TimeoutSeconds: 60, + FeeLimitMsat: noFeeLimitMsat, + }, + ) if err != nil { 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) 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 { 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) // 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 // he does fail, it is almost certainly caused by the sphinx replay // protection, as it is the only validation we do in hodl mode. - resp, err := payStream.Recv() + result, err := getPaymentResult(payStream) if err != nil { t.Fatalf("unable to receive payment response: %v", err) } // Assert that Fred receives the expected failure after Carol sent a // duplicate packet that fails due to sphinx replay detection. - if resp.PaymentError == "" { + if result.Status == lnrpc.Payment_SUCCEEDED { t.Fatalf("expected payment error") } 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 // to the above generated invoice. - sendReq := &lnrpc.SendRequest{ - PaymentRequest: invoiceResp.PaymentRequest, - } - 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) - } + sendAndAssertSuccess( + t, net.Alice, + &routerrpc.SendPaymentRequest{ + PaymentRequest: invoiceResp.PaymentRequest, + TimeoutSeconds: 60, + FeeLimitSat: 1000000, + }, + ) // Grab Alice's list of payments, she should show the existence of // exactly one payment. @@ -5647,7 +5668,9 @@ func testPrivateChannels(net *lntest.NetworkHarness, t *harnessTest) { // Let Carol pay the invoices. ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - err = completePaymentRequests(ctxt, carol, payReqs, true) + err = completePaymentRequests( + ctxt, carol, carol.RouterClient, payReqs, true, + ) if err != nil { t.Fatalf("unable to send payments: %v", err) } @@ -5703,7 +5726,9 @@ func testPrivateChannels(net *lntest.NetworkHarness, t *harnessTest) { // Let Bob pay the invoices. 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 { t.Fatalf("unable to send payments: %v", err) } @@ -6179,7 +6204,9 @@ func testMultiHopOverPrivateChannels(net *lntest.NetworkHarness, t *harnessTest) // Let Alice pay the invoice. payReqs := []string{resp.PaymentRequest} 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 { 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 // which should finalize and settle the invoice. - sendReq := &lnrpc.SendRequest{ + sendReq := &routerrpc.SendPaymentRequest{ PaymentRequest: invoiceResp.PaymentRequest, + TimeoutSeconds: 60, + FeeLimitMsat: noFeeLimitMsat, } ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - resp, err := net.Alice.SendPaymentSync(ctxt, sendReq) + stream, err := net.Alice.RouterClient.SendPaymentV2(ctxt, sendReq) if err != nil { close(quit) t.Fatalf("unable to send payment: %v", err) } - if resp.PaymentError != "" { + result, err := getPaymentResult(stream) + if err != nil { 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 { @@ -6390,7 +6424,7 @@ func testInvoiceSubscriptions(net *lntest.NetworkHarness, t *harnessTest) { // can test that all settled invoices are properly notified. ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) err = completePaymentRequests( - ctxt, net.Alice, payReqs, true, + ctxt, net.Alice, net.Alice.RouterClient, payReqs, true, ) if err != nil { 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 // settle this payment with the wrong preimage. 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 { 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 // generated above. ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - err = completePaymentRequests(ctxt, carol, bobPayReqs[:numInvoices/2], - true) + err = completePaymentRequests( + ctxt, carol, carol.RouterClient, bobPayReqs[:numInvoices/2], + true, + ) if err != nil { 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 // payment hashes. ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - err = completePaymentRequests(ctxt, carol, bobPayReqs[numInvoices/2:], - true) + err = completePaymentRequests( + ctxt, carol, carol.RouterClient, bobPayReqs[numInvoices/2:], + true, + ) if err != nil { 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 // payment hashes. ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - err = completePaymentRequests(ctxt, dave, carolPayReqs, false) + err = completePaymentRequests( + ctxt, dave, dave.RouterClient, carolPayReqs, false, + ) if err != nil { t.Fatalf("unable to send payments: %v", err) } @@ -8002,7 +8044,8 @@ func testRevokedCloseRetributionRemoteHodl(net *lntest.NetworkHarness, // generated above. ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) err = completePaymentRequests( - ctxt, dave, carolPayReqs[:numInvoices/2], false, + ctxt, dave, dave.RouterClient, carolPayReqs[:numInvoices/2], + false, ) if err != nil { t.Fatalf("unable to send payments: %v", err) @@ -8022,7 +8065,8 @@ func testRevokedCloseRetributionRemoteHodl(net *lntest.NetworkHarness, // generated above. ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) err = completePaymentRequests( - ctxt, carol, davePayReqs[:numInvoices/2], false, + ctxt, carol, carol.RouterClient, davePayReqs[:numInvoices/2], + false, ) if err != nil { t.Fatalf("unable to send payments: %v", err) @@ -8070,7 +8114,8 @@ func testRevokedCloseRetributionRemoteHodl(net *lntest.NetworkHarness, // remaining payment hashes. ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) err = completePaymentRequests( - ctxt, dave, carolPayReqs[numInvoices/2:], false, + ctxt, dave, dave.RouterClient, carolPayReqs[numInvoices/2:], + false, ) if err != nil { 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 // payment hashes. - err = completePaymentRequests(ctxb, dave, carolPayReqs, false) + err = completePaymentRequests( + ctxb, dave, dave.RouterClient, carolPayReqs, false, + ) if err != nil { 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 // generated above. ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - err = completePaymentRequests(ctxt, carol, - payReqs[:numInvoices/2], true) + err = completePaymentRequests( + ctxt, carol, carol.RouterClient, + payReqs[:numInvoices/2], true, + ) if err != nil { 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 // payment hashes. ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - err = completePaymentRequests(ctxt, carol, - payReqs[numInvoices/2:], true) + err = completePaymentRequests( + ctxt, carol, carol.RouterClient, + payReqs[numInvoices/2:], true, + ) if err != nil { t.Fatalf("unable to send payments: %v", err) } @@ -9290,7 +9341,8 @@ func testRejectHTLC(net *lntest.NetworkHarness, t *harnessTest) { // Alice pays Carols invoice. ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) err = completePaymentRequests( - ctxt, net.Alice, []string{resp.PaymentRequest}, true, + ctxt, net.Alice, net.Alice.RouterClient, + []string{resp.PaymentRequest}, true, ) if err != nil { 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. ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) err = completePaymentRequests( - ctxt, carol, []string{resp.PaymentRequest}, true, + ctxt, carol, carol.RouterClient, + []string{resp.PaymentRequest}, true, ) if err != nil { t.Fatalf("unable to send payments from carol to bob: %v", err) @@ -9343,7 +9396,8 @@ func testRejectHTLC(net *lntest.NetworkHarness, t *harnessTest) { // --rejecthtlc. ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) err = completePaymentRequests( - ctxt, net.Alice, []string{resp.PaymentRequest}, true, + ctxt, net.Alice, net.Alice.RouterClient, + []string{resp.PaymentRequest}, true, ) if err == nil { t.Fatalf( @@ -9887,33 +9941,45 @@ func testAsyncPayments(net *lntest.NetworkHarness, t *harnessTest) { "timeout: %v", err) } - // Open up a payment stream to Alice that we'll use to send payment to - // Bob. We also create a small helper function to send payments to Bob, - // 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. + // Simultaneously send payments from Alice to Bob using of Bob's payment + // hashes generated above. now := time.Now() + errChan := make(chan error) + statusChan := make(chan *lnrpc.Payment) for i := 0; i < numInvoices; i++ { - sendReq := &lnrpc.SendRequest{ - PaymentRequest: bobPayReqs[i], - } + payReq := 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 { - t.Fatalf("unable to send payment: "+ - "stream has been closed: %v", err) - } + statusChan <- result + }() } // Wait until all the payments have settled. for i := 0; i < numInvoices; i++ { - if _, err := alicePayStream.Recv(); err != nil { - t.Fatalf("payment stream have been closed: %v", err) + select { + 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) } - // 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 // manner. - for i := 0; i < numInvoices; i++ { - aliceSendReq := &lnrpc.SendRequest{ - PaymentRequest: bobPayReqs[i], - } + errChan := make(chan error) + statusChan := make(chan *lnrpc.Payment) - bobSendReq := &lnrpc.SendRequest{ - PaymentRequest: alicePayReqs[i], - } + send := func(node *lntest.HarnessNode, payReq string) { + 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 { - t.Fatalf("unable to send payment: "+ - "%v", err) - } - - if err := bobPayStream.Send(bobSendReq); err != nil { - t.Fatalf("unable to send payment: "+ - "%v", err) - } + statusChan <- result + }() } - errChan := make(chan error) - go func() { - for i := 0; i < numInvoices; 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 - }() + for i := 0; i < numInvoices; i++ { + send(net.Bob, alicePayReqs[i]) + send(net.Alice, bobPayReqs[i]) + } - go func() { - for i := 0; i < 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++ { + // Expect all payments to succeed. + for i := 0; i < 2*numInvoices; i++ { select { - case err := <-errChan: - if err != nil { - t.Fatalf(err.Error()) + case result := <-statusChan: + if result.Status != lnrpc.Payment_SUCCEEDED { + t.Fatalf("payment error: %v", result.Status) } - case <-time.After(lntest.AsyncBenchmarkTimeout): - t.Fatalf("waiting for payments to finish too long "+ - "(%v)", lntest.AsyncBenchmarkTimeout) + + case err := <-errChan: + 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 // above. 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 { 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 // above. 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 { 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 // above. 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 { 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 // above. 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 { 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 // above. 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 { 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 // above. 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 { 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 // above. 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 { 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) } - sendReq := &lnrpc.SendRequest{ + sendReq := &routerrpc.SendPaymentRequest{ PaymentRequest: invoiceResp.PaymentRequest, - FeeLimit: feeLimit, + TimeoutSeconds: 60, + FeeLimitMsat: noFeeLimitMsat, } - ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) - paymentResp, err := net.Alice.SendPaymentSync(ctxt, sendReq) - if err != nil { - t.Fatalf("unable to send payment: %v", err) - } - if paymentResp.PaymentError != "" { - t.Fatalf("unable to send payment: %v", - paymentResp.PaymentError) + switch limit := feeLimit.Limit.(type) { + case *lnrpc.FeeLimit_Fixed: + sendReq.FeeLimitMsat = 1000 * limit.Fixed + case *lnrpc.FeeLimit_Percent: + sendReq.FeeLimitMsat = 1000 * paymentAmt * limit.Percent / 100 } - 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 @@ -13179,8 +13220,8 @@ func testChanRestoreScenario(t *harnessTest, net *lntest.NetworkHarness, ctxt, _ := context.WithTimeout(ctxb, defaultTimeout) err = completePaymentRequests( - ctxt, from, []string{invoiceResp.PaymentRequest}, - true, + ctxt, from, from.RouterClient, + []string{invoiceResp.PaymentRequest}, true, ) if err != nil { t.Fatalf("unable to complete payments: %v", err) @@ -14208,7 +14249,8 @@ func testExternalFundingChanPoint(net *lntest.NetworkHarness, t *harnessTest) { } ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) err = completePaymentRequests( - ctxt, carol, []string{resp.PaymentRequest}, true, + ctxt, carol, carol.RouterClient, []string{resp.PaymentRequest}, + true, ) if err != nil { t.Fatalf("unable to make payments between Carol and Dave") @@ -14259,6 +14301,37 @@ func sendAndAssertSuccess(t *harnessTest, node *lntest.HarnessNode, 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. func getPaymentResult(stream routerrpc.Router_SendPaymentV2Client) ( *lnrpc.Payment, error) { diff --git a/lntest/itest/log_error_whitelist.txt b/lntest/itest/log_error_whitelist.txt index cdb70c3a..dbf7a48a 100644 --- a/lntest/itest/log_error_whitelist.txt +++ b/lntest/itest/log_error_whitelist.txt @@ -31,6 +31,7 @@