github.com/decred/dcrlnd@v0.7.6/channeldb/migration_01_to_11/invoices.go (about) 1 package migration_01_to_11 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "fmt" 7 "io" 8 "time" 9 10 "github.com/decred/dcrd/wire" 11 lnwire "github.com/decred/dcrlnd/channeldb/migration/lnwire21" 12 "github.com/decred/dcrlnd/kvdb" 13 "github.com/decred/dcrlnd/lntypes" 14 "github.com/decred/dcrlnd/tlv" 15 ) 16 17 var ( 18 19 // invoiceBucket is the name of the bucket within the database that 20 // stores all data related to invoices no matter their final state. 21 // Within the invoice bucket, each invoice is keyed by its invoice ID 22 // which is a monotonically increasing uint32. 23 invoiceBucket = []byte("invoices") 24 25 // addIndexBucket is an index bucket that we'll use to create a 26 // monotonically increasing set of add indexes. Each time we add a new 27 // invoice, this sequence number will be incremented and then populated 28 // within the new invoice. 29 // 30 // In addition to this sequence number, we map: 31 // 32 // addIndexNo => invoiceKey 33 addIndexBucket = []byte("invoice-add-index") 34 35 // settleIndexBucket is an index bucket that we'll use to create a 36 // monotonically increasing integer for tracking a "settle index". Each 37 // time an invoice is settled, this sequence number will be incremented 38 // as populate within the newly settled invoice. 39 // 40 // In addition to this sequence number, we map: 41 // 42 // settleIndexNo => invoiceKey 43 settleIndexBucket = []byte("invoice-settle-index") 44 ) 45 46 const ( 47 // MaxMemoSize is maximum size of the memo field within invoices stored 48 // in the database. 49 MaxMemoSize = 1024 50 51 // MaxReceiptSize is the maximum size of the payment receipt stored 52 // within the database along side incoming/outgoing invoices. 53 MaxReceiptSize = 1024 54 55 // MaxPaymentRequestSize is the max size of a payment request for 56 // this invoice. 57 // TODO(halseth): determine the max length payment request when field 58 // lengths are final. 59 MaxPaymentRequestSize = 4096 60 61 // A set of tlv type definitions used to serialize invoice htlcs to the 62 // database. 63 chanIDType tlv.Type = 1 64 htlcIDType tlv.Type = 3 65 amtType tlv.Type = 5 66 acceptHeightType tlv.Type = 7 67 acceptTimeType tlv.Type = 9 68 resolveTimeType tlv.Type = 11 69 expiryHeightType tlv.Type = 13 70 stateType tlv.Type = 15 71 ) 72 73 // ContractState describes the state the invoice is in. 74 type ContractState uint8 75 76 const ( 77 // ContractOpen means the invoice has only been created. 78 ContractOpen ContractState = 0 79 80 // ContractSettled means the htlc is settled and the invoice has been 81 // paid. 82 ContractSettled ContractState = 1 83 84 // ContractCanceled means the invoice has been canceled. 85 ContractCanceled ContractState = 2 86 87 // ContractAccepted means the HTLC has been accepted but not settled 88 // yet. 89 ContractAccepted ContractState = 3 90 ) 91 92 // String returns a human readable identifier for the ContractState type. 93 func (c ContractState) String() string { 94 switch c { 95 case ContractOpen: 96 return "Open" 97 case ContractSettled: 98 return "Settled" 99 case ContractCanceled: 100 return "Canceled" 101 case ContractAccepted: 102 return "Accepted" 103 } 104 105 return "Unknown" 106 } 107 108 // ContractTerm is a companion struct to the Invoice struct. This struct houses 109 // the necessary conditions required before the invoice can be considered fully 110 // settled by the payee. 111 type ContractTerm struct { 112 // PaymentPreimage is the preimage which is to be revealed in the 113 // occasion that an HTLC paying to the hash of this preimage is 114 // extended. 115 PaymentPreimage lntypes.Preimage 116 117 // Value is the expected amount of milli-atoms to be paid to an HTLC 118 // which can be satisfied by the above preimage. 119 Value lnwire.MilliAtom 120 121 // State describes the state the invoice is in. 122 State ContractState 123 } 124 125 // Invoice is a payment invoice generated by a payee in order to request 126 // payment for some good or service. The inclusion of invoices within Lightning 127 // creates a payment work flow for merchants very similar to that of the 128 // existing financial system within PayPal, etc. Invoices are added to the 129 // database when a payment is requested, then can be settled manually once the 130 // payment is received at the upper layer. For record keeping purposes, 131 // invoices are never deleted from the database, instead a bit is toggled 132 // denoting the invoice has been fully settled. Within the database, all 133 // invoices must have a unique payment hash which is generated by taking the 134 // chainhash of the payment preimage. 135 type Invoice struct { 136 // Memo is an optional memo to be stored along side an invoice. The 137 // memo may contain further details pertaining to the invoice itself, 138 // or any other message which fits within the size constraints. 139 Memo []byte 140 141 // Receipt is an optional field dedicated for storing a 142 // cryptographically binding receipt of payment. 143 // 144 // TODO(roasbeef): document scheme. 145 Receipt []byte 146 147 // PaymentRequest is an optional field where a payment request created 148 // for this invoice can be stored. 149 PaymentRequest []byte 150 151 // FinalCltvDelta is the minimum required number of blocks before htlc 152 // expiry when the invoice is accepted. 153 FinalCltvDelta int32 154 155 // Expiry defines how long after creation this invoice should expire. 156 Expiry time.Duration 157 158 // CreationDate is the exact time the invoice was created. 159 CreationDate time.Time 160 161 // SettleDate is the exact time the invoice was settled. 162 SettleDate time.Time 163 164 // Terms are the contractual payment terms of the invoice. Once all the 165 // terms have been satisfied by the payer, then the invoice can be 166 // considered fully fulfilled. 167 // 168 // TODO(roasbeef): later allow for multiple terms to fulfill the final 169 // invoice: payment fragmentation, etc. 170 Terms ContractTerm 171 172 // AddIndex is an auto-incrementing integer that acts as a 173 // monotonically increasing sequence number for all invoices created. 174 // Clients can then use this field as a "checkpoint" of sorts when 175 // implementing a streaming RPC to notify consumers of instances where 176 // an invoice has been added before they re-connected. 177 // 178 // NOTE: This index starts at 1. 179 AddIndex uint64 180 181 // SettleIndex is an auto-incrementing integer that acts as a 182 // monotonically increasing sequence number for all settled invoices. 183 // Clients can then use this field as a "checkpoint" of sorts when 184 // implementing a streaming RPC to notify consumers of instances where 185 // an invoice has been settled before they re-connected. 186 // 187 // NOTE: This index starts at 1. 188 SettleIndex uint64 189 190 // AmtPaid is the final amount that we ultimately accepted for pay for 191 // this invoice. We specify this value independently as it's possible 192 // that the invoice originally didn't specify an amount, or the sender 193 // overpaid. 194 AmtPaid lnwire.MilliAtom 195 196 // Htlcs records all htlcs that paid to this invoice. Some of these 197 // htlcs may have been marked as canceled. 198 Htlcs map[CircuitKey]*InvoiceHTLC 199 } 200 201 // HtlcState defines the states an htlc paying to an invoice can be in. 202 type HtlcState uint8 203 204 // InvoiceHTLC contains details about an htlc paying to this invoice. 205 type InvoiceHTLC struct { 206 // Amt is the amount that is carried by this htlc. 207 Amt lnwire.MilliAtom 208 209 // AcceptHeight is the block height at which the invoice registry 210 // decided to accept this htlc as a payment to the invoice. At this 211 // height, the invoice cltv delay must have been met. 212 AcceptHeight uint32 213 214 // AcceptTime is the wall clock time at which the invoice registry 215 // decided to accept the htlc. 216 AcceptTime time.Time 217 218 // ResolveTime is the wall clock time at which the invoice registry 219 // decided to settle the htlc. 220 ResolveTime time.Time 221 222 // Expiry is the expiry height of this htlc. 223 Expiry uint32 224 225 // State indicates the state the invoice htlc is currently in. A 226 // canceled htlc isn't just removed from the invoice htlcs map, because 227 // we need AcceptHeight to properly cancel the htlc back. 228 State HtlcState 229 } 230 231 func validateInvoice(i *Invoice) error { 232 if len(i.Memo) > MaxMemoSize { 233 return fmt.Errorf("max length a memo is %v, and invoice "+ 234 "of length %v was provided", MaxMemoSize, len(i.Memo)) 235 } 236 if len(i.Receipt) > MaxReceiptSize { 237 return fmt.Errorf("max length a receipt is %v, and invoice "+ 238 "of length %v was provided", MaxReceiptSize, 239 len(i.Receipt)) 240 } 241 if len(i.PaymentRequest) > MaxPaymentRequestSize { 242 return fmt.Errorf("max length of payment request is %v, length "+ 243 "provided was %v", MaxPaymentRequestSize, 244 len(i.PaymentRequest)) 245 } 246 return nil 247 } 248 249 // FetchAllInvoices returns all invoices currently stored within the database. 250 // If the pendingOnly param is true, then only unsettled invoices will be 251 // returned, skipping all invoices that are fully settled. 252 func (d *DB) FetchAllInvoices(pendingOnly bool) ([]Invoice, error) { 253 var invoices []Invoice 254 255 err := kvdb.View(d, func(tx kvdb.RTx) error { 256 invoiceB := tx.ReadBucket(invoiceBucket) 257 if invoiceB == nil { 258 return ErrNoInvoicesCreated 259 } 260 261 // Iterate through the entire key space of the top-level 262 // invoice bucket. If key with a non-nil value stores the next 263 // invoice ID which maps to the corresponding invoice. 264 return invoiceB.ForEach(func(k, v []byte) error { 265 if v == nil { 266 return nil 267 } 268 269 invoiceReader := bytes.NewReader(v) 270 invoice, err := deserializeInvoice(invoiceReader) 271 if err != nil { 272 return err 273 } 274 275 if pendingOnly && 276 invoice.Terms.State == ContractSettled { 277 278 return nil 279 } 280 281 invoices = append(invoices, invoice) 282 283 return nil 284 }) 285 }, func() { 286 invoices = nil 287 }) 288 if err != nil { 289 return nil, err 290 } 291 292 return invoices, nil 293 } 294 295 // serializeInvoice serializes an invoice to a writer. 296 // 297 // Note: this function is in use for a migration. Before making changes that 298 // would modify the on disk format, make a copy of the original code and store 299 // it with the migration. 300 func serializeInvoice(w io.Writer, i *Invoice) error { 301 if err := wire.WriteVarBytes(w, 0, i.Memo); err != nil { 302 return err 303 } 304 if err := wire.WriteVarBytes(w, 0, i.Receipt); err != nil { 305 return err 306 } 307 if err := wire.WriteVarBytes(w, 0, i.PaymentRequest); err != nil { 308 return err 309 } 310 311 if err := binary.Write(w, byteOrder, i.FinalCltvDelta); err != nil { 312 return err 313 } 314 315 if err := binary.Write(w, byteOrder, int64(i.Expiry)); err != nil { 316 return err 317 } 318 319 birthBytes, err := i.CreationDate.MarshalBinary() 320 if err != nil { 321 return err 322 } 323 324 if err := wire.WriteVarBytes(w, 0, birthBytes); err != nil { 325 return err 326 } 327 328 settleBytes, err := i.SettleDate.MarshalBinary() 329 if err != nil { 330 return err 331 } 332 333 if err := wire.WriteVarBytes(w, 0, settleBytes); err != nil { 334 return err 335 } 336 337 if _, err := w.Write(i.Terms.PaymentPreimage[:]); err != nil { 338 return err 339 } 340 341 var scratch [8]byte 342 byteOrder.PutUint64(scratch[:], uint64(i.Terms.Value)) 343 if _, err := w.Write(scratch[:]); err != nil { 344 return err 345 } 346 347 if err := binary.Write(w, byteOrder, i.Terms.State); err != nil { 348 return err 349 } 350 351 if err := binary.Write(w, byteOrder, i.AddIndex); err != nil { 352 return err 353 } 354 if err := binary.Write(w, byteOrder, i.SettleIndex); err != nil { 355 return err 356 } 357 if err := binary.Write(w, byteOrder, int64(i.AmtPaid)); err != nil { 358 return err 359 } 360 361 if err := serializeHtlcs(w, i.Htlcs); err != nil { 362 return err 363 } 364 365 return nil 366 } 367 368 // serializeHtlcs serializes a map containing circuit keys and invoice htlcs to 369 // a writer. 370 func serializeHtlcs(w io.Writer, htlcs map[CircuitKey]*InvoiceHTLC) error { 371 for key, htlc := range htlcs { 372 // Encode the htlc in a tlv stream. 373 chanID := key.ChanID.ToUint64() 374 amt := uint64(htlc.Amt) 375 acceptTime := uint64(htlc.AcceptTime.UnixNano()) 376 resolveTime := uint64(htlc.ResolveTime.UnixNano()) 377 state := uint8(htlc.State) 378 379 tlvStream, err := tlv.NewStream( 380 tlv.MakePrimitiveRecord(chanIDType, &chanID), 381 tlv.MakePrimitiveRecord(htlcIDType, &key.HtlcID), 382 tlv.MakePrimitiveRecord(amtType, &amt), 383 tlv.MakePrimitiveRecord( 384 acceptHeightType, &htlc.AcceptHeight, 385 ), 386 tlv.MakePrimitiveRecord(acceptTimeType, &acceptTime), 387 tlv.MakePrimitiveRecord(resolveTimeType, &resolveTime), 388 tlv.MakePrimitiveRecord(expiryHeightType, &htlc.Expiry), 389 tlv.MakePrimitiveRecord(stateType, &state), 390 ) 391 if err != nil { 392 return err 393 } 394 395 var b bytes.Buffer 396 if err := tlvStream.Encode(&b); err != nil { 397 return err 398 } 399 400 // Write the length of the tlv stream followed by the stream 401 // bytes. 402 err = binary.Write(w, byteOrder, uint64(b.Len())) 403 if err != nil { 404 return err 405 } 406 407 if _, err := w.Write(b.Bytes()); err != nil { 408 return err 409 } 410 } 411 412 return nil 413 } 414 415 func deserializeInvoice(r io.Reader) (Invoice, error) { 416 var err error 417 invoice := Invoice{} 418 419 // TODO(roasbeef): use read full everywhere 420 invoice.Memo, err = wire.ReadVarBytes(r, 0, MaxMemoSize, "") 421 if err != nil { 422 return invoice, err 423 } 424 invoice.Receipt, err = wire.ReadVarBytes(r, 0, MaxReceiptSize, "") 425 if err != nil { 426 return invoice, err 427 } 428 429 invoice.PaymentRequest, err = wire.ReadVarBytes(r, 0, MaxPaymentRequestSize, "") 430 if err != nil { 431 return invoice, err 432 } 433 434 if err := binary.Read(r, byteOrder, &invoice.FinalCltvDelta); err != nil { 435 return invoice, err 436 } 437 438 var expiry int64 439 if err := binary.Read(r, byteOrder, &expiry); err != nil { 440 return invoice, err 441 } 442 invoice.Expiry = time.Duration(expiry) 443 444 birthBytes, err := wire.ReadVarBytes(r, 0, 300, "birth") 445 if err != nil { 446 return invoice, err 447 } 448 if err := invoice.CreationDate.UnmarshalBinary(birthBytes); err != nil { 449 return invoice, err 450 } 451 452 settledBytes, err := wire.ReadVarBytes(r, 0, 300, "settled") 453 if err != nil { 454 return invoice, err 455 } 456 if err := invoice.SettleDate.UnmarshalBinary(settledBytes); err != nil { 457 return invoice, err 458 } 459 460 if _, err := io.ReadFull(r, invoice.Terms.PaymentPreimage[:]); err != nil { 461 return invoice, err 462 } 463 var scratch [8]byte 464 if _, err := io.ReadFull(r, scratch[:]); err != nil { 465 return invoice, err 466 } 467 invoice.Terms.Value = lnwire.MilliAtom(byteOrder.Uint64(scratch[:])) 468 469 if err := binary.Read(r, byteOrder, &invoice.Terms.State); err != nil { 470 return invoice, err 471 } 472 473 if err := binary.Read(r, byteOrder, &invoice.AddIndex); err != nil { 474 return invoice, err 475 } 476 if err := binary.Read(r, byteOrder, &invoice.SettleIndex); err != nil { 477 return invoice, err 478 } 479 if err := binary.Read(r, byteOrder, &invoice.AmtPaid); err != nil { 480 return invoice, err 481 } 482 483 invoice.Htlcs, err = deserializeHtlcs(r) 484 if err != nil { 485 return Invoice{}, err 486 } 487 488 return invoice, nil 489 } 490 491 // deserializeHtlcs reads a list of invoice htlcs from a reader and returns it 492 // as a map. 493 func deserializeHtlcs(r io.Reader) (map[CircuitKey]*InvoiceHTLC, error) { 494 htlcs := make(map[CircuitKey]*InvoiceHTLC) 495 496 for { 497 // Read the length of the tlv stream for this htlc. 498 var streamLen uint64 499 if err := binary.Read(r, byteOrder, &streamLen); err != nil { 500 if err == io.EOF { 501 break 502 } 503 504 return nil, err 505 } 506 507 streamBytes := make([]byte, streamLen) 508 if _, err := r.Read(streamBytes); err != nil { 509 return nil, err 510 } 511 streamReader := bytes.NewReader(streamBytes) 512 513 // Decode the contents into the htlc fields. 514 var ( 515 htlc InvoiceHTLC 516 key CircuitKey 517 chanID uint64 518 state uint8 519 acceptTime, resolveTime uint64 520 amt uint64 521 ) 522 tlvStream, err := tlv.NewStream( 523 tlv.MakePrimitiveRecord(chanIDType, &chanID), 524 tlv.MakePrimitiveRecord(htlcIDType, &key.HtlcID), 525 tlv.MakePrimitiveRecord(amtType, &amt), 526 tlv.MakePrimitiveRecord( 527 acceptHeightType, &htlc.AcceptHeight, 528 ), 529 tlv.MakePrimitiveRecord(acceptTimeType, &acceptTime), 530 tlv.MakePrimitiveRecord(resolveTimeType, &resolveTime), 531 tlv.MakePrimitiveRecord(expiryHeightType, &htlc.Expiry), 532 tlv.MakePrimitiveRecord(stateType, &state), 533 ) 534 if err != nil { 535 return nil, err 536 } 537 538 if err := tlvStream.Decode(streamReader); err != nil { 539 return nil, err 540 } 541 542 key.ChanID = lnwire.NewShortChanIDFromInt(chanID) 543 htlc.AcceptTime = time.Unix(0, int64(acceptTime)) 544 htlc.ResolveTime = time.Unix(0, int64(resolveTime)) 545 htlc.State = HtlcState(state) 546 htlc.Amt = lnwire.MilliAtom(amt) 547 548 htlcs[key] = &htlc 549 } 550 551 return htlcs, nil 552 }