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

lightningnetwork / lnd / 13980275562

20 Mar 2025 10:06PM UTC coverage: 58.6% (-10.2%) from 68.789%
13980275562

Pull #9623

github

web-flow
Merge b9b960345 into 09b674508
Pull Request #9623: Size msg test msg

0 of 1518 new or added lines in 42 files covered. (0.0%)

26603 existing lines in 443 files now uncovered.

96807 of 165200 relevant lines covered (58.6%)

1.82 hits per line

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

39.42
/lnwire/open_channel.go
1
package lnwire
2

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

7
        "github.com/btcsuite/btcd/btcec/v2"
8
        "github.com/btcsuite/btcd/btcutil"
9
        "github.com/btcsuite/btcd/chaincfg/chainhash"
10
        "github.com/lightningnetwork/lnd/tlv"
11
        "pgregory.net/rapid"
12
)
13

14
// FundingFlag represents the possible bit mask values for the ChannelFlags
15
// field within the OpenChannel struct.
16
type FundingFlag uint8
17

18
const (
19
        // FFAnnounceChannel is a FundingFlag that when set, indicates the
20
        // initiator of a funding flow wishes to announce the channel to the
21
        // greater network.
22
        FFAnnounceChannel FundingFlag = 1 << iota
23
)
24

25
// OpenChannel is the message Alice sends to Bob if we should like to create a
26
// channel with Bob where she's the sole provider of funds to the channel.
27
// Single funder channels simplify the initial funding workflow, are supported
28
// by nodes backed by SPV Bitcoin clients, and have a simpler security models
29
// than dual funded channels.
30
type OpenChannel struct {
31
        // ChainHash is the target chain that the initiator wishes to open a
32
        // channel within.
33
        ChainHash chainhash.Hash
34

35
        // PendingChannelID serves to uniquely identify the future channel
36
        // created by the initiated single funder workflow.
37
        PendingChannelID [32]byte
38

39
        // FundingAmount is the amount of satoshis that the initiator of the
40
        // channel wishes to use as the total capacity of the channel. The
41
        // initial balance of the funding will be this value minus the push
42
        // amount (if set).
43
        FundingAmount btcutil.Amount
44

45
        // PushAmount is the value that the initiating party wishes to "push"
46
        // to the responding as part of the first commitment state. If the
47
        // responder accepts, then this will be their initial balance.
48
        PushAmount MilliSatoshi
49

50
        // DustLimit is the specific dust limit the sender of this message
51
        // would like enforced on their version of the commitment transaction.
52
        // Any output below this value will be "trimmed" from the commitment
53
        // transaction, with the amount of the HTLC going to dust.
54
        DustLimit btcutil.Amount
55

56
        // MaxValueInFlight represents the maximum amount of coins that can be
57
        // pending within the channel at any given time. If the amount of funds
58
        // in limbo exceeds this amount, then the channel will be failed.
59
        MaxValueInFlight MilliSatoshi
60

61
        // ChannelReserve is the amount of BTC that the receiving party MUST
62
        // maintain a balance above at all times. This is a safety mechanism to
63
        // ensure that both sides always have skin in the game during the
64
        // channel's lifetime.
65
        ChannelReserve btcutil.Amount
66

67
        // HtlcMinimum is the smallest HTLC that the sender of this message
68
        // will accept.
69
        HtlcMinimum MilliSatoshi
70

71
        // FeePerKiloWeight is the initial fee rate that the initiator suggests
72
        // for both commitment transaction. This value is expressed in sat per
73
        // kilo-weight.
74
        //
75
        // TODO(halseth): make SatPerKWeight when fee estimation is in own
76
        // package. Currently this will cause an import cycle.
77
        FeePerKiloWeight uint32
78

79
        // CsvDelay is the number of blocks to use for the relative time lock
80
        // in the pay-to-self output of both commitment transactions.
81
        CsvDelay uint16
82

83
        // MaxAcceptedHTLCs is the total number of incoming HTLC's that the
84
        // sender of this channel will accept.
85
        MaxAcceptedHTLCs uint16
86

87
        // FundingKey is the key that should be used on behalf of the sender
88
        // within the 2-of-2 multi-sig output that it contained within the
89
        // funding transaction.
90
        FundingKey *btcec.PublicKey
91

92
        // RevocationPoint is the base revocation point for the sending party.
93
        // Any commitment transaction belonging to the receiver of this message
94
        // should use this key and their per-commitment point to derive the
95
        // revocation key for the commitment transaction.
96
        RevocationPoint *btcec.PublicKey
97

98
        // PaymentPoint is the base payment point for the sending party. This
99
        // key should be combined with the per commitment point for a
100
        // particular commitment state in order to create the key that should
101
        // be used in any output that pays directly to the sending party, and
102
        // also within the HTLC covenant transactions.
103
        PaymentPoint *btcec.PublicKey
104

105
        // DelayedPaymentPoint is the delay point for the sending party. This
106
        // key should be combined with the per commitment point to derive the
107
        // keys that are used in outputs of the sender's commitment transaction
108
        // where they claim funds.
109
        DelayedPaymentPoint *btcec.PublicKey
110

111
        // HtlcPoint is the base point used to derive the set of keys for this
112
        // party that will be used within the HTLC public key scripts. This
113
        // value is combined with the receiver's revocation base point in order
114
        // to derive the keys that are used within HTLC scripts.
115
        HtlcPoint *btcec.PublicKey
116

117
        // FirstCommitmentPoint is the first commitment point for the sending
118
        // party. This value should be combined with the receiver's revocation
119
        // base point in order to derive the revocation keys that are placed
120
        // within the commitment transaction of the sender.
121
        FirstCommitmentPoint *btcec.PublicKey
122

123
        // ChannelFlags is a bit-field which allows the initiator of the
124
        // channel to specify further behavior surrounding the channel.
125
        // Currently, the least significant bit of this bit field indicates the
126
        // initiator of the channel wishes to advertise this channel publicly.
127
        ChannelFlags FundingFlag
128

129
        // UpfrontShutdownScript is the script to which the channel funds should
130
        // be paid when mutually closing the channel. This field is optional, and
131
        // and has a length prefix, so a zero will be written if it is not set
132
        // and its length followed by the script will be written if it is set.
133
        UpfrontShutdownScript DeliveryAddress
134

135
        // ChannelType is the explicit channel type the initiator wishes to
136
        // open.
137
        ChannelType *ChannelType
138

139
        // LeaseExpiry represents the absolute expiration height of a channel
140
        // lease. This is a custom TLV record that will only apply when a leased
141
        // channel is being opened using the script enforced lease commitment
142
        // type.
143
        LeaseExpiry *LeaseExpiry
144

145
        // LocalNonce is an optional field that transmits the
146
        // local/verification nonce for a party. This nonce will be used to
147
        // verify the very first commitment transaction signature.  This will
148
        // only be populated if the simple taproot channels type was
149
        // negotiated.
150
        LocalNonce OptMusig2NonceTLV
151

152
        // ExtraData is the set of data that was appended to this message to
153
        // fill out the full maximum transport message size. These fields can
154
        // be used to specify optional data such as custom TLV fields.
155
        //
156
        // NOTE: Since the upfront shutdown script MUST be present (though can
157
        // be zero-length) if any TLV data is available, the script will be
158
        // extracted and removed from this blob when decoding. ExtraData will
159
        // contain all TLV records _except_ the DeliveryAddress record in that
160
        // case.
161
        ExtraData ExtraOpaqueData
162
}
163

