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

lightningnetwork / lnd / 13586005509

28 Feb 2025 10:14AM UTC coverage: 68.629% (+9.9%) from 58.77%
13586005509

Pull #9521

github

web-flow
Merge 37d3a70a5 into 8532955b3
Pull Request #9521: unit: remove GOACC, use Go 1.20 native coverage functionality

129950 of 189351 relevant lines covered (68.63%)

23726.46 hits per line

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

75.0
/channeldb/migration26/channel.go
1
package migration26
2

3
import (
4
        "bytes"
5
        "fmt"
6

7
        lnwire "github.com/lightningnetwork/lnd/channeldb/migration/lnwire21"
8
        mig25 "github.com/lightningnetwork/lnd/channeldb/migration25"
9
        mig "github.com/lightningnetwork/lnd/channeldb/migration_01_to_11"
10
        "github.com/lightningnetwork/lnd/kvdb"
11
        "github.com/lightningnetwork/lnd/tlv"
12
)
13

14
const (
15
        // A tlv type definition used to serialize and deserialize a KeyLocator
16
        // from the database.
17
        keyLocType tlv.Type = 1
18

19
        // A tlv type used to serialize and deserialize the
20
        // `InitialLocalBalance` field.
21
        initialLocalBalanceType tlv.Type = 2
22

23
        // A tlv type used to serialize and deserialize the
24
        // `InitialRemoteBalance` field.
25
        initialRemoteBalanceType tlv.Type = 3
26
)
27

28
var (
29
        // chanInfoKey can be accessed within the bucket for a channel
30
        // (identified by its chanPoint). This key stores all the static
31
        // information for a channel which is decided at the end of  the
32
        // funding flow.
33
        chanInfoKey = []byte("chan-info-key")
34

35
        // localUpfrontShutdownKey can be accessed within the bucket for a
36
        // channel (identified by its chanPoint). This key stores an optional
37
        // upfront shutdown script for the local peer.
38
        localUpfrontShutdownKey = []byte("local-upfront-shutdown-key")
39

40
        // remoteUpfrontShutdownKey can be accessed within the bucket for a
41
        // channel (identified by its chanPoint). This key stores an optional
42
        // upfront shutdown script for the remote peer.
43
        remoteUpfrontShutdownKey = []byte("remote-upfront-shutdown-key")
44

45
        // lastWasRevokeKey is a key that stores true when the last update we
46
        // sent was a revocation and false when it was a commitment signature.
47
        // This is nil in the case of new channels with no updates exchanged.
48
        lastWasRevokeKey = []byte("last-was-revoke")
49

50
        // ErrNoChanInfoFound is returned when a particular channel does not
51
        // have any channels state.
52
        ErrNoChanInfoFound = fmt.Errorf("no chan info found")
53

54
        // ErrNoPastDeltas is returned when the channel delta bucket hasn't been
55
        // created.
56
        ErrNoPastDeltas = fmt.Errorf("channel has no recorded deltas")
57

58
        // ErrLogEntryNotFound is returned when we cannot find a log entry at
59
        // the height requested in the revocation log.
60
        ErrLogEntryNotFound = fmt.Errorf("log entry not found")
61

62
        // ErrNoCommitmentsFound is returned when a channel has not set
63
        // commitment states.
64
        ErrNoCommitmentsFound = fmt.Errorf("no commitments found")
65
)
66

67
// OpenChannel embeds a mig25.OpenChannel with the extra update-to-date
68
// serialization and deserialization methods.
69
//
70
// NOTE: doesn't have the Packager field as it's not used in current migration.
71
type OpenChannel struct {
72
        mig25.OpenChannel
73
}
74

