@@ -7,11 +7,11 @@ import (
7
7
"crypto/sha256"
8
8
"encoding/binary"
9
9
"io"
10
- "io/ioutil"
11
10
"math/big"
12
11
13
12
"github.com/aead/chacha20"
14
13
"github.com/lightningnetwork/lnd/chainntnfs"
14
+ "github.com/pkg/errors"
15
15
"github.com/roasbeef/btcd/btcec"
16
16
"github.com/roasbeef/btcd/chaincfg"
17
17
"github.com/roasbeef/btcutil"
@@ -146,62 +146,33 @@ type HopData struct {
146
146
HMAC [hmacSize ]byte
147
147
}
148
148
149
- // Encode writes the serialized version of the target HopData into the passed
150
- // io.Writer.
151
- func (hd * HopData ) Encode (w io.Writer ) error {
152
- if _ , err := w .Write ([]byte {hd .Realm }); err != nil {
153
- return err
154
- }
155
-
156
- if _ , err := w .Write (hd .NextAddress [:]); err != nil {
157
- return err
158
- }
159
-
160
- if err := binary .Write (w , binary .BigEndian , hd .ForwardAmount ); err != nil {
161
- return err
162
- }
163
-
164
- if err := binary .Write (w , binary .BigEndian , hd .OutgoingCltv ); err != nil {
165
- return err
149
+ // Encode writes the serialized version of the target HopData into the slice.
150
+ func (hd * HopData ) Encode (dst []byte ) error {
151
+ if len (dst ) < hopDataSize {
152
+ errors .New ("destination is too small" )
166
153
}
167
154
168
- if _ , err := w .Write (paddingBytes [:]); err != nil {
169
- return err
170
- }
171
-
172
- if _ , err := w .Write (hd .HMAC [:]); err != nil {
173
- return err
174
- }
155
+ dst [0 ] = hd .Realm
156
+ copy (dst [1 :], hd .NextAddress [:])
157
+ binary .BigEndian .PutUint64 (dst [1 + addressSize :], hd .ForwardAmount )
158
+ binary .BigEndian .PutUint32 (dst [1 + addressSize + 8 :], hd .OutgoingCltv )
159
+ copy (dst [hopDataSize - hmacSize - padSize :], paddingBytes [:])
160
+ copy (dst [hopDataSize - hmacSize :], hd .HMAC [:])
175
161
176
162
return nil
177
163
}
178
164
179
- // Decode deserializes the encoded HopData contained int he passed io.Reader
180
- // instance to the target empty HopData instance.
181
- func (hd * HopData ) Decode (r io.Reader ) error {
182
- if _ , err := io .ReadFull (r , []byte {hd .Realm }); err != nil {
183
- return err
184
- }
185
-
186
- if _ , err := io .ReadFull (r , hd .NextAddress [:]); err != nil {
187
- return err
188
- }
189
-
190
- if err := binary .Read (r , binary .BigEndian , & hd .ForwardAmount ); err != nil {
191
- return err
192
- }
193
-
194
- if err := binary .Read (r , binary .BigEndian , & hd .OutgoingCltv ); err != nil {
195
- return err
196
- }
197
-
198
- if _ , err := io .CopyN (ioutil .Discard , r , padSize ); err != nil {
199
- return err
165
+ // Decode deserializes the encoded HopData contained in the passed slice.
166
+ func (hd * HopData ) Decode (src []byte ) error {
167
+ if len (src ) < hopDataSize {
168
+ errors .New ("source is too small" )
200
169
}
201
170
202
- if _ , err := io .ReadFull (r , hd .HMAC [:]); err != nil {
203
- return err
204
- }
171
+ hd .Realm = src [0 ]
172
+ copy (hd .NextAddress [:], src [1 :])
173
+ hd .ForwardAmount = binary .BigEndian .Uint64 (src [1 + addressSize :])
174
+ hd .OutgoingCltv = binary .BigEndian .Uint32 (src [1 + addressSize + 8 :])
175
+ copy (hd .HMAC [:], src [hopDataSize - hmacSize :])
205
176
206
177
return nil
207
178
}
@@ -292,9 +263,8 @@ func NewOnionPacket(paymentPath []*btcec.PublicKey, sessionKey *btcec.PrivateKey
292
263
// Allocate zero'd out byte slices to store the final mix header packet
293
264
// and the hmac for each hop.
294
265
var (
295
- mixHeader [routingInfoSize ]byte
296
- nextHmac [hmacSize ]byte
297
- hopDataBuf bytes.Buffer
266
+ mixHeader [routingInfoSize ]byte
267
+ nextHmac [hmacSize ]byte
298
268
)
299
269
300
270
// Now we compute the routing information for each hop, along with a
@@ -317,17 +287,16 @@ func NewOnionPacket(paymentPath []*btcec.PublicKey, sessionKey *btcec.PrivateKey
317
287
streamBytes := generateCipherStream (rhoKey , numStreamBytes )
318
288
319
289
// Before we assemble the packet, we'll shift the current
320
- // mix-header to the write in order to make room for this next
290
+ // mix-header to the right in order to make room for this next
321
291
// per-hop data.
322
- rightShift (mixHeader [:], hopDataSize )
292
+ copy (mixHeader [hopDataSize :], mixHeader [: routingInfoSize - hopDataSize ] )
323
293
324
294
// With the mix header right-shifted, we'll encode the current
325
295
// hop data into a buffer we'll re-use during the packet
326
296
// construction.
327
- if err := hopsData [i ].Encode (& hopDataBuf ); err != nil {
297
+ if err := hopsData [i ].Encode (mixHeader [:] ); err != nil {
328
298
return nil , err
329
299
}
330
- copy (mixHeader [:], hopDataBuf .Bytes ())
331
300
332
301
// Once the packet for this hop has been assembled, we'll
333
302
// re-encrypt the packet by XOR'ing with a stream of bytes
@@ -346,8 +315,6 @@ func NewOnionPacket(paymentPath []*btcec.PublicKey, sessionKey *btcec.PrivateKey
346
315
// prevent replay attacks.
347
316
packet := append (mixHeader [:], assocData ... )
348
317
nextHmac = calcMac (muKey , packet )
349
-
350
- hopDataBuf .Reset ()
351
318
}
352
319
353
320
return & OnionPacket {
@@ -358,18 +325,6 @@ func NewOnionPacket(paymentPath []*btcec.PublicKey, sessionKey *btcec.PrivateKey
358
325
}, nil
359
326
}
360
327
361
- // Shift the byte-slice by the given number of bytes to the right and 0-fill
362
- // the resulting gap.
363
- func rightShift (slice []byte , num int ) {
364
- for i := len (slice ) - num - 1 ; i >= 0 ; i -- {
365
- slice [num + i ] = slice [i ]
366
- }
367
-
368
- for i := 0 ; i < num ; i ++ {
369
- slice [i ] = 0
370
- }
371
- }
372
-
373
328
// generateHeaderPadding derives the bytes for padding the mix header to ensure
374
329
// it remains fixed sized throughout route transit. At each step, we add
375
330
// 'hopSize' padding of zeroes, concatenate it to the previous filler, then
@@ -763,7 +718,7 @@ func processOnionPacket(onionPkt *OnionPacket,
763
718
// out the per-hop data so we can derive the specified forwarding
764
719
// instructions.
765
720
var hopData HopData
766
- if err := hopData .Decode (bytes . NewReader ( hopInfo [:]) ); err != nil {
721
+ if err := hopData .Decode (hopInfo [:]); err != nil {
767
722
return nil , err
768
723
}
769
724
0 commit comments