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 }