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

lightningnetwork / lnd / 12115442155

02 Dec 2024 08:28AM UTC coverage: 48.662% (-10.3%) from 58.948%
12115442155

Pull #9175

github

ellemouton
netann: update ChanAnn2 validation to work for P2WSH channels

This commit expands the ChannelAnnouncement2 validation for the case
where it is announcing a P2WSH channel.
Pull Request #9175: lnwire+netann: update structure of g175 messages to be pure TLV

6 of 314 new or added lines in 9 files covered. (1.91%)

27532 existing lines in 434 files now uncovered.

97890 of 201164 relevant lines covered (48.66%)

0.52 hits per line

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

68.38
/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
// MessageType is the unique 2 byte big-endian integer that indicates the type
16
// of message on the wire. All messages have a very simple header which
17
// consists simply of 2-byte message type. We omit a length field, and checksum
18
// as the Lightning Protocol is intended to be encapsulated within a
19
// confidential+authenticated cryptographic messaging protocol.
20
type MessageType uint16
21

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

66
// IsChannelUpdate is a filter function that discerns channel update messages
67
// from the other messages in the Lightning Network Protocol.
68
func (t MessageType) IsChannelUpdate() bool {
1✔
69
        switch t {
1✔
70
        case MsgUpdateAddHTLC:
1✔
71
                return true
1✔
72
        case MsgUpdateFulfillHTLC:
1✔
73
                return true
1✔
74
        case MsgUpdateFailHTLC:
1✔
75
                return true
1✔
76
        case MsgUpdateFailMalformedHTLC:
1✔
77
                return true
1✔
UNCOV
78
        case MsgUpdateFee:
×
UNCOV
79
                return true
×
80
        default:
1✔
81
                return false
1✔
82
        }
83
}
84

85
// ErrorEncodeMessage is used when failed to encode the message payload.
UNCOV
86
func ErrorEncodeMessage(err error) error {
×
UNCOV
87
        return fmt.Errorf("failed to encode message to buffer, got %w", err)
×
UNCOV
88
}
×
89

90
// ErrorWriteMessageType is used when failed to write the message type.
91
func ErrorWriteMessageType(err error) error {
×
92
        return fmt.Errorf("failed to write message type, got %w", err)
×
93
}
×
94

95
// ErrorPayloadTooLarge is used when the payload size exceeds the
96
// MaxMsgBody.
UNCOV
97
func ErrorPayloadTooLarge(size int) error {
×
UNCOV
98
        return fmt.Errorf(
×
UNCOV
99
                "message payload is too large - encoded %d bytes, "+
×
UNCOV
100
                        "but maximum message payload is %d bytes",
×
UNCOV
101
                size, MaxMsgBody,
×
UNCOV
102
        )
×
UNCOV
103
}
×
104

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

191
// UnknownMessage is an implementation of the error interface that allows the
192
// creation of an error in response to an unknown message.
193
type UnknownMessage struct {
194
        messageType MessageType
195
}
196

197
// Error returns a human readable string describing the error.
198
//
199
// This is part of the error interface.
200
func (u *UnknownMessage) Error() string {
1✔
201
        return fmt.Sprintf("unable to parse message of unknown type: %v",
1✔
202
                u.messageType)
1✔
203
}
1✔
204

205
// Serializable is an interface which defines a lightning wire serializable
206
// object.
207
type Serializable interface {
208
        // Decode reads the bytes stream and converts it to the object.
209
        Decode(io.Reader, uint32) error
210

211
        // Encode converts object to the bytes stream and write it into the
212
        // write buffer.
213
        Encode(*bytes.Buffer, uint32) error
214
}
215

216
// Message is an interface that defines a lightning wire protocol message. The
217
// interface is general in order to allow implementing types full control over
218
// the representation of its data.
219
type Message interface {
220
        Serializable
221
        MsgType() MessageType
222
}
223

224
// LinkUpdater is an interface implemented by most messages in BOLT 2 that are
225
// allowed to update the channel state.
226
type LinkUpdater interface {
227
        // All LinkUpdater messages are messages and so we embed the interface
228
        // so that we can treat it as a message if all we know about it is that
229
        // it is a LinkUpdater message.
230
        Message
231

232
        // TargetChanID returns the channel id of the link for which this
233
        // message is intended.
234
        TargetChanID() ChannelID
235
}
236

