Rename ClosingMonitorUpdate MonitorUpdateRegeneratedOnStartup
[rust-lightning] / lightning / src / util / ser_macros.rs
index 0a5c0b643dd0c315f2782d94b7caa469dcf4e46d..d6a03a88fbe827efc72f6fcd96aa1e928aaa2c17 100644 (file)
@@ -39,15 +39,27 @@ macro_rules! _encode_tlv {
                        field.write($stream)?;
                }
        };
-       ($stream: expr, $type: expr, $field: expr, ignorable) => {
+       ($stream: expr, $type: expr, $field: expr, optional_vec) => {
+               if !$field.is_empty() {
+                       $crate::_encode_tlv!($stream, $type, $field, vec_type);
+               }
+       };
+       ($stream: expr, $type: expr, $field: expr, upgradable_required) => {
                $crate::_encode_tlv!($stream, $type, $field, required);
        };
+       ($stream: expr, $type: expr, $field: expr, upgradable_option) => {
+               $crate::_encode_tlv!($stream, $type, $field, option);
+       };
        ($stream: expr, $type: expr, $field: expr, (option, encoding: ($fieldty: ty, $encoding: ident))) => {
                $crate::_encode_tlv!($stream, $type, $field.map(|f| $encoding(f)), option);
        };
        ($stream: expr, $type: expr, $field: expr, (option, encoding: $fieldty: ty)) => {
                $crate::_encode_tlv!($stream, $type, $field, option);
        };
+       ($stream: expr, $type: expr, $field: expr, (option: $trait: ident $(, $read_arg: expr)?)) => {
+               // Just a read-mapped type
+               $crate::_encode_tlv!($stream, $type, $field, option);
+       };
 }
 
 /// Panics if the last seen TLV type is not numerically less than the TLV type currently being checked.
@@ -158,9 +170,20 @@ macro_rules! _get_varint_length_prefixed_tlv_length {
                        $len.0 += field_len;
                }
        };
-       ($len: expr, $type: expr, $field: expr, ignorable) => {
+       ($len: expr, $type: expr, $field: expr, optional_vec) => {
+               if !$field.is_empty() {
+                       $crate::_get_varint_length_prefixed_tlv_length!($len, $type, $field, vec_type);
+               }
+       };
+       ($len: expr, $type: expr, $field: expr, (option: $trait: ident $(, $read_arg: expr)?)) => {
+               $crate::_get_varint_length_prefixed_tlv_length!($len, $type, $field, option);
+       };
+       ($len: expr, $type: expr, $field: expr, upgradable_required) => {
                $crate::_get_varint_length_prefixed_tlv_length!($len, $type, $field, required);
        };
+       ($len: expr, $type: expr, $field: expr, upgradable_option) => {
+               $crate::_get_varint_length_prefixed_tlv_length!($len, $type, $field, option);
+       };
 }
 
 /// See the documentation of [`write_tlv_fields`].
@@ -204,13 +227,22 @@ macro_rules! _check_decoded_tlv_order {
                        return Err(DecodeError::InvalidValue);
                }
        }};
+       ($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, (required: $trait: ident $(, $read_arg: expr)?)) => {{
+               $crate::_check_decoded_tlv_order!($last_seen_type, $typ, $type, $field, required);
+       }};
        ($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, option) => {{
                // no-op
        }};
        ($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, vec_type) => {{
                // no-op
        }};
