• 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/migration21/current/current_codec.go
1
package current
2

3
import (
4
        "bytes"
5
        "encoding/binary"
6
        "fmt"
7
        "io"
8

9
        "github.com/btcsuite/btcd/btcec/v2"
10
        "github.com/btcsuite/btcd/btcutil"
11
        "github.com/btcsuite/btcd/chaincfg/chainhash"
12
        "github.com/btcsuite/btcd/wire"
13
        lnwire "github.com/lightningnetwork/lnd/channeldb/migration/lnwire21"
14
        "github.com/lightningnetwork/lnd/channeldb/migration21/common"
15
        "github.com/lightningnetwork/lnd/keychain"
16
        "github.com/lightningnetwork/lnd/shachain"
17
)
18

19
var (
20
        // Big endian is the preferred byte order, due to cursor scans over
21
        // integer keys iterating in order.
22
        byteOrder = binary.BigEndian
23
)
24

25
// writeOutpoint writes an outpoint to the passed writer using the minimal
26
// amount of bytes possible.
UNCOV
27
func writeOutpoint(w io.Writer, o *wire.OutPoint) error {
×
UNCOV
28
        if _, err := w.Write(o.Hash[:]); err != nil {
×
29
                return err
×
30
        }
×
UNCOV
31
        if err := binary.Write(w, byteOrder, o.Index); err != nil {
×
32
                return err
×
33
        }
×
34

UNCOV
35
        return nil
×
36
}
37

38
// readOutpoint reads an outpoint from the passed reader that was previously
39
// written using the writeOutpoint struct.
UNCOV
40
func readOutpoint(r io.Reader, o *wire.OutPoint) error {
×
UNCOV
41
        if _, err := io.ReadFull(r, o.Hash[:]); err != nil {
×
42
                return err
×
43
        }
×
UNCOV
44
        if err := binary.Read(r, byteOrder, &o.Index); err != nil {
×
45
                return err
×
46
        }
×
47

UNCOV
48
        return nil
×
49
}
50

51
// UnknownElementType is an error returned when the codec is unable to encode or
52
// decode a particular type.
53
type UnknownElementType struct {
54
        method  string
55
        element interface{}
56
}
57

58
// NewUnknownElementType creates a new UnknownElementType error from the passed
59
// method name and element.
60
func NewUnknownElementType(method string, el interface{}) UnknownElementType {
×
61
        return UnknownElementType{method: method, element: el}
×
62
}
×
63

64
// Error returns the name of the method that encountered the error, as well as
65
// the type that was unsupported.
66
func (e UnknownElementType) Error() string {
×
67
        return fmt.Sprintf("Unknown type in %s: %T", e.method, e.element)
×
68
}
×
69

