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 }