75
// FetchChanInfo deserializes the channel info based on the legacy boolean.
76
// After migration25, the legacy format would have the fields
77
// `InitialLocalBalance` and `InitialRemoteBalance` directly encoded as bytes.
78
// For the new format, they will be put inside a tlv stream.
79
func FetchChanInfo(chanBucket kvdb.RBucket, c *OpenChannel, legacy bool) error {
1,894✔
80
        infoBytes := chanBucket.Get(chanInfoKey)
1,894✔
81
        if infoBytes == nil {
1,894✔
82
                return ErrNoChanInfoFound
×
83
        }
×
84
        r := bytes.NewReader(infoBytes)
1,894✔
85

1,894✔
86
        var (
1,894✔
87
                chanType   mig.ChannelType
1,894✔
88
                chanStatus mig.ChannelStatus
1,894✔
89
        )
1,894✔
90

1,894✔
91
        if err := mig.ReadElements(r,
1,894✔
92
                &chanType, &c.ChainHash, &c.FundingOutpoint,
1,894✔
93
                &c.ShortChannelID, &c.IsPending, &c.IsInitiator,
1,894✔
94
                &chanStatus, &c.FundingBroadcastHeight,
1,894✔
95
                &c.NumConfsRequired, &c.ChannelFlags,
1,894✔
96
                &c.IdentityPub, &c.Capacity, &c.TotalMSatSent,
1,894✔
97
                &c.TotalMSatReceived,
1,894✔
98
        ); err != nil {
1,894✔
99
                return err
×
100
        }
×
101

102
        c.ChanType = mig25.ChannelType(chanType)
1,894✔
103
        c.ChanStatus = mig25.ChannelStatus(chanStatus)
1,894✔
104

1,894✔
105
        // If this is the legacy format, we need to read the extra two new
1,894✔
106
        // fields.
1,894✔
107
        if legacy {
1,900✔
108
                if err := mig.ReadElements(r,
6✔
109
                        &c.InitialLocalBalance, &c.InitialRemoteBalance,
6✔
110
                ); err != nil {
6✔
111
                        return err
×
112
                }
×
113
        }
114

115
        // For single funder channels that we initiated and have the funding
116
        // transaction to, read the funding txn.
117
        if c.FundingTxPresent() {
1,895✔
118
                if err := mig.ReadElement(r, &c.FundingTxn); err != nil {
1✔
119
                        return err
×
120
                }
×
121
        }
122

123
        if err := mig.ReadChanConfig(r, &c.LocalChanCfg); err != nil {
1,894✔
124
                return err
×
125
        }
×
126
        if err := mig.ReadChanConfig(r, &c.RemoteChanCfg); err != nil {
1,894✔
127
                return err
×
128
        }
×
129

130
        // Retrieve the boolean stored under lastWasRevokeKey.
131
        lastWasRevokeBytes := chanBucket.Get(lastWasRevokeKey)
1,894✔
132
        if lastWasRevokeBytes == nil {
3,788✔
133
                // If nothing has been stored under this key, we store false in
1,894✔
134
                // the OpenChannel struct.
1,894✔
135
                c.LastWasRevoke = false
1,894✔
136
        } else {
1,894✔
137
                // Otherwise, read the value into the LastWasRevoke field.
×
138
                revokeReader := bytes.NewReader(lastWasRevokeBytes)
×
139
                err := mig.ReadElements(revokeReader, &c.LastWasRevoke)
×
140
                if err != nil {
×
141
                        return err
×
142
                }
×
143
        }
144

145
        // Make the tlv stream based on the legacy param.
146
        var (
1,894✔
147
                ts            *tlv.Stream
1,894✔
148
                err           error
1,894✔
149
                localBalance  uint64
1,894✔
150
                remoteBalance uint64
1,894✔
151
        )
1,894✔
152

1,894✔
153
        keyLocRecord := mig25.MakeKeyLocRecord(
1,894✔
154
                keyLocType, &c.RevocationKeyLocator,
1,894✔
155
        )
1,894✔
156

1,894✔
157
        // If it's legacy, create the stream with a single tlv record.
1,894✔
158
        if legacy {
1,900✔
159
                ts, err = tlv.NewStream(keyLocRecord)
6✔
160
        } else {
1,894✔
161
                // Otherwise, for the new format, we will encode the balance
1,888✔
162
                // fields in the tlv stream too.
1,888✔
163
                ts, err = tlv.NewStream(
1,888✔
164
                        keyLocRecord,
1,888✔
165
                        tlv.MakePrimitiveRecord(
1,888✔
166
                                initialLocalBalanceType, &localBalance,
1,888✔
167
                        ),
1,888✔
168
                        tlv.MakePrimitiveRecord(
1,888✔
169
                                initialRemoteBalanceType, &remoteBalance,
1,888✔
170
                        ),
1,888✔
171
                )
1,888✔
172
        }
1,888✔
173
        if err != nil {
1,894✔
174
                return err
×
175
        }
×
176

177
        if err := ts.Decode(r); err != nil {
1,894✔
178
                return err
×
179
        }
×
180

181
        // For the new format, attach the balance fields.
182
        if !legacy {
3,782✔
183
                c.InitialLocalBalance = lnwire.MilliSatoshi(localBalance)
1,888✔
184
                c.InitialRemoteBalance = lnwire.MilliSatoshi(remoteBalance)
1,888✔
185
        }
1,888✔
186

187
        // Finally, read the optional shutdown scripts.
188
        if err := mig25.GetOptionalUpfrontShutdownScript(
1,894✔
189
                chanBucket, localUpfrontShutdownKey, &c.LocalShutdownScript,
1,894✔
190
        ); err != nil {
1,894✔
191
                return err
×
192
        }
×
193

194
        return mig25.GetOptionalUpfrontShutdownScript(
1,894✔
195
                chanBucket, remoteUpfrontShutdownKey, &c.RemoteShutdownScript,
1,894✔
196
        )
1,894✔
197
}
198

