github.com/decred/dcrlnd@v0.7.6/channeldb/migration12/invoices.go (about) 1 package migration12 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "io" 7 "time" 8 9 "github.com/decred/dcrd/wire" 10 lnwire "github.com/decred/dcrlnd/channeldb/migration/lnwire21" 11 "github.com/decred/dcrlnd/lntypes" 12 "github.com/decred/dcrlnd/tlv" 13 ) 14 15 const ( 16 // MaxMemoSize is maximum size of the memo field within invoices stored 17 // in the database. 18 MaxMemoSize = 1024 19 20 // maxReceiptSize is the maximum size of the payment receipt stored 21 // within the database along side incoming/outgoing invoices. 22 maxReceiptSize = 1024 23 24 // MaxPaymentRequestSize is the max size of a payment request for 25 // this invoice. 26 // TODO(halseth): determine the max length payment request when field 27 // lengths are final. 28 MaxPaymentRequestSize = 4096 29 30 memoType tlv.Type = 0 31 payReqType tlv.Type = 1 32 createTimeType tlv.Type = 2 33 settleTimeType tlv.Type = 3 34 addIndexType tlv.Type = 4 35 settleIndexType tlv.Type = 5 36 preimageType tlv.Type = 6 37 valueType tlv.Type = 7 38 cltvDeltaType tlv.Type = 8 39 expiryType tlv.Type = 9 40 paymentAddrType tlv.Type = 10 41 featuresType tlv.Type = 11 42 invStateType tlv.Type = 12 43 amtPaidType tlv.Type = 13 44 ) 45 46 var ( 47 // invoiceBucket is the name of the bucket within the database that 48 // stores all data related to invoices no matter their final state. 49 // Within the invoice bucket, each invoice is keyed by its invoice ID 50 // which is a monotonically increasing uint32. 51 invoiceBucket = []byte("invoices") 52 53 // Big endian is the preferred byte order, due to cursor scans over 54 // integer keys iterating in order. 55 byteOrder = binary.BigEndian 56 ) 57 58 // ContractState describes the state the invoice is in. 59 type ContractState uint8 60 61 // ContractTerm is a companion struct to the Invoice struct. This struct houses 62 // the necessary conditions required before the invoice can be considered fully 63 // settled by the payee. 64 type ContractTerm struct { 65 // PaymentPreimage is the preimage which is to be revealed in the 66 // occasion that an HTLC paying to the hash of this preimage is 67 // extended. 68 PaymentPreimage lntypes.Preimage 69 70 // Value is the expected amount of milli-satoshis to be paid to an HTLC 71 // which can be satisfied by the above preimage. 72 Value lnwire.MilliAtom 73 74 // State describes the state the invoice is in. 75 State ContractState 76 77 // PaymentAddr is a randomly generated value include in the MPP record 78 // by the sender to prevent probing of the receiver. 79 PaymentAddr [32]byte 80 81 // Features is the feature vectors advertised on the payment request. 82 Features *lnwire.FeatureVector 83 } 84 85 // Invoice is a payment invoice generated by a payee in order to request 86 // payment for some good or service. The inclusion of invoices within Lightning 87 // creates a payment work flow for merchants very similar to that of the 88 // existing financial system within PayPal, etc. Invoices are added to the 89 // database when a payment is requested, then can be settled manually once the 90 // payment is received at the upper layer. For record keeping purposes, 91 // invoices are never deleted from the database, instead a bit is toggled 92 // denoting the invoice has been fully settled. Within the database, all 93 // invoices must have a unique payment hash which is generated by taking the 94 // sha256 of the payment preimage. 95 type Invoice struct { 96 // Memo is an optional memo to be stored along side an invoice. The 97 // memo may contain further details pertaining to the invoice itself, 98 // or any other message which fits within the size constraints. 99 Memo []byte 100 101 // PaymentRequest is an optional field where a payment request created 102 // for this invoice can be stored. 103 PaymentRequest []byte 104 105 // FinalCltvDelta is the minimum required number of blocks before htlc 106 // expiry when the invoice is accepted. 107 FinalCltvDelta int32 108 109 // Expiry defines how long after creation this invoice should expire. 110 Expiry time.Duration 111 112 // CreationDate is the exact time the invoice was created. 113 CreationDate time.Time 114 115 // SettleDate is the exact time the invoice was settled. 116 SettleDate time.Time 117 118 // Terms are the contractual payment terms of the invoice. Once all the 119 // terms have been satisfied by the payer, then the invoice can be 120 // considered fully fulfilled. 121 // 122 // TODO(roasbeef): later allow for multiple terms to fulfill the final 123 // invoice: payment fragmentation, etc. 124 Terms ContractTerm 125 126 // AddIndex is an auto-incrementing integer that acts as a 127 // monotonically increasing sequence number for all invoices created. 128 // Clients can then use this field as a "checkpoint" of sorts when 129 // implementing a streaming RPC to notify consumers of instances where 130 // an invoice has been added before they re-connected. 131 // 132 // NOTE: This index starts at 1. 133 AddIndex uint64 134 135 // SettleIndex is an auto-incrementing integer that acts as a 136 // monotonically increasing sequence number for all settled invoices. 137 // Clients can then use this field as a "checkpoint" of sorts when 138 // implementing a streaming RPC to notify consumers of instances where 139 // an invoice has been settled before they re-connected. 140 // 141 // NOTE: This index starts at 1. 142 SettleIndex uint64 143 144 // AmtPaid is the final amount that we ultimately accepted for pay for 145 // this invoice. We specify this value independently as it's possible 146 // that the invoice originally didn't specify an amount, or the sender 147 // overpaid. 148 AmtPaid lnwire.MilliAtom 149 150 // Htlcs records all htlcs that paid to this invoice. Some of these 151 // htlcs may have been marked as canceled. 152 Htlcs []byte 153 } 154 155 // LegacyDeserializeInvoice decodes an invoice from the passed io.Reader using 156 // the pre-TLV serialization. 157 func LegacyDeserializeInvoice(r io.Reader) (Invoice, error) { 158 var err error 159 invoice := Invoice{} 160 161 // TODO(roasbeef): use read full everywhere 162 invoice.Memo, err = wire.ReadVarBytes(r, 0, MaxMemoSize, "") 163 if err != nil { 164 return invoice, err 165 } 166 _, err = wire.ReadVarBytes(r, 0, maxReceiptSize, "") 167 if err != nil { 168 return invoice, err 169 } 170 171 invoice.PaymentRequest, err = wire.ReadVarBytes(r, 0, MaxPaymentRequestSize, "") 172 if err != nil { 173 return invoice, err 174 } 175 176 if err := binary.Read(r, byteOrder, &invoice.FinalCltvDelta); err != nil { 177 return invoice, err 178 } 179 180 var expiry int64 181 if err := binary.Read(r, byteOrder, &expiry); err != nil { 182 return invoice, err 183 } 184 invoice.Expiry = time.Duration(expiry) 185 186 birthBytes, err := wire.ReadVarBytes(r, 0, 300, "birth") 187 if err != nil { 188 return invoice, err 189 } 190 if err := invoice.CreationDate.UnmarshalBinary(birthBytes); err != nil { 191 return invoice, err 192 } 193 194 settledBytes, err := wire.ReadVarBytes(r, 0, 300, "settled") 195 if err != nil { 196 return invoice, err 197 } 198 if err := invoice.SettleDate.UnmarshalBinary(settledBytes); err != nil { 199 return invoice, err 200 } 201 202 if _, err := io.ReadFull(r, invoice.Terms.PaymentPreimage[:]); err != nil { 203 return invoice, err 204 } 205 var scratch [8]byte 206 if _, err := io.ReadFull(r, scratch[:]); err != nil { 207 return invoice, err 208 } 209 invoice.Terms.Value = lnwire.MilliAtom(byteOrder.Uint64(scratch[:])) 210 211 if err := binary.Read(r, byteOrder, &invoice.Terms.State); err != nil { 212 return invoice, err 213 } 214 215 if err := binary.Read(r, byteOrder, &invoice.AddIndex); err != nil { 216 return invoice, err 217 } 218 if err := binary.Read(r, byteOrder, &invoice.SettleIndex); err != nil { 219 return invoice, err 220 } 221 if err := binary.Read(r, byteOrder, &invoice.AmtPaid); err != nil { 222 return invoice, err 223 } 224 225 invoice.Htlcs, err = deserializeHtlcs(r) 226 if err != nil { 227 return Invoice{}, err 228 } 229 230 return invoice, nil 231 } 232 233 // deserializeHtlcs reads a list of invoice htlcs from a reader and returns it 234 // as a flattened byte slice. 235 func deserializeHtlcs(r io.Reader) ([]byte, error) { 236 var b bytes.Buffer 237 _, err := io.Copy(&b, r) 238 return b.Bytes(), err 239 } 240 241 // SerializeInvoice serializes an invoice to a writer. 242 // 243 // nolint: dupl 244 func SerializeInvoice(w io.Writer, i *Invoice) error { 245 creationDateBytes, err := i.CreationDate.MarshalBinary() 246 if err != nil { 247 return err 248 } 249 250 settleDateBytes, err := i.SettleDate.MarshalBinary() 251 if err != nil { 252 return err 253 } 254 255 var fb bytes.Buffer 256 err = i.Terms.Features.EncodeBase256(&fb) 257 if err != nil { 258 return err 259 } 260 featureBytes := fb.Bytes() 261 262 preimage := [32]byte(i.Terms.PaymentPreimage) 263 value := uint64(i.Terms.Value) 264 cltvDelta := uint32(i.FinalCltvDelta) 265 expiry := uint64(i.Expiry) 266 267 amtPaid := uint64(i.AmtPaid) 268 state := uint8(i.Terms.State) 269 270 tlvStream, err := tlv.NewStream( 271 // Memo and payreq. 272 tlv.MakePrimitiveRecord(memoType, &i.Memo), 273 tlv.MakePrimitiveRecord(payReqType, &i.PaymentRequest), 274 275 // Add/settle metadata. 276 tlv.MakePrimitiveRecord(createTimeType, &creationDateBytes), 277 tlv.MakePrimitiveRecord(settleTimeType, &settleDateBytes), 278 tlv.MakePrimitiveRecord(addIndexType, &i.AddIndex), 279 tlv.MakePrimitiveRecord(settleIndexType, &i.SettleIndex), 280 281 // Terms. 282 tlv.MakePrimitiveRecord(preimageType, &preimage), 283 tlv.MakePrimitiveRecord(valueType, &value), 284 tlv.MakePrimitiveRecord(cltvDeltaType, &cltvDelta), 285 tlv.MakePrimitiveRecord(expiryType, &expiry), 286 tlv.MakePrimitiveRecord(paymentAddrType, &i.Terms.PaymentAddr), 287 tlv.MakePrimitiveRecord(featuresType, &featureBytes), 288 289 // Invoice state. 290 tlv.MakePrimitiveRecord(invStateType, &state), 291 tlv.MakePrimitiveRecord(amtPaidType, &amtPaid), 292 ) 293 if err != nil { 294 return err 295 } 296 297 var b bytes.Buffer 298 if err = tlvStream.Encode(&b); err != nil { 299 return err 300 } 301 302 err = binary.Write(w, byteOrder, uint64(b.Len())) 303 if err != nil { 304 return err 305 } 306 307 if _, err = w.Write(b.Bytes()); err != nil { 308 return err 309 } 310 311 return serializeHtlcs(w, i.Htlcs) 312 } 313 314 // serializeHtlcs writes a serialized list of invoice htlcs into a writer. 315 func serializeHtlcs(w io.Writer, htlcs []byte) error { 316 _, err := w.Write(htlcs) 317 return err 318 }