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

lightningnetwork / lnd / 15561477203

10 Jun 2025 01:54PM UTC coverage: 58.351% (-10.1%) from 68.487%
15561477203

Pull #9356

github

web-flow
Merge 6440b25db into c6d6d4c0b
Pull Request #9356: lnrpc: add incoming/outgoing channel ids filter to forwarding history request

33 of 36 new or added lines in 2 files covered. (91.67%)

28366 existing lines in 455 files now uncovered.

97715 of 167461 relevant lines covered (58.35%)

1.81 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
)
13

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

×
UNCOV
183
        tlvStream, err := tlv.NewStream(tlvRecords...)
×
UNCOV
184
        if err != nil {
×
185
                return err
×
186
        }
×
187

UNCOV
188
        var extraBytesWriter bytes.Buffer
×
UNCOV
189
        if err := tlvStream.Encode(&extraBytesWriter); err != nil {
×
190
                return err
×
191
        }
×
UNCOV
192
        dp.ExtraData = ExtraOpaqueData(extraBytesWriter.Bytes())
×
UNCOV
193

×
UNCOV
194
        if err := WriteChannelID(w, dp.ChanID); err != nil {
×
195
                return err
×
196
        }
×
197

UNCOV
198
        if err := WriteBool(w, dp.Initiator); err != nil {
×
199
                return err
×
200
        }
×
201

UNCOV
202
        return WriteBytes(w, dp.ExtraData)
×
203
}
204

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

216
        // Parse out TLV stream.
UNCOV
217
        var tlvRecords ExtraOpaqueData
×
UNCOV
218
        if err := ReadElements(r, &tlvRecords); err != nil {
×
219
                return err
×
220
        }
×
221

222
        // Prepare receiving buffers to be filled by TLV extraction.
UNCOV
223
        var dustLimitScratch uint64
×
UNCOV
224
        dustLimit := tlv.MakePrimitiveRecord(
×
UNCOV
225
                DPDustLimitSatoshis, &dustLimitScratch,
×
UNCOV
226
        )
×
UNCOV
227

×
UNCOV
228
        var maxValueScratch uint64
×
UNCOV
229
        maxValue := tlv.MakePrimitiveRecord(
×
UNCOV
230
                DPMaxHtlcValueInFlightMsat, &maxValueScratch,
×
UNCOV
231
        )
×
UNCOV
232

×
UNCOV
233
        var reserveScratch uint64
×
UNCOV
234
        reserve := tlv.MakePrimitiveRecord(
×
UNCOV
235
                DPChannelReserveSatoshis, &reserveScratch,
×
UNCOV
236
        )
×
UNCOV
237

×
UNCOV
238
        var csvDelayScratch uint16
×
UNCOV
239
        csvDelay := tlv.MakePrimitiveRecord(DPToSelfDelay, &csvDelayScratch)
×
UNCOV
240

×
UNCOV
241
        var maxHtlcsScratch uint16
×
UNCOV
242
        maxHtlcs := tlv.MakePrimitiveRecord(
×
UNCOV
243
                DPMaxAcceptedHtlcs, &maxHtlcsScratch,
×
UNCOV
244
        )
×
UNCOV
245

×
UNCOV
246
        var fundingKeyScratch *btcec.PublicKey
×
UNCOV
247
        fundingKey := tlv.MakePrimitiveRecord(
×
UNCOV
248
                DPFundingPubkey, &fundingKeyScratch,
×
UNCOV
249
        )
×
UNCOV
250

×
UNCOV
251
        var chanTypeScratch ChannelType
×
UNCOV
252
        chanType := tlv.MakeDynamicRecord(
×
UNCOV
253
                DPChannelType, &chanTypeScratch, chanTypeScratch.featureBitLen,
×
UNCOV
254
                channelTypeEncoder, channelTypeDecoder,
×
UNCOV
255
        )
×
UNCOV
256

×
UNCOV
257
        var kickoffFeerateScratch uint32
×
UNCOV
258
        kickoffFeerate := tlv.MakePrimitiveRecord(
×
UNCOV
259
                DPKickoffFeerate, &kickoffFeerateScratch,
×
UNCOV
260
        )
×
UNCOV
261

×
UNCOV
262
        // Create set of Records to read TLV bytestream into.
×
UNCOV
263
        records := []tlv.Record{
×
UNCOV
264
                dustLimit, maxValue, reserve, csvDelay, maxHtlcs, fundingKey,
×
UNCOV
265
                chanType, kickoffFeerate,
×
UNCOV
266
        }
×
UNCOV
267
        tlv.SortRecords(records)
×
UNCOV
268

×
UNCOV
269
        // Read TLV stream into record set.
×
UNCOV
270
        extraBytesReader := bytes.NewReader(tlvRecords)
×
UNCOV
271
        tlvStream, err := tlv.NewStream(records...)
×
UNCOV
272
        if err != nil {
×
273
                return err
×
274
        }
×
275

UNCOV
276
        typeMap, err := tlvStream.DecodeWithParsedTypesP2P(extraBytesReader)
×
UNCOV
277
        if err != nil {
×
UNCOV
278
                return err
×
UNCOV
279
        }
×
280

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

UNCOV
310
        if len(tlvRecords) != 0 {
×
UNCOV
311
                dp.ExtraData = tlvRecords
×
UNCOV
312
        }
×
313

UNCOV
314
        return nil
×
315
}
316

317
// MsgType returns the MessageType code which uniquely identifies this message
318
// as a DynPropose on the wire.
319
//
320
// This is part of the lnwire.Message interface.
UNCOV
321
func (dp *DynPropose) MsgType() MessageType {
×
UNCOV
322
        return MsgDynPropose
×
UNCOV
323
}
×
324

325
// SerializedSize returns the serialized size of the message in bytes.
326
//
327
// This is part of the lnwire.SizeableMessage interface.
328
func (dp *DynPropose) SerializedSize() (uint32, error) {
×
329
        return MessageSerializedSize(dp)
×
330
}
×
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