Browse Source

common/sphinx: handle decoding of TLV payload.

We add routines to decode the expected fields from both legacy and tlv
hop formats.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
travis-debug
Rusty Russell 5 years ago
committed by Christian Decker
parent
commit
b7bbccd6fa
  1. 102
      common/sphinx.c
  2. 15
      common/sphinx.h
  3. 3
      common/test/Makefile
  4. 39
      common/test/run-sphinx.c
  5. 11
      wallet/test/run-wallet.c

102
common/sphinx.c

@ -477,16 +477,31 @@ static void sphinx_parse_payload(struct route_step *step, const u8 *src)
}
#endif
/* Legacy hop_data support */
/* BOLT #4:
*
* The `length` field determines both the length and the format of the
* `hop_payload` field; the following formats are defined:
*
* - Legacy `hop_data` format, identified by a single `0x00` byte for
* length. In this case the `hop_payload_length` is defined to be 32
* bytes.
*
* - `tlv_payload` format, identified by any length over `1`. In this
* case the `hop_payload_length` is equal to the numeric value of
* `length`.
*/
if (src[0] == 0x00) {
vsize = 1;
raw_size = 32;
hop_size = FRAME_SIZE;
step->type = SPHINX_V0_PAYLOAD;
} else {
} else if (src[0] > 1) {
vsize = bigsize_get(src, 3, &raw_size);
hop_size = raw_size + vsize + HMAC_SIZE;
step->type = SPHINX_TLV_PAYLOAD;
} else {
step->type = SPHINX_INVALID_PAYLOAD;
return;
}
/* Copy common pieces over */
@ -497,6 +512,18 @@ static void sphinx_parse_payload(struct route_step *step, const u8 *src)
* later. */
if (step->type == SPHINX_V0_PAYLOAD)
deserialize_hop_data(&step->payload.v0, src);
else if (step->type == SPHINX_TLV_PAYLOAD) {
const u8 *tlv = step->raw_payload;
size_t max = tal_bytelen(tlv);
step->payload.tlv = tlv_tlv_payload_new(step);
if (!fromwire_tlvs(&tlv, &max, tlvs_tlv_payload,
TLVS_TLV_PAYLOAD_ARRAY_SIZE,
step->payload.tlv)) {
/* FIXME: record offset of violation for error! */
step->type = SPHINX_INVALID_PAYLOAD;
return;
}
}
}
struct onionpacket *create_onionpacket(
@ -781,3 +808,74 @@ struct onionreply *unwrap_onionreply(const tal_t *ctx,
return oreply;
}
/**
* Helper to extract fields from ONION_END.
*/
bool route_step_decode_end(const struct route_step *rs,
struct amount_msat *amt_forward,
u32 *outgoing_cltv)
{
assert(rs->nextcase == ONION_END);
switch (rs->type) {
case SPHINX_V0_PAYLOAD:
*amt_forward = rs->payload.v0.amt_forward;
*outgoing_cltv = rs->payload.v0.outgoing_cltv;
return true;
case SPHINX_TLV_PAYLOAD:
if (!rs->payload.tlv->amt_to_forward)
return false;
amt_forward->millisatoshis /* Raw: tu64 -> millisatoshis */
= rs->payload.tlv->amt_to_forward->amt_to_forward;
if (!rs->payload.tlv->outgoing_cltv_value)
return false;
*outgoing_cltv = rs->payload.tlv->outgoing_cltv_value->outgoing_cltv_value;
return true;
case SPHINX_INVALID_PAYLOAD:
return false;
/* This should probably be removed, as it's just for testing */
case SPHINX_RAW_PAYLOAD:
abort();
}
abort();
}
/**
* Helper to extract fields from ONION_FORWARD.
*/
bool route_step_decode_forward(const struct route_step *rs,
struct amount_msat *amt_forward,
u32 *outgoing_cltv,
struct short_channel_id *scid)
{
assert(rs->nextcase == ONION_FORWARD);
switch (rs->type) {
case SPHINX_V0_PAYLOAD:
*amt_forward = rs->payload.v0.amt_forward;
*outgoing_cltv = rs->payload.v0.outgoing_cltv;
*scid = rs->payload.v0.channel_id;
return true;
case SPHINX_TLV_PAYLOAD:
if (!rs->payload.tlv->amt_to_forward)
return false;
amt_forward->millisatoshis /* Raw: tu64 -> millisatoshis */
= rs->payload.tlv->amt_to_forward->amt_to_forward;
if (!rs->payload.tlv->outgoing_cltv_value)
return false;
*outgoing_cltv = rs->payload.tlv->outgoing_cltv_value->outgoing_cltv_value;
if (!rs->payload.tlv->short_channel_id)
return false;
*scid = rs->payload.tlv->short_channel_id->short_channel_id;
return true;
case SPHINX_INVALID_PAYLOAD:
return false;
/* This should probably be removed, as it's just for testing */
case SPHINX_RAW_PAYLOAD:
abort();
}
abort();
}

15
common/sphinx.h

@ -81,6 +81,7 @@ struct route_step {
enum sphinx_payload_type type;
union {
struct hop_data_legacy v0;
struct tlv_tlv_payload *tlv;
} payload;
u8 *raw_payload;
};
@ -230,4 +231,18 @@ void sphinx_add_v0_hop(struct sphinx_path *path, const struct pubkey *pubkey,
void sphinx_add_raw_hop(struct sphinx_path *path, const struct pubkey *pubkey,
enum sphinx_payload_type type, const u8 *payload);
/**
* Helper to extract fields from ONION_END.
*/
bool route_step_decode_end(const struct route_step *rs,
struct amount_msat *amt_forward,
u32 *outgoing_cltv);
/**
* Helper to extract fields from ONION_FORWARD.
*/
bool route_step_decode_forward(const struct route_step *rs,
struct amount_msat *amt_forward,
u32 *outgoing_cltv,
struct short_channel_id *scid);
#endif /* LIGHTNING_COMMON_SPHINX_H */

3
common/test/Makefile

@ -11,6 +11,9 @@ $(COMMON_TEST_OBJS): $(COMMON_HEADERS) $(WIRE_HEADERS) $(COMMON_SRC)
ALL_TEST_PROGRAMS += $(COMMON_TEST_PROGRAMS)
ALL_OBJS += $(COMMON_TEST_PROGRAMS:=.o)
# Sphinx test wants to decode TLVs.
common/test/run-sphinx: wire/gen_onion_wire.o
update-mocks: $(COMMON_TEST_SRC:%=update-mocks/%)
check-units: $(COMMON_TEST_PROGRAMS:%=unittest/%)

39
common/test/run-sphinx.c

@ -43,13 +43,31 @@ const u8 *fromwire(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, void *copy
/* Generated stub for fromwire_amount_msat */
struct amount_msat fromwire_amount_msat(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
{ fprintf(stderr, "fromwire_amount_msat called!\n"); abort(); }
/* Generated stub for fromwire_bigsize */
bigsize_t fromwire_bigsize(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
{ fprintf(stderr, "fromwire_bigsize called!\n"); abort(); }
/* Generated stub for fromwire_fail */
const void *fromwire_fail(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
{ fprintf(stderr, "fromwire_fail called!\n"); abort(); }
/* Generated stub for fromwire_sha256 */
void fromwire_sha256(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, struct sha256 *sha256 UNNEEDED)
{ fprintf(stderr, "fromwire_sha256 called!\n"); abort(); }
/* Generated stub for fromwire_short_channel_id */
void fromwire_short_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED,
struct short_channel_id *short_channel_id UNNEEDED)
{ fprintf(stderr, "fromwire_short_channel_id called!\n"); abort(); }
/* Generated stub for fromwire_tlvs */
bool fromwire_tlvs(const u8 **cursor UNNEEDED, size_t *max UNNEEDED,
const struct tlv_record_type types[] UNNEEDED,
size_t num_types UNNEEDED,
void *record UNNEEDED)
{ fprintf(stderr, "fromwire_tlvs called!\n"); abort(); }
/* Generated stub for fromwire_tu32 */
u32 fromwire_tu32(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
{ fprintf(stderr, "fromwire_tu32 called!\n"); abort(); }
/* Generated stub for fromwire_tu64 */
u64 fromwire_tu64(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
{ fprintf(stderr, "fromwire_tu64 called!\n"); abort(); }
/* Generated stub for fromwire_u16 */
u16 fromwire_u16(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
{ fprintf(stderr, "fromwire_u16 called!\n"); abort(); }
@ -59,16 +77,34 @@ u32 fromwire_u32(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
/* Generated stub for fromwire_u8 */
u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
{ fprintf(stderr, "fromwire_u8 called!\n"); abort(); }
/* Generated stub for fromwire_u8_array */
void fromwire_u8_array(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, u8 *arr UNNEEDED, size_t num UNNEEDED)
{ fprintf(stderr, "fromwire_u8_array called!\n"); abort(); }
/* Generated stub for towire */
void towire(u8 **pptr UNNEEDED, const void *data UNNEEDED, size_t len UNNEEDED)
{ fprintf(stderr, "towire called!\n"); abort(); }
/* Generated stub for towire_amount_msat */
void towire_amount_msat(u8 **pptr UNNEEDED, const struct amount_msat msat UNNEEDED)
{ fprintf(stderr, "towire_amount_msat called!\n"); abort(); }
/* Generated stub for towire_bigsize */
void towire_bigsize(u8 **pptr UNNEEDED, const bigsize_t val UNNEEDED)
{ fprintf(stderr, "towire_bigsize called!\n"); abort(); }
/* Generated stub for towire_pad */
void towire_pad(u8 **pptr UNNEEDED, size_t num UNNEEDED)
{ fprintf(stderr, "towire_pad called!\n"); abort(); }
/* Generated stub for towire_sha256 */
void towire_sha256(u8 **pptr UNNEEDED, const struct sha256 *sha256 UNNEEDED)
{ fprintf(stderr, "towire_sha256 called!\n"); abort(); }
/* Generated stub for towire_short_channel_id */
void towire_short_channel_id(u8 **pptr UNNEEDED,
const struct short_channel_id *short_channel_id UNNEEDED)
{ fprintf(stderr, "towire_short_channel_id called!\n"); abort(); }
/* Generated stub for towire_tu32 */
void towire_tu32(u8 **pptr UNNEEDED, u32 v UNNEEDED)
{ fprintf(stderr, "towire_tu32 called!\n"); abort(); }
/* Generated stub for towire_tu64 */
void towire_tu64(u8 **pptr UNNEEDED, u64 v UNNEEDED)
{ fprintf(stderr, "towire_tu64 called!\n"); abort(); }
/* Generated stub for towire_u16 */
void towire_u16(u8 **pptr UNNEEDED, u16 v UNNEEDED)
{ fprintf(stderr, "towire_u16 called!\n"); abort(); }
@ -78,6 +114,9 @@ void towire_u32(u8 **pptr UNNEEDED, u32 v UNNEEDED)
/* 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_array */
void towire_u8_array(u8 **pptr UNNEEDED, const u8 *arr UNNEEDED, size_t num UNNEEDED)
{ fprintf(stderr, "towire_u8_array called!\n"); abort(); }
/* AUTOGENERATED MOCKS END */
secp256k1_context *secp256k1_ctx;

11
wallet/test/run-wallet.c

@ -535,6 +535,17 @@ struct route_step *process_onionpacket(
const size_t assocdatalen
)
{ fprintf(stderr, "process_onionpacket called!\n"); abort(); }
/* Generated stub for route_step_decode_end */
bool route_step_decode_end(const struct route_step *rs UNNEEDED,
struct amount_msat *amt_forward UNNEEDED,
u32 *outgoing_cltv UNNEEDED)
{ fprintf(stderr, "route_step_decode_end called!\n"); abort(); }
/* Generated stub for route_step_decode_forward */
bool route_step_decode_forward(const struct route_step *rs UNNEEDED,
struct amount_msat *amt_forward UNNEEDED,
u32 *outgoing_cltv UNNEEDED,
struct short_channel_id *scid UNNEEDED)
{ fprintf(stderr, "route_step_decode_forward called!\n"); abort(); }
/* Generated stub for serialize_onionpacket */
u8 *serialize_onionpacket(
const tal_t *ctx UNNEEDED,

Loading…
Cancel
Save