237
// makeEmptyMessage creates a new empty message of the proper concrete type
238
// based on the passed message type.
239
func makeEmptyMessage(msgType MessageType) (Message, error) {
1✔
240
        var msg Message
1✔
241

1✔
242
        switch msgType {
1✔
UNCOV
243
        case MsgWarning:
×
UNCOV
244
                msg = &Warning{}
×
245
        case MsgStfu:
1✔
246
                msg = &Stfu{}
1✔
247
        case MsgInit:
1✔
248
                msg = &Init{}
1✔
249
        case MsgOpenChannel:
1✔
250
                msg = &OpenChannel{}
1✔
251
        case MsgAcceptChannel:
1✔
252
                msg = &AcceptChannel{}
1✔
253
        case MsgFundingCreated:
1✔
254
                msg = &FundingCreated{}
1✔
255
        case MsgFundingSigned:
1✔
256
                msg = &FundingSigned{}
1✔
257
        case MsgChannelReady:
1✔
258
                msg = &ChannelReady{}
1✔
259
        case MsgShutdown:
1✔
260
                msg = &Shutdown{}
1✔
261
        case MsgClosingSigned:
1✔
262
                msg = &ClosingSigned{}
1✔
UNCOV
263
        case MsgDynPropose:
×
UNCOV
264
                msg = &DynPropose{}
×
UNCOV
265
        case MsgDynAck:
×
UNCOV
266
                msg = &DynAck{}
×
UNCOV
267
        case MsgDynReject:
×
UNCOV
268
                msg = &DynReject{}
×
UNCOV
269
        case MsgKickoffSig:
×
UNCOV
270
                msg = &KickoffSig{}
×
271
        case MsgUpdateAddHTLC:
1✔
272
                msg = &UpdateAddHTLC{}
1✔
273
        case MsgUpdateFailHTLC:
1✔
274
                msg = &UpdateFailHTLC{}
1✔
275
        case MsgUpdateFulfillHTLC:
1✔
276
                msg = &UpdateFulfillHTLC{}
1✔
277
        case MsgCommitSig:
1✔
278
                msg = &CommitSig{}
1✔
279
        case MsgRevokeAndAck:
1✔
280
                msg = &RevokeAndAck{}
1✔
UNCOV
281
        case MsgUpdateFee:
×
UNCOV
282
                msg = &UpdateFee{}
×
283
        case MsgUpdateFailMalformedHTLC:
1✔
284
                msg = &UpdateFailMalformedHTLC{}
1✔
285
        case MsgChannelReestablish:
1✔
286
                msg = &ChannelReestablish{}
1✔
287
        case MsgError:
1✔
288
                msg = &Error{}
1✔
289
        case MsgChannelAnnouncement:
1✔
290
                msg = &ChannelAnnouncement1{}
1✔
291
        case MsgChannelUpdate:
1✔
292
                msg = &ChannelUpdate1{}
1✔
293
        case MsgNodeAnnouncement:
1✔
294
                msg = &NodeAnnouncement{}
1✔
UNCOV
295
        case MsgPing:
×
UNCOV
296
                msg = &Ping{}
×
297
        case MsgAnnounceSignatures:
1✔
298
                msg = &AnnounceSignatures1{}
1✔
UNCOV
299
        case MsgPong:
×
UNCOV
300
                msg = &Pong{}
×
301
        case MsgQueryShortChanIDs:
1✔
302
                msg = &QueryShortChanIDs{}
1✔
303
        case MsgReplyShortChanIDsEnd:
1✔
304
                msg = &ReplyShortChanIDsEnd{}
1✔
305
        case MsgQueryChannelRange:
1✔
306
                msg = &QueryChannelRange{}
1✔
307
        case MsgReplyChannelRange:
1✔
308
                msg = &ReplyChannelRange{}
1✔
309
        case MsgGossipTimestampRange:
1✔
310
                msg = &GossipTimestampRange{}
1✔
UNCOV
311
        case MsgClosingComplete:
×
UNCOV
312
                msg = &ClosingComplete{}
×
UNCOV
313
        case MsgClosingSig:
×
UNCOV
314
                msg = &ClosingSig{}
×
UNCOV
315
        case MsgAnnounceSignatures2:
×
UNCOV
316
                msg = &AnnounceSignatures2{}
×
UNCOV
317
        case MsgChannelAnnouncement2:
×
UNCOV
318
                msg = &ChannelAnnouncement2{}
×
UNCOV
319
        case MsgChannelUpdate2:
×
UNCOV
320
                msg = &ChannelUpdate2{}
×
321
        default:
1✔
322
                // If the message is not within our custom range and has not
1✔
323
                // specifically been overridden, return an unknown message.
1✔
324
                //
1✔
325
                // Note that we do not allow custom message overrides to replace
1✔
326
                // known message types, only protocol messages that are not yet
1✔
327
                // known to lnd.
1✔
328
                if msgType < CustomTypeStart && !IsCustomOverride(msgType) {
2✔
329
                        return nil, &UnknownMessage{msgType}
1✔
330
                }
1✔
331

332
                msg = &Custom{
1✔
333
                        Type: msgType,
1✔
334
                }
1✔
335
        }
336

337
        return msg, nil
1✔
338
}
339

