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

lightningnetwork / lnd / 13211764208

08 Feb 2025 03:08AM UTC coverage: 49.288% (-9.5%) from 58.815%
13211764208

Pull #9489

github

calvinrzachman
itest: verify switchrpc server enforces send then track

We prevent the rpc server from allowing onion dispatches for
attempt IDs which have already been tracked by rpc clients.

This helps protect the client from leaking a duplicate onion
attempt. NOTE: This is not the only method for solving this
issue! The issue could be addressed via careful client side
programming which accounts for the uncertainty and async
nature of dispatching onions to a remote process via RPC.
This would require some lnd ChannelRouter changes for how
we intend to use these RPCs though.
Pull Request #9489: multi: add BuildOnion, SendOnion, and TrackOnion RPCs

474 of 990 new or added lines in 11 files covered. (47.88%)

27321 existing lines in 435 files now uncovered.

101192 of 205306 relevant lines covered (49.29%)

1.54 hits per line

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

0.0
/channeldb/migration/lnwire21/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
// MaxMessagePayload is the maximum bytes a message can be regardless of other
16
// individual limits imposed by messages themselves.
17
const MaxMessagePayload = 65535 // 65KB
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
        MsgInit                    MessageType = 16
30
        MsgError                               = 17
31
        MsgPing                                = 18
32
        MsgPong                                = 19
33
        MsgOpenChannel                         = 32
34
        MsgAcceptChannel                       = 33
35
        MsgFundingCreated                      = 34
36
        MsgFundingSigned                       = 35
37
        MsgFundingLocked                       = 36
38
        MsgShutdown                            = 38
39
        MsgClosingSigned                       = 39
40
        MsgUpdateAddHTLC                       = 128
41
        MsgUpdateFulfillHTLC                   = 130
42
        MsgUpdateFailHTLC                      = 131
43
        MsgCommitSig                           = 132
44
        MsgRevokeAndAck                        = 133
45
        MsgUpdateFee                           = 134
46
        MsgUpdateFailMalformedHTLC             = 135
47
        MsgChannelReestablish                  = 136
48
        MsgChannelAnnouncement                 = 256
49
        MsgNodeAnnouncement                    = 257
50
        MsgChannelUpdate                       = 258
51
        MsgAnnounceSignatures                  = 259
52
        MsgQueryShortChanIDs                   = 261
53
        MsgReplyShortChanIDsEnd                = 262
54
        MsgQueryChannelRange                   = 263
55
        MsgReplyChannelRange                   = 264
56
        MsgGossipTimestampRange                = 265
57
)
58

59
// String return the string representation of message type.
60
func (t MessageType) String() string {
×
61
        switch t {
×
62
        case MsgInit:
×
63
                return "Init"
×
64
        case MsgOpenChannel:
×
65
                return "MsgOpenChannel"
×
66
        case MsgAcceptChannel:
×
67
                return "MsgAcceptChannel"
×
68
        case MsgFundingCreated:
×
69
                return "MsgFundingCreated"
×
70
        case MsgFundingSigned:
×
71
                return "MsgFundingSigned"
×
72
        case MsgFundingLocked:
×
73
                return "FundingLocked"
×
74
        case MsgShutdown:
×
75
                return "Shutdown"
×
76
        case MsgClosingSigned:
×
77
                return "ClosingSigned"
×
78
        case MsgUpdateAddHTLC:
×
79
                return "UpdateAddHTLC"
×
80
        case MsgUpdateFailHTLC:
×
81
                return "UpdateFailHTLC"
×
82
        case MsgUpdateFulfillHTLC:
×
83
                return "UpdateFulfillHTLC"
×
84
        case MsgCommitSig:
×
85
                return "CommitSig"
×
86
        case MsgRevokeAndAck:
×
87
                return "RevokeAndAck"
×
88
        case MsgUpdateFailMalformedHTLC:
×
89
                return "UpdateFailMalformedHTLC"
×
90
        case MsgChannelReestablish:
×
91
                return "ChannelReestablish"
×
92
        case MsgError:
×
93
                return "Error"
×
94
        case MsgChannelAnnouncement:
×
95
                return "ChannelAnnouncement"
×
96
        case MsgChannelUpdate:
×
97
                return "ChannelUpdate"
×
98
        case MsgNodeAnnouncement:
×
99
                return "NodeAnnouncement"
×
100
        case MsgPing:
×
101
                return "Ping"
×
102
        case MsgAnnounceSignatures:
×
103
                return "AnnounceSignatures"
×
104
        case MsgPong:
×
105
                return "Pong"
×
106
        case MsgUpdateFee:
×
107
                return "UpdateFee"
×
108
        case MsgQueryShortChanIDs:
×
109
                return "QueryShortChanIDs"
×
110
        case MsgReplyShortChanIDsEnd:
×
111
                return "ReplyShortChanIDsEnd"
×
112
        case MsgQueryChannelRange:
×
113
                return "QueryChannelRange"
×
114
        case MsgReplyChannelRange:
×
115
                return "ReplyChannelRange"
×
116
        case MsgGossipTimestampRange:
×
117
                return "GossipTimestampRange"
×
118
        default:
×
119
                return "<unknown>"
×
120
        }
121
}
122

