• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lightningnetwork / lnd / 13035292482

29 Jan 2025 03:59PM UTC coverage: 49.3% (-9.5%) from 58.777%
13035292482

Pull #9456

github

mohamedawnallah
docs: update release-notes-0.19.0.md

In this commit, we warn users about the removal
of RPCs `SendToRoute`, `SendToRouteSync`, `SendPayment`,
and `SendPaymentSync` in the next release 0.20.
Pull Request #9456: lnrpc+docs: deprecate warning `SendToRoute`, `SendToRouteSync`, `SendPayment`, and `SendPaymentSync` in Release 0.19

100634 of 204126 relevant lines covered (49.3%)

1.54 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/channeldb/migration32/mission_control_store.go
1
package migration32
2

3
import (
4
        "bytes"
5
        "io"
6
        "math"
7
        "time"
8

9
        "github.com/btcsuite/btcd/wire"
10
        lnwire "github.com/lightningnetwork/lnd/channeldb/migration/lnwire21"
11
        "github.com/lightningnetwork/lnd/fn/v2"
12
        "github.com/lightningnetwork/lnd/tlv"
13
)
14

15
const (
16
        // unknownFailureSourceIdx is the database encoding of an unknown error
17
        // source.
18
        unknownFailureSourceIdx = -1
19
)
20

21
var (
22
        // resultsKey is the fixed key under which the attempt results are
23
        // stored.
24
        resultsKey = []byte("missioncontrol-results")
25
)
26

27
// paymentResultOld is the information that becomes available when a payment
28
// attempt completes.
29
type paymentResultOld struct {
30
        id                 uint64
31
        timeFwd, timeReply time.Time
32
        route              *Route
33
        success            bool
34
        failureSourceIdx   *int
35
        failure            lnwire.FailureMessage
36
}
37

38
// deserializeOldResult deserializes a payment result using the old encoding.
39
func deserializeOldResult(k, v []byte) (*paymentResultOld, error) {
×
40
        // Parse payment id.
×
41
        result := paymentResultOld{
×
42
                id: byteOrder.Uint64(k[8:]),
×
43
        }
×
44

×
45
        r := bytes.NewReader(v)
×
46

×
47
        // Read timestamps, success status and failure source index.
×
48
        var (
×
49
                timeFwd, timeReply uint64
×
50
                dbFailureSourceIdx int32
×
51
        )
×
52

×
53
        err := ReadElements(
×
54
                r, &timeFwd, &timeReply, &result.success, &dbFailureSourceIdx,
×
55
        )
×
56
        if err != nil {
×
57
                return nil, err
×
58
        }
×
59

60
        // Convert time stamps to local time zone for consistent logging.
61
        result.timeFwd = time.Unix(0, int64(timeFwd)).Local()
×
62
        result.timeReply = time.Unix(0, int64(timeReply)).Local()
×
63

×
64
        // Convert from unknown index magic number to nil value.
×
65
        if dbFailureSourceIdx != unknownFailureSourceIdx {
×
66
                failureSourceIdx := int(dbFailureSourceIdx)
×
67
                result.failureSourceIdx = &failureSourceIdx
×
68
        }
×
69

70
        // Read route.
71
        route, err := DeserializeRoute(r)
×
72
        if err != nil {
×
73
                return nil, err
×
74
        }
×
75
        result.route = &route
×
76

×
77
        // Read failure.
×
78
        failureBytes, err := wire.ReadVarBytes(r, 0, math.MaxUint16, "failure")
×
79
        if err != nil {
×
80
                return nil, err
×
81
        }
×
82
        if len(failureBytes) > 0 {
×
83
                result.failure, err = lnwire.DecodeFailureMessage(
×
84
                        bytes.NewReader(failureBytes), 0,
×
85
                )
×
86
                if err != nil {
×
87
                        return nil, err
×
88
                }
×
89
        }
90

91
        return &result, nil
×
92
}
93

94
// convertPaymentResult converts a paymentResultOld to a paymentResultNew.
95
func convertPaymentResult(old *paymentResultOld) *paymentResultNew {
×
96
        var failure *paymentFailure
×
97
        if !old.success {
×
98
                failure = newPaymentFailure(old.failureSourceIdx, old.failure)
×
99
        }
×
100

101
        return newPaymentResult(
×
102
                old.id, extractMCRoute(old.route), old.timeFwd, old.timeReply,
×
103
                failure,
×
104
        )
×
105
}
106

