Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
317 changes: 235 additions & 82 deletions common/sphinx.c

Large diffs are not rendered by default.

86 changes: 71 additions & 15 deletions common/sphinx.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,25 @@
#include <wire/gen_onion_wire.h>
#include <wire/wire.h>

#define SECURITY_PARAMETER 32
#define NUM_MAX_HOPS 20
#define PAYLOAD_SIZE 32
#define HOP_DATA_SIZE (1 + SECURITY_PARAMETER + PAYLOAD_SIZE)
#define ROUTING_INFO_SIZE (HOP_DATA_SIZE * NUM_MAX_HOPS)
#define TOTAL_PACKET_SIZE (1 + 33 + SECURITY_PARAMETER + ROUTING_INFO_SIZE)
#define VERSION_SIZE 1
#define REALM_SIZE 1
#define HMAC_SIZE 32
#define PUBKEY_SIZE 33
#define FRAME_SIZE 65
#define NUM_MAX_FRAMES 20
#define ROUTING_INFO_SIZE (FRAME_SIZE * NUM_MAX_FRAMES)
#define TOTAL_PACKET_SIZE (VERSION_SIZE + PUBKEY_SIZE + HMAC_SIZE + ROUTING_INFO_SIZE)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A properly marked /* BOLT #4 quote here would be illiminating and useful :)


#if EXPERIMENTAL_FEATURES
#define MAX_FRAMES_PER_HOP (1 << 4)
#else
#define MAX_FRAMES_PER_HOP 1
#endif

struct onionpacket {
/* Cleartext information */
u8 version;
u8 mac[SECURITY_PARAMETER];
u8 mac[HMAC_SIZE];
struct pubkey ephemeralkey;

/* Encrypted information */
Expand All @@ -34,6 +42,18 @@ enum route_next_case {
ONION_FORWARD = 1,
};

/**
* A sphinx payment path.
*
* This struct defines a path a payment is taking through the Lightning
* Network, including the session_key used to generate secrets, the associated
* data that'll be included in the HMACs and the payloads at each hop in the
* path. The struct is opaque since it should not be modified externally. Use
* `sphinx_path_new` or `sphinx_path_new_with_key` (testing only) to create a
* new instance.
*/
struct sphinx_path;

/* BOLT #4:
*
* The `hops_data` field is a structure that holds obfuscations of the
Expand Down Expand Up @@ -69,14 +89,23 @@ struct hop_data {
struct short_channel_id channel_id;
struct amount_msat amt_forward;
u32 outgoing_cltv;
/* Padding omitted, will be zeroed */
u8 hmac[SECURITY_PARAMETER];
};

enum sphinx_payload_type {
SPHINX_V0_PAYLOAD = 0,
SPHINX_RAW_PAYLOAD = 255,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whenever we overload values for internal usage, I always worry about leakage (someone sends us a realm 255 onion in future).

Let's make route_step.realm and int, and use negative values for internal ones maybe? Or 256?

};

struct route_step {
enum route_next_case nextcase;
struct onionpacket *next;
struct hop_data hop_data;
u8 realm;
enum sphinx_payload_type type;
union {
struct hop_data v0;
} payload;
u8 *raw_payload;
u8 payload_frames;
};

/**
Expand All @@ -95,11 +124,7 @@ struct route_step {
*/
struct onionpacket *create_onionpacket(
const tal_t * ctx,
struct pubkey path[],
struct hop_data hops_data[],
const u8 * sessionkey,
const u8 *assocdata,
const size_t assocdatalen,
struct sphinx_path *sp,
struct secret **path_secrets
);

Expand Down Expand Up @@ -197,4 +222,35 @@ struct onionreply *unwrap_onionreply(const tal_t *ctx,
const struct secret *shared_secrets,
const int numhops, const u8 *reply);

/**
* Create a new empty sphinx_path.
*
* The sphinx_path instance can then be decorated with other functions and
* passed to `create_onionpacket` to generate the packet.
*/
struct sphinx_path *sphinx_path_new(const tal_t *ctx,
const u8 *associated_data);

