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

lightningnetwork / lnd / 19155841408

07 Nov 2025 02:03AM UTC coverage: 66.675% (-0.04%) from 66.712%
19155841408

Pull #10352

github

web-flow
Merge e4313eba8 into 096ab65b1
Pull Request #10352: [WIP] chainrpc: return Unavailable while notifier starts

137328 of 205965 relevant lines covered (66.68%)

21333.36 hits per line

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

97.43
/lnwire/message.go
1
// Copyright (c) 2013-2017 The btcsuite developers
2
// Copyright (c) 2015-2016 The Decred developers
3
// code derived from https://github .com/btcsuite/btcd/blob/master/wire/message.go
4
// Copyright (C) 2015-2022 The Lightning Network Developers
5

6
package lnwire
7

8
import (
9
        "bytes"
10
        "encoding/binary"
11
        "fmt"
12
        "io"
13
)
14

15
// MessageTypeSize is the size in bytes of the message type field in the header
16
// of all messages.
17
const MessageTypeSize = 2
18

19
// MessageType is the unique 2 byte big-endian integer that indicates the type
20
// of message on the wire. All messages have a very simple header which
21
// consists simply of 2-byte message type. We omit a length field, and checksum
22
// as the Lightning Protocol is intended to be encapsulated within a
23
// confidential+authenticated cryptographic messaging protocol.
24
type MessageType uint16
25

26
// The currently defined message types within this current version of the
27
// Lightning protocol.
28
const (
29
        MsgWarning                 MessageType = 1
30
        MsgStfu                                = 2
31
        MsgInit                                = 16
32
        MsgError                               = 17
33
        MsgPing                                = 18
34
        MsgPong                                = 19
35
        MsgOpenChannel                         = 32
36
        MsgAcceptChannel                       = 33
37
        MsgFundingCreated                      = 34
38
        MsgFundingSigned                       = 35
39
        MsgChannelReady                        = 36
40
        MsgShutdown                            = 38
41
        MsgClosingSigned                       = 39
42
        MsgClosingComplete                     = 40
43
        MsgClosingSig                          = 41
44
        MsgDynPropose                          = 111
45
        MsgDynAck                              = 113
46
        MsgDynReject                           = 115
47
        MsgDynCommit                           = 117
48
        MsgUpdateAddHTLC                       = 128
49
        MsgUpdateFulfillHTLC                   = 130
50
        MsgUpdateFailHTLC                      = 131
51
        MsgCommitSig                           = 132
52
        MsgRevokeAndAck                        = 133
53
        MsgUpdateFee                           = 134
54
        MsgUpdateFailMalformedHTLC             = 135
55
        MsgChannelReestablish                  = 136
56
        MsgChannelAnnouncement                 = 256
57
        MsgNodeAnnouncement                    = 257
58
        MsgChannelUpdate                       = 258
59
        MsgAnnounceSignatures                  = 259
60
        MsgAnnounceSignatures2                 = 260
61
        MsgQueryShortChanIDs                   = 261
62
        MsgReplyShortChanIDsEnd                = 262
63
        MsgQueryChannelRange                   = 263
64
        MsgReplyChannelRange                   = 264
65
        MsgGossipTimestampRange                = 265
66
        MsgChannelAnnouncement2                = 267
67
        MsgNodeAnnouncement2                   = 269
68
        MsgChannelUpdate2                      = 271
69
        MsgKickoffSig                          = 777
70

71
        // MsgEnd defines the end of the official message range of the protocol.
72
        // If a new message is added beyond this message, then this should be
73
        // modified.
74
        MsgEnd = 778
75
)
76

77
// IsChannelUpdate is a filter function that discerns channel update messages
78
// from the other messages in the Lightning Network Protocol.
79
func (t MessageType) IsChannelUpdate() bool {
3,706✔
80
        switch t {
3,706✔
81
        case MsgUpdateAddHTLC:
933✔
82
                return true
933✔
83
        case MsgUpdateFulfillHTLC:
253✔
84
                return true
253✔
85
        case MsgUpdateFailHTLC:
141✔
86
                return true
141✔
87
        case MsgUpdateFailMalformedHTLC:
6✔
88
                return true
6✔
89
        case MsgUpdateFee:
3✔
90
                return true
3✔
91
        default:
2,382✔
92
                return false
2,382✔
93
        }
94
}
95

