diff --git a/channeldb/invoice_test.go b/channeldb/invoice_test.go index b29102fb..901ad86c 100644 --- a/channeldb/invoice_test.go +++ b/channeldb/invoice_test.go @@ -29,6 +29,19 @@ func randInvoice(value lnwire.MilliSatoshi) (*Invoice, error) { i.Memo = []byte("memo") i.Receipt = []byte("recipt") + // Create a random byte slice of MaxPaymentRequestSize bytes to be used + // as a dummy paymentrequest, and determine if it should be set based + // on one of the random bytes. + var r [MaxPaymentRequestSize]byte + if _, err := rand.Read(r[:]); err != nil { + return nil, err + } + if r[0]&1 == 0 { + i.PaymentRequest = r[:] + } else { + i.PaymentRequest = []byte("") + } + return i, nil } @@ -50,6 +63,7 @@ func TestInvoiceWorkflow(t *testing.T) { } fakeInvoice.Memo = []byte("memo") fakeInvoice.Receipt = []byte("recipt") + fakeInvoice.PaymentRequest = []byte("") copy(fakeInvoice.Terms.PaymentPreimage[:], rev[:]) fakeInvoice.Terms.Value = lnwire.NewMSatFromSatoshis(10000) diff --git a/channeldb/invoices.go b/channeldb/invoices.go index 1add9087..98cc1943 100644 --- a/channeldb/invoices.go +++ b/channeldb/invoices.go @@ -43,6 +43,12 @@ const ( // MaxReceiptSize is the maximum size of the payment receipt stored // within the database along side incoming/outgoing invoices. MaxReceiptSize = 1024 + + // MaxPaymentRequestSize is the max size of a a payment request for + // this invoice. + // TODO(halseth): determine the max length payment request when field + // lengths are final. + MaxPaymentRequestSize = 4096 ) // ContractTerm is a companion struct to the Invoice struct. This struct houses @@ -86,6 +92,10 @@ type Invoice struct { // TODO(roasbeef): document scheme. Receipt []byte + // PaymentRequest is an optional field where a payment request created + // for this invoice can be stored. + PaymentRequest []byte + // CreationDate is the exact time the invoice was created. CreationDate time.Time @@ -108,6 +118,11 @@ func validateInvoice(i *Invoice) error { "of length %v was provided", MaxReceiptSize, len(i.Receipt)) } + if len(i.PaymentRequest) > MaxPaymentRequestSize { + return fmt.Errorf("max length of payment request is %v, length "+ + "provided was %v", MaxPaymentRequestSize, + len(i.PaymentRequest)) + } return nil } @@ -306,6 +321,9 @@ func serializeInvoice(w io.Writer, i *Invoice) error { if err := wire.WriteVarBytes(w, 0, i.Receipt[:]); err != nil { return err } + if err := wire.WriteVarBytes(w, 0, i.PaymentRequest[:]); err != nil { + return err + } birthBytes, err := i.CreationDate.MarshalBinary() if err != nil { @@ -361,6 +379,11 @@ func deserializeInvoice(r io.Reader) (*Invoice, error) { return nil, err } + invoice.PaymentRequest, err = wire.ReadVarBytes(r, 0, MaxPaymentRequestSize, "") + if err != nil { + return nil, err + } + birthBytes, err := wire.ReadVarBytes(r, 0, 300, "birth") if err != nil { return nil, err diff --git a/channeldb/payments_test.go b/channeldb/payments_test.go index f84572c2..8c17414d 100644 --- a/channeldb/payments_test.go +++ b/channeldb/payments_test.go @@ -17,9 +17,10 @@ func makeFakePayment() *OutgoingPayment { fakeInvoice := &Invoice{ // Use single second precision to avoid false positive test // failures due to the monotonic time component. - CreationDate: time.Unix(time.Now().Unix(), 0), - Memo: []byte("fake memo"), - Receipt: []byte("fake receipt"), + CreationDate: time.Unix(time.Now().Unix(), 0), + Memo: []byte("fake memo"), + Receipt: []byte("fake receipt"), + PaymentRequest: []byte(""), } copy(fakeInvoice.Terms.PaymentPreimage[:], rev[:]) @@ -69,6 +70,8 @@ func makeRandomFakePayment() (*OutgoingPayment, error) { return nil, err } + fakeInvoice.PaymentRequest = []byte("") + preImg, err := randomBytes(32, 33) if err != nil { return nil, err