• 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

30.66
/lnwire/channel_update.go
1
package lnwire
2

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

8
        "github.com/btcsuite/btcd/chaincfg/chainhash"
9
        "pgregory.net/rapid"
10
)
11

12
// ChanUpdateMsgFlags is a bitfield that signals whether optional fields are
13
// present in the ChannelUpdate.
14
type ChanUpdateMsgFlags uint8
15

16
const (
17
        // ChanUpdateRequiredMaxHtlc is a bit that indicates whether the
18
        // required htlc_maximum_msat field is present in this ChannelUpdate.
19
        ChanUpdateRequiredMaxHtlc ChanUpdateMsgFlags = 1 << iota
20
)
21

22
// String returns the bitfield flags as a string.
23
func (c ChanUpdateMsgFlags) String() string {
3✔
24
        return fmt.Sprintf("%08b", c)
3✔
25
}
3✔
26

27
// HasMaxHtlc returns true if the htlc_maximum_msat option bit is set in the
28
// message flags.
29
func (c ChanUpdateMsgFlags) HasMaxHtlc() bool {
3✔
30
        return c&ChanUpdateRequiredMaxHtlc != 0
3✔
31
}
3✔
32

33
// ChanUpdateChanFlags is a bitfield that signals various options concerning a
34
// particular channel edge. Each bit is to be examined in order to determine
35
// how the ChannelUpdate message is to be interpreted.
36
type ChanUpdateChanFlags uint8
37

38
const (
39
        // ChanUpdateDirection indicates the direction of a channel update. If
40
        // this bit is set to 0 if Node1 (the node with the "smaller" Node ID)
41
        // is updating the channel, and to 1 otherwise.
42
        ChanUpdateDirection ChanUpdateChanFlags = 1 << iota
43

44
        // ChanUpdateDisabled is a bit that indicates if the channel edge
45
        // selected by the ChanUpdateDirection bit is to be treated as being
46
        // disabled.
47
        ChanUpdateDisabled
48
)
49

50
// IsDisabled determines whether the channel flags has the disabled bit set.
51
func (c ChanUpdateChanFlags) IsDisabled() bool {
3✔
52
        return c&ChanUpdateDisabled == ChanUpdateDisabled
3✔
53
}
3✔
54

55
// String returns the bitfield flags as a string.
56
func (c ChanUpdateChanFlags) String() string {
3✔
57
        return fmt.Sprintf("%08b", c)
3✔
58
}
3✔
59

60
// ChannelUpdate1 message is used after channel has been initially announced.
61
// Each side independently announces its fees and minimum expiry for HTLCs and
62
// other parameters. Also this message is used to redeclare initially set
63
// channel parameters.
64
type ChannelUpdate1 struct {
65
        // Signature is used to validate the announced data and prove the
66
        // ownership of node id.
67
        Signature Sig
68

69
        // ChainHash denotes the target chain that this channel was opened
70
        // within. This value should be the genesis hash of the target chain.
71
        // Along with the short channel ID, this uniquely identifies the
72
        // channel globally in a blockchain.
73
        ChainHash chainhash.Hash
74

75
        // ShortChannelID is the unique description of the funding transaction.
76
        ShortChannelID ShortChannelID
77

78
        // Timestamp allows ordering in the case of multiple announcements. We
79
        // should ignore the message if timestamp is not greater than
80
        // the last-received.
81
        Timestamp uint32
82

83
        // MessageFlags is a bitfield that describes whether optional fields
84
        // are present in this update. Currently, the least-significant bit
85
        // must be set to 1 if the optional field MaxHtlc is present.
86
        MessageFlags ChanUpdateMsgFlags
87

88
        // ChannelFlags is a bitfield that describes additional meta-data
89
        // concerning how the update is to be interpreted. Currently, the
90
        // least-significant bit must be set to 0 if the creating node
91
        // corresponds to the first node in the previously sent channel
92
        // announcement and 1 otherwise. If the second bit is set, then the
93
        // channel is set to be disabled.
94
        ChannelFlags ChanUpdateChanFlags
95

96
        // TimeLockDelta is the minimum number of blocks this node requires to
97
        // be added to the expiry of HTLCs. This is a security parameter
98
        // determined by the node operator. This value represents the required
99
        // gap between the time locks of the incoming and outgoing HTLC's set
100
        // to this node.
101
        TimeLockDelta uint16
102

103
        // HtlcMinimumMsat is the minimum HTLC value which will be accepted.
104
        HtlcMinimumMsat MilliSatoshi
105

106
        // BaseFee is the base fee that must be used for incoming HTLC's to
107
        // this particular channel. This value will be tacked onto the required
108
        // for a payment independent of the size of the payment.
109
        BaseFee uint32
110

111
        // FeeRate is the fee rate that will be charged per millionth of a
112
        // satoshi.
113
        FeeRate uint32
114

115
        // HtlcMaximumMsat is the maximum HTLC value which will be accepted.
116
        HtlcMaximumMsat MilliSatoshi
117

118
        // ExtraData is the set of data that was appended to this message to
119
        // fill out the full maximum transport message size. These fields can
120
        // be used to specify optional data such as custom TLV fields.
121
        ExtraOpaqueData ExtraOpaqueData
122
}
123