164
// A compile time check to ensure OpenChannel implements the lnwire.Message
165
// interface.
166
var _ Message = (*OpenChannel)(nil)
167

168
// A compile time check to ensure OpenChannel implements the lnwire.SizeableMessage
169
// interface.
170
var _ SizeableMessage = (*OpenChannel)(nil)
171

172
// Encode serializes the target OpenChannel into the passed io.Writer
173
// implementation. Serialization will observe the rules defined by the passed
174
// protocol version.
175
func (o *OpenChannel) Encode(w *bytes.Buffer, pver uint32) error {
3✔
176
        recordProducers := []tlv.RecordProducer{&o.UpfrontShutdownScript}
3✔
177
        if o.ChannelType != nil {
6✔
178
                recordProducers = append(recordProducers, o.ChannelType)
3✔
179
        }
3✔
180
        if o.LeaseExpiry != nil {
6✔
181
                recordProducers = append(recordProducers, o.LeaseExpiry)
3✔
182
        }
3✔
183
        o.LocalNonce.WhenSome(func(localNonce Musig2NonceTLV) {
6✔
184
                recordProducers = append(recordProducers, &localNonce)
3✔
185
        })
3✔
186
        err := EncodeMessageExtraData(&o.ExtraData, recordProducers...)
3✔
187
        if err != nil {
3✔
188
                return err
×
189
        }
×
190

191
        if err := WriteBytes(w, o.ChainHash[:]); err != nil {
3✔
192
                return err
×
193
        }
×
194

195
        if err := WriteBytes(w, o.PendingChannelID[:]); err != nil {
3✔
196
                return err
×
197
        }
×
198

199
        if err := WriteSatoshi(w, o.FundingAmount); err != nil {
3✔
200
                return err
×
201
        }
×
202

203
        if err := WriteMilliSatoshi(w, o.PushAmount); err != nil {
3✔
204
                return err
×
205
        }
×
206

207
        if err := WriteSatoshi(w, o.DustLimit); err != nil {
3✔
208
                return err
×
209
        }
×
210

211
        if err := WriteMilliSatoshi(w, o.MaxValueInFlight); err != nil {
3✔
212
                return err
×
213
        }
×
214

215
        if err := WriteSatoshi(w, o.ChannelReserve); err != nil {
3✔
216
                return err
×
217
        }
×
218

219
        if err := WriteMilliSatoshi(w, o.HtlcMinimum); err != nil {
3✔
220
                return err
×
221
        }
×
222

223
        if err := WriteUint32(w, o.FeePerKiloWeight); err != nil {
3✔
224
                return err
×
225
        }
×
226

227
        if err := WriteUint16(w, o.CsvDelay); err != nil {
3✔
228
                return err
×
229
        }
×
230

231
        if err := WriteUint16(w, o.MaxAcceptedHTLCs); err != nil {
3✔
232
                return err
×
233
        }
×
234

235
        if err := WritePublicKey(w, o.FundingKey); err != nil {
3✔
236
                return err
×
237
        }
×
238

239
        if err := WritePublicKey(w, o.RevocationPoint); err != nil {
3✔
240
                return err
×
241
        }
×
242

243
        if err := WritePublicKey(w, o.PaymentPoint); err != nil {
3✔
244
                return err
×
245
        }
×
246

247
        if err := WritePublicKey(w, o.DelayedPaymentPoint); err != nil {
3✔
248
                return err
×
249
        }
×
250

251
        if err := WritePublicKey(w, o.HtlcPoint); err != nil {
3✔
252
                return err
×
253
        }
×
254

255
        if err := WritePublicKey(w, o.FirstCommitmentPoint); err != nil {
3✔
256
                return err
×
257
        }
×
258

259
        if err := WriteFundingFlag(w, o.ChannelFlags); err != nil {
3✔
260
                return err
×
261
        }
×
262

263
        return WriteBytes(w, o.ExtraData)
3✔
264
}
265