96
// ErrorEncodeMessage is used when failed to encode the message payload.
97
func ErrorEncodeMessage(err error) error {
4✔
98
        return fmt.Errorf("failed to encode message to buffer, got %w", err)
4✔
99
}
4✔
100

101
// ErrorWriteMessageType is used when failed to write the message type.
102
func ErrorWriteMessageType(err error) error {
×
103
        return fmt.Errorf("failed to write message type, got %w", err)
×
104
}
×
105

106
// ErrorPayloadTooLarge is used when the payload size exceeds the
107
// MaxMsgBody.
108
func ErrorPayloadTooLarge(size int) error {
2✔
109
        return fmt.Errorf(
2✔
110
                "message payload is too large - encoded %d bytes, "+
2✔
111
                        "but maximum message payload is %d bytes",
2✔
112
                size, MaxMsgBody,
2✔
113
        )
2✔
114
}
2✔
115

116
// String return the string representation of message type.
117
func (t MessageType) String() string {
44✔
118
        switch t {
44✔
119
        case MsgWarning:
1✔
120
                return "Warning"
1✔
121
        case MsgStfu:
4✔
122
                return "Stfu"
4✔
123
        case MsgInit:
4✔
124
                return "Init"
4✔
125
        case MsgOpenChannel:
4✔
126
                return "MsgOpenChannel"
4✔
127
        case MsgAcceptChannel:
4✔
128
                return "MsgAcceptChannel"
4✔
129
        case MsgFundingCreated:
4✔
130
                return "MsgFundingCreated"
4✔
131
        case MsgFundingSigned:
4✔
132
                return "MsgFundingSigned"
4✔
133
        case MsgChannelReady:
4✔
134
                return "ChannelReady"
4✔
135
        case MsgShutdown:
4✔
136
                return "Shutdown"
4✔
137
        case MsgClosingSigned:
4✔
138
                return "ClosingSigned"
4✔
139
        case MsgDynPropose:
1✔
140
                return "DynPropose"
1✔
141
        case MsgDynAck:
1✔
142
                return "DynAck"
1✔
143
        case MsgDynReject:
1✔
144
                return "DynReject"
1✔
145
        case MsgDynCommit:
1✔
146
                return "DynCommit"
1✔
147
        case MsgKickoffSig:
1✔
148
                return "KickoffSig"
1✔
149
        case MsgUpdateAddHTLC:
4✔
150
                return "UpdateAddHTLC"
4✔
151
        case MsgUpdateFailHTLC:
4✔
152
                return "UpdateFailHTLC"
4✔
153
        case MsgUpdateFulfillHTLC:
4✔
154
                return "UpdateFulfillHTLC"
4✔
155
        case MsgCommitSig:
4✔
156
                return "CommitSig"
4✔
157
        case MsgRevokeAndAck:
4✔
158
                return "RevokeAndAck"
4✔
159
        case MsgUpdateFailMalformedHTLC:
4✔
160
                return "UpdateFailMalformedHTLC"
4✔
161
        case MsgChannelReestablish:
4✔
162
                return "ChannelReestablish"
4✔
163
        case MsgError:
4✔
164
                return "Error"
4✔
165
        case MsgChannelAnnouncement:
4✔
166
                return "ChannelAnnouncement"
4✔
167
        case MsgChannelUpdate:
4✔
168
                return "ChannelUpdate"
4✔
169
        case MsgNodeAnnouncement:
4✔
170
                return "NodeAnnouncement1"
4✔
171
        case MsgPing:
1✔
172
                return "Ping"
1✔
173
        case MsgAnnounceSignatures:
4✔
174
                return "AnnounceSignatures"
4✔
175
        case MsgPong:
1✔
176
                return "Pong"
1✔
177
        case MsgUpdateFee:
1✔
178
                return "UpdateFee"
1✔
179
        case MsgQueryShortChanIDs:
4✔
180
                return "QueryShortChanIDs"
4✔
181
        case MsgReplyShortChanIDsEnd:
4✔
182
                return "ReplyShortChanIDsEnd"
4✔
183
        case MsgQueryChannelRange:
4✔
184
                return "QueryChannelRange"
4✔
185
        case MsgReplyChannelRange:
4✔
186
                return "ReplyChannelRange"
4✔
187
        case MsgGossipTimestampRange:
4✔
188
                return "GossipTimestampRange"
4✔
189
        case MsgClosingComplete:
4✔
190
                return "ClosingComplete"
4✔
191
        case MsgClosingSig:
4✔
192
                return "ClosingSig"
4✔
193
        case MsgAnnounceSignatures2:
1✔
194
                return "MsgAnnounceSignatures2"
1✔
195
        case MsgChannelAnnouncement2:
1✔
196
                return "ChannelAnnouncement2"
1✔
197
        case MsgNodeAnnouncement2:
1✔
198
                return "NodeAnnouncement2"
1✔
199
        case MsgChannelUpdate2:
1✔
200
                return "ChannelUpdate2"
1✔
201
        default:
3✔
202
                return "<unknown>"
3✔
203
        }
204
}
205

