routerrpc+itest: make sure TrackPayments is compatible

This commit adds an itest case to make sure when the flag
`routerrpc.usestatusinitiated` is not set, the new status is not sent.
This commit is contained in:
yyforyongyu 2023-11-15 19:58:52 +08:00
parent 9acbbf0ec7
commit 99354313d5
No known key found for this signature in database
GPG key ID: 9BCD95C4FF296868
3 changed files with 114 additions and 20 deletions

View file

@ -490,6 +490,10 @@ var allTestCases = []*lntest.TestCase{
Name: "trackpayments", Name: "trackpayments",
TestFunc: testTrackPayments, TestFunc: testTrackPayments,
}, },
{
Name: "trackpayments compatible",
TestFunc: testTrackPaymentsCompatible,
},
{ {
Name: "open channel fee policy", Name: "open channel fee policy",
TestFunc: testOpenChannelUpdateFeePolicy, TestFunc: testOpenChannelUpdateFeePolicy,

View file

@ -14,8 +14,16 @@ import (
// testTrackPayments tests whether a client that calls the TrackPayments api // testTrackPayments tests whether a client that calls the TrackPayments api
// receives payment updates. // receives payment updates.
func testTrackPayments(ht *lntest.HarnessTest) { func testTrackPayments(ht *lntest.HarnessTest) {
// Open a channel between alice and bob.
alice, bob := ht.Alice, ht.Bob alice, bob := ht.Alice, ht.Bob
// Restart Alice with the new flag so she understands the new payment
// status.
ht.RestartNodeWithExtraArgs(alice, []string{
"--routerrpc.usestatusinitiated",
})
// Open a channel between alice and bob.
ht.EnsureConnected(alice, bob)
channel := ht.OpenChannel( channel := ht.OpenChannel(
alice, bob, lntest.OpenChannelParams{ alice, bob, lntest.OpenChannelParams{
Amt: btcutil.Amount(300000), Amt: btcutil.Amount(300000),
@ -47,35 +55,114 @@ func testTrackPayments(ht *lntest.HarnessTest) {
// Make sure the payment doesn't error due to invalid parameters or so. // Make sure the payment doesn't error due to invalid parameters or so.
_, err := paymentClient.Recv() _, err := paymentClient.Recv()
require.NoError(ht, err, "unable to get payment update.") require.NoError(ht, err, "unable to get payment update")
// Assert the first payment update is an inflight update. // Assert the first payment update is an initiated update.
update1, err := tracker.Recv() update1, err := tracker.Recv()
require.NoError(ht, err, "unable to receive payment update 1.") require.NoError(ht, err, "unable to receive payment update 1")
require.Equal( require.Equal(ht, lnrpc.Payment_INITIATED, update1.Status)
ht, lnrpc.PaymentFailureReason_FAILURE_REASON_NONE, require.Equal(ht, lnrpc.PaymentFailureReason_FAILURE_REASON_NONE,
update1.FailureReason, update1.FailureReason)
)
require.Equal(ht, lnrpc.Payment_IN_FLIGHT, update1.Status)
require.Equal(ht, invoice.PaymentRequest, update1.PaymentRequest) require.Equal(ht, invoice.PaymentRequest, update1.PaymentRequest)
require.Equal(ht, amountMsat, update1.ValueMsat) require.Equal(ht, amountMsat, update1.ValueMsat)
// Assert the second payment update is a payment success update. // Assert the first payment update is an inflight update.
update2, err := tracker.Recv() update2, err := tracker.Recv()
require.NoError(ht, err, "unable to receive payment update 2.") require.NoError(ht, err, "unable to receive payment update 2")
require.Equal( require.Equal(ht, lnrpc.Payment_IN_FLIGHT, update2.Status)
ht, lnrpc.PaymentFailureReason_FAILURE_REASON_NONE, require.Equal(ht, lnrpc.PaymentFailureReason_FAILURE_REASON_NONE,
update2.FailureReason, update2.FailureReason)
)
require.Equal(ht, lnrpc.Payment_SUCCEEDED, update2.Status)
require.Equal(ht, invoice.PaymentRequest, update2.PaymentRequest) require.Equal(ht, invoice.PaymentRequest, update2.PaymentRequest)
require.Equal(ht, amountMsat, update2.ValueMsat) require.Equal(ht, amountMsat, update2.ValueMsat)
require.Equal(
ht, hex.EncodeToString(invoice.RPreimage), // Assert the third payment update is a payment success update.
update2.PaymentPreimage, update3, err := tracker.Recv()
) require.NoError(ht, err, "unable to receive payment update 3")
require.Equal(ht, lnrpc.Payment_SUCCEEDED, update3.Status)
require.Equal(ht, lnrpc.PaymentFailureReason_FAILURE_REASON_NONE,
update3.FailureReason)
require.Equal(ht, invoice.PaymentRequest, update3.PaymentRequest)
require.Equal(ht, amountMsat, update3.ValueMsat)
require.Equal(ht, hex.EncodeToString(invoice.RPreimage),
update3.PaymentPreimage)
// TODO(yy): remove the sleep once the following bug is fixed.
// When the invoice is reported settled, the commitment dance is not
// yet finished, which can cause an error when closing the channel,
// saying there's active HTLCs. We need to investigate this issue and
// reverse the order to, first finish the commitment dance, then report
// the invoice as settled.
time.Sleep(2 * time.Second)
ht.CloseChannel(alice, channel)
}
// testTrackPaymentsCompatible checks that when `routerrpc.usestatusinitiated`
// is not set, the new Payment_INITIATED is replaced with Payment_IN_FLIGHT.
func testTrackPaymentsCompatible(ht *lntest.HarnessTest) {
// Open a channel between alice and bob.
alice, bob := ht.Alice, ht.Bob
channel := ht.OpenChannel(
alice, bob, lntest.OpenChannelParams{
Amt: btcutil.Amount(300000),
},
)
// Call the TrackPayments api to listen for payment updates.
req := &routerrpc.TrackPaymentsRequest{
NoInflightUpdates: false,
}
tracker := alice.RPC.TrackPayments(req)
// Create an invoice from bob.
var amountMsat int64 = 1000
invoiceResp := bob.RPC.AddInvoice(
&lnrpc.Invoice{
ValueMsat: amountMsat,
},
)
invoice := bob.RPC.LookupInvoice(invoiceResp.RHash)
// Send payment from alice to bob.
paymentClient := alice.RPC.SendPayment(
&routerrpc.SendPaymentRequest{
PaymentRequest: invoice.PaymentRequest,
TimeoutSeconds: 60,
},
)
// Assert the first track payment update is an inflight update.
update1, err := tracker.Recv()
require.NoError(ht, err, "unable to receive payment update 1")
require.Equal(ht, lnrpc.Payment_IN_FLIGHT, update1.Status)
// Assert the first track payment update is an inflight update.
update2, err := tracker.Recv()
require.NoError(ht, err, "unable to receive payment update 2")
require.Equal(ht, lnrpc.Payment_IN_FLIGHT, update2.Status)
// Assert the third track payment update is a payment success update.
update3, err := tracker.Recv()
require.NoError(ht, err, "unable to receive payment update 3")
require.Equal(ht, lnrpc.Payment_SUCCEEDED, update3.Status)
// Assert the first payment client update is an inflight update.
payment1, err := paymentClient.Recv()
require.NoError(ht, err, "unable to get payment update")
require.Equal(ht, lnrpc.Payment_IN_FLIGHT, payment1.Status)
// Assert the second payment client update is an inflight update.
payment2, err := paymentClient.Recv()
require.NoError(ht, err, "unable to get payment update")
require.Equal(ht, lnrpc.Payment_IN_FLIGHT, payment2.Status)
// Assert the third payment client update is a success update.
payment3, err := paymentClient.Recv()
require.NoError(ht, err, "unable to get payment update")
require.Equal(ht, lnrpc.Payment_SUCCEEDED, payment3.Status)
// TODO(yy): remove the sleep once the following bug is fixed. // TODO(yy): remove the sleep once the following bug is fixed.
// When the invoice is reported settled, the commitment dance is not // When the invoice is reported settled, the commitment dance is not

View file

@ -940,6 +940,9 @@ func (s *Server) trackPaymentStream(context context.Context,
} }
result := item.(*channeldb.MPPayment) result := item.(*channeldb.MPPayment)
log.Tracef("Payment %v updated to state %v",
result.Info.PaymentIdentifier, result.Status)
// Skip in-flight updates unless requested. // Skip in-flight updates unless requested.
if noInflightUpdates { if noInflightUpdates {
if result.Status == channeldb.StatusInitiated { if result.Status == channeldb.StatusInitiated {