channeldb: store optional invoice fields as variable length byte arrays
This commit modifies the on-disk storage of invoices to stop the optional fields (memo+receipt) on-disk as variable length byte arrays. This change saves space as the optional fields now only take up as much space as is strictly needed, rather than always being padded out to max size (1KB).
This commit is contained in:
parent
6ff11ba65c
commit
0b841ec686
@ -25,8 +25,8 @@ func randInvoice(value btcutil.Amount) (*Invoice, error) {
|
|||||||
Value: value,
|
Value: value,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
copy(i.Memo[:], []byte("memo"))
|
i.Memo = []byte("memo")
|
||||||
copy(i.Receipt[:], []byte("recipt"))
|
i.Receipt = []byte("recipt")
|
||||||
|
|
||||||
return i, nil
|
return i, nil
|
||||||
}
|
}
|
||||||
@ -43,8 +43,8 @@ func TestInvoiceWorkflow(t *testing.T) {
|
|||||||
fakeInvoice := &Invoice{
|
fakeInvoice := &Invoice{
|
||||||
CreationDate: time.Now(),
|
CreationDate: time.Now(),
|
||||||
}
|
}
|
||||||
copy(fakeInvoice.Memo[:], []byte("memo"))
|
fakeInvoice.Memo = []byte("memo")
|
||||||
copy(fakeInvoice.Receipt[:], []byte("recipt"))
|
fakeInvoice.Receipt = []byte("recipt")
|
||||||
copy(fakeInvoice.Terms.PaymentPreimage[:], rev[:])
|
copy(fakeInvoice.Terms.PaymentPreimage[:], rev[:])
|
||||||
fakeInvoice.Terms.Value = btcutil.Amount(10000)
|
fakeInvoice.Terms.Value = btcutil.Amount(10000)
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package channeldb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -77,13 +78,13 @@ type Invoice struct {
|
|||||||
// Memo is an optional memo to be stored along side an invoice. The
|
// Memo is an optional memo to be stored along side an invoice. The
|
||||||
// memo may contain further details pertaining to the invoice itself,
|
// memo may contain further details pertaining to the invoice itself,
|
||||||
// or any other message which fits within the size constraints.
|
// or any other message which fits within the size constraints.
|
||||||
Memo [MaxMemoSize]byte
|
Memo []byte
|
||||||
|
|
||||||
// Receipt is an optional field dedicated for storing a
|
// Receipt is an optional field dedicated for storing a
|
||||||
// cryptographically binding receipt of payment.
|
// cryptographically binding receipt of payment.
|
||||||
//
|
//
|
||||||
// TODO(roasbeef): document scheme.
|
// TODO(roasbeef): document scheme.
|
||||||
Receipt [MaxReceiptSize]byte
|
Receipt []byte
|
||||||
|
|
||||||
// CreationDate is the exact time the invoice was created.
|
// CreationDate is the exact time the invoice was created.
|
||||||
CreationDate time.Time
|
CreationDate time.Time
|
||||||
@ -102,6 +103,16 @@ type Invoice struct {
|
|||||||
// insertion will be aborted and rejected due to the strict policy banning any
|
// insertion will be aborted and rejected due to the strict policy banning any
|
||||||
// duplicate payment hashes.
|
// duplicate payment hashes.
|
||||||
func (d *DB) AddInvoice(i *Invoice) error {
|
func (d *DB) AddInvoice(i *Invoice) error {
|
||||||
|
if len(i.Memo) > MaxMemoSize {
|
||||||
|
return fmt.Errorf("max length a memo is %v, and invoice "+
|
||||||
|
"of length %v was provided", MaxMemoSize, len(i.Memo))
|
||||||
|
}
|
||||||
|
if len(i.Receipt) > MaxReceiptSize {
|
||||||
|
return fmt.Errorf("max length a receipt is %v, and invoice "+
|
||||||
|
"of length %v was provided", MaxReceiptSize,
|
||||||
|
len(i.Receipt))
|
||||||
|
}
|
||||||
|
|
||||||
return d.store.Update(func(tx *bolt.Tx) error {
|
return d.store.Update(func(tx *bolt.Tx) error {
|
||||||
invoices, err := tx.CreateBucketIfNotExists(invoiceBucket)
|
invoices, err := tx.CreateBucketIfNotExists(invoiceBucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -283,10 +294,10 @@ func putInvoice(invoices *bolt.Bucket, invoiceIndex *bolt.Bucket,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func serializeInvoice(w io.Writer, i *Invoice) error {
|
func serializeInvoice(w io.Writer, i *Invoice) error {
|
||||||
if _, err := w.Write(i.Memo[:]); err != nil {
|
if err := wire.WriteVarBytes(w, 0, i.Memo[:]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err := w.Write(i.Receipt[:]); err != nil {
|
if err := wire.WriteVarBytes(w, 0, i.Receipt[:]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,13 +342,16 @@ func fetchInvoice(invoiceNum []byte, invoices *bolt.Bucket) (*Invoice, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func deserializeInvoice(r io.Reader) (*Invoice, error) {
|
func deserializeInvoice(r io.Reader) (*Invoice, error) {
|
||||||
|
var err error
|
||||||
invoice := &Invoice{}
|
invoice := &Invoice{}
|
||||||
|
|
||||||
// TODO(roasbeef): use read full everywhere
|
// TODO(roasbeef): use read full everywhere
|
||||||
if _, err := io.ReadFull(r, invoice.Memo[:]); err != nil {
|
invoice.Memo, err = wire.ReadVarBytes(r, 0, MaxMemoSize, "")
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if _, err := io.ReadFull(r, invoice.Receipt[:]); err != nil {
|
invoice.Receipt, err = wire.ReadVarBytes(r, 0, MaxReceiptSize, "")
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -613,12 +613,12 @@ func (r *rpcServer) AddInvoice(ctx context.Context,
|
|||||||
|
|
||||||
i := &channeldb.Invoice{
|
i := &channeldb.Invoice{
|
||||||
CreationDate: time.Now(),
|
CreationDate: time.Now(),
|
||||||
|
Memo: []byte(invoice.Memo),
|
||||||
|
Receipt: invoice.Receipt,
|
||||||
Terms: channeldb.ContractTerm{
|
Terms: channeldb.ContractTerm{
|
||||||
Value: btcutil.Amount(invoice.Value),
|
Value: btcutil.Amount(invoice.Value),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
copy(i.Memo[:], invoice.Memo)
|
|
||||||
copy(i.Receipt[:], invoice.Receipt)
|
|
||||||
copy(i.Terms.PaymentPreimage[:], preImage)
|
copy(i.Terms.PaymentPreimage[:], preImage)
|
||||||
|
|
||||||
if err := r.server.invoices.AddInvoice(i); err != nil {
|
if err := r.server.invoices.AddInvoice(i); err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user