266
// Decode deserializes the serialized OpenChannel stored in the passed
267
// io.Reader into the target OpenChannel using the deserialization rules
268
// defined by the passed protocol version.
269
//
270
// This is part of the lnwire.Message interface.
271
func (o *OpenChannel) Decode(r io.Reader, pver uint32) error {
3✔
272
        // Read all the mandatory fields in the open message.
3✔
273
        err := ReadElements(r,
3✔
274
                o.ChainHash[:],
3✔
275
                o.PendingChannelID[:],
3✔
276
                &o.FundingAmount,
3✔
277
                &o.PushAmount,
3✔
278
                &o.DustLimit,
3✔
279
                &o.MaxValueInFlight,
3✔
280
                &o.ChannelReserve,
3✔
281
                &o.HtlcMinimum,
3✔
282
                &o.FeePerKiloWeight,
3✔
283
                &o.CsvDelay,
3✔
284
                &o.MaxAcceptedHTLCs,
3✔
285
                &o.FundingKey,
3✔
286
                &o.RevocationPoint,
3✔
287
                &o.PaymentPoint,
3✔
288
                &o.DelayedPaymentPoint,
3✔
289
                &o.HtlcPoint,
3✔
290
                &o.FirstCommitmentPoint,
3✔
291
                &o.ChannelFlags,
3✔
292
        )
3✔
293
        if err != nil {
3✔
UNCOV
294
                return err
×
UNCOV
295
        }
×
296

297
        // For backwards compatibility, the optional extra data blob for
298
        // OpenChannel must contain an entry for the upfront shutdown script.
299
        // We'll read it out and attempt to parse it.
300
        var tlvRecords ExtraOpaqueData
3✔
301
        if err := ReadElements(r, &tlvRecords); err != nil {
3✔
302
                return err
×
303
        }
×
304

305
        // Next we'll parse out the set of known records, keeping the raw tlv
306
        // bytes untouched to ensure we don't drop any bytes erroneously.
307
        var (
3✔
308
                chanType    ChannelType
3✔
309
                leaseExpiry LeaseExpiry
3✔
310
                localNonce  = o.LocalNonce.Zero()
3✔
311
        )
3✔
312
        typeMap, err := tlvRecords.ExtractRecords(
3✔
313
                &o.UpfrontShutdownScript, &chanType, &leaseExpiry,
3✔
314
                &localNonce,
3✔
315
        )
3✔
316
        if err != nil {
3✔
UNCOV
317
                return err
×
UNCOV
318
        }
×
319

320
        // Set the corresponding TLV types if they were included in the stream.
321
        if val, ok := typeMap[ChannelTypeRecordType]; ok && val == nil {
6✔
322
                o.ChannelType = &chanType
3✔
323
        }
3✔
324
        if val, ok := typeMap[LeaseExpiryRecordType]; ok && val == nil {
6✔
325
                o.LeaseExpiry = &leaseExpiry
3✔
326
        }
3✔
327
        if val, ok := typeMap[o.LocalNonce.TlvType()]; ok && val == nil {
6✔
328
                o.LocalNonce = tlv.SomeRecordT(localNonce)
3✔
329
        }
3✔
330

331
        o.ExtraData = tlvRecords
3✔
332

3✔
333
        return nil
3✔
334
}
335

