channeldb: move idempotency up the call tree

As a preparation for subscribing to single invoices, InvoiceRegistry
needs to become aware of settling a settled invoice.
This commit is contained in:
Joost Jager 2019-01-14 12:03:26 +01:00
parent 2a4c93cdc4
commit 436dd41c77
No known key found for this signature in database
GPG Key ID: A61B9D4C393C59C7
3 changed files with 20 additions and 16 deletions

@ -359,10 +359,10 @@ func TestDuplicateSettleInvoice(t *testing.T) {
}
// If we try to settle the invoice again, then we should get the very
// same invoice back.
// same invoice back, but with an error this time.
dbInvoice, err = db.SettleInvoice(payHash, amt)
if err != nil {
t.Fatalf("unable to settle invoice: %v", err)
if err != ErrInvoiceAlreadySettled {
t.Fatalf("expected ErrInvoiceAlreadySettled")
}
if dbInvoice == nil {

@ -4,6 +4,7 @@ import (
"bytes"
"crypto/sha256"
"encoding/binary"
"errors"
"fmt"
"io"
"time"
@ -57,6 +58,10 @@ var (
//
// settleIndexNo => invoiceKey
settleIndexBucket = []byte("invoice-settle-index")
// ErrInvoiceAlreadySettled is returned when the invoice is already
// settled.
ErrInvoiceAlreadySettled = errors.New("invoice already settled")
)
const (
@ -626,21 +631,14 @@ func (d *DB) SettleInvoice(paymentHash [32]byte,
return ErrInvoiceNotFound
}
invoice, err := settleInvoice(
settledInvoice, err = settleInvoice(
invoices, settleIndex, invoiceNum, amtPaid,
)
if err != nil {
return err
}
settledInvoice = invoice
return nil
return err
})
if err != nil {
return nil, err
}
return settledInvoice, nil
return settledInvoice, err
}
// InvoicesSettledSince can be used by callers to catch up any settled invoices
@ -898,10 +896,8 @@ func settleInvoice(invoices, settleIndex *bbolt.Bucket, invoiceNum []byte,
return nil, err
}
// Add idempotency to duplicate settles, return here to avoid
// overwriting the previous info.
if invoice.Terms.State == ContractSettled {
return &invoice, nil
return &invoice, ErrInvoiceAlreadySettled
}
// Now that we know the invoice hasn't already been settled, we'll

@ -378,6 +378,14 @@ func (i *InvoiceRegistry) SettleInvoice(rHash lntypes.Hash,
// If this isn't a debug invoice, then we'll attempt to settle an
// invoice matching this rHash on disk (if one exists).
invoice, err := i.cdb.SettleInvoice(rHash, amtPaid)
// Implement idempotency by returning success if the invoice was already
// settled.
if err == channeldb.ErrInvoiceAlreadySettled {
log.Debugf("Invoice %v already settled", rHash)
return nil
}
if err != nil {
return err
}