123
// UnknownMessage is an implementation of the error interface that allows the
124
// creation of an error in response to an unknown message.
125
type UnknownMessage struct {
126
        messageType MessageType
127
}
128

129
// Error returns a human readable string describing the error.
130
//
131
// This is part of the error interface.
132
func (u *UnknownMessage) Error() string {
×
133
        return fmt.Sprintf("unable to parse message of unknown type: %v",
×
134
                u.messageType)
×
135
}
×
136

137
// Serializable is an interface which defines a lightning wire serializable
138
// object.
139
type Serializable interface {
140
        // Decode reads the bytes stream and converts it to the object.
141
        Decode(io.Reader, uint32) error
142

143
        // Encode converts object to the bytes stream and write it into the
144
        // writer.
145
        Encode(io.Writer, uint32) error
146
}
147

148
// Message is an interface that defines a lightning wire protocol message. The
149
// interface is general in order to allow implementing types full control over
150
// the representation of its data.
151
type Message interface {
152
        Serializable
153
        MsgType() MessageType
154
        MaxPayloadLength(uint32) uint32
155
}
156

157
// makeEmptyMessage creates a new empty message of the proper concrete type
158
// based on the passed message type.
UNCOV
159
func makeEmptyMessage(msgType MessageType) (Message, error) {
×
UNCOV
160
        var msg Message
×
UNCOV
161

×
UNCOV
162
        switch msgType {
×
163
        case MsgInit:
×
164
                msg = &Init{}
×
165
        case MsgOpenChannel:
×
166
                msg = &OpenChannel{}
×
167
        case MsgAcceptChannel:
×
168
                msg = &AcceptChannel{}
×
169
        case MsgFundingCreated:
×
170
                msg = &FundingCreated{}
×
171
        case MsgFundingSigned:
×
172
                msg = &FundingSigned{}
×
173
        case MsgFundingLocked:
×
174
                msg = &FundingLocked{}
×
175
        case MsgShutdown:
×
176
                msg = &Shutdown{}
×
177
        case MsgClosingSigned:
×
178
                msg = &ClosingSigned{}
×
UNCOV
179
        case MsgUpdateAddHTLC:
×
UNCOV
180
                msg = &UpdateAddHTLC{}
×
UNCOV
181
        case MsgUpdateFailHTLC:
×
UNCOV
182
                msg = &UpdateFailHTLC{}
×
UNCOV
183
        case MsgUpdateFulfillHTLC:
×
UNCOV
184
                msg = &UpdateFulfillHTLC{}
×
UNCOV
185
        case MsgCommitSig:
×
UNCOV
186
                msg = &CommitSig{}
×
187
        case MsgRevokeAndAck:
×
188
                msg = &RevokeAndAck{}
×
189
        case MsgUpdateFee:
×
190
                msg = &UpdateFee{}
×
191
        case MsgUpdateFailMalformedHTLC:
×
192
                msg = &UpdateFailMalformedHTLC{}
×
UNCOV
193
        case MsgChannelReestablish:
×
UNCOV
194
                msg = &ChannelReestablish{}
×
195
        case MsgError:
×
196
                msg = &Error{}
×
197
        case MsgChannelAnnouncement:
×
198
                msg = &ChannelAnnouncement{}
×
199
        case MsgChannelUpdate:
×
200
                msg = &ChannelUpdate{}
×
201
        case MsgNodeAnnouncement:
×
202
                msg = &NodeAnnouncement{}
×
203
        case MsgPing:
×
204
                msg = &Ping{}
×
UNCOV
205
        case MsgAnnounceSignatures:
×
UNCOV
206
                msg = &AnnounceSignatures{}
×
207
        case MsgPong:
×
208
                msg = &Pong{}
×
209
        case MsgQueryShortChanIDs:
×
210
                msg = &QueryShortChanIDs{}
×
211
        case MsgReplyShortChanIDsEnd:
×
212
                msg = &ReplyShortChanIDsEnd{}
×
213
        case MsgQueryChannelRange:
×
214
                msg = &QueryChannelRange{}
×
215
        case MsgReplyChannelRange:
×
216
                msg = &ReplyChannelRange{}
×
217
        case MsgGossipTimestampRange:
×
218
                msg = &GossipTimestampRange{}
×
219
        default:
×
220
                return nil, &UnknownMessage{msgType}
×
221
        }
222

UNCOV
223
        return msg, nil
×
224
}
225

