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

lightningnetwork / lnd / 13725358077

07 Mar 2025 04:51PM UTC coverage: 58.224% (-10.4%) from 68.615%
13725358077

Pull #9458

github

web-flow
Merge bf4c6625f into ab2dc09eb
Pull Request #9458: multi+server.go: add initial permissions for some peers

346 of 549 new or added lines in 10 files covered. (63.02%)

27466 existing lines in 443 files now uncovered.

94609 of 162492 relevant lines covered (58.22%)

1.81 hits per line

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

0.0
/channeldb/migration13/migration.go
1
package migration13
2

3
import (
4
        "encoding/binary"
5
        "fmt"
6

7
        "github.com/lightningnetwork/lnd/kvdb"
8
)
9

10
var (
11
        paymentsRootBucket = []byte("payments-root-bucket")
12

13
        // paymentCreationInfoKey is a key used in the payment's sub-bucket to
14
        // store the creation info of the payment.
15
        paymentCreationInfoKey = []byte("payment-creation-info")
16

17
        // paymentFailInfoKey is a key used in the payment's sub-bucket to
18
        // store information about the reason a payment failed.
19
        paymentFailInfoKey = []byte("payment-fail-info")
20

21
        // paymentAttemptInfoKey is a key used in the payment's sub-bucket to
22
        // store the info about the latest attempt that was done for the
23
        // payment in question.
24
        paymentAttemptInfoKey = []byte("payment-attempt-info")
25

26
        // paymentSettleInfoKey is a key used in the payment's sub-bucket to
27
        // store the settle info of the payment.
28
        paymentSettleInfoKey = []byte("payment-settle-info")
29

30
        // paymentHtlcsBucket is a bucket where we'll store the information
31
        // about the HTLCs that were attempted for a payment.
32
        paymentHtlcsBucket = []byte("payment-htlcs-bucket")
33

34
        // htlcAttemptInfoKey is a key used in a HTLC's sub-bucket to store the
35
        // info about the attempt that was done for the HTLC in question.
36
        htlcAttemptInfoKey = []byte("htlc-attempt-info")
37

38
        // htlcSettleInfoKey is a key used in a HTLC's sub-bucket to store the
39
        // settle info, if any.
40
        htlcSettleInfoKey = []byte("htlc-settle-info")
41

42
        // htlcFailInfoKey is a key used in a HTLC's sub-bucket to store
43
        // failure information, if any.
44
        htlcFailInfoKey = []byte("htlc-fail-info")
45

46
        byteOrder = binary.BigEndian
47
)
48