107
// newPaymentResult constructs a new paymentResult.
108
func newPaymentResult(id uint64, rt *mcRoute, timeFwd, timeReply time.Time,
109
        failure *paymentFailure) *paymentResultNew {
×
110

×
111
        result := &paymentResultNew{
×
112
                id: id,
×
113
                timeFwd: tlv.NewPrimitiveRecord[tlv.TlvType0](
×
114
                        uint64(timeFwd.UnixNano()),
×
115
                ),
×
116
                timeReply: tlv.NewPrimitiveRecord[tlv.TlvType1](
×
117
                        uint64(timeReply.UnixNano()),
×
118
                ),
×
119
                route: tlv.NewRecordT[tlv.TlvType2](*rt),
×
120
        }
×
121

×
122
        if failure != nil {
×
123
                result.failure = tlv.SomeRecordT(
×
124
                        tlv.NewRecordT[tlv.TlvType3](*failure),
×
125
                )
×
126
        }
×
127

128
        return result
×
129
}
130

131
// paymentResultNew is the information that becomes available when a payment
132
// attempt completes.
133
type paymentResultNew struct {
134
        id        uint64
135
        timeFwd   tlv.RecordT[tlv.TlvType0, uint64]
136
        timeReply tlv.RecordT[tlv.TlvType1, uint64]
137
        route     tlv.RecordT[tlv.TlvType2, mcRoute]
138

139
        // failure holds information related to the failure of a payment. The
140
        // presence of this record indicates a payment failure. The absence of
141
        // this record indicates a successful payment.
142
        failure tlv.OptionalRecordT[tlv.TlvType3, paymentFailure]
143
}
144

145
// paymentFailure represents the presence of a payment failure. It may or may
146
// not include additional information about said failure.
147
type paymentFailure struct {
148
        info tlv.OptionalRecordT[tlv.TlvType0, paymentFailureInfo]
149
}
150

151
// newPaymentFailure constructs a new paymentFailure struct. If the source
152
// index is nil, then an empty paymentFailure is returned. This represents a
153
// failure with unknown details. Otherwise, the index and failure message are
154
// used to populate the info field of the paymentFailure.
155
func newPaymentFailure(sourceIdx *int,
156
        failureMsg lnwire.FailureMessage) *paymentFailure {
×
157

×
158
        if sourceIdx == nil {
×
159
                return &paymentFailure{}
×
160
        }
×
161

162
        info := paymentFailureInfo{
×
163
                sourceIdx: tlv.NewPrimitiveRecord[tlv.TlvType0](
×
164
                        uint8(*sourceIdx),
×
165
                ),
×
166
                msg: tlv.NewRecordT[tlv.TlvType1](failureMessage{failureMsg}),
×
167
        }
×
168

×
169
        return &paymentFailure{
×
170
                info: tlv.SomeRecordT(tlv.NewRecordT[tlv.TlvType0](info)),
×
171
        }
×
172
}
173

174
// Record returns a TLV record that can be used to encode/decode a
175
// paymentFailure to/from a TLV stream.
176
func (r *paymentFailure) Record() tlv.Record {
×
177
        recordSize := func() uint64 {
×
178
                var (
×
179
                        b   bytes.Buffer
×
180
                        buf [8]byte
×
181
                )
×
182
                if err := encodePaymentFailure(&b, r, &buf); err != nil {
×
183
                        panic(err)
×
184
                }
185

186
                return uint64(len(b.Bytes()))
×
187
        }
188

189
        return tlv.MakeDynamicRecord(
×
190
                0, r, recordSize, encodePaymentFailure, decodePaymentFailure,
×
191
        )
×
192
}
193

194
func encodePaymentFailure(w io.Writer, val interface{}, _ *[8]byte) error {
×
195
        if v, ok := val.(*paymentFailure); ok {
×
196
                var recordProducers []tlv.RecordProducer
×
197
                v.info.WhenSome(
×
198
                        func(r tlv.RecordT[tlv.TlvType0, paymentFailureInfo]) {
×
199
                                recordProducers = append(recordProducers, &r)
×
200
                        },
×
201
                )
202

203
                return lnwire.EncodeRecordsTo(
×
204
                        w, lnwire.ProduceRecordsSorted(recordProducers...),
×
205
                )
×
206
        }
207

208
        return tlv.NewTypeForEncodingErr(val, "routing.paymentFailure")
×
209
}
210

