• 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

0.0
/lnwire/dyn_propose.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/lightningnetwork/lnd/fn/v2"
10
        "github.com/lightningnetwork/lnd/lnwallet/chainfee"
11
        "github.com/lightningnetwork/lnd/tlv"
12
        "pgregory.net/rapid"
13
)
14

15
const (
16
        // DPDustLimitSatoshis is the TLV type number that identifies the record
17
        // for DynPropose.DustLimit.
18
        DPDustLimitSatoshis tlv.Type = 0
19

20
        // DPMaxHtlcValueInFlightMsat is the TLV type number that identifies the
21
        // record for DynPropose.MaxValueInFlight.
22
        DPMaxHtlcValueInFlightMsat tlv.Type = 1
23

24
        // DPChannelReserveSatoshis is the TLV type number that identifies the
25
        // for DynPropose.ChannelReserve.
26
        DPChannelReserveSatoshis tlv.Type = 2
27

28
        // DPToSelfDelay is the TLV type number that identifies the record for
29
        // DynPropose.CsvDelay.
30
        DPToSelfDelay tlv.Type = 3
31

32
        // DPMaxAcceptedHtlcs is the TLV type number that identifies the record
33
        // for DynPropose.MaxAcceptedHTLCs.
34
        DPMaxAcceptedHtlcs tlv.Type = 4
35

36
        // DPFundingPubkey is the TLV type number that identifies the record for
37
        // DynPropose.FundingKey.
38
        DPFundingPubkey tlv.Type = 5
39

40
        // DPChannelType is the TLV type number that identifies the record for
41
        // DynPropose.ChannelType.
42
        DPChannelType tlv.Type = 6
43

44
        // DPKickoffFeerate is the TLV type number that identifies the record
45
        // for DynPropose.KickoffFeerate.
46
        DPKickoffFeerate tlv.Type = 7
47
)
48

49
// DynPropose is a message that is sent during a dynamic commitments negotiation
50
// process. It is sent by both parties to propose new channel parameters.
51
type DynPropose struct {
52
        // ChanID identifies the channel whose parameters we are trying to
53
        // re-negotiate.
54
        ChanID ChannelID
55

56
        // Initiator is a byte that identifies whether this message was sent as
57
        // the initiator of a dynamic commitment negotiation or the responder
58
        // of a dynamic commitment negotiation. bool true indicates it is the
59
        // initiator
60
        Initiator bool
61

62
        // DustLimit, if not nil, proposes a change to the dust_limit_satoshis
63
        // for the sender's commitment transaction.
64
        DustLimit fn.Option[btcutil.Amount]
65

66
        // MaxValueInFlight, if not nil, proposes a change to the
67
        // max_htlc_value_in_flight_msat limit of the sender.
68
        MaxValueInFlight fn.Option[MilliSatoshi]
69

70
        // ChannelReserve, if not nil, proposes a change to the
71
        // channel_reserve_satoshis requirement of the recipient.
72
        ChannelReserve fn.Option[btcutil.Amount]
73

74
        // CsvDelay, if not nil, proposes a change to the to_self_delay
75
        // requirement of the recipient.
76
        CsvDelay fn.Option[uint16]
77

78
        // MaxAcceptedHTLCs, if not nil, proposes a change to the
79
        // max_accepted_htlcs limit of the sender.
80
        MaxAcceptedHTLCs fn.Option[uint16]
81

82
        // FundingKey, if not nil, proposes a change to the funding_pubkey
83
        // parameter of the sender.
84
        FundingKey fn.Option[btcec.PublicKey]
85

86
        // ChannelType, if not nil, proposes a change to the channel_type
87
        // parameter.
88
        ChannelType fn.Option[ChannelType]
89

90
        // KickoffFeerate proposes the fee rate in satoshis per kw that it
91
        // is offering for a ChannelType conversion that requires a kickoff
92
        // transaction.
93
        KickoffFeerate fn.Option[chainfee.SatPerKWeight]
94

95
        // ExtraData is the set of data that was appended to this message to
96
        // fill out the full maximum transport message size. These fields can
97
        // be used to specify optional data such as custom TLV fields.
98
        //
99
        // NOTE: Since the fields in this structure are part of the TLV stream,
100
        // ExtraData will contain all TLV records _except_ the ones that are
101
        // present in earlier parts of this structure.
102
        ExtraData ExtraOpaqueData
103
}
104

