From: Matt Corallo Date: Fri, 7 Jul 2023 18:38:06 +0000 (+0000) Subject: Add a `required_vec` TLV deserialization type X-Git-Tag: v0.0.116-rc1~7^2~8 X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=32846d33db1c402d6eb7a268ab0dbc717db39232;p=rust-lightning Add a `required_vec` TLV deserialization type Historically, we used `vec_type` for all TLV Vec reads/writes, but it is asymmetric and thus somewhat confusing - on the write side it always writes a TLV entry, even if there are zero elements. On the read side, it happily accepts a missing TLV, providing a zero-length vector. In 85b573ddad70f3c5ee36e0992d587842af507a8d a new `optional_vec` TLV format was added which was symmetric, but only supports optional vecs. This adds the corresponding required form, always writing a TLV and ensuring it is present. --- diff --git a/lightning/src/util/ser_macros.rs b/lightning/src/util/ser_macros.rs index 8ffcec6d1..37b8be54e 100644 --- a/lightning/src/util/ser_macros.rs +++ b/lightning/src/util/ser_macros.rs @@ -29,6 +29,9 @@ macro_rules! _encode_tlv { BigSize($field.serialized_length() as u64).write($stream)?; $field.write($stream)?; }; + ($stream: expr, $type: expr, $field: expr, required_vec) => { + $crate::_encode_tlv!($stream, $type, $crate::util::ser::WithoutLength(&$field), required); + }; ($stream: expr, $type: expr, $field: expr, vec_type) => { $crate::_encode_tlv!($stream, $type, $crate::util::ser::WithoutLength(&$field), required); }; @@ -41,7 +44,7 @@ macro_rules! _encode_tlv { }; ($stream: expr, $type: expr, $field: expr, optional_vec) => { if !$field.is_empty() { - $crate::_encode_tlv!($stream, $type, $field, vec_type); + $crate::_encode_tlv!($stream, $type, $field, required_vec); } }; ($stream: expr, $type: expr, $field: expr, upgradable_required) => { @@ -159,6 +162,9 @@ macro_rules! _get_varint_length_prefixed_tlv_length { BigSize(field_len as u64).write(&mut $len).expect("No in-memory data may fail to serialize"); $len.0 += field_len; }; + ($len: expr, $type: expr, $field: expr, required_vec) => { + $crate::_get_varint_length_prefixed_tlv_length!($len, $type, $crate::util::ser::WithoutLength(&$field), required); + }; ($len: expr, $type: expr, $field: expr, vec_type) => { $crate::_get_varint_length_prefixed_tlv_length!($len, $type, $crate::util::ser::WithoutLength(&$field), required); }; @@ -172,7 +178,7 @@ macro_rules! _get_varint_length_prefixed_tlv_length { }; ($len: expr, $type: expr, $field: expr, optional_vec) => { if !$field.is_empty() { - $crate::_get_varint_length_prefixed_tlv_length!($len, $type, $field, vec_type); + $crate::_get_varint_length_prefixed_tlv_length!($len, $type, $field, required_vec); } }; ($len: expr, $type: expr, $field: expr, (option: $trait: ident $(, $read_arg: expr)?)) => { @@ -236,6 +242,9 @@ macro_rules! _check_decoded_tlv_order { ($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, option) => {{ // no-op }}; + ($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, required_vec) => {{ + $crate::_check_decoded_tlv_order!($last_seen_type, $typ, $type, $field, required); + }}; ($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, vec_type) => {{ // no-op }}; @@ -281,6 +290,9 @@ macro_rules! _check_missing_tlv { ($last_seen_type: expr, $type: expr, $field: ident, (required: $trait: ident $(, $read_arg: expr)?)) => {{ $crate::_check_missing_tlv!($last_seen_type, $type, $field, required); }}; + ($last_seen_type: expr, $type: expr, $field: ident, required_vec) => {{ + $crate::_check_missing_tlv!($last_seen_type, $type, $field, required); + }}; ($last_seen_type: expr, $type: expr, $field: ident, vec_type) => {{ // no-op }}; @@ -320,6 +332,10 @@ macro_rules! _decode_tlv { ($reader: expr, $field: ident, (required: $trait: ident $(, $read_arg: expr)?)) => {{ $field = $trait::read(&mut $reader $(, $read_arg)*)?; }}; + ($reader: expr, $field: ident, required_vec) => {{ + let f: $crate::util::ser::WithoutLength> = $crate::util::ser::Readable::read(&mut $reader)?; + $field = f.0; + }}; ($reader: expr, $field: ident, vec_type) => {{ let f: $crate::util::ser::WithoutLength> = $crate::util::ser::Readable::read(&mut $reader)?; $field = Some(f.0); @@ -694,6 +710,9 @@ macro_rules! _init_tlv_based_struct_field { ($field: ident, required) => { $field.0.unwrap() }; + ($field: ident, required_vec) => { + $field + }; ($field: ident, vec_type) => { $field.unwrap() }; @@ -720,6 +739,9 @@ macro_rules! _init_tlv_field_var { ($field: ident, (required: $trait: ident $(, $read_arg: expr)?)) => { $crate::_init_tlv_field_var!($field, required); }; + ($field: ident, required_vec) => { + let mut $field = Vec::new(); + }; ($field: ident, vec_type) => { let mut $field = Some(Vec::new()); };