Browse Source
https://github.com/lightningnetwork/lightning-rfc/pull/631 Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>pull/2938/head
Rusty Russell
6 years ago
3 changed files with 905 additions and 9 deletions
@ -0,0 +1,854 @@ |
|||
#include <ccan/array_size/array_size.h> |
|||
#include <ccan/str/hex/hex.h> |
|||
#include <common/utils.h> |
|||
#include <wally_core.h> |
|||
|
|||
static const char *reason; |
|||
#define SUPERVERBOSE(r) do { reason = (r); } while(0) |
|||
|
|||
#include <wire/tlvstream.c> |
|||
#include <wire/fromwire.c> |
|||
#include <wire/towire.c> |
|||
|
|||
/* AUTOGENERATED MOCKS START */ |
|||
/* AUTOGENERATED MOCKS END */ |
|||
|
|||
/* FIXME: Autogenerate these! */ |
|||
/* BOLT-EXPERIMENTAL #1:
|
|||
* 1. tlvs: `n1` |
|||
* 2. types: |
|||
* 1. type: 1 (`tlv1`) |
|||
* 2. data: |
|||
* * [`tu64`:`amount_msat`] |
|||
* 1. type: 2 (`tlv2`) |
|||
* 2. data: |
|||
* * [`short_channel_id`:`scid`] |
|||
* 1. type: 3 (`tlv3`) |
|||
* 2. data: |
|||
* * [`point`:`node_id`] |
|||
* * [`u64`:`amount_msat_1`] |
|||
* * [`u64`:`amount_msat_2`] |
|||
* 1. type: 254 (`tlv4`) |
|||
* 2. data: |
|||
* * [`u16`:`cltv_delta`] |
|||
*/ |
|||
struct tlv_n1_tlv1 { |
|||
u64 amount_msat; |
|||
}; |
|||
|
|||
struct tlv_n1_tlv2 { |
|||
struct short_channel_id scid; |
|||
}; |
|||
|
|||
struct tlv_n1_tlv3 { |
|||
struct pubkey node_id; |
|||
u64 amount_msat_1; |
|||
u64 amount_msat_2; |
|||
}; |
|||
|
|||
struct tlv_n1_tlv4 { |
|||
u16 cltv_delta; |
|||
}; |
|||
|
|||
struct tlv_n1 { |
|||
struct tlv_n1_tlv1 *tlv1; |
|||
struct tlv_n1_tlv2 *tlv2; |
|||
struct tlv_n1_tlv3 *tlv3; |
|||
struct tlv_n1_tlv4 *tlv4; |
|||
}; |
|||
|
|||
static struct tlv_n1 *tlv_n1_new(const tal_t *ctx) |
|||
{ |
|||
/* Initialize everything to NULL. (Quiet, C pedants!) */ |
|||
return talz(ctx, struct tlv_n1); |
|||
} |
|||
|
|||
static u8 *towire_tlv_n1_tlv1(const tal_t *ctx, const void *vrecord) |
|||
{ |
|||
const struct tlv_n1 *r = vrecord; |
|||
u8 *ptr; |
|||
|
|||
if (!r->tlv1) |
|||
return NULL; |
|||
|
|||
ptr = tal_arr(ctx, u8, 0); |
|||
towire_tu64(&ptr, r->tlv1->amount_msat); |
|||
return ptr; |
|||
} |
|||
|
|||
static u8 *towire_tlv_n1_tlv2(const tal_t *ctx, const void *vrecord) |
|||
{ |
|||
const struct tlv_n1 *r = vrecord; |
|||
u8 *ptr; |
|||
|
|||
if (!r->tlv2) |
|||
return NULL; |
|||
|
|||
ptr = tal_arr(ctx, u8, 0); |
|||
towire_short_channel_id(&ptr, &r->tlv2->scid); |
|||
return ptr; |
|||
} |
|||
|
|||
static u8 *towire_tlv_n1_tlv3(const tal_t *ctx, const void *vrecord) |
|||
{ |
|||
const struct tlv_n1 *r = vrecord; |
|||
u8 *ptr; |
|||
|
|||
if (!r->tlv3) |
|||
return NULL; |
|||
|
|||
ptr = tal_arr(ctx, u8, 0); |
|||
towire_pubkey(&ptr, &r->tlv3->node_id); |
|||
towire_u64(&ptr, r->tlv3->amount_msat_1); |
|||
towire_u64(&ptr, r->tlv3->amount_msat_2); |
|||
return ptr; |
|||
} |
|||
|
|||
static u8 *towire_tlv_n1_tlv4(const tal_t *ctx, const void *vrecord) |
|||
{ |
|||
const struct tlv_n1 *r = vrecord; |
|||
u8 *ptr; |
|||
|
|||
if (!r->tlv4) |
|||
return NULL; |
|||
|
|||
ptr = tal_arr(ctx, u8, 0); |
|||
towire_u16(&ptr, r->tlv4->cltv_delta); |
|||
return ptr; |
|||
} |
|||
|
|||
static void fromwire_tlv_n1_tlv1(const u8 **cursor, size_t *max, void *vrecord) |
|||
{ |
|||
struct tlv_n1 *r = vrecord; |
|||
|
|||
r->tlv1 = tal(r, struct tlv_n1_tlv1); |
|||
r->tlv1->amount_msat = fromwire_tu64(cursor, max); |
|||
} |
|||
|
|||
static void fromwire_tlv_n1_tlv2(const u8 **cursor, size_t *max, void *vrecord) |
|||
{ |
|||
struct tlv_n1 *r = vrecord; |
|||
|
|||
r->tlv2 = tal(r, struct tlv_n1_tlv2); |
|||
fromwire_short_channel_id(cursor, max, &r->tlv2->scid); |
|||
} |
|||
|
|||
static void fromwire_tlv_n1_tlv3(const u8 **cursor, size_t *max, void *vrecord) |
|||
{ |
|||
struct tlv_n1 *r = vrecord; |
|||
|
|||
r->tlv3 = tal(r, struct tlv_n1_tlv3); |
|||
|
|||
fromwire_pubkey(cursor, max, &r->tlv3->node_id); |
|||
r->tlv3->amount_msat_1 = fromwire_u64(cursor, max); |
|||
r->tlv3->amount_msat_2 = fromwire_u64(cursor, max); |
|||
} |
|||
|
|||
static void fromwire_tlv_n1_tlv4(const u8 **cursor, size_t *max, void *vrecord) |
|||
{ |
|||
struct tlv_n1 *r = vrecord; |
|||
|
|||
r->tlv4 = tal(r, struct tlv_n1_tlv4); |
|||
r->tlv4->cltv_delta = fromwire_u16(cursor, max); |
|||
} |
|||
|
|||
static const struct tlv_record_type tlvs_n1[] = { |
|||
{ 1, towire_tlv_n1_tlv1, fromwire_tlv_n1_tlv1 }, |
|||
{ 2, towire_tlv_n1_tlv2, fromwire_tlv_n1_tlv2 }, |
|||
{ 3, towire_tlv_n1_tlv3, fromwire_tlv_n1_tlv3 }, |
|||
{ 254, towire_tlv_n1_tlv4, fromwire_tlv_n1_tlv4 }, |
|||
}; |
|||
|
|||
/* BOLT-EXPERIMENTAL #1:
|
|||
* 1. tlvs: `n2` |
|||
* 2. types: |
|||
* 1. type: 0 (`tlv1`) |
|||
* 2. data: |
|||
* * [`tu64`:`amount_msat`] |
|||
* 1. type: 11 (`tlv2`) |
|||
* 2. data: |
|||
* * [`tu32`:`cltv_expiry`] |
|||
*/ |
|||
struct tlv_n2_tlv1 { |
|||
u64 amount_msat; |
|||
}; |
|||
|
|||
struct tlv_n2_tlv2 { |
|||
u16 cltv_expiry; |
|||
}; |
|||
|
|||
struct tlv_n2 { |
|||
struct tlv_n2_tlv1 *tlv1; |
|||
struct tlv_n2_tlv2 *tlv2; |
|||
}; |
|||
|
|||
static struct tlv_n2 *tlv_n2_new(const tal_t *ctx) |
|||
{ |
|||
/* Initialize everything to NULL. (Quiet, C pedants!) */ |
|||
return talz(ctx, struct tlv_n2); |
|||
} |
|||
|
|||
static u8 *towire_tlv_n2_tlv1(const tal_t *ctx, const void *vrecord) |
|||
{ |
|||
const struct tlv_n2 *r = vrecord; |
|||
u8 *ptr; |
|||
|
|||
if (!r->tlv1) |
|||
return NULL; |
|||
|
|||
ptr = tal_arr(ctx, u8, 0); |
|||
towire_tu64(&ptr, r->tlv1->amount_msat); |
|||
return ptr; |
|||
} |
|||
|
|||
static u8 *towire_tlv_n2_tlv2(const tal_t *ctx, const void *vrecord) |
|||
{ |
|||
const struct tlv_n2 *r = vrecord; |
|||
u8 *ptr; |
|||
|
|||
if (!r->tlv2) |
|||
return NULL; |
|||
|
|||
ptr = tal_arr(ctx, u8, 0); |
|||
towire_u16(&ptr, r->tlv2->cltv_expiry); |
|||
return ptr; |
|||
} |
|||
|
|||
static void fromwire_tlv_n2_tlv1(const u8 **cursor, size_t *max, void *vrecord) |
|||
{ |
|||
struct tlv_n2 *r = vrecord; |
|||
|
|||
r->tlv1 = tal(r, struct tlv_n2_tlv1); |
|||
r->tlv1->amount_msat = fromwire_tu64(cursor, max); |
|||
} |
|||
|
|||
static void fromwire_tlv_n2_tlv2(const u8 **cursor, size_t *max, void *vrecord) |
|||
{ |
|||
struct tlv_n2 *r = vrecord; |
|||
|
|||
r->tlv2 = tal(r, struct tlv_n2_tlv2); |
|||
r->tlv2->cltv_expiry = fromwire_u16(cursor, max); |
|||
} |
|||
|
|||
static const struct tlv_record_type tlvs_n2[] = { |
|||
{ 0, towire_tlv_n2_tlv1, fromwire_tlv_n2_tlv1 }, |
|||
{ 11, towire_tlv_n2_tlv2, fromwire_tlv_n2_tlv2 }, |
|||
}; |
|||
|
|||
/* BOLT #1
|
|||
### TLV Decoding Failures |
|||
|
|||
The following TLV streams in any namespace should trigger a decoding failure: |
|||
|
|||
1. Invalid stream: 0xfd |
|||
2. Reason: type truncated |
|||
|
|||
1. Invalid stream: 0xfd01 |
|||
2. Reason: type truncated |
|||
|
|||
1. Invalid stream: 0xfd0001 00 |
|||
2. Reason: not minimally encoded type |
|||
|
|||
1. Invalid stream: 0xfd0101 |
|||
2. Reason: missing length |
|||
|
|||
1. Invalid stream: 0x0f fd |
|||
2. Reason: (length truncated) |
|||
|
|||
1. Invalid stream: 0x0f fd26 |
|||
2. Reason: (length truncated) |
|||
|
|||
1. Invalid stream: 0x0f fd2602 |
|||
2. Reason: missing value |
|||
|
|||
1. Invalid stream: 0x0f fd0001 00 |
|||
2. Reason: not minimally encoded length |
|||
|
|||
1. Invalid stream: 0x0f fd0201 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 |
|||
2. Reason: value truncated |
|||
|
|||
The following TLV streams in either namespace should trigger a |
|||
decoding failure: |
|||
|
|||
1. Invalid stream: 0x12 00 |
|||
2. Reason: unknown even type. |
|||
|
|||
1. Invalid stream: 0xfd0102 00 |
|||
2. Reason: unknown even type. |
|||
|
|||
1. Invalid stream: 0xfe01000002 00 |
|||
2. Reason: unknown even type. |
|||
|
|||
1. Invalid stream: 0xff0100000000000002 00 |
|||
2. Reason: unknown even type. |
|||
*/ |
|||
|
|||
struct invalid_stream { |
|||
const char *hex; |
|||
const char *reason; |
|||
}; |
|||
|
|||
static struct invalid_stream invalid_streams_either[] = { |
|||
{ "fd", "type truncated" }, |
|||
{ "fd01", "type truncated" }, |
|||
{ "fd0001 00", "not minimally encoded type" }, |
|||
{ "fd0101", "missing length" }, |
|||
{ "0f fd", "(length truncated)" }, |
|||
{ "0f fd26", "(length truncated)" }, |
|||
{ "0f fd2602", "missing value" }, |
|||
{ "0f fd0001 00", "not minimally encoded length" }, |
|||
{ "0f fd0201 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "value truncated" }, |
|||
|
|||
{ "12 00", "unknown even type." }, |
|||
{ "fd0102 00", "unknown even type." }, |
|||
{ "fe01000002 00", "unknown even type." }, |
|||
{ "ff0100000000000002 00", "unknown even type." }, |
|||
}; |
|||
|
|||
/* BOLT-EXPERIMENTAL #1:
|
|||
* |
|||
* The following TLV streams in namespace `n1` should trigger a decoding |
|||
failure: |
|||
|
|||
1. Invalid stream: 0x01 09 ffffffffffffffffff |
|||
2. Reason: greater than encoding length for `n1`s `tlv1`. |
|||
|
|||
1. Invalid stream: 0x01 01 00 |
|||
2. Reason: encoding for `n1`s `tlv1`s `amount_msat` is not minimal |
|||
|
|||
1. Invalid stream: 0x01 02 0001 |
|||
2. Reason: encoding for `n1`s `tlv1`s `amount_msat` is not minimal |
|||
|
|||
1. Invalid stream: 0x01 03 000100 |
|||
2. Reason: encoding for `n1`s `tlv1`s `amount_msat` is not minimal |
|||
|
|||
1. Invalid stream: 0x01 04 00010000 |
|||
2. Reason: encoding for `n1`s `tlv1`s `amount_msat` is not minimal |
|||
|
|||
1. Invalid stream: 0x01 05 0001000000 |
|||
2. Reason: encoding for `n1`s `tlv1`s `amount_msat` is not minimal |
|||
|
|||
1. Invalid stream: 0x01 06 000100000000 |
|||
2. Reason: encoding for `n1`s `tlv1`s `amount_msat` is not minimal |
|||
|
|||
1. Invalid stream: 0x01 07 00010000000000 |
|||
2. Reason: encoding for `n1`s `tlv1`s `amount_msat` is not minimal |
|||
|
|||
1. Invalid stream: 0x01 08 0001000000000000 |
|||
2. Reason: encoding for `n1`s `tlv1`s `amount_msat` is not minimal |
|||
|
|||
1. Invalid stream: 0x02 07 01010101010101 |
|||
2. Reason: less than encoding length for `n1`s `tlv2`. |
|||
|
|||
1. Invalid stream: 0x02 09 010101010101010101 |
|||
2. Reason: greater than encoding length for `n1`s `tlv2`. |
|||
|
|||
1. Invalid stream: 0x03 21 023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb |
|||
2. Reason: less than encoding length for `n1`s `tlv3`. |
|||
|
|||
1. Invalid stream: 0x03 29 023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb0000000000000001 |
|||
2. Reason: less than encoding length for `n1`s `tlv3`. |
|||
|
|||
1. Invalid stream: 0x03 30 023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb000000000000000100000000000001 |
|||
2. Reason: less than encoding length for `n1`s `tlv3`. |
|||
|
|||
1. Invalid stream: 0x03 31 043da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb00000000000000010000000000000002 |
|||
2. Reason: `n1`s `node_id` is not a valid point. |
|||
|
|||
1. Invalid stream: 0x03 32 023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb0000000000000001000000000000000001 |
|||
2. Reason: greater than encoding length for `n1`s `tlv3`. |
|||
|
|||
1. Invalid stream: 0xfd00fe 00 |
|||
2. Reason: less than encoding length for `n1`s `tlv4`. |
|||
|
|||
1. Invalid stream: 0xfd00fe 01 01 |
|||
2. Reason: less than encoding length for `n1`s `tlv4`. |
|||
|
|||
1. Invalid stream: 0xfd00fe 03 010101 |
|||
2. Reason: greater than encoding length for `n1`s `tlv4`. |
|||
|
|||
1. Invalid stream: 0x00 00 |
|||
2. Reason: unknown even field for `n1`s namespace. |
|||
*/ |
|||
|
|||
static struct invalid_stream invalid_streams_n1[] = { |
|||
{ "01 09 ffffffffffffffffff", "greater than encoding length for `n1`s `tlv1`." }, |
|||
{ "01 01 00", "encoding for `n1`s `tlv1`s `amount_msat` is not minimal" }, |
|||
{ "01 02 0001", "encoding for `n1`s `tlv1`s `amount_msat` is not minimal" }, |
|||
{ "01 03 000100", "encoding for `n1`s `tlv1`s `amount_msat` is not minimal" }, |
|||
{ "01 04 00010000", "encoding for `n1`s `tlv1`s `amount_msat` is not minimal" }, |
|||
{ "01 05 0001000000", "encoding for `n1`s `tlv1`s `amount_msat` is not minimal" }, |
|||
{ "01 06 000100000000", "encoding for `n1`s `tlv1`s `amount_msat` is not minimal" }, |
|||
{ "01 07 00010000000000", "encoding for `n1`s `tlv1`s `amount_msat` is not minimal" }, |
|||
{ "01 08 0001000000000000", "encoding for `n1`s `tlv1`s `amount_msat` is not minimal" }, |
|||
{ "02 07 01010101010101", "less than encoding length for `n1`s `tlv2`." }, |
|||
{ "02 09 010101010101010101", "greater than encoding length for `n1`s `tlv2`." }, |
|||
{ "03 21 023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb", "less than encoding length for `n1`s `tlv3`." }, |
|||
{ "03 29 023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb0000000000000001", "less than encoding length for `n1`s `tlv3`." }, |
|||
{ "03 30 023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb000000000000000100000000000001", "less than encoding length for `n1`s `tlv3`." }, |
|||
{ "03 31 043da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb00000000000000010000000000000002", "`n1`s `node_id` is not a valid point." }, |
|||
{ "03 32 023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb0000000000000001000000000000000001", "greater than encoding length for `n1`s `tlv3`." }, |
|||
{ "fd00fe 00", "less than encoding length for `n1`s `tlv4`." }, |
|||
{ "fd00fe 01 01", "less than encoding length for `n1`s `tlv4`." }, |
|||
{ "fd00fe 03 010101", "greater than encoding length for `n1`s `tlv4`." }, |
|||
{ "00 00", "unknown even field for `n1`s namespace." }, |
|||
}; |
|||
|
|||
/* BOLT-EXPERIMENTAL #1:
|
|||
### TLV Stream Decoding Failure |
|||
|
|||
Any appending of an invalid stream to a valid stream should trigger |
|||
a decoding failure. |
|||
|
|||
Any appending of a higher-numbered valid stream to a lower-numbered |
|||
valid stream should not trigger a decoding failure. |
|||
|
|||
In addition, the following TLV streams in namespace `n1` should |
|||
trigger a decoding failure: |
|||
|
|||
1. Invalid stream: 0x02 08 0000000000000226 01 01 2a |
|||
2. Reason: valid tlv records but invalid ordering |
|||
|
|||
1. Invalid stream: 0x02 08 0000000000000231 02 08 0000000000000451 |
|||
2. Reason: duplicate tlv type |
|||
|
|||
1. Invalid stream: 0x1f 00 0f 01 2a |
|||
2. Reason: valid (ignored) tlv records but invalid ordering |
|||
|
|||
1. Invalid stream: 0x1f 00 1f 01 2a |
|||
2. Reason: duplicate tlv type (ignored) |
|||
*/ |
|||
static struct invalid_stream invalid_streams_n1_combo[] = { |
|||
{ "02 08 0000000000000226 01 01 2a", "valid tlv records but invalid ordering" }, |
|||
{ "02 08 0000000000000231 02 08 0000000000000451", "duplicate tlv type" }, |
|||
{ "1f 00 0f 01 2a", "valid (ignored) tlv records but invalid ordering" }, |
|||
{ "1f 00 1f 01 2a", "duplicate tlv type (ignored)" } |
|||
}; |
|||
|
|||
/* BOLT-EXPERIMENTAL #1:
|
|||
The following TLV stream in namespace `n2` should trigger a decoding |
|||
failure: |
|||
|
|||
1. Invalid stream: 0xffffffffffffffffff 00 00 00 |
|||
2. Reason: valid tlv records but invalid ordering |
|||
*/ |
|||
static struct invalid_stream invalid_streams_n2_combo[] = { |
|||
{ "ffffffffffffffffff 00 00 00", "valid tlv records but invalid ordering" }, |
|||
}; |
|||
|
|||
/* BOLT-EXPERIMENTAL #1:
|
|||
* |
|||
### TLV Decoding Successes |
|||
|
|||
The following TLV streams in either namespace should correctly decode, |
|||
and be ignored: |
|||
|
|||
1. Valid stream: 0x |
|||
2. Explanation: empty message |
|||
|
|||
1. Valid stream: 0x21 00 |
|||
2. Explanation: Unknown odd type. |
|||
|
|||
1. Valid stream: 0xfd0201 00 |
|||
2. Explanation: Unknown odd type. |
|||
|
|||
1. Valid stream: 0xfd00fd 00 |
|||
2. Explanation: Unknown odd type. |
|||
|
|||
1. Valid stream: 0xfd00ff 00 |
|||
2. Explanation: Unknown odd type. |
|||
|
|||
1. Valid stream: 0xfe02000001 00 |
|||
2. Explanation: Unknown odd type. |
|||
|
|||
1. Valid stream: 0xff0200000000000001 00 |
|||
2. Explanation: Unknown odd type. |
|||
|
|||
The following TLV streams in `n1` namespace should correctly decode, |
|||
with the values given here: |
|||
|
|||
1. Valid stream: 0x01 00 |
|||
2. Values: `tlv1` `amount_msat`=0 |
|||
|
|||
1. Valid stream: 0x01 01 01 |
|||
2. Values: `tlv1` `amount_msat`=1 |
|||
|
|||
1. Valid stream: 0x01 02 0100 |
|||
2. Values: `tlv1` `amount_msat`=256 |
|||
|
|||
1. Valid stream: 0x01 03 010000 |
|||
2. Values: `tlv1` `amount_msat`=65536 |
|||
|
|||
1. Valid stream: 0x01 04 01000000 |
|||
2. Values: `tlv1` `amount_msat`=16777216 |
|||
|
|||
1. Valid stream: 0x01 05 0100000000 |
|||
2. Values: `tlv1` `amount_msat`=4294967296 |
|||
|
|||
1. Valid stream: 0x01 06 010000000000 |
|||
2. Values: `tlv1` `amount_msat`=1099511627776 |
|||
|
|||
1. Valid stream: 0x01 07 01000000000000 |
|||
2. Values: `tlv1` `amount_msat`=281474976710656 |
|||
|
|||
1. Valid stream: 0x01 08 0100000000000000 |
|||
2. Values: `tlv1` `amount_msat`=72057594037927936 |
|||
|
|||
1. Valid stream: 0x02 08 0000000000000226 |
|||
2. Values: `tlv2` `scid`=0x0x550 |
|||
|
|||
1. Valid stream: 0x03 31 023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb00000000000000010000000000000002 |
|||
2. Values: `tlv3` `node_id`=023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb `amount_msat_1`=1 `amount_msat_2`=2 |
|||
|
|||
1. Valid stream: 0xfd00fe 02 0226 |
|||
2. Values: `tlv4` `cltv_delta`=550 |
|||
*/ |
|||
|
|||
struct valid_stream { |
|||
const char *hex; |
|||
const struct tlv_n1 expect; |
|||
}; |
|||
|
|||
static struct tlv_n1_tlv1 tlv1_0 = { .amount_msat = 0 }; |
|||
static struct tlv_n1_tlv1 tlv1_1 = { .amount_msat = 1 }; |
|||
static struct tlv_n1_tlv1 tlv1_256 = { .amount_msat = 256 }; |
|||
static struct tlv_n1_tlv1 tlv1_65536 = { .amount_msat = 65536 }; |
|||
static struct tlv_n1_tlv1 tlv1_16777216 = { .amount_msat = 16777216 }; |
|||
static struct tlv_n1_tlv1 tlv1_4294967296 = { .amount_msat = 4294967296ULL }; |
|||
static struct tlv_n1_tlv1 tlv1_1099511627776 = { .amount_msat = 1099511627776ULL}; |
|||
static struct tlv_n1_tlv1 tlv1_281474976710656 = { .amount_msat = 281474976710656ULL }; |
|||
static struct tlv_n1_tlv1 tlv1_72057594037927936 = { .amount_msat = 72057594037927936ULL }; |
|||
static struct tlv_n1_tlv2 tlv2_0x0x550 = { .scid.u64 = 0x000000000226 }; |
|||
/* node_id filled in at runtime. */ |
|||
static struct tlv_n1_tlv3 tlv3_node_id = { { { { 0 } } }, .amount_msat_1 = 1, .amount_msat_2 = 2 }; |
|||
static struct tlv_n1_tlv4 tlv4_550 = { .cltv_delta = 550 }; |
|||
|
|||
static struct valid_stream valid_streams[] = { |
|||
/* Valid but no (known) content. */ |
|||
{ "", {NULL, NULL, NULL, NULL} }, |
|||
{ "21 00", {NULL, NULL, NULL, NULL} }, |
|||
{ "fd0201 00", {NULL, NULL, NULL, NULL} }, |
|||
{ "fd00fd 00", {NULL, NULL, NULL, NULL} }, |
|||
{ "fd00ff 00", {NULL, NULL, NULL, NULL} }, |
|||
{ "fe02000001 00", {NULL, NULL, NULL, NULL} }, |
|||
{ "ff0200000000000001 00", {NULL, NULL, NULL, NULL} }, |
|||
|
|||
/* TLV1 */ |
|||
{ "01 00", { .tlv1 = &tlv1_0 } }, |
|||
{ "01 01 01", { .tlv1 = &tlv1_1 } }, |
|||
{ "01 02 0100", { .tlv1 = &tlv1_256 } }, |
|||
{ "01 03 010000", { .tlv1 = &tlv1_65536 } }, |
|||
{ "01 04 01000000", { .tlv1 = &tlv1_16777216 } }, |
|||
{ "01 05 0100000000", { .tlv1 = &tlv1_4294967296 } }, |
|||
{ "01 06 010000000000", { .tlv1 = &tlv1_1099511627776 } }, |
|||
{ "01 07 01000000000000", { .tlv1 = &tlv1_281474976710656 } }, |
|||
{ "01 08 0100000000000000", { .tlv1 = &tlv1_72057594037927936 } }, |
|||
{ "02 08 0000000000000226", { .tlv2 = &tlv2_0x0x550 } }, |
|||
{ "03 31 023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb00000000000000010000000000000002", { .tlv3 = &tlv3_node_id } }, |
|||
{ "fd00fe 02 0226", { .tlv4 = &tlv4_550 } }, |
|||
}; |
|||
|
|||
static bool tlv_n1_eq(const struct tlv_n1 *a, const struct tlv_n1 *b) |
|||
{ |
|||
if (a->tlv1) { |
|||
if (!b->tlv1) |
|||
return false; |
|||
if (a->tlv1->amount_msat != b->tlv1->amount_msat) |
|||
return false; |
|||
} else if (b->tlv1) |
|||
return false; |
|||
|
|||
if (a->tlv2) { |
|||
if (!b->tlv2) |
|||
return false; |
|||
if (!short_channel_id_eq(&a->tlv2->scid, &b->tlv2->scid)) |
|||
return false; |
|||
} else if (b->tlv2) |
|||
return false; |
|||
|
|||
if (a->tlv3) { |
|||
if (!b->tlv3) |
|||
return false; |
|||
if (!pubkey_eq(&a->tlv3->node_id, &b->tlv3->node_id)) |
|||
return false; |
|||
if (a->tlv3->amount_msat_1 != b->tlv3->amount_msat_1) |
|||
return false; |
|||
if (a->tlv3->amount_msat_2 != b->tlv3->amount_msat_2) |
|||
return false; |
|||
} else if (b->tlv3) |
|||
return false; |
|||
|
|||
if (a->tlv4) { |
|||
if (!b->tlv4) |
|||
return false; |
|||
if (a->tlv4->cltv_delta != b->tlv4->cltv_delta) |
|||
return false; |
|||
} else if (b->tlv4) |
|||
return false; |
|||
|
|||
return true; |
|||
} |
|||
|
|||
/* hexstr is valid, so pull out first field */ |
|||
static u64 pull_type(const char *hexstr) |
|||
{ |
|||
u8 v; |
|||
|
|||
hex_decode(hexstr, 2, &v, sizeof(v)); |
|||
switch (v) { |
|||
case 0xfd: { |
|||
u16 d; |
|||
hex_decode(hexstr + 2, 2*sizeof(d), &d, sizeof(d)); |
|||
return be16_to_cpu(d); |
|||
} |
|||
case 0xfe: { |
|||
u32 d; |
|||
hex_decode(hexstr + 2, 2*sizeof(d), &d, sizeof(d)); |
|||
return be32_to_cpu(d); |
|||
} |
|||
case 0xff: { |
|||
u64 d; |
|||
hex_decode(hexstr + 2, 2*sizeof(d), &d, sizeof(d)); |
|||
return be64_to_cpu(d); |
|||
} |
|||
default: |
|||
return v; |
|||
} |
|||
} |
|||
|
|||
static u8 *stream(const tal_t *ctx, const char *hex) |
|||
{ |
|||
size_t i, j; |
|||
char *str = tal_arr(tmpctx, char, strlen(hex) + 1); |
|||
|
|||
/* Remove spaces and use normal helper */ |
|||
for (i = j = 0; i <= strlen(hex); i++) { |
|||
if (hex[i] != ' ') |
|||
str[j++] = hex[i]; |
|||
} |
|||
return tal_hexdata(ctx, str, strlen(str)); |
|||
} |
|||
|
|||
static u8 *stream2(const tal_t *ctx, const char *hex1, const char *hex2) |
|||
{ |
|||
u8 *a = stream(tmpctx, hex1), *b = stream(tmpctx, hex2), *ret; |
|||
|
|||
ret = tal_dup_arr(ctx, u8, a, tal_count(a), tal_count(b)); |
|||
memcpy(ret + tal_count(a), b, tal_count(b)); |
|||
return ret; |
|||
} |
|||
|
|||
static bool ignored_fields(const struct tlv_n1 *tlv_n1) |
|||
{ |
|||
return tlv_n1->tlv1 == NULL |
|||
&& tlv_n1->tlv2 == NULL |
|||
&& tlv_n1->tlv3 == NULL |
|||
&& tlv_n1->tlv4 == NULL; |
|||
} |
|||
|
|||
int main(void) |
|||
{ |
|||
setup_locale(); |
|||
wally_init(0); |
|||
secp256k1_ctx = wally_get_secp_context(); |
|||
|
|||
setup_tmpctx(); |
|||
|
|||
if (!pubkey_from_hexstr("023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb", 66, &tlv3_node_id.node_id)) |
|||
abort(); |
|||
|
|||
for (size_t i = 0; i < ARRAY_SIZE(invalid_streams_either); i++) { |
|||
struct tlv_n1 *tlv_n1 = tlv_n1_new(tmpctx); |
|||
struct tlv_n2 *tlv_n2 = tlv_n2_new(tmpctx); |
|||
const u8 *p, *orig_p; |
|||
size_t max; |
|||
|
|||
orig_p = stream(tmpctx, invalid_streams_either[i].hex); |
|||
max = tal_count(orig_p); |
|||
p = orig_p; |
|||
assert(!fromwire_tlvs(&p, &max, tlvs_n1, ARRAY_SIZE(tlvs_n1), |
|||
tlv_n1)); |
|||
assert(!p); |
|||
assert(strstr(invalid_streams_either[i].reason, reason)); |
|||
max = tal_count(orig_p); |
|||
p = orig_p; |
|||
assert(!fromwire_tlvs(&p, &max, tlvs_n2, ARRAY_SIZE(tlvs_n2), |
|||
tlv_n2)); |
|||
assert(!p); |
|||
assert(strstr(invalid_streams_either[i].reason, reason)); |
|||
} |
|||
|
|||
for (size_t i = 0; i < ARRAY_SIZE(invalid_streams_n1); i++) { |
|||
struct tlv_n1 *tlv_n1 = tlv_n1_new(tmpctx); |
|||
const u8 *p; |
|||
size_t max; |
|||
|
|||
p = stream(tmpctx, invalid_streams_n1[i].hex); |
|||
max = tal_count(p); |
|||
assert(!fromwire_tlvs(&p, &max, tlvs_n1, ARRAY_SIZE(tlvs_n1), |
|||
tlv_n1)); |
|||
assert(!p); |
|||
assert(strstr(invalid_streams_n1[i].reason, reason)); |
|||
} |
|||
|
|||
for (size_t i = 0; i < ARRAY_SIZE(invalid_streams_n1_combo); i++) { |
|||
struct tlv_n1 *tlv_n1 = tlv_n1_new(tmpctx); |
|||
const u8 *p; |
|||
size_t max; |
|||
|
|||
p = stream(tmpctx, invalid_streams_n1_combo[i].hex); |
|||
max = tal_count(p); |
|||
assert(!fromwire_tlvs(&p, &max, tlvs_n1, ARRAY_SIZE(tlvs_n1), |
|||
tlv_n1)); |
|||
assert(!p); |
|||
assert(strstr(invalid_streams_n1_combo[i].reason, reason)); |
|||
} |
|||
|
|||
for (size_t i = 0; i < ARRAY_SIZE(invalid_streams_n2_combo); i++) { |
|||
struct tlv_n2 *tlv_n2 = tlv_n2_new(tmpctx); |
|||
const u8 *p; |
|||
size_t max; |
|||
|
|||
p = stream(tmpctx, invalid_streams_n2_combo[i].hex); |
|||
max = tal_count(p); |
|||
assert(!fromwire_tlvs(&p, &max, tlvs_n2, ARRAY_SIZE(tlvs_n2), |
|||
tlv_n2)); |
|||
assert(!p); |
|||
assert(strstr(invalid_streams_n2_combo[i].reason, reason)); |
|||
} |
|||
|
|||
for (size_t i = 0; i < ARRAY_SIZE(valid_streams); i++) { |
|||
struct tlv_n1 *tlv_n1 = tlv_n1_new(tmpctx); |
|||
const u8 *orig_p, *p; |
|||
u8 *p2; |
|||
size_t max; |
|||
|
|||
orig_p = stream(tmpctx, valid_streams[i].hex); |
|||
|
|||
max = tal_count(orig_p); |
|||
p = orig_p; |
|||
assert(fromwire_tlvs(&p, &max, tlvs_n1, ARRAY_SIZE(tlvs_n1), |
|||
tlv_n1)); |
|||
assert(p); |
|||
assert(max == 0); |
|||
assert(tlv_n1_eq(tlv_n1, &valid_streams[i].expect)); |
|||
|
|||
/* Re-encoding should give the same results (except
|
|||
* ignored fields tests!) */ |
|||
if (ignored_fields(tlv_n1)) |
|||
continue; |
|||
|
|||
p2 = tal_arr(tmpctx, u8, 0); |
|||
towire_tlvs(&p2, tlvs_n1, ARRAY_SIZE(tlvs_n1), tlv_n1); |
|||
assert(memeq(p2, tal_count(p2), orig_p, tal_count(orig_p))); |
|||
} |
|||
|
|||
/* BOLT-EXPERIMENTAL #1:
|
|||
* |
|||
* Any appending of an invalid stream to a valid stream should trigger |
|||
* a decoding failure. |
|||
*/ |
|||
for (size_t i = 0; i < ARRAY_SIZE(invalid_streams_either); i++) { |
|||
for (size_t j = 0; j < ARRAY_SIZE(valid_streams); j++) { |
|||
struct tlv_n1 *tlv_n1 = tlv_n1_new(tmpctx); |
|||
struct tlv_n2 *tlv_n2 = tlv_n2_new(tmpctx); |
|||
const u8 *orig_p, *p; |
|||
size_t max; |
|||
|
|||
/* Append */ |
|||
orig_p = stream2(tmpctx, valid_streams[j].hex, |
|||
invalid_streams_either[i].hex); |
|||
max = tal_count(orig_p); |
|||
p = orig_p; |
|||
assert(!fromwire_tlvs(&p, &max, |
|||
tlvs_n1, ARRAY_SIZE(tlvs_n1), |
|||
tlv_n1)); |
|||
assert(!p); |
|||
max = tal_count(orig_p); |
|||
p = orig_p; |
|||
assert(!fromwire_tlvs(&p, &max, |
|||
tlvs_n2, ARRAY_SIZE(tlvs_n2), |
|||
tlv_n2)); |
|||
assert(!p); |
|||
} |
|||
} |
|||
|
|||
for (size_t i = 0; i < ARRAY_SIZE(invalid_streams_n1); i++) { |
|||
for (size_t j = 0; j < ARRAY_SIZE(valid_streams); j++) { |
|||
struct tlv_n1 *tlv_n1 = tlv_n1_new(tmpctx); |
|||
const u8 *p; |
|||
size_t max; |
|||
|
|||
p = stream2(tmpctx, valid_streams[j].hex, |
|||
invalid_streams_n1[i].hex); |
|||
max = tal_count(p); |
|||
assert(!fromwire_tlvs(&p, &max, |
|||
tlvs_n1, ARRAY_SIZE(tlvs_n1), |
|||
tlv_n1)); |
|||
assert(!p); |
|||
} |
|||
} |
|||
|
|||
for (size_t i = 0; i < ARRAY_SIZE(invalid_streams_n1_combo); i++) { |
|||
for (size_t j = 0; j < ARRAY_SIZE(valid_streams); j++) { |
|||
struct tlv_n1 *tlv_n1 = tlv_n1_new(tmpctx); |
|||
const u8 *p; |
|||
size_t max; |
|||
|
|||
p = stream2(tmpctx, valid_streams[j].hex, |
|||
invalid_streams_n1_combo[i].hex); |
|||
max = tal_count(p); |
|||
assert(!fromwire_tlvs(&p, &max, |
|||
tlvs_n1, ARRAY_SIZE(tlvs_n1), |
|||
tlv_n1)); |
|||
assert(!p); |
|||
} |
|||
} |
|||
|
|||
/* BOLT-EXPERIMENTAL #1:
|
|||
* |
|||
* Any appending of a higher-numbered valid stream to a lower-numbered |
|||
* valid stream should not trigger a decoding failure. |
|||
*/ |
|||
for (size_t i = 0; i < ARRAY_SIZE(valid_streams); i++) { |
|||
for (size_t j = i+1; j < ARRAY_SIZE(valid_streams); j++) { |
|||
struct tlv_n1 *tlv_n1 = tlv_n1_new(tmpctx); |
|||
const u8 *orig_p, *p; |
|||
size_t max; |
|||
bool expect_success; |
|||
|
|||
if (strlen(valid_streams[i].hex) == 0 |
|||
|| strlen(valid_streams[j].hex) == 0) |
|||
continue; |
|||
|
|||
orig_p = stream2(tmpctx, valid_streams[i].hex, |
|||
valid_streams[j].hex); |
|||
max = tal_count(orig_p); |
|||
p = orig_p; |
|||
|
|||
/* This comparison works for our simple cases. */ |
|||
expect_success = pull_type(valid_streams[i].hex) |
|||
< pull_type(valid_streams[j].hex); |
|||
|
|||
assert(fromwire_tlvs(&p, &max, |
|||
tlvs_n1, ARRAY_SIZE(tlvs_n1), |
|||
tlv_n1) == expect_success); |
|||
|
|||
if (!expect_success) |
|||
continue; |
|||
|
|||
/* Re-encoding should give the same results (except
|
|||
* ignored fields tests!) */ |
|||
if (ignored_fields(&valid_streams[i].expect) |
|||
|| ignored_fields(&valid_streams[j].expect)) |
|||
continue; |
|||
|
|||
u8 *p2 = tal_arr(tmpctx, u8, 0); |
|||
towire_tlvs(&p2, tlvs_n1, ARRAY_SIZE(tlvs_n1), tlv_n1); |
|||
assert(memeq(orig_p, tal_count(orig_p), |
|||
p2, tal_count(p2))); |
|||
} |
|||
} |
|||
tal_free(tmpctx); |
|||
wally_cleanup(0); |
|||
} |
Loading…
Reference in new issue