• 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

46.74
/watchtower/wtwire/wtwire.go
1
package wtwire
2

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

8
        "github.com/btcsuite/btcd/btcec/v2"
9
        "github.com/btcsuite/btcd/chaincfg/chainhash"
10
        "github.com/btcsuite/btcd/wire"
11
        "github.com/lightningnetwork/lnd/lnwallet/chainfee"
12
        "github.com/lightningnetwork/lnd/lnwire"
13
        "github.com/lightningnetwork/lnd/watchtower/blob"
14
)
15

16
// WriteElement is a one-stop shop to write the big endian representation of
17
// any element which is to be serialized for the wire protocol. The passed
18
// io.Writer should be backed by an appropriately sized byte slice, or be able
19
// to dynamically expand to accommodate additional data.
20
func WriteElement(w io.Writer, element interface{}) error {
3✔
21
        switch e := element.(type) {
3✔
22
        case uint8:
3✔
23
                var b [1]byte
3✔
24
                b[0] = e
3✔
25
                if _, err := w.Write(b[:]); err != nil {
3✔
26
                        return err
×
27
                }
×
28

29
        case uint16:
3✔
30
                var b [2]byte
3✔
31
                binary.BigEndian.PutUint16(b[:], e)
3✔
32
                if _, err := w.Write(b[:]); err != nil {
3✔
33
                        return err
×
34
                }
×
35

36
        case blob.Type:
3✔
37
                var b [2]byte
3✔
38
                binary.BigEndian.PutUint16(b[:], uint16(e))
3✔
39
                if _, err := w.Write(b[:]); err != nil {
3✔
40
                        return err
×
41
                }
×
42

43
        case uint32:
3✔
44
                var b [4]byte
3✔
45
                binary.BigEndian.PutUint32(b[:], e)
3✔
46
                if _, err := w.Write(b[:]); err != nil {
3✔
47
                        return err
×
48
                }
×
49

50
        case uint64:
×
51
                var b [8]byte
×
52
                binary.BigEndian.PutUint64(b[:], e)
×
53
                if _, err := w.Write(b[:]); err != nil {
×
54
                        return err
×
55
                }
×
56

57
        case [16]byte:
3✔
58
                if _, err := w.Write(e[:]); err != nil {
3✔
59
                        return err
×
60
                }
×
61

62
        case [32]byte:
×
63
                if _, err := w.Write(e[:]); err != nil {
×
64
                        return err
×
65
                }
×
66

67
        case [33]byte:
×
68
                if _, err := w.Write(e[:]); err != nil {
×
69
                        return err
×
70
                }
×
71

72
        case []byte:
3✔
73
                if err := wire.WriteVarBytes(w, 0, e); err != nil {
3✔
74
                        return err
×
75
                }
×
76

77
        case chainfee.SatPerKWeight:
3✔
78
                var b [8]byte
3✔
79
                binary.BigEndian.PutUint64(b[:], uint64(e))
3✔
80
                if _, err := w.Write(b[:]); err != nil {
3✔
81
                        return err
×
82
                }
×
83

84
        case ErrorCode:
3✔
85
                var b [2]byte
3✔
86
                binary.BigEndian.PutUint16(b[:], uint16(e))
3✔
87
                if _, err := w.Write(b[:]); err != nil {
3✔
88
                        return err
×
89
                }
×
90

91
        case chainhash.Hash:
3✔
92
                if _, err := w.Write(e[:]); err != nil {
3✔
93
                        return err
×
94
                }
×
95

96
        case *lnwire.RawFeatureVector:
3✔
97
                if e == nil {
3✔
98
                        return fmt.Errorf("cannot write nil feature vector")
×
99
                }
×
100

101
                if err := e.Encode(w); err != nil {
3✔
102
                        return err
×
103
                }
×
104

105
        case *btcec.PublicKey:
×
106
                if e == nil {
×
107
                        return fmt.Errorf("cannot write nil pubkey")
×
108
                }
×
109

110
                var b [33]byte
×
111
                serializedPubkey := e.SerializeCompressed()
×
112
                copy(b[:], serializedPubkey)
×
113
                if _, err := w.Write(b[:]); err != nil {
×
114
                        return err
×
115
                }
×
116

117
        default:
×
118
                return fmt.Errorf("Unknown type in WriteElement: %T", e)
×
119
        }
120

121
        return nil
3✔
122
}
123

124
// WriteElements is writes each element in the elements slice to the passed
125
// io.Writer using WriteElement.
126
func WriteElements(w io.Writer, elements ...interface{}) error {
3✔
127
        for _, element := range elements {
6✔
128
                err := WriteElement(w, element)
3✔
129
                if err != nil {
3✔
130
                        return err
×
131
                }
×
132
        }
133
        return nil
3✔
134
}
135

