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

lightningnetwork / lnd / 15858991938

24 Jun 2025 06:51PM UTC coverage: 55.808% (-2.4%) from 58.173%
15858991938

Pull #9148

github

web-flow
Merge 0e921d6a5 into 29ff13d83
Pull Request #9148: DynComms [2/n]: lnwire: add authenticated wire messages for Dyn*

232 of 267 new or added lines in 5 files covered. (86.89%)

24606 existing lines in 281 files now uncovered.

108380 of 194201 relevant lines covered (55.81%)

22488.12 hits per line

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

78.74
/lnwire/dyn_propose.go
1
package lnwire
2

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

7
        "github.com/btcsuite/btcd/btcutil"
8
        "github.com/lightningnetwork/lnd/tlv"
9
)
10

11
// DynPropose is a message that is sent during a dynamic commitments negotiation
12
// process. It is sent by both parties to propose new channel parameters.
13
type DynPropose struct {
14
        // ChanID identifies the channel whose parameters we are trying to
15
        // re-negotiate.
16
        ChanID ChannelID
17

18
        // DustLimit, if not nil, proposes a change to the dust_limit_satoshis
19
        // for the sender's commitment transaction.
20
        DustLimit tlv.OptionalRecordT[tlv.TlvType0, btcutil.Amount]
21

22
        // MaxValueInFlight, if not nil, proposes a change to the
23
        // max_htlc_value_in_flight_msat limit of the sender.
24
        MaxValueInFlight tlv.OptionalRecordT[tlv.TlvType2, MilliSatoshi]
25

26
        // HtlcMinimum, if not nil, proposes a change to the htlc_minimum_msat
27
        // floor of the sender.
28
        HtlcMinimum tlv.OptionalRecordT[tlv.TlvType4, MilliSatoshi]
29

30
        // ChannelReserve, if not nil, proposes a change to the
31
        // channel_reserve_satoshis requirement of the recipient.
32
        ChannelReserve tlv.OptionalRecordT[tlv.TlvType6, btcutil.Amount]
33

34
        // CsvDelay, if not nil, proposes a change to the to_self_delay
35
        // requirement of the recipient.
36
        CsvDelay tlv.OptionalRecordT[tlv.TlvType8, uint16]
37

38
        // MaxAcceptedHTLCs, if not nil, proposes a change to the
39
        // max_accepted_htlcs limit of the sender.
40
        MaxAcceptedHTLCs tlv.OptionalRecordT[tlv.TlvType10, uint16]
41

42
        // ChannelType, if not nil, proposes a change to the channel_type
43
        // parameter.
44
        ChannelType tlv.OptionalRecordT[tlv.TlvType12, ChannelType]
45

46
        // ExtraData is the set of data that was appended to this message to
47
        // fill out the full maximum transport message size. These fields can
48
        // be used to specify optional data such as custom TLV fields.
49
        //
50
        // NOTE: Since the fields in this structure are part of the TLV stream,
51
        // ExtraData will contain all TLV records _except_ the ones that are
52
        // present in earlier parts of this structure.
53
        ExtraData ExtraOpaqueData
54
}
55

56
// A compile time check to ensure DynPropose implements the lnwire.Message
57
// interface.
58
var _ Message = (*DynPropose)(nil)
59

60
// A compile time check to ensure DynPropose implements the
61
// lnwire.SizeableMessage interface.
62
var _ SizeableMessage = (*DynPropose)(nil)
63

64
// Encode serializes the target DynPropose into the passed io.Writer.
65
// Serialization will observe the rules defined by the passed protocol version.
66
//
67
// This is a part of the lnwire.Message interface.
68
func (dp *DynPropose) Encode(w *bytes.Buffer, _ uint32) error {
103✔
69
        if err := WriteChannelID(w, dp.ChanID); err != nil {
103✔
70
                return err
×
71
        }
×
72

73
        producers := dynProposeRecords(dp)
103✔
74

103✔
75
        err := EncodeMessageExtraData(&dp.ExtraData, producers...)
103✔
76
        if err != nil {
103✔
77
                return err
×
78
        }
×
79

80
        return WriteBytes(w, dp.ExtraData)
103✔
81
}
82