340
// WriteMessage writes a lightning Message to a buffer including the necessary
341
// header information and returns the number of bytes written. If any error is
342
// encountered, the buffer passed will be reset to its original state since we
343
// don't want any broken bytes left. In other words, no bytes will be written
344
// if there's an error. Either all or none of the message bytes will be written
345
// to the buffer.
346
//
347
// NOTE: this method is not concurrent safe.
348
func WriteMessage(buf *bytes.Buffer, msg Message, pver uint32) (int, error) {
1✔
349
        // Record the size of the bytes already written in buffer.
1✔
350
        oldByteSize := buf.Len()
1✔
351

1✔
352
        // cleanBrokenBytes is a helper closure that helps reset the buffer to
1✔
353
        // its original state. It truncates all the bytes written in current
1✔
354
        // scope.
1✔
355
        var cleanBrokenBytes = func(b *bytes.Buffer) int {
1✔
UNCOV
356
                b.Truncate(oldByteSize)
×
UNCOV
357
                return 0
×
UNCOV
358
        }
×
359

360
        // Write the message type.
361
        var mType [2]byte
1✔
362
        binary.BigEndian.PutUint16(mType[:], uint16(msg.MsgType()))
1✔
363
        msgTypeBytes, err := buf.Write(mType[:])
1✔
364
        if err != nil {
1✔
365
                return cleanBrokenBytes(buf), ErrorWriteMessageType(err)
×
366
        }
×
367

368
        // Use the write buffer to encode our message.
369
        if err := msg.Encode(buf, pver); err != nil {
1✔
UNCOV
370
                return cleanBrokenBytes(buf), ErrorEncodeMessage(err)
×
UNCOV
371
        }
×
372

373
        // Enforce maximum overall message payload. The write buffer now has
374
        // the size of len(originalBytes) + len(payload) + len(type). We want
375
        // to enforce the payload here, so we subtract it by the length of the
376
        // type and old bytes.
377
        lenp := buf.Len() - oldByteSize - msgTypeBytes
1✔
378
        if lenp > MaxMsgBody {
1✔
UNCOV
379
                return cleanBrokenBytes(buf), ErrorPayloadTooLarge(lenp)
×
UNCOV
380
        }
×
381

382
        return buf.Len() - oldByteSize, nil
1✔
383
}
384

385
// ReadMessage reads, validates, and parses the next Lightning message from r
386
// for the provided protocol version.
387
func ReadMessage(r io.Reader, pver uint32) (Message, error) {
1✔
388
        // First, we'll read out the first two bytes of the message so we can
1✔
389
        // create the proper empty message.
1✔
390
        var mType [2]byte
1✔
391
        if _, err := io.ReadFull(r, mType[:]); err != nil {
1✔
392
                return nil, err
×
393
        }
×
394

395
        msgType := MessageType(binary.BigEndian.Uint16(mType[:]))
1✔
396

1✔
397
        // Now that we know the target message type, we can create the proper
1✔
398
        // empty message type and decode the message into it.
1✔
399
        msg, err := makeEmptyMessage(msgType)
1✔
400
        if err != nil {
2✔
401
                return nil, err
1✔
402
        }
1✔
403
        if err := msg.Decode(r, pver); err != nil {
1✔
UNCOV
404
                return nil, err
×
UNCOV
405
        }
×
406

407
        return msg, nil
1✔
408
}
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