226
// WriteMessage writes a lightning Message to w including the necessary header
227
// information and returns the number of bytes written.
UNCOV
228
func WriteMessage(w io.Writer, msg Message, pver uint32) (int, error) {
×
UNCOV
229
        totalBytes := 0
×
UNCOV
230

×
UNCOV
231
        // Encode the message payload itself into a temporary buffer.
×
UNCOV
232
        // TODO(roasbeef): create buffer pool
×
UNCOV
233
        var bw bytes.Buffer
×
UNCOV
234
        if err := msg.Encode(&bw, pver); err != nil {
×
235
                return totalBytes, err
×
236
        }
×
UNCOV
237
        payload := bw.Bytes()
×
UNCOV
238
        lenp := len(payload)
×
UNCOV
239

×
UNCOV
240
        // Enforce maximum overall message payload.
×
UNCOV
241
        if lenp > MaxMessagePayload {
×
242
                return totalBytes, fmt.Errorf("message payload is too large - "+
×
243
                        "encoded %d bytes, but maximum message payload is %d bytes",
×
244
                        lenp, MaxMessagePayload)
×
245
        }
×
246

247
        // Enforce maximum message payload on the message type.
UNCOV
248
        mpl := msg.MaxPayloadLength(pver)
×
UNCOV
249
        if uint32(lenp) > mpl {
×
250
                return totalBytes, fmt.Errorf("message payload is too large - "+
×
251
                        "encoded %d bytes, but maximum message payload of "+
×
252
                        "type %v is %d bytes", lenp, msg.MsgType(), mpl)
×
253
        }
×
254

255
        // With the initial sanity checks complete, we'll now write out the
256
        // message type itself.
UNCOV
257
        var mType [2]byte
×
UNCOV
258
        binary.BigEndian.PutUint16(mType[:], uint16(msg.MsgType()))
×
UNCOV
259
        n, err := w.Write(mType[:])
×
UNCOV
260
        totalBytes += n
×
UNCOV
261
        if err != nil {
×
262
                return totalBytes, err
×
263
        }
×
264

265
        // With the message type written, we'll now write out the raw payload
266
        // itself.
UNCOV
267
        n, err = w.Write(payload)
×
UNCOV
268
        totalBytes += n
×
UNCOV
269

×
UNCOV
270
        return totalBytes, err
×
271
}
272

273
// ReadMessage reads, validates, and parses the next Lightning message from r
274
// for the provided protocol version.
UNCOV
275
func ReadMessage(r io.Reader, pver uint32) (Message, error) {
×
UNCOV
276
        // First, we'll read out the first two bytes of the message so we can
×
UNCOV
277
        // create the proper empty message.
×
UNCOV
278
        var mType [2]byte
×
UNCOV
279
        if _, err := io.ReadFull(r, mType[:]); err != nil {
×
280
                return nil, err
×
281
        }
×
282

UNCOV
283
        msgType := MessageType(binary.BigEndian.Uint16(mType[:]))
×
UNCOV
284

×
UNCOV
285
        // Now that we know the target message type, we can create the proper
×
UNCOV
286
        // empty message type and decode the message into it.
×
UNCOV
287
        msg, err := makeEmptyMessage(msgType)
×
UNCOV
288
        if err != nil {
×
289
                return nil, err
×
290
        }
×
UNCOV
291
        if err := msg.Decode(r, pver); err != nil {
×
292
                return nil, err
×
293
        }
×
294

UNCOV
295
        return msg, nil
×
296
}
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