211
func decodePaymentFailure(r io.Reader, val interface{}, _ *[8]byte,
212
        l uint64) error {
×
213

×
214
        if v, ok := val.(*paymentFailure); ok {
×
215
                var h paymentFailure
×
216

×
217
                info := tlv.ZeroRecordT[tlv.TlvType0, paymentFailureInfo]()
×
218
                typeMap, err := lnwire.DecodeRecords(
×
219
                        r, lnwire.ProduceRecordsSorted(&info)...,
×
220
                )
×
221
                if err != nil {
×
222
                        return err
×
223
                }
×
224

225
                if _, ok := typeMap[h.info.TlvType()]; ok {
×
226
                        h.info = tlv.SomeRecordT(info)
×
227
                }
×
228

229
                *v = h
×
230

×
231
                return nil
×
232
        }
233

234
        return tlv.NewTypeForDecodingErr(val, "routing.paymentFailure", l, l)
×
235
}
236

237
// paymentFailureInfo holds additional information about a payment failure.
238
type paymentFailureInfo struct {
239
        sourceIdx tlv.RecordT[tlv.TlvType0, uint8]
240
        msg       tlv.RecordT[tlv.TlvType1, failureMessage]
241
}
242

243
// Record returns a TLV record that can be used to encode/decode a
244
// paymentFailureInfo to/from a TLV stream.
245
func (r *paymentFailureInfo) Record() tlv.Record {
×
246
        recordSize := func() uint64 {
×
247
                var (
×
248
                        b   bytes.Buffer
×
249
                        buf [8]byte
×
250
                )
×
251
                if err := encodePaymentFailureInfo(&b, r, &buf); err != nil {
×
252
                        panic(err)
×
253
                }
254

255
                return uint64(len(b.Bytes()))
×
256
        }
257

258
        return tlv.MakeDynamicRecord(
×
259
                0, r, recordSize, encodePaymentFailureInfo,
×
260
                decodePaymentFailureInfo,
×
261
        )
×
262
}
263

264
func encodePaymentFailureInfo(w io.Writer, val interface{}, _ *[8]byte) error {
×
265
        if v, ok := val.(*paymentFailureInfo); ok {
×
266
                return lnwire.EncodeRecordsTo(
×
267
                        w, lnwire.ProduceRecordsSorted(
×
268
                                &v.sourceIdx, &v.msg,
×
269
                        ),
×
270
                )
×
271
        }
×
272

273
        return tlv.NewTypeForEncodingErr(val, "routing.paymentFailureInfo")
×
274
}
275

276
func decodePaymentFailureInfo(r io.Reader, val interface{}, _ *[8]byte,
277
        l uint64) error {
×
278

×
279
        if v, ok := val.(*paymentFailureInfo); ok {
×
280
                var h paymentFailureInfo
×
281

×
282
                _, err := lnwire.DecodeRecords(
×
283
                        r,
×
284
                        lnwire.ProduceRecordsSorted(&h.sourceIdx, &h.msg)...,
×
285
                )
×
286
                if err != nil {
×
287
                        return err
×
288
                }
×
289

290
                *v = h
×
291

×
292
                return nil
×
293
        }
294

295
        return tlv.NewTypeForDecodingErr(
×
296
                val, "routing.paymentFailureInfo", l, l,
×
297
        )
×
298
}
299

300
type failureMessage struct {
301
        lnwire.FailureMessage
302
}
303

304
// Record returns a TLV record that can be used to encode/decode a list of
305
// failureMessage to/from a TLV stream.
306
func (r *failureMessage) Record() tlv.Record {
×
307
        recordSize := func() uint64 {
×
308
                var (
×
309
                        b   bytes.Buffer
×
310
                        buf [8]byte
×
311
                )
×
312
                if err := encodeFailureMessage(&b, r, &buf); err != nil {
×
313
                        panic(err)
×
314
                }
315

316
                return uint64(len(b.Bytes()))
×
317
        }
318

319
        return tlv.MakeDynamicRecord(
×
320
                0, r, recordSize, encodeFailureMessage, decodeFailureMessage,
×
321
        )
×
322
}
323