336
// MsgType returns the MessageType code which uniquely identifies this message
337
// as an OpenChannel on the wire.
338
//
339
// This is part of the lnwire.Message interface.
340
func (o *OpenChannel) MsgType() MessageType {
3✔
341
        return MsgOpenChannel
3✔
342
}
3✔
343

344
// SerializedSize returns the serialized size of the message in bytes.
345
//
346
// This is part of the lnwire.SizeableMessage interface.
NEW
347
func (o *OpenChannel) SerializedSize() (uint32, error) {
×
NEW
348
        return MessageSerializedSize(o)
×
NEW
349
}
×
350

351
// A compile time check to ensure OpenChannel implements the TestMessage interface.
352
var _ TestMessage = (*OpenChannel)(nil)
353

354
// RandTestMessage populates the message with random data suitable for testing.
355
// It uses the rapid testing framework to generate random values.
356
//
357
// This is part of the TestMessage interface.
NEW
358
func (o *OpenChannel) RandTestMessage(t *rapid.T) Message {
×
NEW
359
        chainHash := RandChainHash(t)
×
NEW
360
        var hash chainhash.Hash
×
NEW
361
        copy(hash[:], chainHash[:])
×
NEW
362

×
NEW
363
        var pendingChanID [32]byte
×
NEW
364
        pendingChanIDBytes := rapid.SliceOfN(rapid.Byte(), 32, 32).Draw(
×
NEW
365
                t, "pendingChanID",
×
NEW
366
        )
×
NEW
367
        copy(pendingChanID[:], pendingChanIDBytes)
×
NEW
368

×
NEW
369
        includeChannelType := rapid.Bool().Draw(t, "includeChannelType")
×
NEW
370
        includeLeaseExpiry := rapid.Bool().Draw(t, "includeLeaseExpiry")
×
NEW
371
        includeLocalNonce := rapid.Bool().Draw(t, "includeLocalNonce")
×
NEW
372

×
NEW
373
        var channelFlags FundingFlag
×
NEW
374
        if rapid.Bool().Draw(t, "announceChannel") {
×
NEW
375
                channelFlags |= FFAnnounceChannel
×
NEW
376
        }
×
377

NEW
378
        var localNonce OptMusig2NonceTLV
×
NEW
379
        if includeLocalNonce {
×
NEW
380
                nonce := RandMusig2Nonce(t)
×
NEW
381
                localNonce = tlv.SomeRecordT(
×
NEW
382
                        tlv.NewRecordT[NonceRecordTypeT, Musig2Nonce](nonce),
×
NEW
383
                )
×
NEW
384
        }
×
385

NEW
386
        var channelType *ChannelType
×
NEW
387
        if includeChannelType {
×
NEW
388
                channelType = RandChannelType(t)
×
NEW
389
        }
×
390

NEW
391
        var leaseExpiry *LeaseExpiry
×
NEW
392
        if includeLeaseExpiry {
×
NEW
393
                leaseExpiry = RandLeaseExpiry(t)
×
NEW
394
        }
×
395

NEW
396
        return &OpenChannel{
×
NEW
397
                ChainHash:        hash,
×
NEW
398
                PendingChannelID: pendingChanID,
×
NEW
399
                FundingAmount: btcutil.Amount(
×
NEW
400
                        rapid.IntRange(5000, 10000000).Draw(t, "fundingAmount"),
×
NEW
401
                ),
×
NEW
402
                PushAmount: MilliSatoshi(
×
NEW
403
                        rapid.IntRange(0, 1000000).Draw(t, "pushAmount"),
×
NEW
404
                ),
×
NEW
405
                DustLimit: btcutil.Amount(
×
NEW
406
                        rapid.IntRange(100, 1000).Draw(t, "dustLimit"),
×
NEW
407
                ),
×
NEW
408
                MaxValueInFlight: MilliSatoshi(
×
NEW
409
                        rapid.IntRange(10000, 1000000).Draw(
×
NEW
410
                                t, "maxValueInFlight",
×
NEW
411
                        ),
×
NEW
412
                ),
×
NEW
413
                ChannelReserve: btcutil.Amount(
×
NEW
414
                        rapid.IntRange(1000, 10000).Draw(t, "channelReserve"),
×
NEW
415
                ),
×
NEW
416
                HtlcMinimum: MilliSatoshi(
×
NEW
417
                        rapid.IntRange(1, 1000).Draw(t, "htlcMinimum"),
×
NEW
418
                ),
×
NEW
419
                FeePerKiloWeight: uint32(
×
NEW
420
                        rapid.IntRange(250, 10000).Draw(t, "feePerKw"),
×
NEW
421
                ),
×
NEW
422
                CsvDelay: uint16(
×
NEW
423
                        rapid.IntRange(144, 1000).Draw(t, "csvDelay"),
×
NEW
424
                ),
×
NEW
425
                MaxAcceptedHTLCs: uint16(
×
NEW
426
                        rapid.IntRange(10, 500).Draw(t, "maxAcceptedHTLCs"),
×
NEW
427
                ),
×
NEW
428
                FundingKey:            RandPubKey(t),
×
NEW
429
                RevocationPoint:       RandPubKey(t),
×
NEW
430
                PaymentPoint:          RandPubKey(t),
×
NEW
431
                DelayedPaymentPoint:   RandPubKey(t),
×
NEW
432
                HtlcPoint:             RandPubKey(t),
×
NEW
433
                FirstCommitmentPoint:  RandPubKey(t),
×
NEW
434
                ChannelFlags:          channelFlags,
×
NEW
435
                UpfrontShutdownScript: RandDeliveryAddress(t),
×
NEW
436
                ChannelType:           channelType,
×
NEW
437
                LeaseExpiry:           leaseExpiry,
×
NEW
438
                LocalNonce:            localNonce,
×
NEW
439
                ExtraData:             RandExtraOpaqueData(t, nil),
×
NEW
440
        }
×
441
}
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