199
// MakeTlvStream creates a tlv stream based on whether we are deadling with
200
// legacy format or not. For the legacy format, we have a single record in the
201
// stream. For the new format, we have the extra balance records.
202
func MakeTlvStream(c *OpenChannel, legacy bool) (*tlv.Stream, error) {
2,675✔
203
        keyLocRecord := mig25.MakeKeyLocRecord(
2,675✔
204
                keyLocType, &c.RevocationKeyLocator,
2,675✔
205
        )
2,675✔
206

2,675✔
207
        // If it's legacy, return the stream with a single tlv record.
2,675✔
208
        if legacy {
2,683✔
209
                return tlv.NewStream(keyLocRecord)
8✔
210
        }
8✔
211

212
        // Otherwise, for the new format, we will encode the balance fields in
213
        // the tlv stream too.
214
        localBalance := uint64(c.InitialLocalBalance)
2,667✔
215
        remoteBalance := uint64(c.InitialRemoteBalance)
2,667✔
216

2,667✔
217
        // Create the tlv stream.
2,667✔
218
        return tlv.NewStream(
2,667✔
219
                keyLocRecord,
2,667✔
220
                tlv.MakePrimitiveRecord(
2,667✔
221
                        initialLocalBalanceType, &localBalance,
2,667✔
222
                ),
2,667✔
223
                tlv.MakePrimitiveRecord(
2,667✔
224
                        initialRemoteBalanceType, &remoteBalance,
2,667✔
225
                ),
2,667✔
226
        )
2,667✔
227
}
228

229
// PutChanInfo serializes the channel info based on the legacy boolean. After
230
// migration25, the legacy format would have the fields `InitialLocalBalance`
231
// and `InitialRemoteBalance` directly encoded as bytes. For the new format,
232
// they will be put inside a tlv stream.
233
func PutChanInfo(chanBucket kvdb.RwBucket, c *OpenChannel, legacy bool) error {
2,669✔
234
        var w bytes.Buffer
2,669✔
235
        if err := mig.WriteElements(&w,
2,669✔
236
                mig.ChannelType(c.ChanType), c.ChainHash, c.FundingOutpoint,
2,669✔
237
                c.ShortChannelID, c.IsPending, c.IsInitiator,
2,669✔
238
                mig.ChannelStatus(c.ChanStatus), c.FundingBroadcastHeight,
2,669✔
239
                c.NumConfsRequired, c.ChannelFlags,
2,669✔
240
                c.IdentityPub, c.Capacity, c.TotalMSatSent,
2,669✔
241
                c.TotalMSatReceived,
2,669✔
242
        ); err != nil {
2,669✔
243
                return err
×
244
        }
×
245

246
        // If this is legacy format, we need to write the extra two fields.
247
        if legacy {
2,675✔
248
                if err := mig.WriteElements(&w,
6✔
249
                        c.InitialLocalBalance, c.InitialRemoteBalance,
6✔
250
                ); err != nil {
6✔
251
                        return err
×
252
                }
×
253
        }
254

255
        // For single funder channels that we initiated, and we have the
256
        // funding transaction, then write the funding txn.
257
        if c.FundingTxPresent() {
2,670✔
258
                if err := mig.WriteElement(&w, c.FundingTxn); err != nil {
1✔
259
                        return err
×
260
                }
×
261
        }
262

263
        if err := mig.WriteChanConfig(&w, &c.LocalChanCfg); err != nil {
2,669✔
264
                return err
×
265
        }
×
266
        if err := mig.WriteChanConfig(&w, &c.RemoteChanCfg); err != nil {
2,669✔
267
                return err
×
268
        }
×
269

270
        // Make the tlv stream based on the legacy param.
271
        tlvStream, err := MakeTlvStream(c, legacy)
2,669✔
272
        if err != nil {
2,669✔
273
                return err
×
274
        }
×
275

276
        if err := tlvStream.Encode(&w); err != nil {
2,669✔
277
                return err
×
278
        }
×
279

280
        if err := chanBucket.Put(chanInfoKey, w.Bytes()); err != nil {
2,669✔
281
                return err
×
282
        }
×
283

284
        // Finally, add optional shutdown scripts for the local and remote peer
285
        // if they are present.
286
        if err := mig25.PutOptionalUpfrontShutdownScript(
2,669✔
287
                chanBucket, localUpfrontShutdownKey, c.LocalShutdownScript,
2,669✔
288
        ); err != nil {
2,669✔
289
                return err
×
290
        }
×
291

292
        return mig25.PutOptionalUpfrontShutdownScript(
2,669✔
293
                chanBucket, remoteUpfrontShutdownKey, c.RemoteShutdownScript,
2,669✔
294
        )
2,669✔
295
}
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