@@ -16,46 +16,55 @@ import (
1616)
1717
1818const (
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 {
118127type 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.
150161func (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.
180191func (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.
210221func 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.
362377func 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.
622637type 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.
710725func (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.
835849func (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