324
func encodeFailureMessage(w io.Writer, val interface{}, _ *[8]byte) error {
×
325
        if v, ok := val.(*failureMessage); ok {
×
326
                var b bytes.Buffer
×
327
                err := lnwire.EncodeFailureMessage(&b, v.FailureMessage, 0)
×
328
                if err != nil {
×
329
                        return err
×
330
                }
×
331

332
                _, err = w.Write(b.Bytes())
×
333

×
334
                return err
×
335
        }
336

337
        return tlv.NewTypeForEncodingErr(val, "routing.failureMessage")
×
338
}
339

340
func decodeFailureMessage(r io.Reader, val interface{}, _ *[8]byte,
341
        l uint64) error {
×
342

×
343
        if v, ok := val.(*failureMessage); ok {
×
344
                msg, err := lnwire.DecodeFailureMessage(r, 0)
×
345
                if err != nil {
×
346
                        return err
×
347
                }
×
348

349
                *v = failureMessage{
×
350
                        FailureMessage: msg,
×
351
                }
×
352

×
353
                return nil
×
354
        }
355

356
        return tlv.NewTypeForDecodingErr(val, "routing.failureMessage", l, l)
×
357
}
358

359
// extractMCRoute extracts the fields required by MC from the Route struct to
360
// create the more minimal mcRoute struct.
361
func extractMCRoute(r *Route) *mcRoute {
×
362
        return &mcRoute{
×
363
                sourcePubKey: tlv.NewRecordT[tlv.TlvType0](r.SourcePubKey),
×
364
                totalAmount:  tlv.NewRecordT[tlv.TlvType1](r.TotalAmount),
×
365
                hops: tlv.NewRecordT[tlv.TlvType2](
×
366
                        extractMCHops(r.Hops),
×
367
                ),
×
368
        }
×
369
}
×
370

371
// extractMCHops extracts the Hop fields that MC actually uses from a slice of
372
// Hops.
373
func extractMCHops(hops []*Hop) mcHops {
×
374
        return fn.Map(hops, extractMCHop)
×
375
}
×
376

377
// extractMCHop extracts the Hop fields that MC actually uses from a Hop.
378
func extractMCHop(hop *Hop) *mcHop {
×
379
        h := mcHop{
×
380
                channelID: tlv.NewPrimitiveRecord[tlv.TlvType0, uint64](
×
381
                        hop.ChannelID,
×
382
                ),
×
383
                pubKeyBytes: tlv.NewRecordT[tlv.TlvType1, Vertex](
×
384
                        hop.PubKeyBytes,
×
385
                ),
×
386
                amtToFwd: tlv.NewRecordT[tlv.TlvType2, lnwire.MilliSatoshi](
×
387
                        hop.AmtToForward,
×
388
                ),
×
389
        }
×
390

×
391
        if hop.BlindingPoint != nil {
×
392
                h.hasBlindingPoint = tlv.SomeRecordT(
×
393
                        tlv.NewRecordT[tlv.TlvType3, lnwire.TrueBoolean](
×
394
                                lnwire.TrueBoolean{},
×
395
                        ),
×
396
                )
×
397
        }
×
398

399
        if len(hop.CustomRecords) != 0 {
×
400
                h.hasCustomRecords = tlv.SomeRecordT(
×
401
                        tlv.NewRecordT[tlv.TlvType4, lnwire.TrueBoolean](
×
402
                                lnwire.TrueBoolean{},
×
403
                        ),
×
404
                )
×
405
        }
×
406

407
        return &h
×
408
}
409

410
// mcRoute holds the bare minimum info about a payment attempt route that MC
411
// requires.
412
type mcRoute struct {
413
        sourcePubKey tlv.RecordT[tlv.TlvType0, Vertex]
414
        totalAmount  tlv.RecordT[tlv.TlvType1, lnwire.MilliSatoshi]
415
        hops         tlv.RecordT[tlv.TlvType2, mcHops]
416
}
417

418
// Record returns a TLV record that can be used to encode/decode an mcRoute
419
// to/from a TLV stream.
420
func (r *mcRoute) Record() tlv.Record {
×
421
        recordSize := func() uint64 {
×
422
                var (
×
423
                        b   bytes.Buffer
×
424
                        buf [8]byte
×
425
                )
×
426
                if err := encodeMCRoute(&b, r, &buf); err != nil {
×
427
                        panic(err)
×
428
                }
429

430
                return uint64(len(b.Bytes()))
×
431
        }
432

433
        return tlv.MakeDynamicRecord(
×
434
                0, r, recordSize, encodeMCRoute, decodeMCRoute,
×
435
        )
×
436
}
437

