Skip to content

Commit 148f914

Browse files
committed
multi: Support custom size onion packets
Onion messages allow for payloads that exceed 1300 bytes, in which case the payload should become 32768 bytes. This commit introduces support for those custom size packets and the tests for this feature. NewOnionPacket now allows for a final variadic argument payloadSizes. The sizes passed are then compared to the actual payload size of the entire path, and the first value that fits the actual payload size will then be used as the size of the routing info. We use this to fix the size of onion messages at 1300 or 32768 bytes as suggested by BOLT-0004 but it can be used to fix the size at any value. If no values are passed the func defaults to MaxRoutingPayloadSize. MaxRoutingPayloadSize and MaxOnionMessagePayloadSize are exposed to facilitate easy usage of this library. sphinx_test now has a helper function to create onion messages of a specified length. This helper is then used to test the handling of packets larger than 1300 bytes specifically for onion messages.
1 parent 77d81d8 commit 148f914

File tree

5 files changed

+489
-76
lines changed

5 files changed

+489
-76
lines changed

cmd/main.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,13 @@ func main() {
7070
"data.",
7171
Value: defaultHopDataPath,
7272
},
73+
cli.IntFlag{
74+
Name: "payload-size",
75+
Usage: "The size for a payload for a " +
76+
"single hop. Defaults to the " +
77+
"max routing payload size",
78+
Value: sphinx.MaxRoutingPayloadSize,
79+
},
7380
},
7481
},
7582
{
@@ -203,8 +210,10 @@ func generate(ctx *cli.Context) error {
203210
return fmt.Errorf("could not peel onion spec: %v", err)
204211
}
205212

213+
payloadSize := ctx.Int("payload-size")
206214
msg, err := sphinx.NewOnionPacket(
207215
path, sessionKey, assocData, sphinx.DeterministicPacketFiller,
216+
sphinx.WithMaxPayloadSize(payloadSize),
208217
)
209218
if err != nil {
210219
return fmt.Errorf("error creating message: %v", err)

error.go

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,35 @@ var (
2424
ErrInvalidOnionKey = fmt.Errorf("invalid onion key: pubkey isn't on " +
2525
"secp256k1 curve")
2626

27-
// ErrLogEntryNotFound is an error returned when a packet lookup in a replay
28-
// log fails because it is missing.
29-
ErrLogEntryNotFound = fmt.Errorf("sphinx packet is not in log")
27+
// ErrLogEntryNotFound is an error returned when a packet lookup in a
28+
// replay log fails because it is missing.
29+
ErrLogEntryNotFound = errors.New("sphinx packet is not in log")
30+
31+
// ErrPayloadSizeExceeded is returned when the payload size exceeds the
32+
// configured payload size of the onion packet.
33+
ErrPayloadSizeExceeded = errors.New("max payload size exceeded")
34+
35+
// ErrSharedSecretDerivation is returned when we fail to derive the
36+
// shared secret for a hop.
37+
ErrSharedSecretDerivation = errors.New("error generating shared secret")
38+
39+
// ErrMissingHMAC is returned when the onion packet is too small to
40+
// contain a valid HMAC.
41+
ErrMissingHMAC = errors.New("onion packet is too small, missing HMAC")
42+
43+
// ErrNegativeRoutingInfoSize is returned when a negative routing info
44+
// size is specified in the Sphinx configuration.
45+
ErrNegativeRoutingInfoSize = errors.New("routing info size must be " +
46+
"non-negative")
47+
48+
// ErrNegativePayloadSize is returned when a negative payload size is
49+
// specified in the Sphinx configuration.
50+
ErrNegativePayloadSize = errors.New("payload size must be " +
51+
"non-negative")
52+
53+
// ErrZeroHops is returned when attempting to create a route with zero
54+
// hops.
55+
ErrZeroHops = errors.New("route of length zero passed in")
3056

3157
// ErrIOReadFull is returned when an io read full operation fails.
3258
ErrIOReadFull = errors.New("io read full error")

packetfiller.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,17 @@ import (
1212
// in order to ensure we don't leak information on the true route length to the
1313
// receiver. The packet filler may also use the session key to generate a set
1414
// of filler bytes if it wishes to be deterministic.
15-
type PacketFiller func(*btcec.PrivateKey, *[routingInfoSize]byte) error
15+
type PacketFiller func(*btcec.PrivateKey, []byte) error
1616

1717
// RandPacketFiller is a packet filler that reads a set of random bytes from a
1818
// CSPRNG.
19-
func RandPacketFiller(_ *btcec.PrivateKey, mixHeader *[routingInfoSize]byte) error {
19+
func RandPacketFiller(_ *btcec.PrivateKey, mixHeader []byte) error {
2020
// Read out random bytes to fill out the rest of the starting packet
2121
// after the hop payload for the final node. This mitigates a privacy
2222
// leak that may reveal a lower bound on the true path length to the
2323
// receiver.
24-
if _, err := rand.Read(mixHeader[:]); err != nil {
24+
_, err := rand.Read(mixHeader)
25+
if err != nil {
2526
return err
2627
}
2728

@@ -31,15 +32,15 @@ func RandPacketFiller(_ *btcec.PrivateKey, mixHeader *[routingInfoSize]byte) err
3132
// BlankPacketFiller is a packet filler that doesn't attempt to fill out the
3233
// packet at all. It should ONLY be used for generating test vectors or other
3334
// instances that required deterministic packet generation.
34-
func BlankPacketFiller(_ *btcec.PrivateKey, _ *[routingInfoSize]byte) error {
35+
func BlankPacketFiller(_ *btcec.PrivateKey, _ []byte) error {
3536
return nil
3637
}
3738

3839
// DeterministicPacketFiller is a packet filler that generates a deterministic
3940
// set of filler bytes by using chacha20 with a key derived from the session
4041
// key.
4142
func DeterministicPacketFiller(sessionKey *btcec.PrivateKey,
42-
mixHeader *[routingInfoSize]byte) error {
43+
mixHeader []byte) error {
4344

4445
// First, we'll generate a new key that'll be used to generate some
4546
// random bytes for our padding purposes. To derive this new key, we
@@ -55,7 +56,8 @@ func DeterministicPacketFiller(sessionKey *btcec.PrivateKey,
5556
if err != nil {
5657
return err
5758
}
58-
padCipher.XORKeyStream(mixHeader[:], mixHeader[:])
59+
60+
padCipher.XORKeyStream(mixHeader, mixHeader)
5961

6062
return nil
6163
}

0 commit comments

Comments
 (0)