diff --git a/wire/fromwire.c b/wire/fromwire.c index 629683fac..b99f74762 100644 --- a/wire/fromwire.c +++ b/wire/fromwire.c @@ -1,4 +1,5 @@ #include "wire.h" +#include #include #include #include @@ -86,6 +87,58 @@ u64 fromwire_u64(const u8 **cursor, size_t *max) return be64_to_cpu(ret); } +static u64 fromwire_tlv_uint(const u8 **cursor, size_t *max, size_t maxlen) +{ + u8 bytes[8]; + size_t length; + be64 val; + + assert(maxlen <= sizeof(bytes)); + + /* BOLT-EXPERIMENTAL #1: + * + * - if `length` is not exactly equal to that required for the + * known encoding for `type`: + * - MUST fail to parse the `tlv_stream`. + */ + length = *max; + if (length > maxlen) { + fromwire_fail(cursor, max); + return 0; + } + + memset(bytes, 0, sizeof(bytes)); + fromwire(cursor, max, bytes + sizeof(bytes) - length, length); + + /* BOLT-EXPERIMENTAL #1: + * - if variable-length fields within the known encoding for `type` are + * not minimal: + * - MUST fail to parse the `tlv_stream`. + */ + if (length > 0 && bytes[sizeof(bytes) - length] == 0) { + fromwire_fail(cursor, max); + return 0; + } + BUILD_ASSERT(sizeof(val) == sizeof(bytes)); + memcpy(&val, bytes, sizeof(bytes)); + return be64_to_cpu(val); +} + +u16 fromwire_tu16(const u8 **cursor, size_t *max) +{ + return fromwire_tlv_uint(cursor, max, 2); +} + +u32 fromwire_tu32(const u8 **cursor, size_t *max) +{ + return fromwire_tlv_uint(cursor, max, 4); +} + +u64 fromwire_tu64(const u8 **cursor, size_t *max) +{ + return fromwire_tlv_uint(cursor, max, 8); +} + void fromwire_double(const u8 **cursor, size_t *max, double *ret) { fromwire(cursor, max, ret, sizeof(*ret)); diff --git a/wire/towire.c b/wire/towire.c index 4a5fac821..d83867550 100644 --- a/wire/towire.c +++ b/wire/towire.c @@ -44,6 +44,38 @@ void towire_u64(u8 **pptr, u64 v) towire(pptr, &l, sizeof(l)); } +static void towire_tlv_uint(u8 **pptr, u64 v) +{ + u8 bytes[8]; + size_t num_zeroes; + be64 val; + + val = cpu_to_be64(v); + BUILD_ASSERT(sizeof(val) == sizeof(bytes)); + memcpy(bytes, &val, sizeof(bytes)); + + for (num_zeroes = 0; num_zeroes < sizeof(bytes); num_zeroes++) + if (bytes[num_zeroes] != 0) + break; + + towire(pptr, bytes + num_zeroes, sizeof(bytes) - num_zeroes); +} + +void towire_tu16(u8 **pptr, u16 v) +{ + return towire_tlv_uint(pptr, v); +} + +void towire_tu32(u8 **pptr, u32 v) +{ + return towire_tlv_uint(pptr, v); +} + +void towire_tu64(u8 **pptr, u64 v) +{ + return towire_tlv_uint(pptr, v); +} + void towire_double(u8 **pptr, const double *v) { towire(pptr, v, sizeof(*v)); @@ -223,4 +255,4 @@ void towire_bip32_key_version(u8 **pptr, const struct bip32_key_version *version { towire_u32(pptr, version->bip32_pubkey_version); towire_u32(pptr, version->bip32_privkey_version); -} \ No newline at end of file +} diff --git a/wire/wire.h b/wire/wire.h index 90e237768..26a102396 100644 --- a/wire/wire.h +++ b/wire/wire.h @@ -66,6 +66,9 @@ void towire_u8(u8 **pptr, u8 v); void towire_u16(u8 **pptr, u16 v); void towire_u32(u8 **pptr, u32 v); void towire_u64(u8 **pptr, u64 v); +void towire_tu16(u8 **pptr, u16 v); +void towire_tu32(u8 **pptr, u32 v); +void towire_tu64(u8 **pptr, u64 v); void towire_double(u8 **pptr, const double *v); void towire_pad(u8 **pptr, size_t num); void towire_bool(u8 **pptr, bool v); @@ -84,6 +87,9 @@ u8 fromwire_u8(const u8 **cursor, size_t *max); u16 fromwire_u16(const u8 **cursor, size_t *max); u32 fromwire_u32(const u8 **cursor, size_t *max); u64 fromwire_u64(const u8 **cursor, size_t *max); +u16 fromwire_tu16(const u8 **cursor, size_t *max); +u32 fromwire_tu32(const u8 **cursor, size_t *max); +u64 fromwire_tu64(const u8 **cursor, size_t *max); void fromwire_double(const u8 **cursor, size_t *max, double *v); bool fromwire_bool(const u8 **cursor, size_t *max); u64 fromwire_bigsize(const u8 **cursor, size_t *max);