438
func encodeMCRoute(w io.Writer, val interface{}, _ *[8]byte) error {
×
439
        if v, ok := val.(*mcRoute); ok {
×
440
                return serializeRoute(w, v)
×
441
        }
×
442

443
        return tlv.NewTypeForEncodingErr(val, "routing.mcRoute")
×
444
}
445

446
func decodeMCRoute(r io.Reader, val interface{}, _ *[8]byte, l uint64) error {
×
447
        if v, ok := val.(*mcRoute); ok {
×
448
                route, err := deserializeRoute(io.LimitReader(r, int64(l)))
×
449
                if err != nil {
×
450
                        return err
×
451
                }
×
452

453
                *v = *route
×
454

×
455
                return nil
×
456
        }
457

458
        return tlv.NewTypeForDecodingErr(val, "routing.mcRoute", l, l)
×
459
}
460

461
// mcHops is a list of mcHop records.
462
type mcHops []*mcHop
463

464
// Record returns a TLV record that can be used to encode/decode a list of
465
// mcHop to/from a TLV stream.
466
func (h *mcHops) Record() tlv.Record {
×
467
        recordSize := func() uint64 {
×
468
                var (
×
469
                        b   bytes.Buffer
×
470
                        buf [8]byte
×
471
                )
×
472
                if err := encodeMCHops(&b, h, &buf); err != nil {
×
473
                        panic(err)
×
474
                }
475

476
                return uint64(len(b.Bytes()))
×
477
        }
478

479
        return tlv.MakeDynamicRecord(
×
480
                0, h, recordSize, encodeMCHops, decodeMCHops,
×
481
        )
×
482
}
483

484
func encodeMCHops(w io.Writer, val interface{}, buf *[8]byte) error {
×
485
        if v, ok := val.(*mcHops); ok {
×
486
                // Encode the number of hops as a var int.
×
487
                if err := tlv.WriteVarInt(w, uint64(len(*v)), buf); err != nil {
×
488
                        return err
×
489
                }
×
490

491
                // With that written out, we'll now encode the entries
492
                // themselves as a sub-TLV record, which includes its _own_
493
                // inner length prefix.
494
                for _, hop := range *v {
×
495
                        var hopBytes bytes.Buffer
×
496
                        if err := serializeNewHop(&hopBytes, hop); err != nil {
×
497
                                return err
×
498
                        }
×
499

500
                        // We encode the record with a varint length followed by
501
                        // the _raw_ TLV bytes.
502
                        tlvLen := uint64(len(hopBytes.Bytes()))
×
503
                        if err := tlv.WriteVarInt(w, tlvLen, buf); err != nil {
×
504
                                return err
×
505
                        }
×
506

507
                        if _, err := w.Write(hopBytes.Bytes()); err != nil {
×
508
                                return err
×
509
                        }
×
510
                }
511

512
                return nil
×
513
        }
514

515
        return tlv.NewTypeForEncodingErr(val, "routing.mcHops")
×
516
}
517

518
func decodeMCHops(r io.Reader, val interface{}, buf *[8]byte, l uint64) error {
×
519
        if v, ok := val.(*mcHops); ok {
×
520
                // First, we'll decode the varint that encodes how many hops
×
521
                // are encoded in the stream.
×
522
                numHops, err := tlv.ReadVarInt(r, buf)
×
523
                if err != nil {
×
524
                        return err
×
525
                }
×
526

527
                // Now that we know how many records we'll need to read, we can
528
                // iterate and read them all out in series.
529
                for i := uint64(0); i < numHops; i++ {
×
530
                        // Read out the varint that encodes the size of this
×
531
                        // inner TLV record.
×
532
                        hopSize, err := tlv.ReadVarInt(r, buf)
×
533
                        if err != nil {
×
534
                                return err
×
535
                        }
×
536

537
                        // Using this information, we'll create a new limited
538
                        // reader that'll return an EOF once the end has been
539
                        // reached so the stream stops consuming bytes.
540
                        innerTlvReader := &io.LimitedReader{
×
541
                                R: r,
×
542
                                N: int64(hopSize),
×
543
                        }
×
544

×
545
                        hop, err := deserializeNewHop(innerTlvReader)
×
546
                        if err != nil {
×
547
                                return err
×
548
                        }
×
549

550
                        *v = append(*v, hop)
×
551
                }
552

553
                return nil
×
554
        }
555

556
        return tlv.NewTypeForDecodingErr(val, "routing.mcHops", l, l)
×
557
}
558