206
// UnknownMessage is an implementation of the error interface that allows the
207
// creation of an error in response to an unknown message.
208
type UnknownMessage struct {
209
        messageType MessageType
210
}
211

212
// Error returns a human readable string describing the error.
213
//
214
// This is part of the error interface.
215
func (u *UnknownMessage) Error() string {
3✔
216
        return fmt.Sprintf("unable to parse message of unknown type: %v",
3✔
217
                u.messageType)
3✔
218
}
3✔
219

220
// Serializable is an interface which defines a lightning wire serializable
221
// object.
222
type Serializable interface {
223
        // Decode reads the bytes stream and converts it to the object.
224
        Decode(io.Reader, uint32) error
225

226
        // Encode converts object to the bytes stream and write it into the
227
        // write buffer.
228
        Encode(*bytes.Buffer, uint32) error
229
}
230

231
// Message is an interface that defines a lightning wire protocol message. The
232
// interface is general in order to allow implementing types full control over
233
// the representation of its data.
234
type Message interface {
235
        Serializable
236
        MsgType() MessageType
237
}
238

239
// LinkUpdater is an interface implemented by most messages in BOLT 2 that are
240
// allowed to update the channel state.
241
type LinkUpdater interface {
242
        // All LinkUpdater messages are messages and so we embed the interface
243
        // so that we can treat it as a message if all we know about it is that
244
        // it is a LinkUpdater message.
245
        Message
246

247
        // TargetChanID returns the channel id of the link for which this
248
        // message is intended.
249
        TargetChanID() ChannelID
250
}
251

252
// SizeableMessage is an interface that extends the base Message interface with
253
// a method to calculate the serialized size of a message.
254
type SizeableMessage interface {
255
        Message
256

257
        // SerializedSize returns the serialized size of the message in bytes.
258
        // The returned size includes the message type header bytes.
259
        SerializedSize() (uint32, error)
260
}
261

262
// MessageSerializedSize calculates the serialized size of a message in bytes.
263
// This is a helper function that can be used by all message types to implement
264
// the SerializedSize method.
265
func MessageSerializedSize(msg Message) (uint32, error) {
196✔
266
        var buf bytes.Buffer
196✔
267

196✔
268
        // Encode the message to the buffer.
196✔
269
        if err := msg.Encode(&buf, 0); err != nil {
200✔
270
                return 0, err
4✔
271
        }
4✔
272

273
        // Add the size of the message type.
274
        return uint32(buf.Len()) + MessageTypeSize, nil
192✔
275
}
276

