]> git.bitcoin.ninja Git - rust-lightning/commitdiff
Add a `required_vec` TLV deserialization type
authorMatt Corallo <git@bluematt.me>
Fri, 7 Jul 2023 18:38:06 +0000 (18:38 +0000)
committerMatt Corallo <git@bluematt.me>
Fri, 7 Jul 2023 21:06:52 +0000 (21:06 +0000)
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.

lightning/src/util/ser_macros.rs

index 8ffcec6d17530a7c5674b93e227730da6c097260..37b8be54ebc2d4db6d53fe0c06582650edecc9f5 100644 (file)
@@ -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<Vec<_>> = $crate::util::ser::Readable::read(&mut $reader)?;
+               $field = f.0;
+       }};
        ($reader: expr, $field: ident, vec_type) => {{
                let f: $crate::util::ser::WithoutLength<Vec<_>> = $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());
        };