83
// Decode deserializes the serialized DynPropose stored in the passed io.Reader
84
// into the target DynPropose using the deserialization rules defined by the
85
// passed protocol version.
86
//
87
// This is a part of the lnwire.Message interface.
88
func (dp *DynPropose) Decode(r io.Reader, _ uint32) error {
208✔
89
        // Parse out the only required field.
208✔
90
        if err := ReadElements(r, &dp.ChanID); err != nil {
210✔
91
                return err
2✔
92
        }
2✔
93

94
        // Parse out TLV stream.
95
        var tlvRecords ExtraOpaqueData
206✔
96
        if err := ReadElements(r, &tlvRecords); err != nil {
206✔
97
                return err
×
98
        }
×
99

100
        // Prepare receiving buffers to be filled by TLV extraction.
101
        var dustLimit tlv.RecordT[tlv.TlvType0, uint64]
206✔
102
        var maxValue tlv.RecordT[tlv.TlvType2, uint64]
206✔
103
        var htlcMin tlv.RecordT[tlv.TlvType4, uint64]
206✔
104
        var reserve tlv.RecordT[tlv.TlvType6, uint64]
206✔
105
        csvDelay := dp.CsvDelay.Zero()
206✔
106
        maxHtlcs := dp.MaxAcceptedHTLCs.Zero()
206✔
107
        chanType := dp.ChannelType.Zero()
206✔
108

206✔
109
        typeMap, err := tlvRecords.ExtractRecords(
206✔
110
                &dustLimit, &maxValue, &htlcMin, &reserve, &csvDelay, &maxHtlcs,
206✔
111
                &chanType,
206✔
112
        )
206✔
113
        if err != nil {
306✔
114
                return err
100✔
115
        }
100✔
116

117
        // Check the results of the TLV Stream decoding and appropriately set
118
        // message fields.
119
        if val, ok := typeMap[dp.DustLimit.TlvType()]; ok && val == nil {
156✔
120
                var rec tlv.RecordT[tlv.TlvType0, btcutil.Amount]
50✔
121
                rec.Val = btcutil.Amount(dustLimit.Val)
50✔
122
                dp.DustLimit = tlv.SomeRecordT(rec)
50✔
123
        }
50✔
124
        if val, ok := typeMap[dp.MaxValueInFlight.TlvType()]; ok && val == nil {
150✔
125
                var rec tlv.RecordT[tlv.TlvType2, MilliSatoshi]
44✔
126
                rec.Val = MilliSatoshi(maxValue.Val)
44✔
127
                dp.MaxValueInFlight = tlv.SomeRecordT(rec)
44✔
128
        }
44✔
129
        if val, ok := typeMap[dp.HtlcMinimum.TlvType()]; ok && val == nil {
106✔
NEW
130
                var rec tlv.RecordT[tlv.TlvType4, MilliSatoshi]
×
NEW
131
                rec.Val = MilliSatoshi(htlcMin.Val)
×
NEW
132
                dp.HtlcMinimum = tlv.SomeRecordT(rec)
×
133
        }
×
134
        if val, ok := typeMap[dp.ChannelReserve.TlvType()]; ok && val == nil {
163✔
135
                var rec tlv.RecordT[tlv.TlvType6, btcutil.Amount]
57✔
136
                rec.Val = btcutil.Amount(reserve.Val)
57✔
137
                dp.ChannelReserve = tlv.SomeRecordT(rec)
57✔
138
        }
57✔
139
        if val, ok := typeMap[dp.CsvDelay.TlvType()]; ok && val == nil {
152✔
140
                dp.CsvDelay = tlv.SomeRecordT(csvDelay)
46✔
141
        }
46✔
142
        if val, ok := typeMap[dp.MaxAcceptedHTLCs.TlvType()]; ok && val == nil {
156✔
143
                dp.MaxAcceptedHTLCs = tlv.SomeRecordT(maxHtlcs)
50✔
144
        }
50✔
145
        if val, ok := typeMap[dp.ChannelType.TlvType()]; ok && val == nil {
162✔
146
                dp.ChannelType = tlv.SomeRecordT(chanType)
56✔
147
        }
56✔
148

149
        if len(tlvRecords) != 0 {
207✔
150
                dp.ExtraData = tlvRecords
101✔
151
        }
101✔
152

153
        return nil
106✔
154
}
155