277
// makeEmptyMessage creates a new empty message of the proper concrete type
278
// based on the passed message type.
279
func makeEmptyMessage(msgType MessageType) (Message, error) {
20,207✔
280
        var msg Message
20,207✔
281

20,207✔
282
        switch msgType {
20,207✔
283
        case MsgWarning:
225✔
284
                msg = &Warning{}
225✔
285
        case MsgStfu:
245✔
286
                msg = &Stfu{}
245✔
287
        case MsgInit:
265✔
288
                msg = &Init{}
265✔
289
        case MsgOpenChannel:
371✔
290
                msg = &OpenChannel{}
371✔
291
        case MsgAcceptChannel:
337✔
292
                msg = &AcceptChannel{}
337✔
293
        case MsgFundingCreated:
277✔
294
                msg = &FundingCreated{}
277✔
295
        case MsgFundingSigned:
272✔
296
                msg = &FundingSigned{}
272✔
297
        case MsgChannelReady:
297✔
298
                msg = &ChannelReady{}
297✔
299
        case MsgShutdown:
289✔
300
                msg = &Shutdown{}
289✔
301
        case MsgClosingSigned:
277✔
302
                msg = &ClosingSigned{}
277✔
303
        case MsgDynPropose:
369✔
304
                msg = &DynPropose{}
369✔
305
        case MsgDynAck:
304✔
306
                msg = &DynAck{}
304✔
307
        case MsgDynReject:
260✔
308
                msg = &DynReject{}
260✔
309
        case MsgDynCommit:
287✔
310
                msg = &DynCommit{}
287✔
311
        case MsgKickoffSig:
230✔
312
                msg = &KickoffSig{}
230✔
313
        case MsgUpdateAddHTLC:
2,458✔
314
                msg = &UpdateAddHTLC{}
2,458✔
315
        case MsgUpdateFailHTLC:
674✔
316
                msg = &UpdateFailHTLC{}
674✔
317
        case MsgUpdateFulfillHTLC:
1,245✔
318
                msg = &UpdateFulfillHTLC{}
1,245✔
319
        case MsgCommitSig:
2,428✔
320
                msg = &CommitSig{}
2,428✔
321
        case MsgRevokeAndAck:
267✔
322
                msg = &RevokeAndAck{}
267✔
323
        case MsgUpdateFee:
304✔
324
                msg = &UpdateFee{}
304✔
325
        case MsgUpdateFailMalformedHTLC:
239✔
326
                msg = &UpdateFailMalformedHTLC{}
239✔
327
        case MsgChannelReestablish:
280✔
328
                msg = &ChannelReestablish{}
280✔
329
        case MsgError:
217✔
330
                msg = &Error{}
217✔
331
        case MsgChannelAnnouncement:
253✔
332
                msg = &ChannelAnnouncement1{}
253✔
333
        case MsgChannelUpdate:
268✔
334
                msg = &ChannelUpdate1{}
268✔
335
        case MsgNodeAnnouncement:
596✔
336
                msg = &NodeAnnouncement1{}
596✔
337
        case MsgPing:
213✔
338
                msg = &Ping{}
213✔
339
        case MsgAnnounceSignatures:
232✔
340
                msg = &AnnounceSignatures1{}
232✔
341
        case MsgPong:
210✔
342
                msg = &Pong{}
210✔
343
        case MsgQueryShortChanIDs:
1,261✔
344
                msg = &QueryShortChanIDs{}
1,261✔
345
        case MsgReplyShortChanIDsEnd:
234✔
346
                msg = &ReplyShortChanIDsEnd{}
234✔
347
        case MsgQueryChannelRange:
303✔
348
                msg = &QueryChannelRange{}
303✔
349
        case MsgReplyChannelRange:
1,320✔
350
                msg = &ReplyChannelRange{}
1,320✔
351
        case MsgGossipTimestampRange:
281✔
352
                msg = &GossipTimestampRange{}
281✔
353
        case MsgClosingComplete:
294✔
354
                msg = &ClosingComplete{}
294✔
355
        case MsgClosingSig:
281✔
356
                msg = &ClosingSig{}
281✔
357
        case MsgAnnounceSignatures2:
282✔
358
                msg = &AnnounceSignatures2{}
282✔
359
        case MsgChannelAnnouncement2:
352✔
360
                msg = &ChannelAnnouncement2{}
352✔
361
        case MsgNodeAnnouncement2:
324✔
362
                msg = &NodeAnnouncement2{}
324✔
363
        case MsgChannelUpdate2:
339✔
364
                msg = &ChannelUpdate2{}
339✔
365
        default:
831✔
366
                // If the message is not within our custom range and has not
831✔
367
                // specifically been overridden, return an unknown message.
831✔
368
                //
831✔
369
                // Note that we do not allow custom message overrides to replace
831✔
370
                // known message types, only protocol messages that are not yet
831✔
371
                // known to lnd.
831✔
372
                if msgType < CustomTypeStart && !IsCustomOverride(msgType) {
1,647✔
373
                        return nil, &UnknownMessage{msgType}
816✔
374
                }
816✔
375

376
                msg = &Custom{
18✔
377
                        Type: msgType,
18✔
378
                }
18✔
379
        }
380

381
        return msg, nil
19,394✔
382
}
383