-       ($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, ignorable) => {{
+       ($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, optional_vec) => {{
+               // no-op
+       }};
+       ($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, upgradable_required) => {{
+               _check_decoded_tlv_order!($last_seen_type, $typ, $type, $field, required)
+       }};
+       ($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, upgradable_option) => {{
                // no-op
        }};
        ($last_seen_type: expr, $typ: expr, $type: expr, $field: ident, (option: $trait: ident $(, $read_arg: expr)?)) => {{
@@ -243,13 +275,22 @@ macro_rules! _check_missing_tlv {
                        return Err(DecodeError::InvalidValue);
                }
        }};
+       ($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, vec_type) => {{
                // no-op
        }};
        ($last_seen_type: expr, $type: expr, $field: ident, option) => {{
                // no-op
        }};
-       ($last_seen_type: expr, $type: expr, $field: ident, ignorable) => {{
+       ($last_seen_type: expr, $type: expr, $field: ident, optional_vec) => {{
+               // no-op
+       }};
+       ($last_seen_type: expr, $type: expr, $field: ident, upgradable_required) => {{
+               _check_missing_tlv!($last_seen_type, $type, $field, required)
+       }};
+       ($last_seen_type: expr, $type: expr, $field: ident, upgradable_option) => {{
                // no-op
        }};
        ($last_seen_type: expr, $type: expr, $field: ident, (option: $trait: ident $(, $read_arg: expr)?)) => {{
@@ -273,6 +314,9 @@ macro_rules! _decode_tlv {
        ($reader: expr, $field: ident, required) => {{
                $field = $crate::util::ser::Readable::read(&mut $reader)?;
        }};
+       ($reader: expr, $field: ident, (required: $trait: ident $(, $read_arg: expr)?)) => {{
+               $field = $trait::read(&mut $reader $(, $read_arg)*)?;
+       }};
        ($reader: expr, $field: ident, vec_type) => {{
                let f: $crate::util::ser::WithoutLength<Vec<_>> = $crate::util::ser::Readable::read(&mut $reader)?;
                $field = Some(f.0);
@@ -280,7 +324,23 @@ macro_rules! _decode_tlv {
        ($reader: expr, $field: ident, option) => {{
                $field = Some($crate::util::ser::Readable::read(&mut $reader)?);
        }};
-       ($reader: expr, $field: ident, ignorable) => {{
+       ($reader: expr, $field: ident, optional_vec) => {{
+               $crate::_decode_tlv!($reader, $field, vec_type);
+       }};
+       // `upgradable_required` indicates we're reading a required TLV that may have been upgraded
+       // without backwards compat. We'll error if the field is missing, and return `Ok(None)` if the
+       // field is present but we can no longer understand it.
+       // Note that this variant can only be used within a `MaybeReadable` read.
+       ($reader: expr, $field: ident, upgradable_required) => {{
+               $field = match $crate::util::ser::MaybeReadable::read(&mut $reader)? {
+                       Some(res) => res,
+                       _ => return Ok(None)
+               };
+       }};
+       // `upgradable_option` indicates we're reading an Option-al TLV that may have been upgraded
+       // without backwards compat. $field will be None if the TLV is missing or if the field is present
+       // but we can no longer understand it.
+       ($reader: expr, $field: ident, upgradable_option) => {{
                $field = $crate::util::ser::MaybeReadable::read(&mut $reader)?;
        }};
        ($reader: expr, $field: ident, (option: $trait: ident $(, $read_arg: expr)?)) => {{
@@ -494,7 +554,7 @@ macro_rules! impl_writeable_msg {
                impl $crate::util::ser::Writeable for $st {
                        fn write<W: $crate::util::ser::Writer>(&self, w: &mut W) -> Result<(), $crate::io::Error> {
                                $( self.$field.write(w)?; )*
-                               $crate::encode_tlv_stream!(w, {$(($type, self.$tlvfield, $fieldty)),*});
+                               $crate::encode_tlv_stream!(w, {$(($type, self.$tlvfield.as_ref(), $fieldty)),*});
                                Ok(())
                        }
                }
@@ -619,8 +679,14 @@ macro_rules! _init_tlv_based_struct_field {
        ($field: ident, option) => {
                $field
        };
-       ($field: ident, ignorable) => {
-               if $field.is_none() { return Ok(None); } else { $field.unwrap() }
+       ($field: ident, (option: $trait: ident $(, $read_arg: expr)?)) => {
+               $crate::_init_tlv_based_struct_field!($field, option)
+       };
+       ($field: ident, upgradable_required) => {
+               $field.0.unwrap()
+       };
+       ($field: ident, upgradable_option) => {
+               $field
        };
        ($field: ident, required) => {
                $field.0.unwrap()
@@ -628,6 +694,9 @@ macro_rules! _init_tlv_based_struct_field {
        ($field: ident, vec_type) => {
                $field.unwrap()
        };
+       ($field: ident, optional_vec) => {
+               $field.unwrap()
+       };
 }
 
 /// Initializes the variable we are going to read the TLV into.
@@ -637,13 +706,16 @@ macro_rules! _init_tlv_based_struct_field {
 #[macro_export]
 macro_rules! _init_tlv_field_var {
        ($field: ident, (default_value, $default: expr)) => {
-               let mut $field = $crate::util::ser::OptionDeserWrapper(None);
+               let mut $field = $crate::util::ser::RequiredWrapper(None);
        };
        ($field: ident, (static_value, $value: expr)) => {
                let $field;
        };
        ($field: ident, required) => {
-               let mut $field = $crate::util::ser::OptionDeserWrapper(None);
+               let mut $field = $crate::util::ser::RequiredWrapper(None);
+       };
+       ($field: ident, (required: $trait: ident $(, $read_arg: expr)?)) => {
+               $crate::_init_tlv_field_var!($field, required);
        };
        ($field: ident, vec_type) => {
                let mut $field = Some(Vec::new());
@@ -651,7 +723,19 @@ macro_rules! _init_tlv_field_var {
        ($field: ident, option) => {
                let mut $field = None;
        };
-       ($field: ident, ignorable) => {
+       ($field: ident, optional_vec) => {
+               let mut $field = Some(Vec::new());
+       };
+       ($field: ident, (option, encoding: ($fieldty: ty, $encoding: ident))) => {
+               $crate::_init_tlv_field_var!($field, option);
+       };
+       ($field: ident, (option: $trait: ident $(, $read_arg: expr)?)) => {
+               $crate::_init_tlv_field_var!($field, option);
+       };
+       ($field: ident, upgradable_required) => {
+               let mut $field = $crate::util::ser::UpgradableRequired(None);
+       };
+       ($field: ident, upgradable_option) => {
                let mut $field = None;
        };
 }
@@ -677,7 +761,8 @@ macro_rules! _init_and_read_tlv_fields {
 /// If `$fieldty` is `required`, then `$field` is a required field that is not an [`Option`] nor a [`Vec`].
 /// If `$fieldty` is `(default_value, $default)`, then `$field` will be set to `$default` if not present.
 /// If `$fieldty` is `option`, then `$field` is optional field.
-/// If `$fieldty` is `vec_type`, then `$field` is a [`Vec`], which needs to have its individual elements serialized.
+/// If `$fieldty` is `optional_vec`, then `$field` is a [`Vec`], which needs to have its individual elements serialized.
+///    Note that for `optional_vec` no bytes are written if the vec is empty
 ///
 /// For example,
 /// ```
@@ -693,7 +778,7 @@ macro_rules! _init_and_read_tlv_fields {
 ///    (0, tlv_integer, required),
 ///    (1, tlv_default_integer, (default_value, 7)),
 ///    (2, tlv_optional_integer, option),
-///    (3, tlv_vec_type_integer, vec_type),
+///    (3, tlv_vec_type_integer, optional_vec),
 /// });
 /// ```
 ///
@@ -818,6 +903,8 @@ macro_rules! tlv_record_ref_type {
        ($type:ty) => { &'a $type };
 }
 
+#[doc(hidden)]
+#[macro_export]
 macro_rules! _impl_writeable_tlv_based_enum_common {
        ($st: ident, $(($variant_id: expr, $variant_name: ident) =>
                {$(($type: expr, $field: ident, $fieldty: tt)),* $(,)*}
@@ -829,7 +916,7 @@ macro_rules! _impl_writeable_tlv_based_enum_common {
                                        $($st::$variant_name { $(ref $field),* } => {
                                                let id: u8 = $variant_id;
                                                id.write(writer)?;
-                                               write_tlv_fields!(writer, {
+                                               $crate::write_tlv_fields!(writer, {
                                                        $(($type, *$field, $fieldty)),*
                                                });
                                        }),*
@@ -851,7 +938,7 @@ macro_rules! _impl_writeable_tlv_based_enum_common {
 /// ```ignore
 /// impl_writeable_tlv_based_enum!(EnumName,
 ///   (0, StructVariantA) => {(0, required_variant_field, required), (1, optional_variant_field, option)},
-///   (1, StructVariantB) => {(0, variant_field_a, required), (1, variant_field_b, required), (2, variant_vec_field, vec_type)};
+///   (1, StructVariantB) => {(0, variant_field_a, required), (1, variant_field_b, required), (2, variant_vec_field, optional_vec)};
 ///   (2, TupleVariantA), (3, TupleVariantB),
 /// );
 /// ```
@@ -867,7 +954,7 @@ macro_rules! impl_writeable_tlv_based_enum {
                {$(($type: expr, $field: ident, $fieldty: tt)),* $(,)*}
        ),* $(,)*;
        $(($tuple_variant_id: expr, $tuple_variant_name: ident)),*  $(,)*) => {
-               _impl_writeable_tlv_based_enum_common!($st,
+               $crate::_impl_writeable_tlv_based_enum_common!($st,
                        $(($variant_id, $variant_name) => {$(($type, $field, $fieldty)),*}),*;
                        $(($tuple_variant_id, $tuple_variant_name)),*);
 
@@ -879,12 +966,12 @@ macro_rules! impl_writeable_tlv_based_enum {
                                                // Because read_tlv_fields creates a labeled loop, we cannot call it twice
                                                // in the same function body. Instead, we define a closure and call it.
                                                let f = || {
-                                                       _init_and_read_tlv_fields!(reader, {
+                                                       $crate::_init_and_read_tlv_fields!(reader, {
                                                                $(($type, $field, $fieldty)),*
                                                        });
                                                        Ok($st::$variant_name {
                                                                $(
-                                                                       $field: _init_tlv_based_struct_field!($field, $fieldty)
+                                                                       $field: $crate::_init_tlv_based_struct_field!($field, $fieldty)
                                                                ),*
                                                        })
                                                };
@@ -921,7 +1008,7 @@ macro_rules! impl_writeable_tlv_based_enum_upgradable {
        ),* $(,)*
        $(;
        $(($tuple_variant_id: expr, $tuple_variant_name: ident)),*  $(,)*)*) => {
-               _impl_writeable_tlv_based_enum_common!($st,
+               $crate::_impl_writeable_tlv_based_enum_common!($st,
                        $(($variant_id, $variant_name) => {$(($type, $field, $fieldty)),*}),*;
                        $($(($tuple_variant_id, $tuple_variant_name)),*)*);
 
@@ -933,12 +1020,12 @@ macro_rules! impl_writeable_tlv_based_enum_upgradable {
                                                // Because read_tlv_fields creates a labeled loop, we cannot call it twice
                                                // in the same function body. Instead, we define a closure and call it.
                                                let f = || {
-                                                       _init_and_read_tlv_fields!(reader, {
+                                                       $crate::_init_and_read_tlv_fields!(reader, {
                                                                $(($type, $field, $fieldty)),*
                                                        });
                                                        Ok(Some($st::$variant_name {
                                                                $(
-                                                                       $field: _init_tlv_based_struct_field!($field, $fieldty)
+                                                                       $field: $crate::_init_tlv_based_struct_field!($field, $fieldty)
                                                                ),*
                                                        }))
                                                };
@@ -948,7 +1035,7 @@ macro_rules! impl_writeable_tlv_based_enum_upgradable {
                                                Ok(Some($st::$tuple_variant_name(Readable::read(reader)?)))
                                        }),*)*
                                        _ if id % 2 == 1 => Ok(None),
-                                       _ => Err(DecodeError::UnknownRequiredFeature),
+                                       _ => Err($crate::ln::msgs::DecodeError::UnknownRequiredFeature),
                                }
                        }
                }
@@ -1028,6 +1115,47 @@ mod tests {
                        (0xdeadbeef1badbeef, 0x1bad1dea, Some(0x01020304)));
        }
 
+       #[derive(Debug, PartialEq)]
+       struct TestUpgradable {
+               a: u32,
+               b: u32,
+               c: Option<u32>,
+       }
+
+       fn upgradable_tlv_reader(s: &[u8]) -> Result<Option<TestUpgradable>, DecodeError> {
+               let mut s = Cursor::new(s);
+               let mut a = 0;
+               let mut b = 0;
+               let mut c: Option<u32> = None;
+               decode_tlv_stream!(&mut s, {(2, a, upgradable_required), (3, b, upgradable_required), (4, c, upgradable_option)});
+               Ok(Some(TestUpgradable { a, b, c, }))
+       }
+
+       #[test]
+       fn upgradable_tlv_simple_good_cases() {
+               assert_eq!(upgradable_tlv_reader(&::hex::decode(
+                       concat!("0204deadbeef", "03041bad1dea", "0404deadbeef")
+               ).unwrap()[..]).unwrap(),
+               Some(TestUpgradable { a: 0xdeadbeef, b: 0x1bad1dea, c: Some(0xdeadbeef) }));
+
+               assert_eq!(upgradable_tlv_reader(&::hex::decode(
+                       concat!("0204deadbeef", "03041bad1dea")
+               ).unwrap()[..]).unwrap(),
+               Some(TestUpgradable { a: 0xdeadbeef, b: 0x1bad1dea, c: None}));
+       }
+
+       #[test]
+       fn missing_required_upgradable() {
+               if let Err(DecodeError::InvalidValue) = upgradable_tlv_reader(&::hex::decode(
+                       concat!("0100", "0204deadbeef")
+                       ).unwrap()[..]) {
+               } else { panic!(); }
+               if let Err(DecodeError::InvalidValue) = upgradable_tlv_reader(&::hex::decode(
+                       concat!("0100", "03041bad1dea")
+               ).unwrap()[..]) {
+               } else { panic!(); }
+       }
+
        // BOLT TLV test cases
        fn tlv_reader_n1(s: &[u8]) -> Result<(Option<HighZeroBytesDroppedBigSize<u64>>, Option<u64>, Option<(PublicKey, u64, u64)>, Option<u16>), DecodeError> {
                let mut s = Cursor::new(s);