105
// A compile time check to ensure DynPropose implements the lnwire.Message
106
// interface.
107
var _ Message = (*DynPropose)(nil)
108

109
// A compile time check to ensure DynPropose implements the lnwire.SizeableMessage
110
// interface.
111
var _ SizeableMessage = (*DynPropose)(nil)
112

113
// A compile time check to ensure DynPropose implements the lnwire.TestMessage
114
// interface.
115
var _ TestMessage = (*DynPropose)(nil)
116

117
// Encode serializes the target DynPropose into the passed io.Writer.
118
// Serialization will observe the rules defined by the passed protocol version.
119
//
120
// This is a part of the lnwire.Message interface.
UNCOV
121
func (dp *DynPropose) Encode(w *bytes.Buffer, _ uint32) error {
×
UNCOV
122
        var tlvRecords []tlv.Record
×
UNCOV
123
        dp.DustLimit.WhenSome(func(dl btcutil.Amount) {
×
UNCOV
124
                protoSats := uint64(dl)
×
UNCOV
125
                tlvRecords = append(
×
UNCOV
126
                        tlvRecords, tlv.MakePrimitiveRecord(
×
UNCOV
127
                                DPDustLimitSatoshis, &protoSats,
×
UNCOV
128
                        ),
×
UNCOV
129
                )
×
UNCOV
130
        })
×
UNCOV
131
        dp.MaxValueInFlight.WhenSome(func(max MilliSatoshi) {
×
UNCOV
132
                protoSats := uint64(max)
×
UNCOV
133
                tlvRecords = append(
×
UNCOV
134
                        tlvRecords, tlv.MakePrimitiveRecord(
×
UNCOV
135
                                DPMaxHtlcValueInFlightMsat, &protoSats,
×
UNCOV
136
                        ),
×
UNCOV
137
                )
×
UNCOV
138
        })
×
UNCOV
139
        dp.ChannelReserve.WhenSome(func(min btcutil.Amount) {
×
UNCOV
140
                channelReserve := uint64(min)
×
UNCOV
141
                tlvRecords = append(
×
UNCOV
142
                        tlvRecords, tlv.MakePrimitiveRecord(
×
UNCOV
143
                                DPChannelReserveSatoshis, &channelReserve,
×
UNCOV
144
                        ),
×
UNCOV
145
                )
×
UNCOV
146
        })
×
UNCOV
147
        dp.CsvDelay.WhenSome(func(wait uint16) {
×
UNCOV
148
                tlvRecords = append(
×
UNCOV
149
                        tlvRecords, tlv.MakePrimitiveRecord(
×
UNCOV
150
                                DPToSelfDelay, &wait,
×
UNCOV
151
                        ),
×
UNCOV
152
                )
×
UNCOV
153
        })
×
UNCOV
154
        dp.MaxAcceptedHTLCs.WhenSome(func(max uint16) {
×
UNCOV
155
                tlvRecords = append(
×
UNCOV
156
                        tlvRecords, tlv.MakePrimitiveRecord(
×
UNCOV
157
                                DPMaxAcceptedHtlcs, &max,
×
UNCOV
158
                        ),
×
UNCOV
159
                )
×
UNCOV
160
        })
×
UNCOV
161
        dp.FundingKey.WhenSome(func(key btcec.PublicKey) {
×
UNCOV
162
                keyScratch := &key
×
UNCOV
163
                tlvRecords = append(
×
UNCOV
164
                        tlvRecords, tlv.MakePrimitiveRecord(
×
UNCOV
165
                                DPFundingPubkey, &keyScratch,
×
UNCOV
166
                        ),
×
UNCOV
167
                )
×
UNCOV
168
        })
×
UNCOV
169
        dp.ChannelType.WhenSome(func(ty ChannelType) {
×
UNCOV
170
                tlvRecords = append(
×
UNCOV
171
                        tlvRecords, tlv.MakeDynamicRecord(
×
UNCOV
172
                                DPChannelType, &ty,
×
UNCOV
173
                                ty.featureBitLen,
×
UNCOV
174
                                channelTypeEncoder, channelTypeDecoder,
×
UNCOV
175
                        ),
×
UNCOV
176
                )
×
UNCOV
177
        })
×
UNCOV
178
        dp.KickoffFeerate.WhenSome(func(kickoffFeerate chainfee.SatPerKWeight) {
×
UNCOV
179
                protoSats := uint32(kickoffFeerate)
×
UNCOV
180
                tlvRecords = append(
×
UNCOV
181
                        tlvRecords, tlv.MakePrimitiveRecord(
×
UNCOV
182
                                DPKickoffFeerate, &protoSats,
×
UNCOV
183
                        ),
×
UNCOV
184
                )
×
UNCOV
185
        })
×
UNCOV
186
        tlv.SortRecords(tlvRecords)
×
UNCOV
187

×
UNCOV
188
        tlvStream, err := tlv.NewStream(tlvRecords...)
×
UNCOV
189
        if err != nil {
×
190
                return err
×
191
        }
×
192

UNCOV
193
        var extraBytesWriter bytes.Buffer
×
UNCOV
194
        if err := tlvStream.Encode(&extraBytesWriter); err != nil {
×
195
                return err
×
196
        }
×
UNCOV
197
        dp.ExtraData = ExtraOpaqueData(extraBytesWriter.Bytes())
×
UNCOV
198

×
UNCOV
199
        if err := WriteChannelID(w, dp.ChanID); err != nil {
×
200
                return err
×
201
        }
×
202

UNCOV
203
        if err := WriteBool(w, dp.Initiator); err != nil {
×
204
                return err
×
205
        }
×
206

UNCOV
207
        return WriteBytes(w, dp.ExtraData)
×
208
}
209