124
// A compile time check to ensure ChannelUpdate implements the lnwire.Message
125
// interface.
126
var _ Message = (*ChannelUpdate1)(nil)
127

128
// A compile time check to ensure ChannelUpdate1 implements the lnwire.SizeableMessage interface.
129
var _ SizeableMessage = (*ChannelUpdate1)(nil)
130

131
// Decode deserializes a serialized ChannelUpdate stored in the passed
132
// io.Reader observing the specified protocol version.
133
//
134
// This is part of the lnwire.Message interface.
135
func (a *ChannelUpdate1) Decode(r io.Reader, pver uint32) error {
3✔
136
        err := ReadElements(r,
3✔
137
                &a.Signature,
3✔
138
                a.ChainHash[:],
3✔
139
                &a.ShortChannelID,
3✔
140
                &a.Timestamp,
3✔
141
                &a.MessageFlags,
3✔
142
                &a.ChannelFlags,
3✔
143
                &a.TimeLockDelta,
3✔
144
                &a.HtlcMinimumMsat,
3✔
145
                &a.BaseFee,
3✔
146
                &a.FeeRate,
3✔
147
        )
3✔
148
        if err != nil {
3✔
UNCOV
149
                return err
×
UNCOV
150
        }
×
151

152
        // Now check whether the max HTLC field is present and read it if so.
153
        if a.MessageFlags.HasMaxHtlc() {
6✔
154
                if err := ReadElements(r, &a.HtlcMaximumMsat); err != nil {
3✔
UNCOV
155
                        return err
×
UNCOV
156
                }
×
157
        }
158

159
        return a.ExtraOpaqueData.Decode(r)
3✔
160
}
161

