Skip to content

Commit 7b63003

Browse files
committed
sphinx: export new constants related to packet construction, style nits
1 parent 925a87d commit 7b63003

File tree

2 files changed

+71
-53
lines changed

2 files changed

+71
-53
lines changed

bench_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func BenchmarkPathPacketConstruction(b *testing.B) {
3232
var hopsData []HopData
3333
for i := 0; i < len(route); i++ {
3434
hopsData = append(hopsData, HopData{
35-
Realm: 0x00,
35+
Realm: [RealmByteSize]byte{0x00},
3636
ForwardAmount: uint64(i),
3737
OutgoingCltv: uint32(i),
3838
})

sphinx.go

Lines changed: 70 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -16,46 +16,55 @@ import (
1616
)
1717

1818
const (
19-
// hmacSize is the length of the HMACs used to verify the integrity of
19+
// HMACSize is the length of the HMACs used to verify the integrity of
2020
// the onion. Any value lower than 32 will truncate the HMAC both
2121
// during onion creation as well as during the verification.
22-
hmacSize = 32
22+
HMACSize = 32
2323

2424
// addressSize is the length of the serialized address used to uniquely
2525
// identify the next hop to forward the onion to. BOLT 04 defines this
2626
// as 8 byte channel_id.
27-
addressSize = 8
27+
AddressSize = 8
2828

29-
// NumMaxHops is the the maximum path length. This should be set to an
30-
// estiamate of the upper limit of the diameter of the node graph.
31-
NumMaxHops = 20
29+
// RealmByteSize is the number of bytes that the realm byte occupies.
30+
RealmByteSize = 1
3231

33-
// padSize is the number of padding bytes in the hopData. These bytes
34-
// are currently unused within the protocol, and are reserved for
35-
// future use.
36-
padSize = 12
32+
// AmtForwardSize is the number of bytes that the amount to forward
33+
// occupies.
34+
AmtForwardSize = 8
3735

38-
// hopDataSize is the fixed size of hop_data. BOLT 04 currently
36+
// OutgoingCLTVSize is the number of bytes that the outgoing CLTV value
37+
// occupies.
38+
OutgoingCLTVSize = 4
39+
40+
// NumPaddingBytes is the number of padding bytes in the hopData. These
41+
// bytes are currently unused within the protocol, and are reserved for
42+
// future use. However, if a hop contains extra data, then we'll
43+
// utilize this space to pack in the unrolled bytes.
44+
NumPaddingBytes = 12
45+
46+
// HopDataSize is the fixed size of hop_data. BOLT 04 currently
3947
// specifies this to be 1 byte realm, 8 byte channel_id, 8 byte amount
4048
// to forward, 4 byte outgoing CLTV value, 12 bytes padding and 32
4149
// bytes HMAC for a total of 65 bytes per hop.
42-
hopDataSize = (1 + addressSize + 8 + 4 + padSize + hmacSize)
50+
HopDataSize = (RealmByteSize + AddressSize + AmtForwardSize +
51+
OutgoingCLTVSize + NumPaddingBytes + HMACSize)
4352

4453
// sharedSecretSize is the size in bytes of the shared secrets.
4554
sharedSecretSize = 32
4655

4756
// routingInfoSize is the fixed size of the the routing info. This
48-
// consists of a addressSize byte address and a hmacSize byte HMAC for
57+
// consists of a addressSize byte address and a HMACSize byte HMAC for
4958
// each hop of the route, the first pair in cleartext and the following
5059
// pairs increasingly obfuscated. In case fewer than numMaxHops are
5160
// used, then the remainder is padded with null-bytes, also obfuscated.
52-
routingInfoSize = NumMaxHops * hopDataSize
61+
routingInfoSize = NumMaxHops * HopDataSize
5362

5463
// numStreamBytes is the number of bytes produced by our CSPRG for the
5564
// key stream implementing our stream cipher to encrypt/decrypt the mix
5665
// header. The last hopDataSize bytes are only used in order to
5766
// generate/check the MAC over the header.
58-
numStreamBytes = routingInfoSize + hopDataSize
67+
numStreamBytes = routingInfoSize + HopDataSize
5968

6069
// keyLen is the length of the keys used to generate cipher streams and
6170
// encrypt payloads. Since we use SHA256 to generate the keys, the
@@ -72,7 +81,7 @@ type Hash256 [sha256.Size]byte
7281

7382
// zeroHMAC is the special HMAC value that allows the final node to determine
7483
// if it is the payment destination or not.
75-
var zeroHMAC [hmacSize]byte
84+
var zeroHMAC [HMACSize]byte
7685

7786
// OnionPacket is the onion wrapped hop-to-hop routing information necessary to
7887
// propagate a message through the mix-net without intermediate nodes having
@@ -106,7 +115,7 @@ type OnionPacket struct {
106115
// data and the associated data for this route. Including the
107116
// associated data lets each hop authenticate higher-level data that is
108117
// critical for the forwarding of this HTLC.
109-
HeaderMAC [hmacSize]byte
118+
HeaderMAC [HMACSize]byte
110119
}
111120

112121
// HopData is the information destined for individual hops. It is a fixed size
@@ -118,11 +127,11 @@ type OnionPacket struct {
118127
type HopData struct {
119128
// Realm denotes the "real" of target chain of the next hop. For
120129
// bitcoin, this value will be 0x00.
121-
Realm byte
130+
Realm [RealmByteSize]byte
122131

123132
// NextAddress is the address of the next hop that this packet should
124133
// be forward to.
125-
NextAddress [addressSize]byte
134+
NextAddress [AddressSize]byte
126135

127136
// ForwardAmount is the HTLC amount that the next hop should forward.
128137
// This value should take into account the fee require by this
@@ -138,17 +147,19 @@ type HopData struct {
138147
// package additional data within the per-hop payload, or signal that a
139148
// portion of the remaining set of hops are to be consumed as Extra
140149
// Onion Blobs.
141-
ExtraBytes [padSize]byte
150+
//
151+
// TODO(roasbeef): rename to padding bytes?
152+
ExtraBytes [NumPaddingBytes]byte
142153

143154
// HMAC is an HMAC computed over the entire per-hop payload that also
144155
// includes the higher-level (optional) associated data bytes.
145-
HMAC [hmacSize]byte
156+
HMAC [HMACSize]byte
146157
}
147158

148159
// Encode writes the serialized version of the target HopData into the passed
149160
// io.Writer.
150161
func (hd *HopData) Encode(w io.Writer) error {
151-
if _, err := w.Write([]byte{hd.Realm}); err != nil {
162+
if _, err := w.Write(hd.Realm[:]); err != nil {
152163
return err
153164
}
154165

@@ -178,7 +189,7 @@ func (hd *HopData) Encode(w io.Writer) error {
178189
// Decode deserializes the encoded HopData contained int he passed io.Reader
179190
// instance to the target empty HopData instance.
180191
func (hd *HopData) Decode(r io.Reader) error {
181-
if _, err := io.ReadFull(r, []byte{hd.Realm}); err != nil {
192+
if _, err := io.ReadFull(r, hd.Realm[:]); err != nil {
182193
return err
183194
}
184195

@@ -209,6 +220,7 @@ func (hd *HopData) Decode(r io.Reader) error {
209220
// secrets.
210221
func generateSharedSecrets(paymentPath []*btcec.PublicKey,
211222
sessionKey *btcec.PrivateKey) []Hash256 {
223+
212224
// Each hop performs ECDH with our ephemeral key pair to arrive at a
213225
// shared secret. Additionally, each hop randomizes the group element
214226
// for the next hop by multiplying it by the blinding factor. This way
@@ -256,7 +268,8 @@ func generateSharedSecrets(paymentPath []*btcec.PublicKey,
256268
// = ( Y_i ^ x )^( b_0 * ... * b_{i-1} )
257269
// (Y_their_pub_key x x_our_priv) x all prev blinding factors
258270
hopBlindedPubKey := blindGroupElement(
259-
paymentPath[i], cachedBlindingFactor.Bytes())
271+
paymentPath[i], cachedBlindingFactor.Bytes(),
272+
)
260273

261274
// s_i = sha256( e_i )
262275
// = sha256( Y_i ^ (x * b_0 * ... * b_{i-1} )
@@ -268,8 +281,9 @@ func generateSharedSecrets(paymentPath []*btcec.PublicKey,
268281
}
269282

270283
// b_i = sha256( a_i || s_i )
271-
lastBlindingFactor = computeBlindingFactor(lastEphemeralPubKey,
272-
hopSharedSecrets[i][:])
284+
lastBlindingFactor = computeBlindingFactor(
285+
lastEphemeralPubKey, hopSharedSecrets[i][:],
286+
)
273287
}
274288

275289
return hopSharedSecrets
@@ -285,14 +299,15 @@ func NewOnionPacket(paymentPath []*btcec.PublicKey, sessionKey *btcec.PrivateKey
285299
hopSharedSecrets := generateSharedSecrets(paymentPath, sessionKey)
286300

287301
// Generate the padding, called "filler strings" in the paper.
288-
filler := generateHeaderPadding("rho", numHops, hopDataSize,
289-
hopSharedSecrets)
302+
filler := generateHeaderPadding(
303+
"rho", numHops, HopDataSize, hopSharedSecrets,
304+
)
290305

291306
// Allocate zero'd out byte slices to store the final mix header packet
292307
// and the hmac for each hop.
293308
var (
294309
mixHeader [routingInfoSize]byte
295-
nextHmac [hmacSize]byte
310+
nextHmac [HMACSize]byte
296311
hopDataBuf bytes.Buffer
297312
)
298313

@@ -318,7 +333,7 @@ func NewOnionPacket(paymentPath []*btcec.PublicKey, sessionKey *btcec.PrivateKey
318333
// Before we assemble the packet, we'll shift the current
319334
// mix-header to the write in order to make room for this next
320335
// per-hop data.
321-
rightShift(mixHeader[:], hopDataSize)
336+
rightShift(mixHeader[:], HopDataSize)
322337

323338
// With the mix header right-shifted, we'll encode the current
324339
// hop data into a buffer we'll re-use during the packet
@@ -357,8 +372,8 @@ func NewOnionPacket(paymentPath []*btcec.PublicKey, sessionKey *btcec.PrivateKey
357372
}, nil
358373
}
359374

360-
// Shift the byte-slice by the given number of bytes to the right and 0-fill
361-
// the resulting gap.
375+
// rightShift shifts the byte-slice by the given number of bytes to the right
376+
// and 0-fill the resulting gap.
362377
func rightShift(slice []byte, num int) {
363378
for i := len(slice) - num - 1; i >= 0; i-- {
364379
slice[num+i] = slice[i]
@@ -460,13 +475,13 @@ func (f *OnionPacket) Decode(r io.Reader) error {
460475

461476
// calcMac calculates HMAC-SHA-256 over the message using the passed secret key
462477
// as input to the HMAC.
463-
func calcMac(key [keyLen]byte, msg []byte) [hmacSize]byte {
478+
func calcMac(key [keyLen]byte, msg []byte) [HMACSize]byte {
464479
hmac := hmac.New(sha256.New, key[:])
465480
hmac.Write(msg)
466481
h := hmac.Sum(nil)
467482

468-
var mac [hmacSize]byte
469-
copy(mac[:], h[:hmacSize])
483+
var mac [HMACSize]byte
484+
copy(mac[:], h[:HMACSize])
470485

471486
return mac
472487
}
@@ -620,7 +635,7 @@ type ProcessedPacket struct {
620635
// of processing incoming Sphinx onion packets thereby "peeling" a layer off
621636
// the onion encryption which the packet is wrapped with.
622637
type Router struct {
623-
nodeID [addressSize]byte
638+
nodeID [AddressSize]byte
624639
nodeAddr *btcutil.AddressPubKeyHash
625640

626641
onionKey *btcec.PrivateKey
@@ -630,9 +645,8 @@ type Router struct {
630645

631646
// NewRouter creates a new instance of a Sphinx onion Router given the node's
632647
// currently advertised onion private key, and the target Bitcoin network.
633-
func NewRouter(nodeKey *btcec.PrivateKey, net *chaincfg.Params, log ReplayLog,
634-
) *Router {
635-
var nodeID [addressSize]byte
648+
func NewRouter(nodeKey *btcec.PrivateKey, net *chaincfg.Params, log ReplayLog) *Router {
649+
var nodeID [AddressSize]byte
636650
copy(nodeID[:], btcutil.Hash160(nodeKey.PubKey().SerializeCompressed()))
637651

638652
// Safe to ignore the error here, nodeID is 20 bytes.
@@ -705,6 +719,7 @@ func (r *Router) ProcessOnionPacket(onionPkt *OnionPacket,
705719
}
706720

707721
// ReconstructOnionPacket rederives the subsequent onion packet.
722+
//
708723
// NOTE: This method does not do any sort of replay protection, and should only
709724
// be used to reconstruct packets that were successfully processed previously.
710725
func (r *Router) ReconstructOnionPacket(onionPkt *OnionPacket,
@@ -745,8 +760,8 @@ func processOnionPacket(onionPkt *OnionPacket,
745760
generateKey("rho", sharedSecret),
746761
numStreamBytes,
747762
)
748-
headerWithPadding := append(routeInfo[:],
749-
bytes.Repeat([]byte{0}, hopDataSize)...)
763+
zeroBytes := bytes.Repeat([]byte{0}, HopDataSize)
764+
headerWithPadding := append(routeInfo[:], zeroBytes...)
750765

751766
var hopInfo [numStreamBytes]byte
752767
xor(hopInfo[:], headerWithPadding, streamBytes)
@@ -767,8 +782,8 @@ func processOnionPacket(onionPkt *OnionPacket,
767782
// With the necessary items extracted, we'll copy of the onion packet
768783
// for the next node, snipping off our per-hop data.
769784
var nextMixHeader [routingInfoSize]byte
770-
copy(nextMixHeader[:], hopInfo[hopDataSize:])
771785
nextFwdMsg := &OnionPacket{
786+
copy(nextMixHeader[:], hopInfo[HopDataSize:])
772787
Version: onionPkt.Version,
773788
EphemeralKey: nextDHKey,
774789
RoutingInfo: nextMixHeader,
@@ -791,8 +806,7 @@ func processOnionPacket(onionPkt *OnionPacket,
791806
}
792807

793808
// generateSharedSecret generates the shared secret by given ephemeral key.
794-
func (r *Router) generateSharedSecret(dhKey *btcec.PublicKey) (Hash256,
795-
error) {
809+
func (r *Router) generateSharedSecret(dhKey *btcec.PublicKey) (Hash256, error) {
796810
var sharedSecret Hash256
797811

798812
// Ensure that the public key is on our curve.
@@ -829,9 +843,9 @@ type Tx struct {
829843
// BeginTxn creates a new transaction that can later be committed back to the
830844
// sphinx router's replay log.
831845
//
832-
// NOTE: The nels parameter should represent the maximum number of that could be
833-
// added to the batch, using sequence numbers that match or exceed this value
834-
// could result in an out-of-bounds panic.
846+
// NOTE: The nels parameter should represent the maximum number of that could
847+
// be added to the batch, using sequence numbers that match or exceed this
848+
// value could result in an out-of-bounds panic.
835849
func (r *Router) BeginTxn(id []byte, nels int) *Tx {
836850
return &Tx{
837851
batch: NewBatch(id),
@@ -854,7 +868,8 @@ func (t *Tx) ProcessOnionPacket(seqNum uint16, onionPkt *OnionPacket,
854868

855869
// Compute the shared secret for this onion packet.
856870
sharedSecret, err := t.router.generateSharedSecret(
857-
onionPkt.EphemeralKey)
871+
onionPkt.EphemeralKey,
872+
)
858873
if err != nil {
859874
return err
860875
}
@@ -866,7 +881,9 @@ func (t *Tx) ProcessOnionPacket(seqNum uint16, onionPkt *OnionPacket,
866881
// Continue to optimistically process this packet, deferring replay
867882
// protection until the end to reduce the penalty of multiple IO
868883
// operations.
869-
packet, err := processOnionPacket(onionPkt, &sharedSecret, assocData)
884+
packet, err := processOnionPacket(
885+
onionPkt, &sharedSecret, assocData, t.router,
886+
)
870887
if err != nil {
871888
return err
872889
}
@@ -878,9 +895,10 @@ func (t *Tx) ProcessOnionPacket(seqNum uint16, onionPkt *OnionPacket,
878895
return err
879896
}
880897

881-
// If we successfully added this packet to the batch, cache the processed
882-
// packet within the Tx which can be accessed after committing if this
883-
// sequence number does not appear in the replay set.
898+
// If we successfully added this packet to the batch, cache the
899+
// processed packet within the Tx which can be accessed after
900+
// committing if this sequence number does not appear in the replay
901+
// set.
884902
t.packets[seqNum] = *packet
885903

886904
return nil

0 commit comments

Comments
 (0)