559
// serializeRoute serializes a mcRoute and writes the resulting bytes to the
560
// given io.Writer.
561
func serializeRoute(w io.Writer, r *mcRoute) error {
×
562
        records := lnwire.ProduceRecordsSorted(
×
563
                &r.sourcePubKey,
×
564
                &r.totalAmount,
×
565
                &r.hops,
×
566
        )
×
567

×
568
        return lnwire.EncodeRecordsTo(w, records)
×
569
}
×
570

571
// deserializeRoute deserializes the mcRoute from the given io.Reader.
572
func deserializeRoute(r io.Reader) (*mcRoute, error) {
×
573
        var rt mcRoute
×
574
        records := lnwire.ProduceRecordsSorted(
×
575
                &rt.sourcePubKey,
×
576
                &rt.totalAmount,
×
577
                &rt.hops,
×
578
        )
×
579

×
580
        _, err := lnwire.DecodeRecords(r, records...)
×
581
        if err != nil {
×
582
                return nil, err
×
583
        }
×
584

585
        return &rt, nil
×
586
}
587

588
// deserializeNewHop deserializes the mcHop from the given io.Reader.
589
func deserializeNewHop(r io.Reader) (*mcHop, error) {
×
590
        var (
×
591
                h        mcHop
×
592
                blinding = tlv.ZeroRecordT[tlv.TlvType3, lnwire.TrueBoolean]()
×
593
                custom   = tlv.ZeroRecordT[tlv.TlvType4, lnwire.TrueBoolean]()
×
594
        )
×
595
        records := lnwire.ProduceRecordsSorted(
×
596
                &h.channelID,
×
597
                &h.pubKeyBytes,
×
598
                &h.amtToFwd,
×
599
                &blinding,
×
600
                &custom,
×
601
        )
×
602

×
603
        typeMap, err := lnwire.DecodeRecords(r, records...)
×
604
        if err != nil {
×
605
                return nil, err
×
606
        }
×
607

608
        if _, ok := typeMap[h.hasBlindingPoint.TlvType()]; ok {
×
609
                h.hasBlindingPoint = tlv.SomeRecordT(blinding)
×
610
        }
×
611

612
        if _, ok := typeMap[h.hasCustomRecords.TlvType()]; ok {
×
613
                h.hasCustomRecords = tlv.SomeRecordT(custom)
×
614
        }
×
615

616
        return &h, nil
×
617
}
618

619
// serializeNewHop serializes a mcHop and writes the resulting bytes to the
620
// given io.Writer.
621
func serializeNewHop(w io.Writer, h *mcHop) error {
×
622
        recordProducers := []tlv.RecordProducer{
×
623
                &h.channelID,
×
624
                &h.pubKeyBytes,
×
625
                &h.amtToFwd,
×
626
        }
×
627

×
628
        h.hasBlindingPoint.WhenSome(func(
×
629
                hasBlinding tlv.RecordT[tlv.TlvType3, lnwire.TrueBoolean]) {
×
630

×
631
                recordProducers = append(recordProducers, &hasBlinding)
×
632
        })
×
633

634
        h.hasCustomRecords.WhenSome(func(
×
635
                hasCustom tlv.RecordT[tlv.TlvType4, lnwire.TrueBoolean]) {
×
636

×
637
                recordProducers = append(recordProducers, &hasCustom)
×
638
        })
×
639

640
        return lnwire.EncodeRecordsTo(
×
641
                w, lnwire.ProduceRecordsSorted(recordProducers...),
×
642
        )
×
643
}
644

645
// mcHop holds the bare minimum info about a payment attempt route hop that MC
646
// requires.
647
type mcHop struct {
648
        channelID        tlv.RecordT[tlv.TlvType0, uint64]
649
        pubKeyBytes      tlv.RecordT[tlv.TlvType1, Vertex]
650
        amtToFwd         tlv.RecordT[tlv.TlvType2, lnwire.MilliSatoshi]
651
        hasBlindingPoint tlv.OptionalRecordT[tlv.TlvType3, lnwire.TrueBoolean]
652
        hasCustomRecords tlv.OptionalRecordT[tlv.TlvType4, lnwire.TrueBoolean]
653
}
654

