diff --git a/crates/storage/codecs/derive/src/compact/generator.rs b/crates/storage/codecs/derive/src/compact/generator.rs index 2b408ec03b..bdb81893b4 100644 --- a/crates/storage/codecs/derive/src/compact/generator.rs +++ b/crates/storage/codecs/derive/src/compact/generator.rs @@ -58,7 +58,12 @@ fn generate_from_compact(fields: &FieldList, ident: &Ident, is_zstd: bool) -> To // it's hard to figure out with derive_macro which types have bytes::Bytes fields. // // This removes the requirement of the field to be placed last in the struct. - known_types.append(&mut vec!["TransactionKind", "AccessList", "Signature"]); + known_types.append(&mut vec![ + "TransactionKind", + "AccessList", + "Signature", + "CheckpointBlockRange", + ]); // let mut handle = FieldListHandler::new(fields); let is_enum = fields.iter().any(|field| matches!(field, FieldTypes::EnumVariant(_))); diff --git a/crates/storage/codecs/derive/src/compact/structs.rs b/crates/storage/codecs/derive/src/compact/structs.rs index aec1d7c66e..1cbdd90457 100644 --- a/crates/storage/codecs/derive/src/compact/structs.rs +++ b/crates/storage/codecs/derive/src/compact/structs.rs @@ -116,17 +116,26 @@ impl<'a> StructHandler<'a> { format_ident!("specialized_from_compact") }; + // ! Be careful before changing the following assert ! Especially if the type does not + // implement proptest tests. + // + // The limitation of the last placed field applies to fields with potentially large sizes, + // like the `Transaction` field. These fields may have inner "Bytes" fields, sometimes even + // nested further, making it impossible to check with `proc_macro`. The goal is to place + // such fields as the last ones, so we don't need to store their length separately. Instead, + // we can simply read them until the end of the buffer. + // + // However, certain types don't require this approach because they don't contain inner + // "Bytes" fields. For these types, we can add them to a "known_types" list so it doesn't + // trigger this error. These types can handle their own deserialization without + // relying on the length provided by the higher-level deserializer. For example, a + // type "T" with two "u64" fields doesn't need the length parameter from + // "T::from_compact(buf, len)" since the length of "u64" is known internally (bitpacked). assert!( known_types.contains(&ftype.as_str()) || is_flag_type(ftype) || - self.fields_iterator.peek().map_or(true, |ftypes| { - if let FieldTypes::StructField((_, ftype, _, _)) = ftypes { - !known_types.contains(&ftype.as_str()) - } else { - false - } - }), - "`{ftype}` field should be placed as the last one since it's not known. + self.fields_iterator.peek().is_none(), + "`{ftype}` field should be placed as the last one since it's not known. If it's an alias type (which are not supported by proc_macro), be sure to add it to either `known_types` or `get_bit_size` lists in the derive crate." ); diff --git a/crates/storage/codecs/derive/src/lib.rs b/crates/storage/codecs/derive/src/lib.rs index 6d2c88c907..071f7499ae 100644 --- a/crates/storage/codecs/derive/src/lib.rs +++ b/crates/storage/codecs/derive/src/lib.rs @@ -23,11 +23,13 @@ pub fn derive_zstd(input: TokenStream) -> TokenStream { compact::derive(input, is_zstd) } -/// Implements the main codec. If the codec supports it, it will call `derive_arbitrary(..)`. +/// This code implements the main codec. If the codec supports it, it will also provide the [derive_arbitrary()] function, which automatically implements arbitrary traits and roundtrip fuzz tests. +/// +/// If you prefer to manually implement the arbitrary traits, you can still use the [add_arbitrary_tests()] function to add arbitrary fuzz tests. /// /// Example usage: /// * `#[main_codec(rlp)]`: will implement `derive_arbitrary(rlp)` or `derive_arbitrary(compact, rlp)`, if `compact` is the `main_codec`. -/// * `#[main_codec(no_arbitrary)]`: will skip `derive_arbitrary` +/// * `#[main_codec(no_arbitrary)]`: will skip `derive_arbitrary` (both trait implementations and tests) #[proc_macro_attribute] #[rustfmt::skip] #[allow(unreachable_code)]