156
// MsgType returns the MessageType code which uniquely identifies this message
157
// as a DynPropose on the wire.
158
//
159
// This is part of the lnwire.Message interface.
160
func (dp *DynPropose) MsgType() MessageType {
103✔
161
        return MsgDynPropose
103✔
162
}
103✔
163

164
// SerializedSize returns the serialized size of the message in bytes.
165
//
166
// This is part of the lnwire.SizeableMessage interface.
167
func (dp *DynPropose) SerializedSize() (uint32, error) {
×
168
        return MessageSerializedSize(dp)
×
169
}
×
170

171
// SerializeTlvData takes just the TLV data of DynPropose (which covers all of
172
// the parameters on deck for changing) and serializes just this component. The
173
// main purpose of this is to make it easier to validate the DynAck signature.
NEW
174
func (dp *DynPropose) SerializeTlvData() ([]byte, error) {
×
NEW
175
        producers := dynProposeRecords(dp)
×
NEW
176

×
NEW
177
        var extra ExtraOpaqueData
×
NEW
178
        err := extra.PackRecords(producers...)
×
NEW
179
        if err != nil {
×
NEW
180
                return nil, err
×
NEW
181
        }
×
182

NEW
183
        return extra, nil
×
184
}
185

186
func dynProposeRecords(dp *DynPropose) []tlv.RecordProducer {
203✔
187
        recordProducers := make([]tlv.RecordProducer, 0, 7)
203✔
188

203✔
189
        dp.DustLimit.WhenSome(
203✔
190
                func(dl tlv.RecordT[tlv.TlvType0, btcutil.Amount]) {
311✔
191
                        rec := tlv.NewPrimitiveRecord[tlv.TlvType0](
108✔
192
                                uint64(dl.Val),
108✔
193
                        )
108✔
194
                        recordProducers = append(recordProducers, &rec)
108✔
195
                },
108✔
196
        )
197
        dp.MaxValueInFlight.WhenSome(
203✔
198
                func(max tlv.RecordT[tlv.TlvType2, MilliSatoshi]) {
302✔
199
                        rec := tlv.NewPrimitiveRecord[tlv.TlvType2](
99✔
200
                                uint64(max.Val),
99✔
201
                        )
99✔
202
                        recordProducers = append(recordProducers, &rec)
99✔
203
                },
99✔
204
        )
205
        dp.HtlcMinimum.WhenSome(
203✔
206
                func(min tlv.RecordT[tlv.TlvType4, MilliSatoshi]) {
203✔
NEW
207
                        rec := tlv.NewPrimitiveRecord[tlv.TlvType4](
×
NEW
208
                                uint64(min.Val),
×
NEW
209
                        )
×
NEW
210
                        recordProducers = append(recordProducers, &rec)
×
NEW
211
                },
×
212
        )
213
        dp.ChannelReserve.WhenSome(
203✔
214
                func(reserve tlv.RecordT[tlv.TlvType6, btcutil.Amount]) {
310✔
215
                        rec := tlv.NewPrimitiveRecord[tlv.TlvType6](
107✔
216
                                uint64(reserve.Val),
107✔
217
                        )
107✔
218
                        recordProducers = append(recordProducers, &rec)
107✔
219
                },
107✔
220
        )
221
        dp.CsvDelay.WhenSome(
203✔
222
                func(wait tlv.RecordT[tlv.TlvType8, uint16]) {
289✔
223
                        recordProducers = append(recordProducers, &wait)
86✔
224
                },
86✔
225
        )
226
        dp.MaxAcceptedHTLCs.WhenSome(
203✔
227
                func(max tlv.RecordT[tlv.TlvType10, uint16]) {
296✔
228
                        recordProducers = append(recordProducers, &max)
93✔
229
                },
93✔
230
        )
231
        dp.ChannelType.WhenSome(
203✔
232
                func(ty tlv.RecordT[tlv.TlvType12, ChannelType]) {
309✔
233
                        recordProducers = append(recordProducers, &ty)
106✔
234
                },
106✔
235
        )
236

237
        return recordProducers
203✔
238
}
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