162
// Encode serializes the target ChannelUpdate into the passed io.Writer
163
// observing the protocol version specified.
164
//
165
// This is part of the lnwire.Message interface.
166
func (a *ChannelUpdate1) Encode(w *bytes.Buffer, pver uint32) error {
3✔
167
        if err := WriteSig(w, a.Signature); err != nil {
3✔
UNCOV
168
                return err
×
169
        }
×
170

171
        if err := WriteBytes(w, a.ChainHash[:]); err != nil {
3✔
UNCOV
172
                return err
×
173
        }
×
174

175
        if err := WriteShortChannelID(w, a.ShortChannelID); err != nil {
3✔
UNCOV
176
                return err
×
177
        }
×
178

179
        if err := WriteUint32(w, a.Timestamp); err != nil {
3✔
UNCOV
180
                return err
×
181
        }
×
182

183
        if err := WriteChanUpdateMsgFlags(w, a.MessageFlags); err != nil {
3✔
UNCOV
184
                return err
×
185
        }
×
186

187
        if err := WriteChanUpdateChanFlags(w, a.ChannelFlags); err != nil {
3✔
UNCOV
188
                return err
×
189
        }
×
190

191
        if err := WriteUint16(w, a.TimeLockDelta); err != nil {
3✔
UNCOV
192
                return err
×
193
        }
×
194

195
        if err := WriteMilliSatoshi(w, a.HtlcMinimumMsat); err != nil {
3✔
UNCOV
196
                return err
×
197
        }
×
198

199
        if err := WriteUint32(w, a.BaseFee); err != nil {
3✔
UNCOV
200
                return err
×
201
        }
×
202

203
        if err := WriteUint32(w, a.FeeRate); err != nil {
3✔
UNCOV
204
                return err
×
205
        }
×
206

207
        // Now append optional fields if they are set. Currently, the only
208
        // optional field is max HTLC.
209
        if a.MessageFlags.HasMaxHtlc() {
6✔
210
                err := WriteMilliSatoshi(w, a.HtlcMaximumMsat)
3✔
211
                if err != nil {
3✔
UNCOV
212
                        return err
×
213
                }
×
214
        }
215

216
        // Finally, append any extra opaque data.
217
        return WriteBytes(w, a.ExtraOpaqueData)
3✔
218
}
219

220
// MsgType returns the integer uniquely identifying this message type on the
221
// wire.
222
//
223
// This is part of the lnwire.Message interface.
224
func (a *ChannelUpdate1) MsgType() MessageType {
3✔
225
        return MsgChannelUpdate
3✔
226
}
3✔
227

228
// DataToSign is used to retrieve part of the announcement message which should
229
// be signed.
230
func (a *ChannelUpdate1) DataToSign() ([]byte, error) {
3✔
231
        // We should not include the signatures itself.
3✔
232
        b := make([]byte, 0, MaxMsgBody)
3✔
233
        buf := bytes.NewBuffer(b)
3✔
234
        if err := WriteBytes(buf, a.ChainHash[:]); err != nil {
3✔
UNCOV
235
                return nil, err
×
236
        }
×
237

238
        if err := WriteShortChannelID(buf, a.ShortChannelID); err != nil {
3✔
UNCOV
239
                return nil, err
×
240
        }
×
241

242
        if err := WriteUint32(buf, a.Timestamp); err != nil {
3✔
UNCOV
243
                return nil, err
×
244
        }
×
245

246
        if err := WriteChanUpdateMsgFlags(buf, a.MessageFlags); err != nil {
3✔
UNCOV
247
                return nil, err
×
248
        }
×
249

250
        if err := WriteChanUpdateChanFlags(buf, a.ChannelFlags); err != nil {
3✔
UNCOV
251
                return nil, err
×
252
        }
×
253

254
        if err := WriteUint16(buf, a.TimeLockDelta); err != nil {
3✔
UNCOV
255
                return nil, err
×
256
        }
×
257

258
        if err := WriteMilliSatoshi(buf, a.HtlcMinimumMsat); err != nil {
3✔
UNCOV
259
                return nil, err
×
260
        }
×
261

262
        if err := WriteUint32(buf, a.BaseFee); err != nil {
3✔
UNCOV
263
                return nil, err
×
264
        }
×
265

266
        if err := WriteUint32(buf, a.FeeRate); err != nil {
3✔
UNCOV
267
                return nil, err
×
268
        }
×
269

270
        // Now append optional fields if they are set. Currently, the only
271
        // optional field is max HTLC.
272
        if a.MessageFlags.HasMaxHtlc() {
6✔
273
                err := WriteMilliSatoshi(buf, a.HtlcMaximumMsat)
3✔
274
                if err != nil {
3✔
UNCOV
275
                        return nil, err
×
276
                }
×
277
        }
278

279
        // Finally, append any extra opaque data.
280
        if err := WriteBytes(buf, a.ExtraOpaqueData); err != nil {
3✔
UNCOV
281
                return nil, err
×
282
        }
×
283

284
        return buf.Bytes(), nil
3✔
285
}
286

