Optionally parameterize decode_tlv_stream with custom decode closure
authorValentine Wallace <vwallace@protonmail.com>
Mon, 17 Oct 2022 20:07:40 +0000 (16:07 -0400)
committerValentine Wallace <vwallace@protonmail.com>
Mon, 17 Oct 2022 20:07:42 +0000 (16:07 -0400)
Useful for decoding custom or user-provided TLVs. See macro docs for more info.

Used in upcoming commit(s) to support custom onion message TLVs

lightning/src/util/ser_macros.rs

index 782c0ef27d5de87be4992797a352fb3652c07584..8c0a38670b5ad811dffd534721e3980b02fb444d 100644 (file)
@@ -174,8 +174,13 @@ macro_rules! decode_tlv {
        }};
 }
 
+// `$decode_custom_tlv` is a closure that may be optionally provided to handle custom message types.
+// If it is provided, it will be called with the custom type and the `FixedLengthReader` containing
+// the message contents. It should return `Ok(true)` if the custom message is successfully parsed,
+// `Ok(false)` if the message type is unknown, and `Err(DecodeError)` if parsing fails.
 macro_rules! decode_tlv_stream {
-       ($stream: expr, {$(($type: expr, $field: ident, $fieldty: tt)),* $(,)*}) => { {
+       ($stream: expr, {$(($type: expr, $field: ident, $fieldty: tt)),* $(,)*}
+        $(, $decode_custom_tlv: expr)?) => { {
                use ln::msgs::DecodeError;
                let mut last_seen_type: Option<u64> = None;
                let mut stream_ref = $stream;
@@ -226,10 +231,19 @@ macro_rules! decode_tlv_stream {
                                                return Err(DecodeError::InvalidValue);
                                        }
                                },)*
-                               x if x % 2 == 0 => {
-                                       return Err(DecodeError::UnknownRequiredFeature);
-                               },
-                               _ => {},
+                               t => {
+                                       $(
+                                               if $decode_custom_tlv(t, &mut s)? {
+                                                       // If a custom TLV was successfully read (i.e. decode_custom_tlv returns true),
+                                                       // continue to the next TLV read.
+                                                       s.eat_remaining()?;
+                                                       continue 'tlv_read;
+                                               }
+                                       )?
+                                       if t % 2 == 0 {
+                                               return Err(DecodeError::UnknownRequiredFeature);
+                                       }
+                               }
                        }
                        s.eat_remaining()?;
                }