655
// serializeOldResult serializes a payment result and returns a key and value
656
// byte slice to insert into the bucket.
657
func serializeOldResult(rp *paymentResultOld) ([]byte, []byte, error) {
×
658
        // Write timestamps, success status, failure source index and route.
×
659
        var b bytes.Buffer
×
660
        var dbFailureSourceIdx int32
×
661
        if rp.failureSourceIdx == nil {
×
662
                dbFailureSourceIdx = unknownFailureSourceIdx
×
663
        } else {
×
664
                dbFailureSourceIdx = int32(*rp.failureSourceIdx)
×
665
        }
×
666
        err := WriteElements(
×
667
                &b,
×
668
                uint64(rp.timeFwd.UnixNano()),
×
669
                uint64(rp.timeReply.UnixNano()),
×
670
                rp.success, dbFailureSourceIdx,
×
671
        )
×
672
        if err != nil {
×
673
                return nil, nil, err
×
674
        }
×
675

676
        if err := SerializeRoute(&b, *rp.route); err != nil {
×
677
                return nil, nil, err
×
678
        }
×
679

680
        // Write failure. If there is no failure message, write an empty
681
        // byte slice.
682
        var failureBytes bytes.Buffer
×
683
        if rp.failure != nil {
×
684
                err := lnwire.EncodeFailureMessage(&failureBytes, rp.failure, 0)
×
685
                if err != nil {
×
686
                        return nil, nil, err
×
687
                }
×
688
        }
689
        err = wire.WriteVarBytes(&b, 0, failureBytes.Bytes())
×
690
        if err != nil {
×
691
                return nil, nil, err
×
692
        }
×
693
        // Compose key that identifies this result.
694
        key := getResultKeyOld(rp)
×
695

×
696
        return key, b.Bytes(), nil
×
697
}
698

699
// getResultKeyOld returns a byte slice representing a unique key for this
700
// payment result.
701
func getResultKeyOld(rp *paymentResultOld) []byte {
×
702
        var keyBytes [8 + 8 + 33]byte
×
703

×
704
        // Identify records by a combination of time, payment id and sender pub
×
705
        // key. This allows importing mission control data from an external
×
706
        // source without key collisions and keeps the records sorted
×
707
        // chronologically.
×
708
        byteOrder.PutUint64(keyBytes[:], uint64(rp.timeReply.UnixNano()))
×
709
        byteOrder.PutUint64(keyBytes[8:], rp.id)
×
710
        copy(keyBytes[16:], rp.route.SourcePubKey[:])
×
711

×
712
        return keyBytes[:]
×
713
}
×
714

715
// serializeNewResult serializes a payment result and returns a key and value
716
// byte slice to insert into the bucket.
717
func serializeNewResult(rp *paymentResultNew) ([]byte, []byte, error) {
×
718
        recordProducers := []tlv.RecordProducer{
×
719
                &rp.timeFwd,
×
720
                &rp.timeReply,
×
721
                &rp.route,
×
722
        }
×
723

×
724
        rp.failure.WhenSome(
×
725
                func(failure tlv.RecordT[tlv.TlvType3, paymentFailure]) {
×
726
                        recordProducers = append(recordProducers, &failure)
×
727
                },
×
728
        )
729

730
        // Compose key that identifies this result.
731
        key := getResultKeyNew(rp)
×
732

×
733
        var buff bytes.Buffer
×
734
        err := lnwire.EncodeRecordsTo(
×
735
                &buff, lnwire.ProduceRecordsSorted(recordProducers...),
×
736
        )
×
737
        if err != nil {
×
738
                return nil, nil, err
×
739
        }
×
740

741
        return key, buff.Bytes(), err
×
742
}
743

744
// getResultKeyNew returns a byte slice representing a unique key for this
745
// payment result.
746
func getResultKeyNew(rp *paymentResultNew) []byte {
×
747
        var keyBytes [8 + 8 + 33]byte
×
748

×
749
        // Identify records by a combination of time, payment id and sender pub
×
750
        // key. This allows importing mission control data from an external
×
751
        // source without key collisions and keeps the records sorted
×
752
        // chronologically.
×
753
        byteOrder.PutUint64(keyBytes[:], rp.timeReply.Val)
×
754
        byteOrder.PutUint64(keyBytes[8:], rp.id)
×
755
        copy(keyBytes[16:], rp.route.Val.sourcePubKey.Val[:])
×
756

×
757
        return keyBytes[:]
×
758
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc