github.com/decred/dcrlnd@v0.7.6/channeldb/migration_01_to_11/payments.go (about)

     1  package migration_01_to_11
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"errors"
     7  	"fmt"
     8  	"io"
     9  	"sort"
    10  	"time"
    11  
    12  	"github.com/decred/dcrd/dcrec/secp256k1/v4"
    13  	"github.com/decred/dcrd/wire"
    14  	lnwire "github.com/decred/dcrlnd/channeldb/migration/lnwire21"
    15  	"github.com/decred/dcrlnd/kvdb"
    16  	"github.com/decred/dcrlnd/lntypes"
    17  	"github.com/decred/dcrlnd/tlv"
    18  )
    19  
    20  var (
    21  	// paymentsRootBucket is the name of the top-level bucket within the
    22  	// database that stores all data related to payments. Within this
    23  	// bucket, each payment hash its own sub-bucket keyed by its payment
    24  	// hash.
    25  	//
    26  	// Bucket hierarchy:
    27  	//
    28  	// root-bucket
    29  	//      |
    30  	//      |-- <paymenthash>
    31  	//      |        |--sequence-key: <sequence number>
    32  	//      |        |--creation-info-key: <creation info>
    33  	//      |        |--attempt-info-key: <attempt info>
    34  	//      |        |--settle-info-key: <settle info>
    35  	//      |        |--fail-info-key: <fail info>
    36  	//      |        |
    37  	//      |        |--duplicate-bucket (only for old, completed payments)
    38  	//      |                 |
    39  	//      |                 |-- <seq-num>
    40  	//      |                 |       |--sequence-key: <sequence number>
    41  	//      |                 |       |--creation-info-key: <creation info>
    42  	//      |                 |       |--attempt-info-key: <attempt info>
    43  	//      |                 |       |--settle-info-key: <settle info>
    44  	//      |                 |       |--fail-info-key: <fail info>
    45  	//      |                 |
    46  	//      |                 |-- <seq-num>
    47  	//      |                 |       |
    48  	//      |                ...     ...
    49  	//      |
    50  	//      |-- <paymenthash>
    51  	//      |        |
    52  	//      |       ...
    53  	//     ...
    54  	//
    55  	paymentsRootBucket = []byte("payments-root-bucket")
    56  
    57  	// paymentDublicateBucket is the name of a optional sub-bucket within
    58  	// the payment hash bucket, that is used to hold duplicate payments to
    59  	// a payment hash. This is needed to support information from earlier
    60  	// versions of lnd, where it was possible to pay to a payment hash more
    61  	// than once.
    62  	paymentDuplicateBucket = []byte("payment-duplicate-bucket")
    63  
    64  	// paymentSequenceKey is a key used in the payment's sub-bucket to
    65  	// store the sequence number of the payment.
    66  	paymentSequenceKey = []byte("payment-sequence-key")
    67  
    68  	// paymentCreationInfoKey is a key used in the payment's sub-bucket to
    69  	// store the creation info of the payment.
    70  	paymentCreationInfoKey = []byte("payment-creation-info")
    71  
    72  	// paymentAttemptInfoKey is a key used in the payment's sub-bucket to
    73  	// store the info about the latest attempt that was done for the
    74  	// payment in question.
    75  	paymentAttemptInfoKey = []byte("payment-attempt-info")
    76  
    77  	// paymentSettleInfoKey is a key used in the payment's sub-bucket to
    78  	// store the settle info of the payment.
    79  	paymentSettleInfoKey = []byte("payment-settle-info")
    80  
    81  	// paymentFailInfoKey is a key used in the payment's sub-bucket to
    82  	// store information about the reason a payment failed.
    83  	paymentFailInfoKey = []byte("payment-fail-info")
    84  )
    85  
    86  // FailureReason encodes the reason a payment ultimately failed.
    87  type FailureReason byte
    88  
    89  const (
    90  	// FailureReasonTimeout indicates that the payment did timeout before a
    91  	// successful payment attempt was made.
    92  	FailureReasonTimeout FailureReason = 0
    93  
    94  	// FailureReasonNoRoute indicates no successful route to the
    95  	// destination was found during path finding.
    96  	FailureReasonNoRoute FailureReason = 1
    97  
    98  	// FailureReasonError indicates that an unexpected error happened during
    99  	// payment.
   100  	FailureReasonError FailureReason = 2
   101  
   102  	// FailureReasonIncorrectPaymentDetails indicates that either the hash
   103  	// is unknown or the final cltv delta or amount is incorrect.
   104  	FailureReasonIncorrectPaymentDetails FailureReason = 3
   105  
   106  	// TODO(halseth): cancel state.
   107  
   108  	// TODO(joostjager): Add failure reasons for:
   109  	// LocalLiquidityInsufficient, RemoteCapacityInsufficient.
   110  )
   111  
   112  // String returns a human readable FailureReason
   113  func (r FailureReason) String() string {
   114  	switch r {
   115  	case FailureReasonTimeout:
   116  		return "timeout"
   117  	case FailureReasonNoRoute:
   118  		return "no_route"
   119  	case FailureReasonError:
   120  		return "error"
   121  	case FailureReasonIncorrectPaymentDetails:
   122  		return "incorrect_payment_details"
   123  	}
   124  
   125  	return "unknown"
   126  }
   127  
   128  // PaymentStatus represent current status of payment
   129  type PaymentStatus byte
   130  
   131  const (
   132  	// StatusUnknown is the status where a payment has never been initiated
   133  	// and hence is unknown.
   134  	StatusUnknown PaymentStatus = 0
   135  
   136  	// StatusInFlight is the status where a payment has been initiated, but
   137  	// a response has not been received.
   138  	StatusInFlight PaymentStatus = 1
   139  
   140  	// StatusSucceeded is the status where a payment has been initiated and
   141  	// the payment was completed successfully.
   142  	StatusSucceeded PaymentStatus = 2
   143  
   144  	// StatusFailed is the status where a payment has been initiated and a
   145  	// failure result has come back.
   146  	StatusFailed PaymentStatus = 3
   147  )
   148  
   149  // Bytes returns status as slice of bytes.
   150  func (ps PaymentStatus) Bytes() []byte {
   151  	return []byte{byte(ps)}
   152  }
   153  
   154  // FromBytes sets status from slice of bytes.
   155  func (ps *PaymentStatus) FromBytes(status []byte) error {
   156  	if len(status) != 1 {
   157  		return errors.New("payment status is empty")
   158  	}
   159  
   160  	switch PaymentStatus(status[0]) {
   161  	case StatusUnknown, StatusInFlight, StatusSucceeded, StatusFailed:
   162  		*ps = PaymentStatus(status[0])
   163  	default:
   164  		return errors.New("unknown payment status")
   165  	}
   166  
   167  	return nil
   168  }
   169  
   170  // String returns readable representation of payment status.
   171  func (ps PaymentStatus) String() string {
   172  	switch ps {
   173  	case StatusUnknown:
   174  		return "Unknown"
   175  	case StatusInFlight:
   176  		return "In Flight"
   177  	case StatusSucceeded:
   178  		return "Succeeded"
   179  	case StatusFailed:
   180  		return "Failed"
   181  	default:
   182  		return "Unknown"
   183  	}
   184  }
   185  
   186  // PaymentCreationInfo is the information necessary to have ready when
   187  // initiating a payment, moving it into state InFlight.
   188  type PaymentCreationInfo struct {
   189  	// PaymentHash is the hash this payment is paying to.
   190  	PaymentHash lntypes.Hash
   191  
   192  	// Value is the amount we are paying.
   193  	Value lnwire.MilliAtom
   194  
   195  	// CreatingDate is the time when this payment was initiated.
   196  	CreationDate time.Time
   197  
   198  	// PaymentRequest is the full payment request, if any.
   199  	PaymentRequest []byte
   200  }
   201  
   202  // PaymentAttemptInfo contains information about a specific payment attempt for
   203  // a given payment. This information is used by the router to handle any errors
   204  // coming back after an attempt is made, and to query the switch about the
   205  // status of a payment. For settled payment this will be the information for
   206  // the succeeding payment attempt.
   207  type PaymentAttemptInfo struct {
   208  	// PaymentID is the unique ID used for this attempt.
   209  	PaymentID uint64
   210  
   211  	// SessionKey is the ephemeral key used for this payment attempt.
   212  	SessionKey *secp256k1.PrivateKey
   213  
   214  	// Route is the route attempted to send the HTLC.
   215  	Route Route
   216  }
   217  
   218  // Payment is a wrapper around a payment's PaymentCreationInfo,
   219  // PaymentAttemptInfo, and preimage. All payments will have the
   220  // PaymentCreationInfo set, the PaymentAttemptInfo will be set only if at least
   221  // one payment attempt has been made, while only completed payments will have a
   222  // non-zero payment preimage.
   223  type Payment struct {
   224  	// sequenceNum is a unique identifier used to sort the payments in
   225  	// order of creation.
   226  	sequenceNum uint64
   227  
   228  	// Status is the current PaymentStatus of this payment.
   229  	Status PaymentStatus
   230  
   231  	// Info holds all static information about this payment, and is
   232  	// populated when the payment is initiated.
   233  	Info *PaymentCreationInfo
   234  
   235  	// Attempt is the information about the last payment attempt made.
   236  	//
   237  	// NOTE: Can be nil if no attempt is yet made.
   238  	Attempt *PaymentAttemptInfo
   239  
   240  	// PaymentPreimage is the preimage of a successful payment. This serves
   241  	// as a proof of payment. It will only be non-nil for settled payments.
   242  	//
   243  	// NOTE: Can be nil if payment is not settled.
   244  	PaymentPreimage *lntypes.Preimage
   245  
   246  	// Failure is a failure reason code indicating the reason the payment
   247  	// failed. It is only non-nil for failed payments.
   248  	//
   249  	// NOTE: Can be nil if payment is not failed.
   250  	Failure *FailureReason
   251  }
   252  
   253  // FetchPayments returns all sent payments found in the DB.
   254  func (db *DB) FetchPayments() ([]*Payment, error) {
   255  	var payments []*Payment
   256  
   257  	err := kvdb.View(db, func(tx kvdb.RTx) error {
   258  		paymentsBucket := tx.ReadBucket(paymentsRootBucket)
   259  		if paymentsBucket == nil {
   260  			return nil
   261  		}
   262  
   263  		return paymentsBucket.ForEach(func(k, v []byte) error {
   264  			bucket := paymentsBucket.NestedReadBucket(k)
   265  			if bucket == nil {
   266  				// We only expect sub-buckets to be found in
   267  				// this top-level bucket.
   268  				return fmt.Errorf("non bucket element in " +
   269  					"payments bucket")
   270  			}
   271  
   272  			p, err := fetchPayment(bucket)
   273  			if err != nil {
   274  				return err
   275  			}
   276  
   277  			payments = append(payments, p)
   278  
   279  			// For older versions of lnd, duplicate payments to a
   280  			// payment has was possible. These will be found in a
   281  			// sub-bucket indexed by their sequence number if
   282  			// available.
   283  			dup := bucket.NestedReadBucket(paymentDuplicateBucket)
   284  			if dup == nil {
   285  				return nil
   286  			}
   287  
   288  			return dup.ForEach(func(k, v []byte) error {
   289  				subBucket := dup.NestedReadBucket(k)
   290  				if subBucket == nil {
   291  					// We one bucket for each duplicate to
   292  					// be found.
   293  					return fmt.Errorf("non bucket element" +
   294  						"in duplicate bucket")
   295  				}
   296  
   297  				p, err := fetchPayment(subBucket)
   298  				if err != nil {
   299  					return err
   300  				}
   301  
   302  				payments = append(payments, p)
   303  				return nil
   304  			})
   305  		})
   306  	}, func() {
   307  		payments = nil
   308  	})
   309  	if err != nil {
   310  		return nil, err
   311  	}
   312  
   313  	// Before returning, sort the payments by their sequence number.
   314  	sort.Slice(payments, func(i, j int) bool {
   315  		return payments[i].sequenceNum < payments[j].sequenceNum
   316  	})
   317  
   318  	return payments, nil
   319  }
   320  
   321  func fetchPayment(bucket kvdb.RBucket) (*Payment, error) {
   322  	var (
   323  		err error
   324  		p   = &Payment{}
   325  	)
   326  
   327  	seqBytes := bucket.Get(paymentSequenceKey)
   328  	if seqBytes == nil {
   329  		return nil, fmt.Errorf("sequence number not found")
   330  	}
   331  
   332  	p.sequenceNum = binary.BigEndian.Uint64(seqBytes)
   333  
   334  	// Get the payment status.
   335  	p.Status = fetchPaymentStatus(bucket)
   336  
   337  	// Get the PaymentCreationInfo.
   338  	b := bucket.Get(paymentCreationInfoKey)
   339  	if b == nil {
   340  		return nil, fmt.Errorf("creation info not found")
   341  	}
   342  
   343  	r := bytes.NewReader(b)
   344  	p.Info, err = deserializePaymentCreationInfo(r)
   345  	if err != nil {
   346  		return nil, err
   347  
   348  	}
   349  
   350  	// Get the PaymentAttemptInfo. This can be unset.
   351  	b = bucket.Get(paymentAttemptInfoKey)
   352  	if b != nil {
   353  		r = bytes.NewReader(b)
   354  		p.Attempt, err = deserializePaymentAttemptInfo(r)
   355  		if err != nil {
   356  			return nil, err
   357  		}
   358  	}
   359  
   360  	// Get the payment preimage. This is only found for
   361  	// completed payments.
   362  	b = bucket.Get(paymentSettleInfoKey)
   363  	if b != nil {
   364  		var preimg lntypes.Preimage
   365  		copy(preimg[:], b[:])
   366  		p.PaymentPreimage = &preimg
   367  	}
   368  
   369  	// Get failure reason if available.
   370  	b = bucket.Get(paymentFailInfoKey)
   371  	if b != nil {
   372  		reason := FailureReason(b[0])
   373  		p.Failure = &reason
   374  	}
   375  
   376  	return p, nil
   377  }
   378  
   379  func serializePaymentCreationInfo(w io.Writer, c *PaymentCreationInfo) error {
   380  	var scratch [8]byte
   381  
   382  	if _, err := w.Write(c.PaymentHash[:]); err != nil {
   383  		return err
   384  	}
   385  
   386  	byteOrder.PutUint64(scratch[:], uint64(c.Value))
   387  	if _, err := w.Write(scratch[:]); err != nil {
   388  		return err
   389  	}
   390  
   391  	byteOrder.PutUint64(scratch[:], uint64(c.CreationDate.Unix()))
   392  	if _, err := w.Write(scratch[:]); err != nil {
   393  		return err
   394  	}
   395  
   396  	byteOrder.PutUint32(scratch[:4], uint32(len(c.PaymentRequest)))
   397  	if _, err := w.Write(scratch[:4]); err != nil {
   398  		return err
   399  	}
   400  
   401  	if _, err := w.Write(c.PaymentRequest[:]); err != nil {
   402  		return err
   403  	}
   404  
   405  	return nil
   406  }
   407  
   408  func deserializePaymentCreationInfo(r io.Reader) (*PaymentCreationInfo, error) {
   409  	var scratch [8]byte
   410  
   411  	c := &PaymentCreationInfo{}
   412  
   413  	if _, err := io.ReadFull(r, c.PaymentHash[:]); err != nil {
   414  		return nil, err
   415  	}
   416  
   417  	if _, err := io.ReadFull(r, scratch[:]); err != nil {
   418  		return nil, err
   419  	}
   420  	c.Value = lnwire.MilliAtom(byteOrder.Uint64(scratch[:]))
   421  
   422  	if _, err := io.ReadFull(r, scratch[:]); err != nil {
   423  		return nil, err
   424  	}
   425  	c.CreationDate = time.Unix(int64(byteOrder.Uint64(scratch[:])), 0)
   426  
   427  	if _, err := io.ReadFull(r, scratch[:4]); err != nil {
   428  		return nil, err
   429  	}
   430  
   431  	reqLen := byteOrder.Uint32(scratch[:4])
   432  	payReq := make([]byte, reqLen)
   433  	if reqLen > 0 {
   434  		if _, err := io.ReadFull(r, payReq[:]); err != nil {
   435  			return nil, err
   436  		}
   437  	}
   438  	c.PaymentRequest = payReq
   439  
   440  	return c, nil
   441  }
   442  
   443  func serializePaymentAttemptInfo(w io.Writer, a *PaymentAttemptInfo) error {
   444  	if err := WriteElements(w, a.PaymentID, a.SessionKey); err != nil {
   445  		return err
   446  	}
   447  
   448  	if err := SerializeRoute(w, a.Route); err != nil {
   449  		return err
   450  	}
   451  
   452  	return nil
   453  }
   454  
   455  func deserializePaymentAttemptInfo(r io.Reader) (*PaymentAttemptInfo, error) {
   456  	a := &PaymentAttemptInfo{}
   457  	err := ReadElements(r, &a.PaymentID, &a.SessionKey)
   458  	if err != nil {
   459  		return nil, err
   460  	}
   461  	a.Route, err = DeserializeRoute(r)
   462  	if err != nil {
   463  		return nil, err
   464  	}
   465  	return a, nil
   466  }
   467  
   468  func serializeHop(w io.Writer, h *Hop) error {
   469  	if err := WriteElements(w,
   470  		h.PubKeyBytes[:], h.ChannelID, h.OutgoingTimeLock,
   471  		h.AmtToForward,
   472  	); err != nil {
   473  		return err
   474  	}
   475  
   476  	if err := binary.Write(w, byteOrder, h.LegacyPayload); err != nil {
   477  		return err
   478  	}
   479  
   480  	// For legacy payloads, we don't need to write any TLV records, so
   481  	// we'll write a zero indicating the our serialized TLV map has no
   482  	// records.
   483  	if h.LegacyPayload {
   484  		return WriteElements(w, uint32(0))
   485  	}
   486  
   487  	// Otherwise, we'll transform our slice of records into a map of the
   488  	// raw bytes, then serialize them in-line with a length (number of
   489  	// elements) prefix.
   490  	mapRecords, err := tlv.RecordsToMap(h.TLVRecords)
   491  	if err != nil {
   492  		return err
   493  	}
   494  
   495  	numRecords := uint32(len(mapRecords))
   496  	if err := WriteElements(w, numRecords); err != nil {
   497  		return err
   498  	}
   499  
   500  	for recordType, rawBytes := range mapRecords {
   501  		if err := WriteElements(w, recordType); err != nil {
   502  			return err
   503  		}
   504  
   505  		if err := wire.WriteVarBytes(w, 0, rawBytes); err != nil {
   506  			return err
   507  		}
   508  	}
   509  
   510  	return nil
   511  }
   512  
   513  // maxOnionPayloadSize is the largest Sphinx payload possible, so we don't need
   514  // to read/write a TLV stream larger than this.
   515  const maxOnionPayloadSize = 1300
   516  
   517  func deserializeHop(r io.Reader) (*Hop, error) {
   518  	h := &Hop{}
   519  
   520  	var pub []byte
   521  	if err := ReadElements(r, &pub); err != nil {
   522  		return nil, err
   523  	}
   524  	copy(h.PubKeyBytes[:], pub)
   525  
   526  	if err := ReadElements(r,
   527  		&h.ChannelID, &h.OutgoingTimeLock, &h.AmtToForward,
   528  	); err != nil {
   529  		return nil, err
   530  	}
   531  
   532  	// TODO(roasbeef): change field to allow LegacyPayload false to be the
   533  	// legacy default?
   534  	err := binary.Read(r, byteOrder, &h.LegacyPayload)
   535  	if err != nil {
   536  		return nil, err
   537  	}
   538  
   539  	var numElements uint32
   540  	if err := ReadElements(r, &numElements); err != nil {
   541  		return nil, err
   542  	}
   543  
   544  	// If there're no elements, then we can return early.
   545  	if numElements == 0 {
   546  		return h, nil
   547  	}
   548  
   549  	tlvMap := make(map[uint64][]byte)
   550  	for i := uint32(0); i < numElements; i++ {
   551  		var tlvType uint64
   552  		if err := ReadElements(r, &tlvType); err != nil {
   553  			return nil, err
   554  		}
   555  
   556  		rawRecordBytes, err := wire.ReadVarBytes(
   557  			r, 0, maxOnionPayloadSize, "tlv",
   558  		)
   559  		if err != nil {
   560  			return nil, err
   561  		}
   562  
   563  		tlvMap[tlvType] = rawRecordBytes
   564  	}
   565  
   566  	h.TLVRecords = tlv.MapToRecords(tlvMap)
   567  
   568  	return h, nil
   569  }
   570  
   571  // SerializeRoute serializes a route.
   572  func SerializeRoute(w io.Writer, r Route) error {
   573  	if err := WriteElements(w,
   574  		r.TotalTimeLock, r.TotalAmount, r.SourcePubKey[:],
   575  	); err != nil {
   576  		return err
   577  	}
   578  
   579  	if err := WriteElements(w, uint32(len(r.Hops))); err != nil {
   580  		return err
   581  	}
   582  
   583  	for _, h := range r.Hops {
   584  		if err := serializeHop(w, h); err != nil {
   585  			return err
   586  		}
   587  	}
   588  
   589  	return nil
   590  }
   591  
   592  // DeserializeRoute deserializes a route.
   593  func DeserializeRoute(r io.Reader) (Route, error) {
   594  	rt := Route{}
   595  	if err := ReadElements(r,
   596  		&rt.TotalTimeLock, &rt.TotalAmount,
   597  	); err != nil {
   598  		return rt, err
   599  	}
   600  
   601  	var pub []byte
   602  	if err := ReadElements(r, &pub); err != nil {
   603  		return rt, err
   604  	}
   605  	copy(rt.SourcePubKey[:], pub)
   606  
   607  	var numHops uint32
   608  	if err := ReadElements(r, &numHops); err != nil {
   609  		return rt, err
   610  	}
   611  
   612  	var hops []*Hop
   613  	for i := uint32(0); i < numHops; i++ {
   614  		hop, err := deserializeHop(r)
   615  		if err != nil {
   616  			return rt, err
   617  		}
   618  		hops = append(hops, hop)
   619  	}
   620  	rt.Hops = hops
   621  
   622  	return rt, nil
   623  }