210
// Decode deserializes the serialized DynPropose stored in the passed io.Reader
211
// into the target DynPropose using the deserialization rules defined by the
212
// passed protocol version.
213
//
214
// This is a part of the lnwire.Message interface.
UNCOV
215
func (dp *DynPropose) Decode(r io.Reader, _ uint32) error {
×
UNCOV
216
        // Parse out the only required field.
×
UNCOV
217
        if err := ReadElements(r, &dp.ChanID, &dp.Initiator); err != nil {
×
UNCOV
218
                return err
×
UNCOV
219
        }
×
220

221
        // Parse out TLV stream.
UNCOV
222
        var tlvRecords ExtraOpaqueData
×
UNCOV
223
        if err := ReadElements(r, &tlvRecords); err != nil {
×
224
                return err
×
225
        }
×
226

227
        // Prepare receiving buffers to be filled by TLV extraction.
UNCOV
228
        var dustLimitScratch uint64
×
UNCOV
229
        dustLimit := tlv.MakePrimitiveRecord(
×
UNCOV
230
                DPDustLimitSatoshis, &dustLimitScratch,
×
UNCOV
231
        )
×
UNCOV
232

×
UNCOV
233
        var maxValueScratch uint64
×
UNCOV
234
        maxValue := tlv.MakePrimitiveRecord(
×
UNCOV
235
                DPMaxHtlcValueInFlightMsat, &maxValueScratch,
×
UNCOV
236
        )
×
UNCOV
237

×
UNCOV
238
        var reserveScratch uint64
×
UNCOV
239
        reserve := tlv.MakePrimitiveRecord(
×
UNCOV
240
                DPChannelReserveSatoshis, &reserveScratch,
×
UNCOV
241
        )
×
UNCOV
242

×
UNCOV
243
        var csvDelayScratch uint16
×
UNCOV
244
        csvDelay := tlv.MakePrimitiveRecord(DPToSelfDelay, &csvDelayScratch)
×
UNCOV
245

×
UNCOV
246
        var maxHtlcsScratch uint16
×
UNCOV
247
        maxHtlcs := tlv.MakePrimitiveRecord(
×
UNCOV
248
                DPMaxAcceptedHtlcs, &maxHtlcsScratch,
×
UNCOV
249
        )
×
UNCOV
250

×
UNCOV
251
        var fundingKeyScratch *btcec.PublicKey
×
UNCOV
252
        fundingKey := tlv.MakePrimitiveRecord(
×
UNCOV
253
                DPFundingPubkey, &fundingKeyScratch,
×
UNCOV
254
        )
×
UNCOV
255

×
UNCOV
256
        var chanTypeScratch ChannelType
×
UNCOV
257
        chanType := tlv.MakeDynamicRecord(
×
UNCOV
258
                DPChannelType, &chanTypeScratch, chanTypeScratch.featureBitLen,
×
UNCOV
259
                channelTypeEncoder, channelTypeDecoder,
×
UNCOV
260
        )
×
UNCOV
261

×
UNCOV
262
        var kickoffFeerateScratch uint32
×
UNCOV
263
        kickoffFeerate := tlv.MakePrimitiveRecord(
×
UNCOV
264
                DPKickoffFeerate, &kickoffFeerateScratch,
×
UNCOV
265
        )
×
UNCOV
266

×
UNCOV
267
        // Create set of Records to read TLV bytestream into.
×
UNCOV
268
        records := []tlv.Record{
×
UNCOV
269
                dustLimit, maxValue, reserve, csvDelay, maxHtlcs, fundingKey,
×
UNCOV
270
                chanType, kickoffFeerate,
×
UNCOV
271
        }
×
UNCOV
272
        tlv.SortRecords(records)
×
UNCOV
273

×
UNCOV
274
        // Read TLV stream into record set.
×
UNCOV
275
        extraBytesReader := bytes.NewReader(tlvRecords)
×
UNCOV
276
        tlvStream, err := tlv.NewStream(records...)
×
UNCOV
277
        if err != nil {
×
278
                return err
×
279
        }
×
280

UNCOV
281
        typeMap, err := tlvStream.DecodeWithParsedTypesP2P(extraBytesReader)
×
UNCOV
282
        if err != nil {
×
UNCOV
283
                return err
×
UNCOV
284
        }
×
285

286
        // Check the results of the TLV Stream decoding and appropriately set
287
        // message fields.
UNCOV
288
        if val, ok := typeMap[DPDustLimitSatoshis]; ok && val == nil {
×
UNCOV
289
                dp.DustLimit = fn.Some(btcutil.Amount(dustLimitScratch))
×
UNCOV
290
        }
×
UNCOV
291
        if val, ok := typeMap[DPMaxHtlcValueInFlightMsat]; ok && val == nil {
×
UNCOV
292
                dp.MaxValueInFlight = fn.Some(MilliSatoshi(maxValueScratch))
×
UNCOV
293
        }
×
UNCOV
294
        if val, ok := typeMap[DPChannelReserveSatoshis]; ok && val == nil {
×
UNCOV
295
                dp.ChannelReserve = fn.Some(btcutil.Amount(reserveScratch))
×
UNCOV
296
        }
×
UNCOV
297
        if val, ok := typeMap[DPToSelfDelay]; ok && val == nil {
×
UNCOV
298
                dp.CsvDelay = fn.Some(csvDelayScratch)
×
UNCOV
299
        }
×
UNCOV
300
        if val, ok := typeMap[DPMaxAcceptedHtlcs]; ok && val == nil {
×
UNCOV
301
                dp.MaxAcceptedHTLCs = fn.Some(maxHtlcsScratch)
×
UNCOV
302
        }
×
UNCOV
303
        if val, ok := typeMap[DPFundingPubkey]; ok && val == nil {
×
UNCOV
304
                dp.FundingKey = fn.Some(*fundingKeyScratch)
×
UNCOV
305
        }
×
UNCOV
306
        if val, ok := typeMap[DPChannelType]; ok && val == nil {
×
UNCOV
307
                dp.ChannelType = fn.Some(chanTypeScratch)
×
UNCOV
308
        }
×
UNCOV
309
        if val, ok := typeMap[DPKickoffFeerate]; ok && val == nil {
×
UNCOV
310
                dp.KickoffFeerate = fn.Some(
×
UNCOV
311
                        chainfee.SatPerKWeight(kickoffFeerateScratch),
×
UNCOV
312
                )
×
UNCOV
313
        }
×
314

UNCOV
315
        if len(tlvRecords) != 0 {
×
UNCOV
316
                dp.ExtraData = tlvRecords
×
UNCOV
317
        }
×
318

UNCOV
319
        return nil
×
320
}
321