287
// SCID returns the ShortChannelID of the channel that the update applies to.
288
//
289
// NOTE: this is part of the ChannelUpdate interface.
UNCOV
290
func (a *ChannelUpdate1) SCID() ShortChannelID {
×
291
        return a.ShortChannelID
×
292
}
×
293

294
// IsNode1 is true if the update was produced by node 1 of the channel peers.
295
// Node 1 is the node with the lexicographically smaller public key.
296
//
297
// NOTE: this is part of the ChannelUpdate interface.
UNCOV
298
func (a *ChannelUpdate1) IsNode1() bool {
×
299
        return a.ChannelFlags&ChanUpdateDirection == 0
×
300
}
×
301

302
// IsDisabled is true if the update is announcing that the channel should be
303
// considered disabled.
304
//
305
// NOTE: this is part of the ChannelUpdate interface.
UNCOV
306
func (a *ChannelUpdate1) IsDisabled() bool {
×
307
        return a.ChannelFlags&ChanUpdateDisabled == ChanUpdateDisabled
×
308
}
×
309

310
// GetChainHash returns the hash of the chain that the message is referring to.
311
//
312
// NOTE: this is part of the ChannelUpdate interface.
UNCOV
313
func (a *ChannelUpdate1) GetChainHash() chainhash.Hash {
×
314
        return a.ChainHash
×
315
}
×
316

317
// ForwardingPolicy returns the set of forwarding constraints of the update.
318
//
319
// NOTE: this is part of the ChannelUpdate interface.
UNCOV
320
func (a *ChannelUpdate1) ForwardingPolicy() *ForwardingPolicy {
×
321
        return &ForwardingPolicy{
×
322
                TimeLockDelta: a.TimeLockDelta,
×
323
                BaseFee:       MilliSatoshi(a.BaseFee),
×
324
                FeeRate:       MilliSatoshi(a.FeeRate),
×
325
                MinHTLC:       a.HtlcMinimumMsat,
×
326
                HasMaxHTLC:    a.MessageFlags.HasMaxHtlc(),
×
327
                MaxHTLC:       a.HtlcMaximumMsat,
×
328
        }
×
329
}
×
330

331
// CmpAge can be used to determine if the update is older or newer than the
332
// passed update. It returns 1 if this update is newer, -1 if it is older, and
333
// 0 if they are the same age.
334
//
335
// NOTE: this is part of the ChannelUpdate interface.
UNCOV
336
func (a *ChannelUpdate1) CmpAge(update ChannelUpdate) (CompareResult, error) {
×
337
        other, ok := update.(*ChannelUpdate1)
×
338
        if !ok {
×
339
                return 0, fmt.Errorf("expected *ChannelUpdate1, got: %T",
×
340
                        update)
×
341
        }
×
342

UNCOV
343
        switch {
×
344
        case a.Timestamp > other.Timestamp:
×
345
                return GreaterThan, nil
×
346
        case a.Timestamp < other.Timestamp:
×
347
                return LessThan, nil
×
348
        default:
×
349
                return EqualTo, nil
×
350
        }
351
}
352

353
// SetDisabledFlag can be used to adjust the disabled flag of an update.
354
//
355
// NOTE: this is part of the ChannelUpdate interface.
UNCOV
356
func (a *ChannelUpdate1) SetDisabledFlag(disabled bool) {
×
357
        if disabled {
×
358
                a.ChannelFlags |= ChanUpdateDisabled
×
359
        } else {
×
360
                a.ChannelFlags &= ^ChanUpdateDisabled
×
361
        }
×
362
}
363

364
// SetSCID can be used to overwrite the SCID of the update.
365
//
366
// NOTE: this is part of the ChannelUpdate interface.
UNCOV
367
func (a *ChannelUpdate1) SetSCID(scid ShortChannelID) {
×
368
        a.ShortChannelID = scid
×
369
}
×
370

371
// A compile time assertion to ensure ChannelUpdate1 implements the
372
// ChannelUpdate interface.
373
var _ ChannelUpdate = (*ChannelUpdate1)(nil)
374

