Skip to content

Commit

Permalink
channeldb+invoices+lnrpc: fix what pending invoice means in ChannelDB
Browse files Browse the repository at this point in the history
This commits builds on top of PR lightningnetwork#3694 to further clarify invoice
state by defining pending invoices as the ones which are not
settled or canceled. Automatic cancellation of expired invoices
makes this possbile. While this change only directly affects
ChannelDB, users of the listinvoices RPC will receive actual
pending invoices when pending_only flag is set.

This commit also updates the doc for ListInvoiceRequest pending_only
flag to update the meaning such that pending_only means invoices that
are not settled or invoices that are not canceled.
  • Loading branch information
bhandras committed Dec 19, 2019
1 parent bd16ed8 commit fd0ac52
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 19 deletions.
23 changes: 23 additions & 0 deletions channeldb/invoice_test.go
Expand Up @@ -52,6 +52,29 @@ func randInvoice(value lnwire.MilliSatoshi) (*Invoice, error) {
return i, nil
}

// Tests that pendind state is correctly returned when calling the
// Invoice.IsPending() function.
func TestInvoiceIsPending(t *testing.T) {
contractStates := []ContractState{
ContractOpen, ContractSettled, ContractCanceled, ContractAccepted,
}

for _, state := range contractStates {
invoice := Invoice{
State: state,
}

// We expect that an invoice is panding if it's either in ContractOpen
// or ContractAccepted state.
pending := (state == ContractOpen || state == ContractAccepted)

if invoice.IsPending() != pending {
t.Fatalf("expected pending: %v, got: %v, invoice: %v",
pending, invoice.IsPending(), invoice)
}
}
}

func TestInvoiceWorkflow(t *testing.T) {
t.Parallel()

Expand Down
31 changes: 15 additions & 16 deletions channeldb/invoices.go
Expand Up @@ -149,15 +149,13 @@ const (
// ContractOpen means the invoice has only been created.
ContractOpen ContractState = 0

// ContractSettled means the htlc is settled and the invoice has been
// paid.
// ContractSettled means the htlc is settled and the invoice has been paid.
ContractSettled ContractState = 1

// ContractCanceled means the invoice has been canceled.
ContractCanceled ContractState = 2

// ContractAccepted means the HTLC has been accepted but not settled
// yet.
// ContractAccepted means the HTLC has been accepted but not settled yet.
ContractAccepted ContractState = 3
)

Expand Down Expand Up @@ -385,6 +383,12 @@ func validateInvoice(i *Invoice) error {
return nil
}

// IsPending returns true if the invoice is in ContractOpen or in
// ContractAccepted state.
func (i *Invoice) IsPending() bool {
return i.State == ContractOpen || i.State == ContractAccepted
}

// AddInvoice inserts the targeted invoice into the database. If the invoice has
// *any* payment hashes which already exists within the database, then the
// insertion will be aborted and rejected due to the strict policy banning any
Expand Down Expand Up @@ -578,9 +582,9 @@ type InvoiceWithPaymentHash struct {

// FetchAllInvoicesWithPaymentHash returns all invoices and their payment hashes
// currently stored within the database. If the pendingOnly param is true, then
// only unsettled invoices and their payment hashes will be returned, skipping
// all invoices that are fully settled or canceled. Note that the returned
// array is not ordered by add index.
// only open or accepted invoices and their payment hashes will be returned,
// skipping all invoices that are fully settled or canceled. Note that the
// returned array is not ordered by add index.
func (d *DB) FetchAllInvoicesWithPaymentHash(pendingOnly bool) (
[]InvoiceWithPaymentHash, error) {

Expand Down Expand Up @@ -617,10 +621,7 @@ func (d *DB) FetchAllInvoicesWithPaymentHash(pendingOnly bool) (
return err
}

if pendingOnly &&
(invoice.State == ContractSettled ||
invoice.State == ContractCanceled) {

if pendingOnly && !invoice.IsPending() {
return nil
}

Expand Down Expand Up @@ -772,11 +773,9 @@ func (d *DB) QueryInvoices(q InvoiceQuery) (InvoiceSlice, error) {
return err
}

// Skip any settled invoices if the caller is only
// interested in unsettled.
if q.PendingOnly &&
invoice.State == ContractSettled {

// Skip any settled or canceled invoices if the caller is
// only interested in pending ones.
if q.PendingOnly && !invoice.IsPending() {
continue
}

Expand Down
4 changes: 3 additions & 1 deletion lnrpc/rpc.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion lnrpc/rpc.proto
Expand Up @@ -2482,7 +2482,10 @@ message PaymentHash {
}

message ListInvoiceRequest {
/// If set, only unsettled invoices will be returned in the response.
/**
If set, only invoices that are not settled and not canceled will be returned
in the response.
*/
bool pending_only = 1 [json_name = "pending_only"];

/**
Expand Down
2 changes: 1 addition & 1 deletion lnrpc/rpc.swagger.json
Expand Up @@ -896,7 +896,7 @@
"parameters": [
{
"name": "pending_only",
"description": "/ If set, only unsettled invoices will be returned in the response.",
"description": "*\nIf set, only invoices that are not settled and not canceled will be returned\nin the response.",
"in": "query",
"required": false,
"type": "boolean",
Expand Down

0 comments on commit fd0ac52

Please sign in to comment.