384
// MakeEmptyMessage creates a new empty message of the proper concrete type
385
// based on the passed message type. This is exported to be used in tests.
386
func MakeEmptyMessage(msgType MessageType) (Message, error) {
4,978✔
387
        return makeEmptyMessage(msgType)
4,978✔
388
}
4,978✔
389

390
// WriteMessage writes a lightning Message to a buffer including the necessary
391
// header information and returns the number of bytes written. If any error is
392
// encountered, the buffer passed will be reset to its original state since we
393
// don't want any broken bytes left. In other words, no bytes will be written
394
// if there's an error. Either all or none of the message bytes will be written
395
// to the buffer.
396
//
397
// NOTE: this method is not concurrent safe.
398
func WriteMessage(buf *bytes.Buffer, msg Message, pver uint32) (int, error) {
13,385✔
399
        // Record the size of the bytes already written in buffer.
13,385✔
400
        oldByteSize := buf.Len()
13,385✔
401

13,385✔
402
        // cleanBrokenBytes is a helper closure that helps reset the buffer to
13,385✔
403
        // its original state. It truncates all the bytes written in current
13,385✔
404
        // scope.
13,385✔
405
        var cleanBrokenBytes = func(b *bytes.Buffer) int {
13,389✔
406
                b.Truncate(oldByteSize)
4✔
407
                return 0
4✔
408
        }
4✔
409

410
        // Write the message type.
411
        var mType [2]byte
13,385✔
412
        binary.BigEndian.PutUint16(mType[:], uint16(msg.MsgType()))
13,385✔
413
        msgTypeBytes, err := buf.Write(mType[:])
13,385✔
414
        if err != nil {
13,385✔
415
                return cleanBrokenBytes(buf), ErrorWriteMessageType(err)
×
416
        }
×
417

418
        // Use the write buffer to encode our message.
419
        if err := msg.Encode(buf, pver); err != nil {
13,388✔
420
                return cleanBrokenBytes(buf), ErrorEncodeMessage(err)
3✔
421
        }
3✔
422

423
        // Enforce maximum overall message payload. The write buffer now has
424
        // the size of len(originalBytes) + len(payload) + len(type). We want
425
        // to enforce the payload here, so we subtract it by the length of the
426
        // type and old bytes.
427
        lenp := buf.Len() - oldByteSize - msgTypeBytes
13,382✔
428
        if lenp > MaxMsgBody {
13,383✔
429
                return cleanBrokenBytes(buf), ErrorPayloadTooLarge(lenp)
1✔
430
        }
1✔
431

432
        return buf.Len() - oldByteSize, nil
13,381✔
433
}
434

435
// ReadMessage reads, validates, and parses the next Lightning message from r
436
// for the provided protocol version.
437
func ReadMessage(r io.Reader, pver uint32) (Message, error) {
15,228✔
438
        // First, we'll read out the first two bytes of the message so we can
15,228✔
439
        // create the proper empty message.
15,228✔
440
        var mType [2]byte
15,228✔
441
        if _, err := io.ReadFull(r, mType[:]); err != nil {
15,228✔
442
                return nil, err
×
443
        }
×
444

445
        msgType := MessageType(binary.BigEndian.Uint16(mType[:]))
15,228✔
446

15,228✔
447
        // Now that we know the target message type, we can create the proper
15,228✔
448
        // empty message type and decode the message into it.
15,228✔
449
        msg, err := makeEmptyMessage(msgType)
15,228✔
450
        if err != nil {
15,231✔
451
                return nil, err
3✔
452
        }
3✔
453
        if err := msg.Decode(r, pver); err != nil {
17,645✔
454
                return nil, err
2,417✔
455
        }
2,417✔
456

457
        return msg, nil
12,811✔
458
}
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