Merge pull request #7159 from yyforyongyu/code-review-6542

Payments and invoices filtering by creation date
This commit is contained in:
Oliver Gugger authored and GitHub committed 2022-12-05 14:39:17 +01:00
commit e23c5dca73
14 files changed
+1499 -1040

No files matched your search

+113
View File
@@ -1090,6 +1090,9 @@ func TestQueryInvoices(t *testing.T) {
for i := 1; i <= numInvoices; i++ { for i := 1; i <= numInvoices; i++ {
amt := lnwire.MilliSatoshi(i) amt := lnwire.MilliSatoshi(i)
invoice, err := randInvoice(amt) invoice, err := randInvoice(amt)
invoice.CreationDate = invoice.CreationDate.Add(
time.Duration(i-1) * time.Second,
)
if err != nil { if err != nil {
t.Fatalf("unable to create invoice: %v", err) t.Fatalf("unable to create invoice: %v", err)
} }
@@ -1337,6 +1340,116 @@ func TestQueryInvoices(t *testing.T) {
}, },
expected: invoices, expected: invoices,
}, },
// Fetch invoices <= 25 by creation date.
{
query: InvoiceQuery{
NumMaxInvoices: numInvoices,
CreationDateEnd: time.Unix(25, 0),
},
expected: invoices[:25],
},
// Fetch invoices >= 26 creation date.
{
query: InvoiceQuery{
NumMaxInvoices: numInvoices,
CreationDateStart: time.Unix(26, 0),
},
expected: invoices[25:],
},
// Fetch pending invoices <= 25 by creation date.
{
query: InvoiceQuery{
PendingOnly: true,
NumMaxInvoices: numInvoices,
CreationDateEnd: time.Unix(25, 0),
},
expected: pendingInvoices[:13],
},
// Fetch pending invoices >= 26 creation date.
{
query: InvoiceQuery{
PendingOnly: true,
NumMaxInvoices: numInvoices,
CreationDateStart: time.Unix(26, 0),
},
expected: pendingInvoices[13:],
},
// Fetch pending invoices with offset and end creation date.
{
query: InvoiceQuery{
IndexOffset: 20,
NumMaxInvoices: numInvoices,
CreationDateEnd: time.Unix(30, 0),
},
// Since we're skipping to invoice 20 and iterating
// to invoice 30, we'll expect those invoices.
expected: invoices[20:30],
},
// Fetch pending invoices with offset and start creation date
// in reversed order.
{
query: InvoiceQuery{
IndexOffset: 21,
Reversed: true,
NumMaxInvoices: numInvoices,
CreationDateStart: time.Unix(11, 0),
},
// Since we're skipping to invoice 20 and iterating
// backward to invoice 10, we'll expect those invoices.
expected: invoices[10:20],
},
// Fetch invoices with start and end creation date.
{
query: InvoiceQuery{
NumMaxInvoices: numInvoices,
CreationDateStart: time.Unix(11, 0),
CreationDateEnd: time.Unix(20, 0),
},
expected: invoices[10:20],
},
// Fetch pending invoices with start and end creation date.
{
query: InvoiceQuery{
PendingOnly: true,
NumMaxInvoices: numInvoices,
CreationDateStart: time.Unix(11, 0),
CreationDateEnd: time.Unix(20, 0),
},
expected: pendingInvoices[5:10],
},
// Fetch invoices with start and end creation date in reverse
// order.
{
query: InvoiceQuery{
Reversed: true,
NumMaxInvoices: numInvoices,
CreationDateStart: time.Unix(11, 0),
CreationDateEnd: time.Unix(20, 0),
},
expected: invoices[10:20],
},
// Fetch pending invoices with start and end creation date in
// reverse order.
{
query: InvoiceQuery{
PendingOnly: true,
Reversed: true,
NumMaxInvoices: numInvoices,
CreationDateStart: time.Unix(11, 0),
CreationDateEnd: time.Unix(20, 0),
},
expected: pendingInvoices[5:10],
},
// Fetch invoices with a start date greater than end date
// should result in an empty slice.
{
query: InvoiceQuery{
NumMaxInvoices: numInvoices,
CreationDateStart: time.Unix(20, 0),
CreationDateEnd: time.Unix(11, 0),
},
expected: nil,
},
} }
for i, testCase := range testCases { for i, testCase := range testCases {
+31 -1
View File
@@ -1279,6 +1279,14 @@ type InvoiceQuery struct {
// Reversed, if set, indicates that the invoices returned should start // Reversed, if set, indicates that the invoices returned should start
// from the IndexOffset and go backwards. // from the IndexOffset and go backwards.
Reversed bool Reversed bool
// CreationDateStart, if set, filters out all invoices with a creation
// date greater than or euqal to it.
CreationDateStart time.Time
// CreationDateEnd, if set, filters out all invoices with a creation
// date less than or euqal to it.
CreationDateEnd time.Time
} }
// InvoiceSlice is the response to a invoice query. It includes the original // InvoiceSlice is the response to a invoice query. It includes the original
@@ -1309,7 +1317,11 @@ type InvoiceSlice struct {
// QueryInvoices allows a caller to query the invoice database for invoices // QueryInvoices allows a caller to query the invoice database for invoices
// within the specified add index range. // within the specified add index range.
func (d *DB) QueryInvoices(q InvoiceQuery) (InvoiceSlice, error) { func (d *DB) QueryInvoices(q InvoiceQuery) (InvoiceSlice, error) {
var resp InvoiceSlice var (
resp InvoiceSlice
startDateSet = !q.CreationDateStart.IsZero()
endDateSet = !q.CreationDateEnd.IsZero()
)
err := kvdb.View(d, func(tx kvdb.RTx) error { err := kvdb.View(d, func(tx kvdb.RTx) error {
// If the bucket wasn't found, then there aren't any invoices // If the bucket wasn't found, then there aren't any invoices
@@ -1349,6 +1361,24 @@ func (d *DB) QueryInvoices(q InvoiceQuery) (InvoiceSlice, error) {
return false, nil return false, nil
} }
// Skip any invoices that were created before the
// specified time.
if startDateSet && invoice.CreationDate.Before(
q.CreationDateStart,
) {
return false, nil
}
// Skip any invoices that were created after the
// specified time.
if endDateSet && invoice.CreationDate.After(
q.CreationDateEnd,
) {
return false, nil
}
// At this point, we've exhausted the offset, so we'll // At this point, we've exhausted the offset, so we'll
// begin collecting invoices found within the range. // begin collecting invoices found within the range.
resp.Invoices = append(resp.Invoices, invoice) resp.Invoices = append(resp.Invoices, invoice)
+31 -1
View File
@@ -536,6 +536,14 @@ type PaymentsQuery struct {
// CountTotal indicates that all payments currently present in the // CountTotal indicates that all payments currently present in the
// payment index (complete and incomplete) should be counted. // payment index (complete and incomplete) should be counted.
CountTotal bool CountTotal bool
// CreationDateStart, if set, filters out all payments with a creation
// date greater than or euqal to it.
CreationDateStart time.Time
// CreationDateEnd, if set, filters out all payments with a creation
// date less than or euqal to it.
CreationDateEnd time.Time
} }
// PaymentsResponse contains the result of a query to the payments database. // PaymentsResponse contains the result of a query to the payments database.
@@ -570,7 +578,11 @@ type PaymentsResponse struct {
// to a subset of payments by the payments query, containing an offset // to a subset of payments by the payments query, containing an offset
// index and a maximum number of returned payments. // index and a maximum number of returned payments.
func (d *DB) QueryPayments(query PaymentsQuery) (PaymentsResponse, error) { func (d *DB) QueryPayments(query PaymentsQuery) (PaymentsResponse, error) {
var resp PaymentsResponse var (
resp PaymentsResponse
startDateSet = !query.CreationDateStart.IsZero()
endDateSet = !query.CreationDateEnd.IsZero()
)
if err := kvdb.View(d, func(tx kvdb.RTx) error { if err := kvdb.View(d, func(tx kvdb.RTx) error {
// Get the root payments bucket. // Get the root payments bucket.
@@ -615,6 +627,24 @@ func (d *DB) QueryPayments(query PaymentsQuery) (PaymentsResponse, error) {
return false, err return false, err
} }
// Skip any payments that were created before the
// specified time.
if startDateSet && payment.Info.CreationTime.Before(
query.CreationDateStart,
) {
return false, nil
}
// Skip any payments that were created after the
// specified time.
if endDateSet && payment.Info.CreationTime.After(
query.CreationDateEnd,
) {
return false, nil
}
// At this point, we've exhausted the offset, so we'll // At this point, we've exhausted the offset, so we'll
// begin collecting invoices found within the range. // begin collecting invoices found within the range.
resp.Payments = append(resp.Payments, payment) resp.Payments = append(resp.Payments, payment)
+45
View File
@@ -391,6 +391,48 @@ func TestQueryPayments(t *testing.T) {
lastIndex: 4, lastIndex: 4,
expectedSeqNrs: []uint64{3, 4}, expectedSeqNrs: []uint64{3, 4},
}, },
{
name: "query in forwards order, with start creation " +
"time",
query: PaymentsQuery{
IndexOffset: 0,
MaxPayments: 2,
Reversed: false,
IncludeIncomplete: true,
CreationDateStart: time.Unix(0, 5),
},
firstIndex: 5,
lastIndex: 6,
expectedSeqNrs: []uint64{5, 6},
},
{
name: "query in forwards order, with start creation " +
"time at end, overflow",
query: PaymentsQuery{
IndexOffset: 0,
MaxPayments: 2,
Reversed: false,
IncludeIncomplete: true,
CreationDateStart: time.Unix(0, 7),
},
firstIndex: 7,
lastIndex: 7,
expectedSeqNrs: []uint64{7},
},
{
name: "query with start and end creation time",
query: PaymentsQuery{
IndexOffset: 9,
MaxPayments: math.MaxUint64,
Reversed: true,
IncludeIncomplete: true,
CreationDateStart: time.Unix(0, 3),
CreationDateEnd: time.Unix(0, 5),
},
firstIndex: 3,
lastIndex: 5,
expectedSeqNrs: []uint64{3, 4, 5},
},
} }
for _, tt := range tests { for _, tt := range tests {
@@ -426,6 +468,9 @@ func TestQueryPayments(t *testing.T) {
t.Fatalf("unable to create test "+ t.Fatalf("unable to create test "+
"payment: %v", err) "payment: %v", err)
} }
// Override creation time to allow for testing
// of CreationDateStart and CreationDateEnd.
info.CreationTime = time.Unix(0, int64(i+1))
// Create a new payment entry in the database. // Create a new payment entry in the database.
err = pControl.InitPayment(info.PaymentIdentifier, info) err = pControl.InitPayment(info.PaymentIdentifier, info)
+18 -4
View File
@@ -234,6 +234,18 @@ var listInvoicesCommand = cli.Command{
Usage: "if set, invoices succeeding the " + Usage: "if set, invoices succeeding the " +
"index_offset will be returned", "index_offset will be returned",
}, },
cli.Uint64Flag{
Name: "creation_date_start",
Usage: "timestamp in seconds, if set, filter " +
"invoices with creation date greater than or " +
"equal to it",
},
cli.Uint64Flag{
Name: "creation_date_end",
Usage: "timestamp in seconds, if set, filter " +
"invoices with creation date less than or " +
"equal to it",
},
}, },
Action: actionDecorator(listInvoices), Action: actionDecorator(listInvoices),
} }
@@ -244,10 +256,12 @@ func listInvoices(ctx *cli.Context) error {
defer cleanUp() defer cleanUp()
req := &lnrpc.ListInvoiceRequest{ req := &lnrpc.ListInvoiceRequest{
PendingOnly: ctx.Bool("pending_only"), PendingOnly: ctx.Bool("pending_only"),
IndexOffset: ctx.Uint64("index_offset"), IndexOffset: ctx.Uint64("index_offset"),
NumMaxInvoices: ctx.Uint64("max_invoices"), NumMaxInvoices: ctx.Uint64("max_invoices"),
Reversed: !ctx.Bool("paginate-forwards"), Reversed: !ctx.Bool("paginate-forwards"),
CreationDateStart: ctx.Uint64("creation_date_start"),
CreationDateEnd: ctx.Uint64("creation_date_end"),
} }
invoices, err := client.ListInvoices(ctxc, req) invoices, err := client.ListInvoices(ctxc, req)
+14
View File
@@ -1229,6 +1229,18 @@ var listPaymentsCommand = cli.Command{
"be counted; can take a long time on systems " + "be counted; can take a long time on systems " +
"with many payments", "with many payments",
}, },
cli.Uint64Flag{
Name: "creation_date_start",
Usage: "timestamp in seconds, if set, filter " +
"payments with creation date greater than or " +
"equal to it",
},
cli.Uint64Flag{
Name: "creation_date_end",
Usage: "timestamp in seconds, if set, filter " +
"payments with creation date less than or " +
"equal to it",
},
}, },
Action: actionDecorator(listPayments), Action: actionDecorator(listPayments),
} }
@@ -1244,6 +1256,8 @@ func listPayments(ctx *cli.Context) error {
MaxPayments: uint64(ctx.Uint("max_payments")), MaxPayments: uint64(ctx.Uint("max_payments")),
Reversed: !ctx.Bool("paginate_forwards"), Reversed: !ctx.Bool("paginate_forwards"),
CountTotalPayments: ctx.Bool("count_total_payments"), CountTotalPayments: ctx.Bool("count_total_payments"),
CreationDateStart: ctx.Uint64("creation_date_start"),
CreationDateEnd: ctx.Uint64("creation_date_end"),
} }
payments, err := client.ListPayments(ctxc, req) payments, err := client.ListPayments(ctxc, req)
@@ -69,6 +69,10 @@
hints](https://github.com/lightningnetwork/lnd/pull/7082), up to `maxHopHints` hints](https://github.com/lightningnetwork/lnd/pull/7082), up to `maxHopHints`
(20 currently). (20 currently).
* [Add `creation_date_start` and `creation_date_end` filter fields to
`ListInvoiceRequest` and
`ListPaymentsRequest`](https://github.com/lightningnetwork/lnd/pull/7159).
## Wallet ## Wallet
* [Allows Taproot public keys and tap scripts to be imported as watch-only * [Allows Taproot public keys and tap scripts to be imported as watch-only
@@ -290,4 +294,5 @@ refactor the itest for code health and maintenance.
* Oliver Gugger * Oliver Gugger
* Priyansh Rastogi * Priyansh Rastogi
* Roei Erez * Roei Erez
* Tommy Volk
* Yong Yu * Yong Yu
+3 -4
View File
@@ -469,18 +469,17 @@
}, },
"settled": { "settled": {
"type": "boolean", "type": "boolean",
"description": "The field is deprecated. Use the state field instead (compare to SETTLED).", "description": "Whether this invoice has been fulfilled.\n\nThe field is deprecated. Use the state field instead (compare to SETTLED)."
"title": "Whether this invoice has been fulfilled"
}, },
"creation_date": { "creation_date": {
"type": "string", "type": "string",
"format": "int64", "format": "int64",
"description": "When this invoice was created.\nNote: Output only, don't specify for creating an invoice." "description": "When this invoice was created.\nMeasured in seconds since the unix epoch.\nNote: Output only, don't specify for creating an invoice."
}, },
"settle_date": { "settle_date": {
"type": "string", "type": "string",
"format": "int64", "format": "int64",
"description": "When this invoice was settled.\nNote: Output only, don't specify for creating an invoice." "description": "When this invoice was settled.\nMeasured in seconds since the unix epoch.\nNote: Output only, don't specify for creating an invoice."
}, },
"payment_request": { "payment_request": {
"type": "string", "type": "string",
+1075 -1022
View File
File diff suppressed because it is too large. Load diff
+20 -1
View File
@@ -3351,7 +3351,7 @@ message Invoice {
int64 value_msat = 23; int64 value_msat = 23;
/* /*
Whether this invoice has been fulfilled Whether this invoice has been fulfilled.
The field is deprecated. Use the state field instead (compare to SETTLED). The field is deprecated. Use the state field instead (compare to SETTLED).
*/ */
@@ -3359,12 +3359,14 @@ message Invoice {
/* /*
When this invoice was created. When this invoice was created.
Measured in seconds since the unix epoch.
Note: Output only, don't specify for creating an invoice. Note: Output only, don't specify for creating an invoice.
*/ */
int64 creation_date = 7; int64 creation_date = 7;
/* /*
When this invoice was settled. When this invoice was settled.
Measured in seconds since the unix epoch.
Note: Output only, don't specify for creating an invoice. Note: Output only, don't specify for creating an invoice.
*/ */
int64 settle_date = 8; int64 settle_date = 8;
@@ -3631,7 +3633,16 @@ message ListInvoiceRequest {
specified index offset. This can be used to paginate backwards. specified index offset. This can be used to paginate backwards.
*/ */
bool reversed = 6; bool reversed = 6;
// If set, returns all invoices with a creation date greater than or euqal
// to it. Measured in seconds since the unix epoch.
uint64 creation_date_start = 7;
// If set, returns all invoices with a creation date less than or euqal to
// it. Measured in seconds since the unix epoch.
uint64 creation_date_end = 8;
} }
message ListInvoiceResponse { message ListInvoiceResponse {
/* /*
A list of invoices from the time slice of the time series specified in the A list of invoices from the time slice of the time series specified in the
@@ -3830,6 +3841,14 @@ message ListPaymentsRequest {
of payments, as all of them have to be iterated through to be counted. of payments, as all of them have to be iterated through to be counted.
*/ */
bool count_total_payments = 5; bool count_total_payments = 5;
// If set, returns all invoices with a creation date greater than or euqal
// to it. Measured in seconds since the unix epoch.
uint64 creation_date_start = 6;
// If set, returns all invoices with a creation date less than or euqal to
// it. Measured in seconds since the unix epoch.
uint64 creation_date_end = 7;
} }
message ListPaymentsResponse { message ListPaymentsResponse {
+35 -4
View File
@@ -1719,6 +1719,22 @@
"in": "query", "in": "query",
"required": false, "required": false,
"type": "boolean" "type": "boolean"
},
{
"name": "creation_date_start",
"description": "If set, returns all invoices with a creation date greater than or euqal\nto it. Measured in seconds since the unix epoch.",
"in": "query",
"required": false,
"type": "string",
"format": "uint64"
},
{
"name": "creation_date_end",
"description": "If set, returns all invoices with a creation date less than or euqal to\nit. Measured in seconds since the unix epoch.",
"in": "query",
"required": false,
"type": "string",
"format": "uint64"
} }
], ],
"tags": [ "tags": [
@@ -2127,6 +2143,22 @@
"in": "query", "in": "query",
"required": false, "required": false,
"type": "boolean" "type": "boolean"
},
{
"name": "creation_date_start",
"description": "If set, returns all invoices with a creation date greater than or euqal\nto it. Measured in seconds since the unix epoch.",
"in": "query",
"required": false,
"type": "string",
"format": "uint64"
},
{
"name": "creation_date_end",
"description": "If set, returns all invoices with a creation date less than or euqal to\nit. Measured in seconds since the unix epoch.",
"in": "query",
"required": false,
"type": "string",
"format": "uint64"
} }
], ],
"tags": [ "tags": [
@@ -5003,18 +5035,17 @@
}, },
"settled": { "settled": {
"type": "boolean", "type": "boolean",
"description": "The field is deprecated. Use the state field instead (compare to SETTLED).", "description": "Whether this invoice has been fulfilled.\n\nThe field is deprecated. Use the state field instead (compare to SETTLED)."
"title": "Whether this invoice has been fulfilled"
}, },
"creation_date": { "creation_date": {
"type": "string", "type": "string",
"format": "int64", "format": "int64",
"description": "When this invoice was created.\nNote: Output only, don't specify for creating an invoice." "description": "When this invoice was created.\nMeasured in seconds since the unix epoch.\nNote: Output only, don't specify for creating an invoice."
}, },
"settle_date": { "settle_date": {
"type": "string", "type": "string",
"format": "int64", "format": "int64",
"description": "When this invoice was settled.\nNote: Output only, don't specify for creating an invoice." "description": "When this invoice was settled.\nMeasured in seconds since the unix epoch.\nNote: Output only, don't specify for creating an invoice."
}, },
"payment_request": { "payment_request": {
"type": "string", "type": "string",
+2 -1
View File
@@ -1273,7 +1273,8 @@ func (h *HarnessTest) findPayment(hn *node.HarnessNode,
return p return p
} }
require.Fail(h, "payment: %v not found", paymentHash) require.Failf(h, "payment not found", "payment %v cannot be found",
paymentHash)
return nil return nil
} }
+62 -2
View File
@@ -72,11 +72,71 @@ func testListPayments(ht *lntemp.HarnessTest) {
require.Zero(ht, p.FeeSat, "fee should be 0") require.Zero(ht, p.FeeSat, "fee should be 0")
require.Zero(ht, p.FeeMsat, "fee should be 0") require.Zero(ht, p.FeeMsat, "fee should be 0")
// Finally, verify that the payment request returned by the rpc matches // Now verify that the payment request returned by the rpc matches the
// the invoice that we paid. // invoice that we paid.
require.Equal(ht, invoiceResp.PaymentRequest, p.PaymentRequest, require.Equal(ht, invoiceResp.PaymentRequest, p.PaymentRequest,
"incorrect payreq") "incorrect payreq")
// We now check the timestamp filters in `ListPayments`.
//
// Use a start date long time ago should return us the payment.
req := &lnrpc.ListPaymentsRequest{
CreationDateStart: 1227035905,
}
resp := alice.RPC.ListPayments(req)
require.Len(ht, resp.Payments, 1)
// Use an end date long time ago should return us nothing.
req = &lnrpc.ListPaymentsRequest{
CreationDateEnd: 1227035905,
}
resp = alice.RPC.ListPayments(req)
require.Empty(ht, resp.Payments)
// Use a start date far in the future should return us nothing.
req = &lnrpc.ListPaymentsRequest{
CreationDateStart: 5392552705,
}
resp = alice.RPC.ListPayments(req)
require.Empty(ht, resp.Payments)
// Use an end date far in the future should return us the payment.
req = &lnrpc.ListPaymentsRequest{
CreationDateEnd: 5392552705,
}
resp = alice.RPC.ListPayments(req)
require.Len(ht, resp.Payments, 1)
// We now do the same check for `ListInvoices`
//
// Use a start date long time ago should return us the invoice.
invReq := &lnrpc.ListInvoiceRequest{
CreationDateStart: 1227035905,
}
invResp := bob.RPC.ListInvoices(invReq)
require.Len(ht, invResp.Invoices, 1)
// Use an end date long time ago should return us nothing.
invReq = &lnrpc.ListInvoiceRequest{
CreationDateEnd: 1227035905,
}
invResp = bob.RPC.ListInvoices(invReq)
require.Empty(ht, invResp.Invoices)
// Use a start date far in the future should return us nothing.
invReq = &lnrpc.ListInvoiceRequest{
CreationDateStart: 5392552705,
}
invResp = bob.RPC.ListInvoices(invReq)
require.Empty(ht, invResp.Invoices)
// Use an end date far in the future should return us the invoice.
invReq = &lnrpc.ListInvoiceRequest{
CreationDateEnd: 5392552705,
}
invResp = bob.RPC.ListInvoices(invReq)
require.Len(ht, invResp.Invoices, 1)
// Delete all payments from Alice. DB should have no payments. // Delete all payments from Alice. DB should have no payments.
alice.RPC.DeleteAllPayments() alice.RPC.DeleteAllPayments()
+45
View File
@@ -5516,6 +5516,16 @@ func (r *rpcServer) ListInvoices(ctx context.Context,
req.NumMaxInvoices = 100 req.NumMaxInvoices = 100
} }
// If both dates are set, we check that the start date is less than the
// end date, otherwise we'll get an empty result.
if req.CreationDateStart != 0 && req.CreationDateEnd != 0 {
if req.CreationDateStart >= req.CreationDateEnd {
return nil, fmt.Errorf("start date(%v) must be before "+
"end date(%v)", req.CreationDateStart,
req.CreationDateEnd)
}
}
// Next, we'll map the proto request into a format that is understood by // Next, we'll map the proto request into a format that is understood by
// the database. // the database.
q := channeldb.InvoiceQuery{ q := channeldb.InvoiceQuery{
@@ -5524,6 +5534,17 @@ func (r *rpcServer) ListInvoices(ctx context.Context,
PendingOnly: req.PendingOnly, PendingOnly: req.PendingOnly,
Reversed: req.Reversed, Reversed: req.Reversed,
} }
// Attach the start date if set.
if req.CreationDateStart != 0 {
q.CreationDateStart = time.Unix(int64(req.CreationDateStart), 0)
}
// Attach the end date if set.
if req.CreationDateEnd != 0 {
q.CreationDateEnd = time.Unix(int64(req.CreationDateEnd), 0)
}
invoiceSlice, err := r.server.miscDB.QueryInvoices(q) invoiceSlice, err := r.server.miscDB.QueryInvoices(q)
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to query invoices: %v", err) return nil, fmt.Errorf("unable to query invoices: %v", err)
@@ -6338,6 +6359,16 @@ func (r *rpcServer) ListPayments(ctx context.Context,
rpcsLog.Debugf("[ListPayments]") rpcsLog.Debugf("[ListPayments]")
// If both dates are set, we check that the start date is less than the
// end date, otherwise we'll get an empty result.
if req.CreationDateStart != 0 && req.CreationDateEnd != 0 {
if req.CreationDateStart >= req.CreationDateEnd {
return nil, fmt.Errorf("start date(%v) must be before "+
"end date(%v)", req.CreationDateStart,
req.CreationDateEnd)
}
}
query := channeldb.PaymentsQuery{ query := channeldb.PaymentsQuery{
IndexOffset: req.IndexOffset, IndexOffset: req.IndexOffset,
MaxPayments: req.MaxPayments, MaxPayments: req.MaxPayments,
@@ -6346,6 +6377,20 @@ func (r *rpcServer) ListPayments(ctx context.Context,
CountTotal: req.CountTotalPayments, CountTotal: req.CountTotalPayments,
} }
// Attach the start date if set.
if req.CreationDateStart != 0 {
query.CreationDateStart = time.Unix(
int64(req.CreationDateStart), 0,
)
}
// Attach the end date if set.
if req.CreationDateEnd != 0 {
query.CreationDateEnd = time.Unix(
int64(req.CreationDateEnd), 0,
)
}
// If the maximum number of payments wasn't specified, then we'll // If the maximum number of payments wasn't specified, then we'll
// default to return the maximal number of payments representable. // default to return the maximal number of payments representable.
if req.MaxPayments == 0 { if req.MaxPayments == 0 {