channeldb: store the invoice counter within the invoice index bucket

This commit moves the location of the invoice counter key which is an
auto-incrementing primary key for all invoices. Rather than storing the counter
in the same top-level invoice bucket, the counter is now stored within the
invoiceIndex bucket. With this change, the top-level bucket can now cleanly be
scanned in a sequential manner to retrieve all invoices.
This commit is contained in:
Olaoluwa Osuntokun 2016-09-19 11:46:48 -07:00
parent 28b72d368c
commit fa70990452
No known key found for this signature in database
GPG Key ID: 9CC5B105D03521A2
2 changed files with 35 additions and 34 deletions

View File

@ -9,6 +9,7 @@ var (
ErrChannelNoExist = fmt.Errorf("this channel does not exist")
ErrNoPastDeltas = fmt.Errorf("channel has no recorded deltas")
ErrInvoiceNotFound = fmt.Errorf("unable to locate invoice")
ErrDuplicateInvoice = fmt.Errorf("invoice with payment hash already exists")
ErrInvoiceNotFound = fmt.Errorf("unable to locate invoice")
ErrNoInvoicesCreated = fmt.Errorf("there are no existing invoices")
ErrDuplicateInvoice = fmt.Errorf("invoice with payment hash already exists")
)

View File

@ -18,19 +18,20 @@ var (
// which is a monotonically increasing uint32.
invoiceBucket = []byte("invoices")
// numInvoicesKey is the name of key which houses the auto-incrementing
// invoice ID which is essentially used as a primary key. With each
// invoice inserted, the primary key is incremented by one. Within the
// above bucket invoices are uniquely identified by the invoice ID.
numInvoicesKey = []byte("nik")
// paymentHashIndexBucket is the name of the sub-bucket within the
// invoiceBucket which indexes all invoices by their payment hash. The
// payment hash is the sha256 of the invoice's payment preimage. This
// index is used to detect duplicates, and also to provide a fast path
// for looking up incoming HTLC's to determine if we're able to settle
// them fully.
paymentHashIndexBucket = []byte("paymenthashes")
invoiceIndexBucket = []byte("paymenthashes")
// numInvoicesKey is the name of key which houses the auto-incrementing
// invoice ID which is essentially used as a primary key. With each
// invoice inserted, the primary key is incremented by one. This key is
// stored within the invoiceIndexBucket. Within the invoiceBucket
// invoices are uniquely identified by the invoice ID.
numInvoicesKey = []byte("nik")
)
const (
@ -43,6 +44,24 @@ const (
MaxReceiptSize = 1024
)
// ContractTerm is a companion struct to the Invoice struct. This struct houses
// the necessary conditions required before the invoice can be considered fully
// settled by the payee.
type ContractTerm struct {
// PaymentPreimage is the preimage which is to be revealed in the
// occasion that an HTLC paying to the hash of this preimage is
// extended.
PaymentPreimage [32]byte
// Value is the expected amount to be payed to an HTLC which can be
// satisfied by the above preimage.
Value btcutil.Amount
// Settled indicates if this particular contract term has been fully
// settled by the payer.
Settled bool
}
// Invoice is a payment invoice generated by a payee in order to request
// payment for some good or service. The inclusion of invoices within Lightning
// creates a payment work flow for merchants very similar to that of the
@ -78,24 +97,6 @@ type Invoice struct {
Terms ContractTerm
}
// ContractTerm is a companion struct to the Invoice struct. This struct houses
// the necessary conditions required before the invoice can be considered fully
// settled by the payee.
type ContractTerm struct {
// PaymentPreimage is the preimage which is to be revealed in the
// occasion that an HTLC paying to the hash of this preimage is
// extended.
PaymentPreimage [32]byte
// Value is the expected amount to be payed to an HTLC which can be
// satisfied by the above preimage.
Value btcutil.Amount
// Settled indicates if this particular contract term has been fully
// settled by the payer.
Settled bool
}
// 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
@ -107,7 +108,7 @@ func (d *DB) AddInvoice(i *Invoice) error {
return err
}
invoiceIndex, err := invoices.CreateBucketIfNotExists(paymentHashIndexBucket)
invoiceIndex, err := invoices.CreateBucketIfNotExists(invoiceIndexBucket)
if err != nil {
return err
}
@ -122,18 +123,17 @@ func (d *DB) AddInvoice(i *Invoice) error {
// If the current running payment ID counter hasn't yet been
// created, then create it now.
var invoiceNum uint32
invoiceCounter := invoices.Get(numInvoicesKey)
invoiceCounter := invoiceIndex.Get(numInvoicesKey)
if invoiceCounter == nil {
var scratch [4]byte
byteOrder.PutUint32(scratch[:], invoiceNum)
if err := invoices.Put(numInvoicesKey, scratch[:]); err != nil {
if err := invoiceIndex.Put(numInvoicesKey, scratch[:]); err != nil {
return nil
}
} else {
invoiceNum = byteOrder.Uint32(invoiceCounter)
}
// index from payment hash to ID?
return putInvoice(invoices, invoiceIndex, i, invoiceNum)
})
}
@ -151,7 +151,7 @@ func (d *DB) LookupInvoice(paymentHash [32]byte) (*Invoice, error) {
if invoices == nil {
return ErrInvoiceNotFound
}
invoiceIndex := invoices.Bucket(paymentHashIndexBucket)
invoiceIndex := invoices.Bucket(invoiceIndexBucket)
if invoiceIndex == nil {
return ErrInvoiceNotFound
}
@ -190,7 +190,7 @@ func (d *DB) SettleInvoice(paymentHash [32]byte) error {
if err != nil {
return err
}
invoiceIndex, err := invoices.CreateBucketIfNotExists(paymentHashIndexBucket)
invoiceIndex, err := invoices.CreateBucketIfNotExists(invoiceIndexBucket)
if err != nil {
return err
}
@ -219,7 +219,7 @@ func putInvoice(invoices *bolt.Bucket, invoiceIndex *bolt.Bucket,
var scratch [4]byte
invoiceCounter := invoiceNum + 1
byteOrder.PutUint32(scratch[:], invoiceCounter)
if err := invoices.Put(numInvoicesKey, scratch[:]); err != nil {
if err := invoiceIndex.Put(numInvoicesKey, scratch[:]); err != nil {
return err
}