375
// SerializedSize returns the serialized size of the message in bytes.
376
//
377
// This is part of the lnwire.SizeableMessage interface.
NEW
378
func (a *ChannelUpdate1) SerializedSize() (uint32, error) {
×
NEW
379
        return MessageSerializedSize(a)
×
NEW
380
}
×
381

382
// A compile time check to ensure ChannelUpdate1 implements the TestMessage interface.
383
var _ TestMessage = (*ChannelUpdate1)(nil)
384

385
// RandTestMessage populates the message with random data suitable for testing.
386
// It uses the rapid testing framework to generate random values.
387
//
388
// This is part of the TestMessage interface.
NEW
389
func (a *ChannelUpdate1) RandTestMessage(t *rapid.T) Message {
×
NEW
390
        // Generate random message flags
×
NEW
391
        // Randomly decide whether to include max HTLC field
×
NEW
392
        includeMaxHtlc := rapid.Bool().Draw(t, "includeMaxHtlc")
×
NEW
393
        var msgFlags ChanUpdateMsgFlags
×
NEW
394
        if includeMaxHtlc {
×
NEW
395
                msgFlags |= ChanUpdateRequiredMaxHtlc
×
NEW
396
        }
×
397

398
        // Generate random channel flags
399
        // Randomly decide direction (node1 or node2)
NEW
400
        isNode2 := rapid.Bool().Draw(t, "isNode2")
×
NEW
401
        var chanFlags ChanUpdateChanFlags
×
NEW
402
        if isNode2 {
×
NEW
403
                chanFlags |= ChanUpdateDirection
×
NEW
404
        }
×
405

406
        // Randomly decide if channel is disabled
NEW
407
        isDisabled := rapid.Bool().Draw(t, "isDisabled")
×
NEW
408
        if isDisabled {
×
NEW
409
                chanFlags |= ChanUpdateDisabled
×
NEW
410
        }
×
411

412
        // Generate chain hash
NEW
413
        chainHash := RandChainHash(t)
×
NEW
414
        var hash chainhash.Hash
×
NEW
415
        copy(hash[:], chainHash[:])
×
NEW
416

×
NEW
417
        // Generate other random fields
×
NEW
418
        maxHtlc := MilliSatoshi(rapid.Uint64().Draw(t, "maxHtlc"))
×
NEW
419

×
NEW
420
        // If max HTLC flag is not set, we need to zero the value
×
NEW
421
        if !includeMaxHtlc {
×
NEW
422
                maxHtlc = 0
×
NEW
423
        }
×
424

NEW
425
        return &ChannelUpdate1{
×
NEW
426
                Signature:      RandSignature(t),
×
NEW
427
                ChainHash:      hash,
×
NEW
428
                ShortChannelID: RandShortChannelID(t),
×
NEW
429
                Timestamp: uint32(rapid.IntRange(0, 0x7FFFFFFF).Draw(
×
NEW
430
                        t, "timestamp"),
×
NEW
431
                ),
×
NEW
432
                MessageFlags: msgFlags,
×
NEW
433
                ChannelFlags: chanFlags,
×
NEW
434
                TimeLockDelta: uint16(rapid.IntRange(0, 65535).Draw(
×
NEW
435
                        t, "timelockDelta"),
×
NEW
436
                ),
×
NEW
437
                HtlcMinimumMsat: MilliSatoshi(rapid.Uint64().Draw(
×
NEW
438
                        t, "htlcMinimum"),
×
NEW
439
                ),
×
NEW
440
                BaseFee: uint32(rapid.IntRange(0, 0x7FFFFFFF).Draw(
×
NEW
441
                        t, "baseFee"),
×
NEW
442
                ),
×
NEW
443
                FeeRate: uint32(rapid.IntRange(0, 0x7FFFFFFF).Draw(
×
NEW
444
                        t, "feeRate"),
×
NEW
445
                ),
×
NEW
446
                HtlcMaximumMsat: maxHtlc,
×
NEW
447
                ExtraOpaqueData: RandExtraOpaqueData(t, nil),
×
NEW
448
        }
×
449
}
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