49
// MigrateMPP migrates the payments to a new structure that accommodates for mpp
50
// payments.
UNCOV
51
func MigrateMPP(tx kvdb.RwTx) error {
×
UNCOV
52
        log.Infof("Migrating payments to mpp structure")
×
UNCOV
53

×
UNCOV
54
        // Iterate over all payments and store their indexing keys. This is
×
UNCOV
55
        // needed, because no modifications are allowed inside a Bucket.ForEach
×
UNCOV
56
        // loop.
×
UNCOV
57
        paymentsBucket := tx.ReadWriteBucket(paymentsRootBucket)
×
UNCOV
58
        if paymentsBucket == nil {
×
59
                return nil
×
60
        }
×
61

UNCOV
62
        var paymentKeys [][]byte
×
UNCOV
63
        err := paymentsBucket.ForEach(func(k, v []byte) error {
×
UNCOV
64
                paymentKeys = append(paymentKeys, k)
×
UNCOV
65
                return nil
×
UNCOV
66
        })
×
UNCOV
67
        if err != nil {
×
68
                return err
×
69
        }
×
70

71
        // With all keys retrieved, start the migration.
UNCOV
72
        for _, k := range paymentKeys {
×
UNCOV
73
                bucket := paymentsBucket.NestedReadWriteBucket(k)
×
UNCOV
74

×
UNCOV
75
                // We only expect sub-buckets to be found in
×
UNCOV
76
                // this top-level bucket.
×
UNCOV
77
                if bucket == nil {
×
78
                        return fmt.Errorf("non bucket element in " +
×
79
                                "payments bucket")
×
80
                }
×
81

82
                // Fetch old format creation info.
UNCOV
83
                creationInfo := bucket.Get(paymentCreationInfoKey)
×
UNCOV
84
                if creationInfo == nil {
×
85
                        return fmt.Errorf("creation info not found")
×
86
                }
×
87

88
                // Make a copy because bbolt doesn't allow this value to be
89
                // changed in-place.
UNCOV
90
                newCreationInfo := make([]byte, len(creationInfo))
×
UNCOV
91
                copy(newCreationInfo, creationInfo)
×
UNCOV
92

×
UNCOV
93
                // Convert to nano seconds.
×
UNCOV
94
                timeBytes := newCreationInfo[32+8 : 32+8+8]
×
UNCOV
95
                time := byteOrder.Uint64(timeBytes)
×
UNCOV
96
                timeNs := time * 1000000000
×
UNCOV
97
                byteOrder.PutUint64(timeBytes, timeNs)
×
UNCOV
98

×
UNCOV
99
                // Write back new format creation info.
×
UNCOV
100
                err := bucket.Put(paymentCreationInfoKey, newCreationInfo)
×
UNCOV
101
                if err != nil {
×
102
                        return err
×
103
                }
×
104

105
                // No migration needed if there is no attempt stored.
UNCOV
106
                attemptInfo := bucket.Get(paymentAttemptInfoKey)
×
UNCOV
107
                if attemptInfo == nil {
×
108
                        continue
×
109
                }
110

111
                // Delete attempt info on the payment level.
UNCOV
112
                if err := bucket.Delete(paymentAttemptInfoKey); err != nil {
×
113
                        return err
×
114
                }
×
115

116
                // Save attempt id for later use.
UNCOV
117
                attemptID := attemptInfo[:8]
×
UNCOV
118

×
UNCOV
119
                // Discard attempt id. It will become a bucket key in the new
×
UNCOV
120
                // structure.
×
UNCOV
121
                attemptInfo = attemptInfo[8:]
×
UNCOV
122

×
UNCOV
123
                // Append unknown (zero) attempt time.
×
UNCOV
124
                var zero [8]byte
×
UNCOV
125
                attemptInfo = append(attemptInfo, zero[:]...)
×
UNCOV
126

×
UNCOV
127
                // Create bucket that contains all htlcs.
×
UNCOV
128
                htlcsBucket, err := bucket.CreateBucket(paymentHtlcsBucket)
×
UNCOV
129
                if err != nil {
×
130
                        return err
×
131
                }
×
132

133
                // Create an htlc for this attempt.
UNCOV
134
                htlcBucket, err := htlcsBucket.CreateBucket(attemptID)
×
UNCOV
135
                if err != nil {
×
136
                        return err
×
137
                }
×
138

139
                // Save migrated attempt info.
UNCOV
140
                err = htlcBucket.Put(htlcAttemptInfoKey, attemptInfo)
×
UNCOV
141
                if err != nil {
×
142
                        return err
×
143
                }
×
144

145
                // Migrate settle info.
UNCOV
146
                settleInfo := bucket.Get(paymentSettleInfoKey)
×
UNCOV
147
                if settleInfo != nil {
×
UNCOV
148
                        // Payment-level settle info can be deleted.
×
UNCOV
149
                        err := bucket.Delete(paymentSettleInfoKey)
×
UNCOV
150
                        if err != nil {
×
151
                                return err
×
152
                        }
×
153

154
                        // Append unknown (zero) settle time.
UNCOV
155
                        settleInfo = append(settleInfo, zero[:]...)
×
UNCOV
156

×
UNCOV
157
                        // Save settle info.
×
UNCOV
158
                        err = htlcBucket.Put(htlcSettleInfoKey, settleInfo)
×
UNCOV
159
                        if err != nil {
×
160
                                return err
×
161
                        }
×
162

163
                        // Migration for settled htlc completed.
UNCOV
164
                        continue
×
165
                }
166

167
                // If there is no payment-level failure reason, the payment is
168
                // still in flight and nothing else needs to be migrated.
169
                // Otherwise the payment-level failure reason can remain
170
                // unchanged.
UNCOV
171
                inFlight := bucket.Get(paymentFailInfoKey) == nil
×
UNCOV
172
                if inFlight {
×
UNCOV
173
                        continue
×
174
                }
175

176
                // The htlc failed. Add htlc fail info with reason unknown. We
177
                // don't have access to the original failure reason anymore.
UNCOV
178
                failInfo := []byte{
×
UNCOV
179
                        // Fail time unknown.
×
UNCOV
180
                        0, 0, 0, 0, 0, 0, 0, 0,
×
UNCOV
181

×
UNCOV
182
                        // Zero length wire message.
×
UNCOV
183
                        0,
×
UNCOV
184

×
UNCOV
185
                        // Failure reason unknown.
×
UNCOV
186
                        0,
×
UNCOV
187

×
UNCOV
188
                        // Failure source index zero.
×
UNCOV
189
                        0, 0, 0, 0,
×
UNCOV
190
                }
×
UNCOV
191

×
UNCOV
192
                // Save fail info.
×
UNCOV
193
                err = htlcBucket.Put(htlcFailInfoKey, failInfo)
×
UNCOV
194
                if err != nil {
×
195
                        return err
×
196
                }
×
197
        }
198

UNCOV
199
        log.Infof("Migration of payments to mpp structure complete!")
×
UNCOV
200

×
UNCOV
201
        return nil
×
202
}
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