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  }