136
// ReadElement is a one-stop utility function to deserialize any datastructure
137
// encoded using the serialization format of lnwire.
138
func ReadElement(r io.Reader, element interface{}) error {
3✔
139
        switch e := element.(type) {
3✔
140
        case *uint8:
3✔
141
                var b [1]uint8
3✔
142
                if _, err := r.Read(b[:]); err != nil {
3✔
UNCOV
143
                        return err
×
UNCOV
144
                }
×
145
                *e = b[0]
3✔
146

147
        case *uint16:
3✔
148
                var b [2]byte
3✔
149
                if _, err := io.ReadFull(r, b[:]); err != nil {
3✔
UNCOV
150
                        return err
×
UNCOV
151
                }
×
152
                *e = binary.BigEndian.Uint16(b[:])
3✔
153

154
        case *blob.Type:
3✔
155
                var b [2]byte
3✔
156
                if _, err := io.ReadFull(r, b[:]); err != nil {
3✔
UNCOV
157
                        return err
×
UNCOV
158
                }
×
159
                *e = blob.Type(binary.BigEndian.Uint16(b[:]))
3✔
160

161
        case *uint32:
3✔
162
                var b [4]byte
3✔
163
                if _, err := io.ReadFull(r, b[:]); err != nil {
3✔
UNCOV
164
                        return err
×
UNCOV
165
                }
×
166
                *e = binary.BigEndian.Uint32(b[:])
3✔
167

168
        case *uint64:
×
169
                var b [8]byte
×
170
                if _, err := io.ReadFull(r, b[:]); err != nil {
×
171
                        return err
×
172
                }
×
173
                *e = binary.BigEndian.Uint64(b[:])
×
174

175
        case *[16]byte:
3✔
176
                if _, err := io.ReadFull(r, e[:]); err != nil {
3✔
UNCOV
177
                        return err
×
UNCOV
178
                }
×
179

180
        case *[32]byte:
×
181
                if _, err := io.ReadFull(r, e[:]); err != nil {
×
182
                        return err
×
183
                }
×
184

185
        case *[33]byte:
×
186
                if _, err := io.ReadFull(r, e[:]); err != nil {
×
187
                        return err
×
188
                }
×
189

190
        case *[]byte:
3✔
191
                bytes, err := wire.ReadVarBytes(r, 0, 66000, "[]byte")
3✔
192
                if err != nil {
3✔
UNCOV
193
                        return err
×
UNCOV
194
                }
×
195
                *e = bytes
3✔
196

197
        case *chainfee.SatPerKWeight:
3✔
198
                var b [8]byte
3✔
199
                if _, err := io.ReadFull(r, b[:]); err != nil {
3✔
UNCOV
200
                        return err
×
UNCOV
201
                }
×
202
                *e = chainfee.SatPerKWeight(binary.BigEndian.Uint64(b[:]))
3✔
203

204
        case *ErrorCode:
3✔
205
                var b [2]byte
3✔
206
                if _, err := io.ReadFull(r, b[:]); err != nil {
3✔
UNCOV
207
                        return err
×
UNCOV
208
                }
×
209
                *e = ErrorCode(binary.BigEndian.Uint16(b[:]))
3✔
210

211
        case *chainhash.Hash:
3✔
212
                if _, err := io.ReadFull(r, e[:]); err != nil {
3✔
UNCOV
213
                        return err
×
UNCOV
214
                }
×
215

216
        case **lnwire.RawFeatureVector:
3✔
217
                f := lnwire.NewRawFeatureVector()
3✔
218
                err := f.Decode(r)
3✔
219
                if err != nil {
3✔
UNCOV
220
                        return err
×
UNCOV
221
                }
×
222

223
                *e = f
3✔
224

225
        case **btcec.PublicKey:
×
226
                var b [btcec.PubKeyBytesLenCompressed]byte
×
227
                if _, err := io.ReadFull(r, b[:]); err != nil {
×
228
                        return err
×
229
                }
×
230

231
                pubKey, err := btcec.ParsePubKey(b[:])
×
232
                if err != nil {
×
233
                        return err
×
234
                }
×
235
                *e = pubKey
×
236

237
        default:
×
238
                return fmt.Errorf("Unknown type in ReadElement: %T", e)
×
239
        }
240

241
        return nil
3✔
242
}
243

244
// ReadElements deserializes a variable number of elements into the passed
245
// io.Reader, with each element being deserialized according to the ReadElement
246
// function.
247
func ReadElements(r io.Reader, elements ...interface{}) error {
3✔
248
        for _, element := range elements {
6✔
249
                err := ReadElement(r, element)
3✔
250
                if err != nil {
3✔
UNCOV
251
                        return err
×
UNCOV
252
                }
×
253
        }
254
        return nil
3✔
255
}
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