/**
* Create a new empty sphinx_path with a given `session_key`.
*
* This MUST NOT be used outside of tests and tools as it may leak the path
* details if the `session_key` is not randomly generated.
*/
struct sphinx_path *sphinx_path_new_with_key(const tal_t *ctx,
const u8 *associated_data,
const struct secret *session_key);

/**
* Add a V0 (Realm 0) single frame hop to the path.
*/
void sphinx_add_v0_hop(struct sphinx_path *path, const struct pubkey *pubkey,
const struct short_channel_id *scid, struct amount_msat forward,
u32 outgoing_cltv);
/**
* Add a raw payload hop to the path.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe note it's expose for testing...

*/
void sphinx_add_raw_hop(struct sphinx_path *path, const struct pubkey *pubkey,
u8 realm, const u8 *payload);

#endif /* LIGHTNING_COMMON_SPHINX_H */
42 changes: 42 additions & 0 deletions common/test/onion-test-v0.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would prefer to see this tested in a unit test rather than a devtool, though.

"comment": "This is a simple testcase in which we only use v0 payloads, and all hops have single frame payloads",
"generate": {
"session_key": "4141414141414141414141414141414141414141414141414141414141414141",
"associated_data": "4242424242424242424242424242424242424242424242424242424242424242",
"hops": [
{
"realm": 0,
"pubkey": "02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619",
"payload": "0000000000000000000000000000000000000000000000000000000000000000"
},
{
"realm": 0,
"pubkey": "0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c",
"payload": "0101010101010101000000000000000100000001000000000000000000000000"
},
{
"realm": 0,
"pubkey": "027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007",
"payload": "0202020202020202000000000000000200000002000000000000000000000000"
},
{
"realm": 0,
"pubkey": "032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991",
"payload": "0303030303030303000000000000000300000003000000000000000000000000"
},
{
"realm": 0,
"pubkey": "02edabbd16b41c8371b92ef2f04c1185b4f03b6dcd52ba9b78d9d7c89c8f221145",
"payload": "0404040404040404000000000000000400000004000000000000000000000000"
}
]
},
"onion": "0002eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619e5f14350c2a76fc232b5e46d421e9615471ab9e0bc887beff8c95fdb878f7b3a71da571226458c510bbadd1276f045c21c520a07d35da256ef75b4367962437b0dd10f7d61ab590531cf08000178a333a347f8b4072e216400406bdf3bf038659793a86cae5f52d32f3438527b47a1cfc54285a8afec3a4c9f3323db0c946f5d4cb2ce721caad69320c3a469a202f3e468c67eaf7a7cda226d0fd32f7b48084dca885d15222e60826d5d971f64172d98e0760154400958f00e86697aa1aa9d41bee8119a1ec866abe044a9ad635778ba61fc0776dc832b39451bd5d35072d2269cf9b040d6ba38b54ec35f81d7fc67678c3be47274f3c4cc472aff005c3469eb3bc140769ed4c7f0218ff8c6c7dd7221d189c65b3b9aaa71a01484b122846c7c7b57e02e679ea8469b70e14fe4f70fee4d87b910cf144be6fe48eef24da475c0b0bcc6565ae82cd3f4e3b24c76eaa5616c6111343306ab35c1fe5ca4a77c0e314ed7dba39d6f1e0de791719c241a939cc493bea2bae1c1e932679ea94d29084278513c77b899cc98059d06a27d171b0dbdf6bee13ddc4fc17a0c4d2827d488436b57baa167544138ca2e64a11b43ac8a06cd0c2fba2d4d900ed2d9205305e2d7383cc98dacb078133de5f6fb6bed2ef26ba92cea28aafc3b9948dd9ae5559e8bd6920b8cea462aa445ca6a95e0e7ba52961b181c79e73bd581821df2b10173727a810c92b83b5ba4a0403eb710d2ca10689a35bec6c3a708e9e92f7d78ff3c5d9989574b00c6736f84c199256e76e19e78f0c98a9d580b4a658c84fc8f2096c2fbea8f5f8c59d0fdacb3be2802ef802abbecb3aba4acaac69a0e965abd8981e9896b1f6ef9d60f7a164b371af869fd0e48073742825e9434fc54da837e120266d53302954843538ea7c6c3dbfb4ff3b2fdbe244437f2a153ccf7bdb4c92aa08102d4f3cff2ae5ef86fab4653595e6a5837fa2f3e29f27a9cde5966843fb847a4a61f1e76c281fe8bb2b0a181d096100db5a1a5ce7a910238251a43ca556712eaadea167fb4d7d75825e440f3ecd782036d7574df8bceacb397abefc5f5254d2722215c53ff54af8299aaaad642c6d72a14d27882d9bbd539e1cc7a527526ba89b8c037ad09120e98ab042d3e8652b31ae0e478516bfaf88efca9f3676ffe99d2819dcaeb7610a626695f53117665d267d3f7abebd6bbd6733f645c72c389f03855bdf1e4b8075b516569b118233a0f0971d24b83113c0b096f5216a207ca99a7cddc81c130923fe3d91e7508c9ac5f2e914ff5dccab9e558566fa14efb34ac98d878580814b94b73acbfde9072f30b881f7f0fff42d4045d1ace6322d86a97d164aa84d93a60498065cc7c20e636f5862dc81531a88c60305a2e59a985be327a6902e4bed986dbf4a0b50c217af0ea7fdf9ab37f9ea1a1aaa72f54cf40154ea9b269f1a7c09f9f43245109431a175d50e2db0132337baa0ef97eed0fcf20489da36b79a1172faccc2f7ded7c60e00694282d93359c4682135642bc81f433574aa8ef0c97b4ade7ca372c5ffc23c7eddd839bab4e0f14d6df15c9dbeab176bec8b5701cf054eb3072f6dadc98f88819042bf10c407516ee58bce33fbe3b3d86a54255e577db4598e30a135361528c101683a5fcde7e8ba53f3456254be8f45fe3a56120ae96ea3773631fcb3873aa3abd91bcff00bd38bd43697a2e789e00da6077482e7b1b1a677b5afae4c54e6cbdf7377b694eb7d7a5b913476a5be923322d3de06060fd5e819635232a2cf4f0731da13b8546d1d6d4f8d75b9fce6c2341a71b0ea6f780df54bfdb0dd5cd9855179f602f917265f21f9190c70217774a6fbaaa7d63ad64199f4664813b955cff954949076dcf",
"decode": [
"4141414141414141414141414141414141414141414141414141414141414141",
"4242424242424242424242424242424242424242424242424242424242424242",
"4343434343434343434343434343434343434343434343434343434343434343",
"4444444444444444444444444444444444444444444444444444444444444444",
"4545454545454545454545454545454545454545454545454545454545454545"
]
}
3 changes: 3 additions & 0 deletions common/test/run-sphinx.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ void towire_u16(u8 **pptr UNNEEDED, u16 v UNNEEDED)
/* Generated stub for towire_u32 */
void towire_u32(u8 **pptr UNNEEDED, u32 v UNNEEDED)
{ fprintf(stderr, "towire_u32 called!\n"); abort(); }
/* Generated stub for towire_u64 */
void towire_u64(u8 **pptr UNNEEDED, u64 v UNNEEDED)
{ fprintf(stderr, "towire_u64 called!\n"); abort(); }
/* Generated stub for towire_u8 */
void towire_u8(u8 **pptr UNNEEDED, u8 v UNNEEDED)
{ fprintf(stderr, "towire_u8 called!\n"); abort(); }
Expand Down
2 changes: 2 additions & 0 deletions devtools/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ DEVTOOLS_COMMON_OBJS := \
common/decode_short_channel_ids.o \
common/hash_u5.o \
common/node_id.o \
common/json.o \
common/json_helpers.o \
common/type_to_string.o \
common/utils.o \
common/version.o \
Expand Down
Loading