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

     1  package channeldb
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"io"
     7  	"time"
     8  
     9  	"github.com/decred/dcrd/dcrec/secp256k1/v4"
    10  	"github.com/decred/dcrd/wire"
    11  	"github.com/decred/dcrlnd/lntypes"
    12  	"github.com/decred/dcrlnd/lnwire"
    13  	"github.com/decred/dcrlnd/routing/route"
    14  )
    15  
    16  // HTLCAttemptInfo contains static information about a specific HTLC attempt
    17  // for a payment. This information is used by the router to handle any errors
    18  // coming back after an attempt is made, and to query the switch about the
    19  // status of the attempt.
    20  type HTLCAttemptInfo struct {
    21  	// AttemptID is the unique ID used for this attempt.
    22  	AttemptID uint64
    23  
    24  	// sessionKey is the raw bytes ephemeral key used for this attempt.
    25  	// These bytes are lazily read off disk to save ourselves the expensive
    26  	// EC operations used by secp256k1.PrivKeyFromBytes.
    27  	sessionKey [secp256k1.PrivKeyBytesLen]byte
    28  
    29  	// cachedSessionKey is our fully deserialized sesionKey. This value
    30  	// may be nil if the attempt has just been read from disk and its
    31  	// session key has not been used yet.
    32  	cachedSessionKey *secp256k1.PrivateKey
    33  
    34  	// Route is the route attempted to send the HTLC.
    35  	Route route.Route
    36  
    37  	// AttemptTime is the time at which this HTLC was attempted.
    38  	AttemptTime time.Time
    39  
    40  	// Hash is the hash used for this single HTLC attempt. For AMP payments
    41  	// this will differ across attempts, for non-AMP payments each attempt
    42  	// will use the same hash. This can be nil for older payment attempts,
    43  	// in which the payment's PaymentHash in the PaymentCreationInfo should
    44  	// be used.
    45  	Hash *lntypes.Hash
    46  }
    47  
    48  // NewHtlcAttemptInfo creates a htlc attempt.
    49  func NewHtlcAttemptInfo(attemptID uint64, sessionKey *secp256k1.PrivateKey,
    50  	route route.Route, attemptTime time.Time,
    51  	hash *lntypes.Hash) *HTLCAttemptInfo {
    52  
    53  	var scratch [secp256k1.PrivKeyBytesLen]byte
    54  	copy(scratch[:], sessionKey.Serialize())
    55  
    56  	return &HTLCAttemptInfo{
    57  		AttemptID:        attemptID,
    58  		sessionKey:       scratch,
    59  		cachedSessionKey: sessionKey,
    60  		Route:            route,
    61  		AttemptTime:      attemptTime,
    62  		Hash:             hash,
    63  	}
    64  }
    65  
    66  // SessionKey returns the ephemeral key used for a htlc attempt. This function
    67  // performs expensive ec-ops to obtain the session key if it is not cached.
    68  func (h *HTLCAttemptInfo) SessionKey() *secp256k1.PrivateKey {
    69  	if h.cachedSessionKey == nil {
    70  		h.cachedSessionKey = secp256k1.PrivKeyFromBytes(
    71  			h.sessionKey[:],
    72  		)
    73  	}
    74  
    75  	return h.cachedSessionKey
    76  }
    77  
    78  // HTLCAttempt contains information about a specific HTLC attempt for a given
    79  // payment. It contains the HTLCAttemptInfo used to send the HTLC, as well
    80  // as a timestamp and any known outcome of the attempt.
    81  type HTLCAttempt struct {
    82  	HTLCAttemptInfo
    83  
    84  	// Settle is the preimage of a successful payment. This serves as a
    85  	// proof of payment. It will only be non-nil for settled payments.
    86  	//
    87  	// NOTE: Can be nil if payment is not settled.
    88  	Settle *HTLCSettleInfo
    89  
    90  	// Fail is a failure reason code indicating the reason the payment
    91  	// failed. It is only non-nil for failed payments.
    92  	//
    93  	// NOTE: Can be nil if payment is not failed.
    94  	Failure *HTLCFailInfo
    95  }
    96  
    97  // HTLCSettleInfo encapsulates the information that augments an HTLCAttempt in
    98  // the event that the HTLC is successful.
    99  type HTLCSettleInfo struct {
   100  	// Preimage is the preimage of a successful HTLC. This serves as a proof
   101  	// of payment.
   102  	Preimage lntypes.Preimage
   103  
   104  	// SettleTime is the time at which this HTLC was settled.
   105  	SettleTime time.Time
   106  }
   107  
   108  // HTLCFailReason is the reason an htlc failed.
   109  type HTLCFailReason byte
   110  
   111  const (
   112  	// HTLCFailUnknown is recorded for htlcs that failed with an unknown
   113  	// reason.
   114  	HTLCFailUnknown HTLCFailReason = 0
   115  
   116  	// HTLCFailUnknown is recorded for htlcs that had a failure message that
   117  	// couldn't be decrypted.
   118  	HTLCFailUnreadable HTLCFailReason = 1
   119  
   120  	// HTLCFailInternal is recorded for htlcs that failed because of an
   121  	// internal error.
   122  	HTLCFailInternal HTLCFailReason = 2
   123  
   124  	// HTLCFailMessage is recorded for htlcs that failed with a network
   125  	// failure message.
   126  	HTLCFailMessage HTLCFailReason = 3
   127  )
   128  
   129  // HTLCFailInfo encapsulates the information that augments an HTLCAttempt in the
   130  // event that the HTLC fails.
   131  type HTLCFailInfo struct {
   132  	// FailTime is the time at which this HTLC was failed.
   133  	FailTime time.Time
   134  
   135  	// Message is the wire message that failed this HTLC. This field will be
   136  	// populated when the failure reason is HTLCFailMessage.
   137  	Message lnwire.FailureMessage
   138  
   139  	// Reason is the failure reason for this HTLC.
   140  	Reason HTLCFailReason
   141  
   142  	// The position in the path of the intermediate or final node that
   143  	// generated the failure message. Position zero is the sender node. This
   144  	// field will be populated when the failure reason is either
   145  	// HTLCFailMessage or HTLCFailUnknown.
   146  	FailureSourceIndex uint32
   147  }
   148  
   149  // MPPayment is a wrapper around a payment's PaymentCreationInfo and
   150  // HTLCAttempts. All payments will have the PaymentCreationInfo set, any
   151  // HTLCs made in attempts to be completed will populated in the HTLCs slice.
   152  // Each populated HTLCAttempt represents an attempted HTLC, each of which may
   153  // have the associated Settle or Fail struct populated if the HTLC is no longer
   154  // in-flight.
   155  type MPPayment struct {
   156  	// SequenceNum is a unique identifier used to sort the payments in
   157  	// order of creation.
   158  	SequenceNum uint64
   159  
   160  	// Info holds all static information about this payment, and is
   161  	// populated when the payment is initiated.
   162  	Info *PaymentCreationInfo
   163  
   164  	// HTLCs holds the information about individual HTLCs that we send in
   165  	// order to make the payment.
   166  	HTLCs []HTLCAttempt
   167  
   168  	// FailureReason is the failure reason code indicating the reason the
   169  	// payment failed.
   170  	//
   171  	// NOTE: Will only be set once the daemon has given up on the payment
   172  	// altogether.
   173  	FailureReason *FailureReason
   174  
   175  	// Status is the current PaymentStatus of this payment.
   176  	Status PaymentStatus
   177  }
   178  
   179  // TerminalInfo returns any HTLC settle info recorded. If no settle info is
   180  // recorded, any payment level failure will be returned. If neither a settle
   181  // nor a failure is recorded, both return values will be nil.
   182  func (m *MPPayment) TerminalInfo() (*HTLCSettleInfo, *FailureReason) {
   183  	for _, h := range m.HTLCs {
   184  		if h.Settle != nil {
   185  			return h.Settle, nil
   186  		}
   187  	}
   188  
   189  	return nil, m.FailureReason
   190  }
   191  
   192  // SentAmt returns the sum of sent amount and fees for HTLCs that are either
   193  // settled or still in flight.
   194  func (m *MPPayment) SentAmt() (lnwire.MilliAtom, lnwire.MilliAtom) {
   195  	var sent, fees lnwire.MilliAtom
   196  	for _, h := range m.HTLCs {
   197  		if h.Failure != nil {
   198  			continue
   199  		}
   200  
   201  		// The attempt was not failed, meaning the amount was
   202  		// potentially sent to the receiver.
   203  		sent += h.Route.ReceiverAmt()
   204  		fees += h.Route.TotalFees()
   205  	}
   206  
   207  	return sent, fees
   208  }
   209  
   210  // InFlightHTLCs returns the HTLCs that are still in-flight, meaning they have
   211  // not been settled or failed.
   212  func (m *MPPayment) InFlightHTLCs() []HTLCAttempt {
   213  	var inflights []HTLCAttempt
   214  	for _, h := range m.HTLCs {
   215  		if h.Settle != nil || h.Failure != nil {
   216  			continue
   217  		}
   218  
   219  		inflights = append(inflights, h)
   220  	}
   221  
   222  	return inflights
   223  }
   224  
   225  // GetAttempt returns the specified htlc attempt on the payment.
   226  func (m *MPPayment) GetAttempt(id uint64) (*HTLCAttempt, error) {
   227  	for _, htlc := range m.HTLCs {
   228  		htlc := htlc
   229  		if htlc.AttemptID == id {
   230  			return &htlc, nil
   231  		}
   232  	}
   233  
   234  	return nil, errors.New("htlc attempt not found on payment")
   235  }
   236  
   237  // serializeHTLCSettleInfo serializes the details of a settled htlc.
   238  func serializeHTLCSettleInfo(w io.Writer, s *HTLCSettleInfo) error {
   239  	if _, err := w.Write(s.Preimage[:]); err != nil {
   240  		return err
   241  	}
   242  
   243  	if err := serializeTime(w, s.SettleTime); err != nil {
   244  		return err
   245  	}
   246  
   247  	return nil
   248  }
   249  
   250  // deserializeHTLCSettleInfo deserializes the details of a settled htlc.
   251  func deserializeHTLCSettleInfo(r io.Reader) (*HTLCSettleInfo, error) {
   252  	s := &HTLCSettleInfo{}
   253  	if _, err := io.ReadFull(r, s.Preimage[:]); err != nil {
   254  		return nil, err
   255  	}
   256  
   257  	var err error
   258  	s.SettleTime, err = deserializeTime(r)
   259  	if err != nil {
   260  		return nil, err
   261  	}
   262  
   263  	return s, nil
   264  }
   265  
   266  // serializeHTLCFailInfo serializes the details of a failed htlc including the
   267  // wire failure.
   268  func serializeHTLCFailInfo(w io.Writer, f *HTLCFailInfo) error {
   269  	if err := serializeTime(w, f.FailTime); err != nil {
   270  		return err
   271  	}
   272  
   273  	// Write failure. If there is no failure message, write an empty
   274  	// byte slice.
   275  	var messageBytes bytes.Buffer
   276  	if f.Message != nil {
   277  		err := lnwire.EncodeFailureMessage(&messageBytes, f.Message, 0)
   278  		if err != nil {
   279  			return err
   280  		}
   281  	}
   282  	if err := wire.WriteVarBytes(w, 0, messageBytes.Bytes()); err != nil {
   283  		return err
   284  	}
   285  
   286  	return WriteElements(w, byte(f.Reason), f.FailureSourceIndex)
   287  }
   288  
   289  // deserializeHTLCFailInfo deserializes the details of a failed htlc including
   290  // the wire failure.
   291  func deserializeHTLCFailInfo(r io.Reader) (*HTLCFailInfo, error) {
   292  	f := &HTLCFailInfo{}
   293  	var err error
   294  	f.FailTime, err = deserializeTime(r)
   295  	if err != nil {
   296  		return nil, err
   297  	}
   298  
   299  	// Read failure.
   300  	failureBytes, err := wire.ReadVarBytes(
   301  		r, 0, lnwire.FailureMessageLength, "failure",
   302  	)
   303  	if err != nil {
   304  		return nil, err
   305  	}
   306  	if len(failureBytes) > 0 {
   307  		f.Message, err = lnwire.DecodeFailureMessage(
   308  			bytes.NewReader(failureBytes), 0,
   309  		)
   310  		if err != nil {
   311  			return nil, err
   312  		}
   313  	}
   314  
   315  	var reason byte
   316  	err = ReadElements(r, &reason, &f.FailureSourceIndex)
   317  	if err != nil {
   318  		return nil, err
   319  	}
   320  	f.Reason = HTLCFailReason(reason)
   321  
   322  	return f, nil
   323  }
   324  
   325  // deserializeTime deserializes time as unix nanoseconds.
   326  func deserializeTime(r io.Reader) (time.Time, error) {
   327  	var scratch [8]byte
   328  	if _, err := io.ReadFull(r, scratch[:]); err != nil {
   329  		return time.Time{}, err
   330  	}
   331  
   332  	// Convert to time.Time. Interpret unix nano time zero as a zero
   333  	// time.Time value.
   334  	unixNano := byteOrder.Uint64(scratch[:])
   335  	if unixNano == 0 {
   336  		return time.Time{}, nil
   337  	}
   338  
   339  	return time.Unix(0, int64(unixNano)), nil
   340  }
   341  
   342  // serializeTime serializes time as unix nanoseconds.
   343  func serializeTime(w io.Writer, t time.Time) error {
   344  	var scratch [8]byte
   345  
   346  	// Convert to unix nano seconds, but only if time is non-zero. Calling
   347  	// UnixNano() on a zero time yields an undefined result.
   348  	var unixNano int64
   349  	if !t.IsZero() {
   350  		unixNano = t.UnixNano()
   351  	}
   352  
   353  	byteOrder.PutUint64(scratch[:], uint64(unixNano))
   354  	_, err := w.Write(scratch[:])
   355  	return err
   356  }