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

lightningnetwork / lnd / 13408822928

19 Feb 2025 08:59AM UTC coverage: 41.123% (-17.7%) from 58.794%
13408822928

Pull #9521

github

web-flow
Merge d2f397b3c into 0e8786348
Pull Request #9521: unit: remove GOACC, use Go 1.20 native coverage functionality

92496 of 224923 relevant lines covered (41.12%)

18825.83 hits per line

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

73.81
/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 {
8✔
80
        infoBytes := chanBucket.Get(chanInfoKey)
8✔
81
        if infoBytes == nil {
8✔
82
                return ErrNoChanInfoFound
×
83
        }
×
84
        r := bytes.NewReader(infoBytes)
8✔
85

8✔
86
        var (
8✔
87
                chanType   mig.ChannelType
8✔
88
                chanStatus mig.ChannelStatus
8✔
89
        )
8✔
90

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

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

8✔
105
        // If this is the legacy format, we need to read the extra two new
8✔
106
        // fields.
8✔
107
        if legacy {
12✔
108
                if err := mig.ReadElements(r,
4✔
109
                        &c.InitialLocalBalance, &c.InitialRemoteBalance,
4✔
110
                ); err != nil {
4✔
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() {
8✔
118
                if err := mig.ReadElement(r, &c.FundingTxn); err != nil {
×
119
                        return err
×
120
                }
×
121
        }
122

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

130
        // Retrieve the boolean stored under lastWasRevokeKey.
131
        lastWasRevokeBytes := chanBucket.Get(lastWasRevokeKey)
8✔
132
        if lastWasRevokeBytes == nil {
16✔
133
                // If nothing has been stored under this key, we store false in
8✔
134
                // the OpenChannel struct.
8✔
135
                c.LastWasRevoke = false
8✔
136
        } else {
8✔
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 (
8✔
147
                ts            *tlv.Stream
8✔
148
                err           error
8✔
149
                localBalance  uint64
8✔
150
                remoteBalance uint64
8✔
151
        )
8✔
152

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

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

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

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

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

194
        return mig25.GetOptionalUpfrontShutdownScript(
8✔
195
                chanBucket, remoteUpfrontShutdownKey, &c.RemoteShutdownScript,
8✔
196
        )
8✔
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) {
8✔
203
        keyLocRecord := mig25.MakeKeyLocRecord(
8✔
204
                keyLocType, &c.RevocationKeyLocator,
8✔
205
        )
8✔
206

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

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

4✔
217
        // Create the tlv stream.
4✔
218
        return tlv.NewStream(
4✔
219
                keyLocRecord,
4✔
220
                tlv.MakePrimitiveRecord(
4✔
221
                        initialLocalBalanceType, &localBalance,
4✔
222
                ),
4✔
223
                tlv.MakePrimitiveRecord(
4✔
224
                        initialRemoteBalanceType, &remoteBalance,
4✔
225
                ),
4✔
226
        )
4✔
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 {
8✔
234
        var w bytes.Buffer
8✔
235
        if err := mig.WriteElements(&w,
8✔
236
                mig.ChannelType(c.ChanType), c.ChainHash, c.FundingOutpoint,
8✔
237
                c.ShortChannelID, c.IsPending, c.IsInitiator,
8✔
238
                mig.ChannelStatus(c.ChanStatus), c.FundingBroadcastHeight,
8✔
239
                c.NumConfsRequired, c.ChannelFlags,
8✔
240
                c.IdentityPub, c.Capacity, c.TotalMSatSent,
8✔
241
                c.TotalMSatReceived,
8✔
242
        ); err != nil {
8✔
243
                return err
×
244
        }
×
245

246
        // If this is legacy format, we need to write the extra two fields.
247
        if legacy {
12✔
248
                if err := mig.WriteElements(&w,
4✔
249
                        c.InitialLocalBalance, c.InitialRemoteBalance,
4✔
250
                ); err != nil {
4✔
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() {
8✔
258
                if err := mig.WriteElement(&w, c.FundingTxn); err != nil {
×
259
                        return err
×
260
                }
×
261
        }
262

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

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

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

280
        if err := chanBucket.Put(chanInfoKey, w.Bytes()); err != nil {
8✔
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(
8✔
287
                chanBucket, localUpfrontShutdownKey, c.LocalShutdownScript,
8✔
288
        ); err != nil {
8✔
289
                return err
×
290
        }
×
291

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