70
// WriteElement is a one-stop shop to write the big endian representation of
71
// any element which is to be serialized for storage on disk. The passed
72
// io.Writer should be backed by an appropriately sized byte slice, or be able
73
// to dynamically expand to accommodate additional data.
UNCOV
74
func WriteElement(w io.Writer, element interface{}) error {
×
UNCOV
75
        switch e := element.(type) {
×
UNCOV
76
        case keychain.KeyDescriptor:
×
UNCOV
77
                if err := binary.Write(w, byteOrder, e.Family); err != nil {
×
78
                        return err
×
79
                }
×
UNCOV
80
                if err := binary.Write(w, byteOrder, e.Index); err != nil {
×
81
                        return err
×
82
                }
×
83

UNCOV
84
                if e.PubKey != nil {
×
85
                        if err := binary.Write(w, byteOrder, true); err != nil {
×
86
                                return fmt.Errorf("error writing serialized "+
×
87
                                        "element: %w", err)
×
88
                        }
×
89

90
                        return WriteElement(w, e.PubKey)
×
91
                }
92

UNCOV
93
                return binary.Write(w, byteOrder, false)
×
94

UNCOV
95
        case chainhash.Hash:
×
UNCOV
96
                if _, err := w.Write(e[:]); err != nil {
×
97
                        return err
×
98
                }
×
99

UNCOV
100
        case wire.OutPoint:
×
UNCOV
101
                return writeOutpoint(w, &e)
×
102

UNCOV
103
        case lnwire.ShortChannelID:
×
UNCOV
104
                if err := binary.Write(w, byteOrder, e.ToUint64()); err != nil {
×
105
                        return err
×
106
                }
×
107

108
        case lnwire.ChannelID:
×
109
                if _, err := w.Write(e[:]); err != nil {
×
110
                        return err
×
111
                }
×
112

UNCOV
113
        case int64, uint64:
×
UNCOV
114
                if err := binary.Write(w, byteOrder, e); err != nil {
×
115
                        return err
×
116
                }
×
117

UNCOV
118
        case uint32:
×
UNCOV
119
                if err := binary.Write(w, byteOrder, e); err != nil {
×
120
                        return err
×
121
                }
×
122

123
        case int32:
×
124
                if err := binary.Write(w, byteOrder, e); err != nil {
×
125
                        return err
×
126
                }
×
127

UNCOV
128
        case uint16:
×
UNCOV
129
                if err := binary.Write(w, byteOrder, e); err != nil {
×
130
                        return err
×
131
                }
×
132

133
        case uint8:
×
134
                if err := binary.Write(w, byteOrder, e); err != nil {
×
135
                        return err
×
136
                }
×
137

UNCOV
138
        case bool:
×
UNCOV
139
                if err := binary.Write(w, byteOrder, e); err != nil {
×
140
                        return err
×
141
                }
×
142

UNCOV
143
        case btcutil.Amount:
×
UNCOV
144
                if err := binary.Write(w, byteOrder, uint64(e)); err != nil {
×
145
                        return err
×
146
                }
×
147

UNCOV
148
        case lnwire.MilliSatoshi:
×
UNCOV
149
                if err := binary.Write(w, byteOrder, uint64(e)); err != nil {
×
150
                        return err
×
151
                }
×
152

153
        case *btcec.PrivateKey:
×
154
                b := e.Serialize()
×
155
                if _, err := w.Write(b); err != nil {
×
156
                        return err
×
157
                }
×
158

UNCOV
159
        case *btcec.PublicKey:
×
UNCOV
160
                b := e.SerializeCompressed()
×
UNCOV
161
                if _, err := w.Write(b); err != nil {
×
162
                        return err
×
163
                }
×
164

165
        case shachain.Producer:
×
166
                return e.Encode(w)
×
167

168
        case shachain.Store:
×
169
                return e.Encode(w)
×
170

UNCOV
171
        case *wire.MsgTx:
×
UNCOV
172
                return e.Serialize(w)
×
173

174
        case [32]byte:
×
175
                if _, err := w.Write(e[:]); err != nil {
×
176
                        return err
×
177
                }
×
178

UNCOV
179
        case []byte:
×
UNCOV
180
                if err := wire.WriteVarBytes(w, 0, e); err != nil {
×
181
                        return err
×
182
                }
×
183

UNCOV
184
        case lnwire.Message:
×
UNCOV
185
                var msgBuf bytes.Buffer
×
UNCOV
186
                if _, err := lnwire.WriteMessage(&msgBuf, e, 0); err != nil {
×
187
                        return err
×
188
                }
×
189

UNCOV
190
                msgLen := uint16(len(msgBuf.Bytes()))
×
UNCOV
191
                if err := WriteElements(w, msgLen); err != nil {
×
192
                        return err
×
193
                }
×
194

UNCOV
195
                if _, err := w.Write(msgBuf.Bytes()); err != nil {
×
196
                        return err
×
197
                }
×
198

UNCOV
199
        case common.ClosureType:
×
UNCOV
200
                if err := binary.Write(w, byteOrder, e); err != nil {
×
201
                        return err
×
202
                }
×
203

204
        case lnwire.FundingFlag:
×
205
                if err := binary.Write(w, byteOrder, e); err != nil {
×
206
                        return err
×
207
                }
×
208

209
        default:
×
210
                return UnknownElementType{"WriteElement", e}
×
211
        }
212

UNCOV
213
        return nil
×
214
}
215