322
// MsgType returns the MessageType code which uniquely identifies this message
323
// as a DynPropose on the wire.
324
//
325
// This is part of the lnwire.Message interface.
UNCOV
326
func (dp *DynPropose) MsgType() MessageType {
×
UNCOV
327
        return MsgDynPropose
×
UNCOV
328
}
×
329

330
// SerializedSize returns the serialized size of the message in bytes.
331
//
332
// This is part of the lnwire.SizeableMessage interface.
NEW
333
func (dp *DynPropose) SerializedSize() (uint32, error) {
×
NEW
334
        return MessageSerializedSize(dp)
×
NEW
335
}
×
336

337
// RandTestMessage populates the message with random data suitable for testing.
338
// It uses the rapid testing framework to generate random values.
339
//
340
// This is part of the TestMessage interface.
NEW
341
func (dp *DynPropose) RandTestMessage(t *rapid.T) Message {
×
NEW
342
        msg := &DynPropose{
×
NEW
343
                ChanID:    RandChannelID(t),
×
NEW
344
                Initiator: rapid.Bool().Draw(t, "initiator"),
×
NEW
345
                ExtraData: RandExtraOpaqueData(t, nil),
×
NEW
346
        }
×
NEW
347

×
NEW
348
        // Randomly decide which optional fields to include
×
NEW
349
        includeDustLimit := rapid.Bool().Draw(t, "includeDustLimit")
×
NEW
350
        includeMaxValueInFlight := rapid.Bool().Draw(
×
NEW
351
                t, "includeMaxValueInFlight",
×
NEW
352
        )
×
NEW
353
        includeChannelReserve := rapid.Bool().Draw(t, "includeChannelReserve")
×
NEW
354
        includeCsvDelay := rapid.Bool().Draw(t, "includeCsvDelay")
×
NEW
355
        includeMaxAcceptedHTLCs := rapid.Bool().Draw(
×
NEW
356
                t, "includeMaxAcceptedHTLCs",
×
NEW
357
        )
×
NEW
358
        includeFundingKey := rapid.Bool().Draw(t, "includeFundingKey")
×
NEW
359
        includeChannelType := rapid.Bool().Draw(t, "includeChannelType")
×
NEW
360
        includeKickoffFeerate := rapid.Bool().Draw(t, "includeKickoffFeerate")
×
NEW
361

×
NEW
362
        // Generate random values for each included field
×
NEW
363
        if includeDustLimit {
×
NEW
364
                dl := btcutil.Amount(rapid.Uint32().Draw(t, "dustLimit"))
×
NEW
365
                msg.DustLimit = fn.Some(dl)
×
NEW
366
        }
×
367

NEW
368
        if includeMaxValueInFlight {
×
NEW
369
                mvif := MilliSatoshi(rapid.Uint64().Draw(t, "maxValueInFlight"))
×
NEW
370
                msg.MaxValueInFlight = fn.Some(mvif)
×
NEW
371
        }
×
372

NEW
373
        if includeChannelReserve {
×
NEW
374
                cr := btcutil.Amount(rapid.Uint32().Draw(t, "channelReserve"))
×
NEW
375
                msg.ChannelReserve = fn.Some(cr)
×
NEW
376
        }
×
377

NEW
378
        if includeCsvDelay {
×
NEW
379
                cd := uint16(rapid.Uint16().Draw(t, "csvDelay"))
×
NEW
380
                msg.CsvDelay = fn.Some(cd)
×
NEW
381
        }
×
382

NEW
383
        if includeMaxAcceptedHTLCs {
×
NEW
384
                mah := uint16(rapid.Uint16().Draw(t, "maxAcceptedHTLCs"))
×
NEW
385
                msg.MaxAcceptedHTLCs = fn.Some(mah)
×
NEW
386
        }
×
387

NEW
388
        if includeFundingKey {
×
NEW
389
                msg.FundingKey = fn.Some(*RandPubKey(t))
×
NEW
390
        }
×
391

NEW
392
        if includeChannelType {
×
NEW
393
                msg.ChannelType = fn.Some(*RandChannelType(t))
×
NEW
394
        }
×
395

NEW
396
        if includeKickoffFeerate {
×
NEW
397
                kf := chainfee.SatPerKWeight(rapid.Uint32().Draw(
×
NEW
398
                        t, "kickoffFeerate"),
×
NEW
399
                )
×
NEW
400
                msg.KickoffFeerate = fn.Some(kf)
×
NEW
401
        }
×
402

NEW
403
        return msg
×
404
}
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