216
// WriteElements is writes each element in the elements slice to the passed
217
// io.Writer using WriteElement.
UNCOV
218
func WriteElements(w io.Writer, elements ...interface{}) error {
×
UNCOV
219
        for _, element := range elements {
×
UNCOV
220
                err := WriteElement(w, element)
×
UNCOV
221
                if err != nil {
×
222
                        return err
×
223
                }
×
224
        }
UNCOV
225
        return nil
×
226
}
227

228
// ReadElement is a one-stop utility function to deserialize any datastructure
229
// encoded using the serialization format of the database.
UNCOV
230
func ReadElement(r io.Reader, element interface{}) error {
×
UNCOV
231
        switch e := element.(type) {
×
UNCOV
232
        case *keychain.KeyDescriptor:
×
UNCOV
233
                if err := binary.Read(r, byteOrder, &e.Family); err != nil {
×
234
                        return err
×
235
                }
×
UNCOV
236
                if err := binary.Read(r, byteOrder, &e.Index); err != nil {
×
237
                        return err
×
238
                }
×
239

UNCOV
240
                var hasPubKey bool
×
UNCOV
241
                if err := binary.Read(r, byteOrder, &hasPubKey); err != nil {
×
242
                        return err
×
243
                }
×
244

UNCOV
245
                if hasPubKey {
×
246
                        return ReadElement(r, &e.PubKey)
×
247
                }
×
248

UNCOV
249
        case *chainhash.Hash:
×
UNCOV
250
                if _, err := io.ReadFull(r, e[:]); err != nil {
×
251
                        return err
×
252
                }
×
253

UNCOV
254
        case *wire.OutPoint:
×
UNCOV
255
                return readOutpoint(r, e)
×
256

UNCOV
257
        case *lnwire.ShortChannelID:
×
UNCOV
258
                var a uint64
×
UNCOV
259
                if err := binary.Read(r, byteOrder, &a); err != nil {
×
260
                        return err
×
261
                }
×
UNCOV
262
                *e = lnwire.NewShortChanIDFromInt(a)
×
263

264
        case *lnwire.ChannelID:
×
265
                if _, err := io.ReadFull(r, e[:]); err != nil {
×
266
                        return err
×
267
                }
×
268

UNCOV
269
        case *int64, *uint64:
×
UNCOV
270
                if err := binary.Read(r, byteOrder, e); err != nil {
×
271
                        return err
×
272
                }
×
273

UNCOV
274
        case *uint32:
×
UNCOV
275
                if err := binary.Read(r, byteOrder, e); err != nil {
×
276
                        return err
×
277
                }
×
278

279
        case *int32:
×
280
                if err := binary.Read(r, byteOrder, e); err != nil {
×
281
                        return err
×
282
                }
×
283

UNCOV
284
        case *uint16:
×
UNCOV
285
                if err := binary.Read(r, byteOrder, e); err != nil {
×
286
                        return err
×
287
                }
×
288

289
        case *uint8:
×
290
                if err := binary.Read(r, byteOrder, e); err != nil {
×
291
                        return err
×
292
                }
×
293

UNCOV
294
        case *bool:
×
UNCOV
295
                if err := binary.Read(r, byteOrder, e); err != nil {
×
296
                        return err
×
297
                }
×
298

UNCOV
299
        case *btcutil.Amount:
×
UNCOV
300
                var a uint64
×
UNCOV
301
                if err := binary.Read(r, byteOrder, &a); err != nil {
×
302
                        return err
×
303
                }
×
304

UNCOV
305
                *e = btcutil.Amount(a)
×
306

UNCOV
307
        case *lnwire.MilliSatoshi:
×
UNCOV
308
                var a uint64
×
UNCOV
309
                if err := binary.Read(r, byteOrder, &a); err != nil {
×
310
                        return err
×
311
                }
×
312

UNCOV
313
                *e = lnwire.MilliSatoshi(a)
×
314

315
        case **btcec.PrivateKey:
×
316
                var b [btcec.PrivKeyBytesLen]byte
×
317
                if _, err := io.ReadFull(r, b[:]); err != nil {
×
318
                        return err
×
319
                }
×
320

321
                priv, _ := btcec.PrivKeyFromBytes(b[:])
×
322
                *e = priv
×
323

UNCOV
324
        case **btcec.PublicKey:
×
UNCOV
325
                var b [btcec.PubKeyBytesLenCompressed]byte
×
UNCOV
326
                if _, err := io.ReadFull(r, b[:]); err != nil {
×
327
                        return err
×
328
                }
×
329

UNCOV
330
                pubKey, err := btcec.ParsePubKey(b[:])
×
UNCOV
331
                if err != nil {
×
332
                        return err
×
333
                }
×
UNCOV
334
                *e = pubKey
×
335

336
        case *shachain.Producer:
×
337
                var root [32]byte
×
338
                if _, err := io.ReadFull(r, root[:]); err != nil {
×
339
                        return err
×
340
                }
×
341

342
                // TODO(roasbeef): remove
343
                producer, err := shachain.NewRevocationProducerFromBytes(root[:])
×
344
                if err != nil {
×
345
                        return err
×
346
                }
×
347

348
                *e = producer
×
349

350
        case *shachain.Store:
×
351
                store, err := shachain.NewRevocationStoreFromBytes(r)
×
352
                if err != nil {
×
353
                        return err
×
354
                }
×
355

356
                *e = store
×
357

UNCOV
358
        case **wire.MsgTx:
×
UNCOV
359
                tx := wire.NewMsgTx(2)
×
UNCOV
360
                if err := tx.Deserialize(r); err != nil {
×
361
                        return err
×
362
                }
×
363

UNCOV
364
                *e = tx
×
365

366
        case *[32]byte:
×
367
                if _, err := io.ReadFull(r, e[:]); err != nil {
×
368
                        return err
×
369
                }
×
370

UNCOV
371
        case *[]byte:
×
UNCOV
372
                bytes, err := wire.ReadVarBytes(r, 0, 66000, "[]byte")
×
UNCOV
373
                if err != nil {
×
374
                        return err
×
375
                }
×
376

UNCOV
377
                *e = bytes
×
378

UNCOV
379
        case *lnwire.Message:
×
UNCOV
380
                var msgLen uint16
×
UNCOV
381
                if err := ReadElement(r, &msgLen); err != nil {
×
382
                        return err
×
383
                }
×
384

UNCOV
385
                msgReader := io.LimitReader(r, int64(msgLen))
×
UNCOV
386
                msg, err := lnwire.ReadMessage(msgReader, 0)
×
UNCOV
387
                if err != nil {
×
388
                        return err
×
389
                }
×
390

UNCOV
391
                *e = msg
×
392

UNCOV
393
        case *common.ClosureType:
×
UNCOV
394
                if err := binary.Read(r, byteOrder, e); err != nil {
×
395
                        return err
×
396
                }
×
397

398
        case *lnwire.FundingFlag:
×
399
                if err := binary.Read(r, byteOrder, e); err != nil {
×
400
                        return err
×
401
                }
×
402

403
        default:
×
404
                return UnknownElementType{"ReadElement", e}
×
405
        }
406

UNCOV
407
        return nil
×
408
}
409

410
// ReadElements deserializes a variable number of elements into the passed
411
// io.Reader, with each element being deserialized according to the ReadElement
412
// function.
UNCOV
413
func ReadElements(r io.Reader, elements ...interface{}) error {
×
UNCOV
414
        for _, element := range elements {
×
UNCOV
415
                err := ReadElement(r, element)
×
UNCOV
416
                if err != nil {
×
417
                        return err
×
418
                }
×
419
        }
UNCOV
420
        return nil
×
421
}
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