diff --git a/Cargo.lock b/Cargo.lock index 94d0033d4bb..70400b7fdfd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -900,7 +900,7 @@ dependencies = [ "slasher", "slot_clock", "smallvec", - "ssz_types", + "ssz_types 0.11.0", "state_processing", "store", "strum", @@ -1767,21 +1767,22 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "context_deserialize" version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8af5929fa85d5e9775a2674a7d8653386d87d9046ec01955bb88eda06db09fe" dependencies = [ "context_deserialize_derive", "milhouse", "serde", - "ssz_types", + "ssz_types 0.12.2", ] [[package]] name = "context_deserialize_derive" version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1128f0946e42aebda0fb69b8b25d07d68e6c685141cae63ce2af030f593d26e2" dependencies = [ - "context_deserialize", "quote", - "serde", - "serde_json", "syn 1.0.109", ] @@ -2869,7 +2870,7 @@ dependencies = [ "serde", "serde_json", "slashing_protection", - "ssz_types", + "ssz_types 0.11.0", "test_random_derive", "tokio", "types", @@ -3360,7 +3361,7 @@ dependencies = [ "serde_json", "sha2 0.9.9", "slot_clock", - "ssz_types", + "ssz_types 0.11.0", "state_processing", "strum", "superstruct", @@ -5650,7 +5651,7 @@ dependencies = [ "sha2 0.9.9", "smallvec", "snap", - "ssz_types", + "ssz_types 0.11.0", "strum", "superstruct", "task_executor", @@ -6347,7 +6348,7 @@ dependencies = [ "serde_json", "slot_clock", "smallvec", - "ssz_types", + "ssz_types 0.11.0", "store", "strum", "task_executor", @@ -8800,7 +8801,7 @@ dependencies = [ "redb", "safe_arith", "serde", - "ssz_types", + "ssz_types 0.11.0", "strum", "tempfile", "tracing", @@ -8938,6 +8939,22 @@ dependencies = [ "typenum", ] +[[package]] +name = "ssz_types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704671195db617afa3d919da8f220f2535f20d0fa8dad96a1c27a38a5f8f6e9c" +dependencies = [ + "ethereum_serde_utils", + "ethereum_ssz", + "itertools 0.14.0", + "serde", + "serde_derive", + "smallvec", + "tree_hash", + "typenum", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -8964,7 +8981,7 @@ dependencies = [ "rayon", "safe_arith", "smallvec", - "ssz_types", + "ssz_types 0.11.0", "test_random_derive", "tokio", "tracing", @@ -9011,7 +9028,7 @@ dependencies = [ "safe_arith", "serde", "smallvec", - "ssz_types", + "ssz_types 0.11.0", "state_processing", "strum", "superstruct", @@ -9918,7 +9935,7 @@ dependencies = [ "serde_json", "serde_yaml", "smallvec", - "ssz_types", + "ssz_types 0.11.0", "state_processing", "superstruct", "swap_or_not_shuffle", diff --git a/Cargo.toml b/Cargo.toml index e471c4e2388..d237649b94e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,8 +49,6 @@ members = [ "common/validator_dir", "common/warp_utils", "common/workspace_members", - "consensus/context_deserialize/context_deserialize", - "consensus/context_deserialize/context_deserialize_derive", "consensus/fixed_bytes", "consensus/fork_choice", "consensus/int_to_bytes", @@ -124,10 +122,7 @@ clap_utils = { path = "common/clap_utils" } compare_fields = { path = "common/compare_fields" } compare_fields_derive = { path = "common/compare_fields_derive" } console-subscriber = "0.4" -context_deserialize = { path = "consensus/context_deserialize/context_deserialize", features = [ - "all", -] } -context_deserialize_derive = { path = "consensus/context_deserialize/context_deserialize_derive" } +context_deserialize = { version = "0.1", features = ["all"] } criterion = "0.5" delay_map = "0.4" deposit_contract = { path = "common/deposit_contract" } diff --git a/consensus/context_deserialize/context_deserialize/Cargo.toml b/consensus/context_deserialize/context_deserialize/Cargo.toml deleted file mode 100644 index 0e4a97b9ae3..00000000000 --- a/consensus/context_deserialize/context_deserialize/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "context_deserialize" -version = "0.1.0" -edition = "2021" - -[features] -default = ["derive"] -derive = ["dep:context_deserialize_derive"] -milhouse = ["dep:milhouse"] -ssz = ["dep:ssz_types"] -all = ["derive", "milhouse", "ssz"] - -[dependencies] -context_deserialize_derive = { version = "0.1.0", path = "../context_deserialize_derive", optional = true } -milhouse = { workspace = true, optional = true } -serde = { workspace = true } -ssz_types = { workspace = true, optional = true } diff --git a/consensus/context_deserialize/context_deserialize/src/impls/core.rs b/consensus/context_deserialize/context_deserialize/src/impls/core.rs deleted file mode 100644 index 803619365f1..00000000000 --- a/consensus/context_deserialize/context_deserialize/src/impls/core.rs +++ /dev/null @@ -1,103 +0,0 @@ -use crate::ContextDeserialize; -use serde::de::{Deserialize, DeserializeSeed, Deserializer, SeqAccess, Visitor}; -use std::marker::PhantomData; -use std::sync::Arc; - -impl<'de, C, T> ContextDeserialize<'de, T> for Arc -where - C: ContextDeserialize<'de, T>, -{ - fn context_deserialize(deserializer: D, context: T) -> Result - where - D: Deserializer<'de>, - { - Ok(Arc::new(C::context_deserialize(deserializer, context)?)) - } -} - -impl<'de, T, C> ContextDeserialize<'de, C> for Vec -where - T: ContextDeserialize<'de, C>, - C: Clone, -{ - fn context_deserialize(deserializer: D, context: C) -> Result - where - D: Deserializer<'de>, - { - // Our Visitor, which owns one copy of the context T - struct ContextVisitor { - context: T, - _marker: PhantomData, - } - - impl<'de, C, T> Visitor<'de> for ContextVisitor - where - C: ContextDeserialize<'de, T>, - T: Clone, - { - type Value = Vec; - - fn expecting(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { - fmt.write_str("a sequence of context‐deserialized elements") - } - - fn visit_seq(self, mut seq: A) -> Result, A::Error> - where - A: SeqAccess<'de>, - { - let mut out = Vec::with_capacity(seq.size_hint().unwrap_or(0)); - // for each element, we clone the context and hand it to the seed - while let Some(elem) = seq.next_element_seed(ContextSeed { - context: self.context.clone(), - _marker: PhantomData, - })? { - out.push(elem); - } - Ok(out) - } - } - - // A little seed that hands the deserializer + context into C::context_deserialize - struct ContextSeed { - context: C, - _marker: PhantomData, - } - - impl<'de, T, C> DeserializeSeed<'de> for ContextSeed - where - T: ContextDeserialize<'de, C>, - C: Clone, - { - type Value = T; - - fn deserialize(self, deserializer: D) -> Result - where - D: Deserializer<'de>, - { - T::context_deserialize(deserializer, self.context) - } - } - - deserializer.deserialize_seq(ContextVisitor { - context, - _marker: PhantomData, - }) - } -} - -macro_rules! trivial_deserialize { - ($($t:ty),* $(,)?) => { - $( - impl<'de, T> ContextDeserialize<'de, T> for $t { - fn context_deserialize(deserializer: D, _context: T) -> Result - where - D: Deserializer<'de>, - { - <$t>::deserialize(deserializer) - } - } - )* - }; -} - -trivial_deserialize!(bool, u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, f32, f64); diff --git a/consensus/context_deserialize/context_deserialize/src/impls/milhouse.rs b/consensus/context_deserialize/context_deserialize/src/impls/milhouse.rs deleted file mode 100644 index 3b86f067a3e..00000000000 --- a/consensus/context_deserialize/context_deserialize/src/impls/milhouse.rs +++ /dev/null @@ -1,45 +0,0 @@ -use crate::ContextDeserialize; -use milhouse::{List, Value, Vector}; -use serde::de::Deserializer; -use ssz_types::typenum::Unsigned; - -impl<'de, C, T, N> ContextDeserialize<'de, C> for List -where - T: ContextDeserialize<'de, C> + Value, - N: Unsigned, - C: Clone, -{ - fn context_deserialize(deserializer: D, context: C) -> Result - where - D: Deserializer<'de>, - { - // First deserialize as a Vec. - // This is not the most efficient implementation as it allocates a temporary Vec. In future - // we could write a more performant implementation using `List::builder()`. - let vec = Vec::::context_deserialize(deserializer, context)?; - - // Then convert to List, which will check the length. - List::new(vec) - .map_err(|e| serde::de::Error::custom(format!("Failed to create List: {:?}", e))) - } -} - -impl<'de, C, T, N> ContextDeserialize<'de, C> for Vector -where - T: ContextDeserialize<'de, C> + Value, - N: Unsigned, - C: Clone, -{ - fn context_deserialize(deserializer: D, context: C) -> Result - where - D: Deserializer<'de>, - { - // First deserialize as a List - let list = List::::context_deserialize(deserializer, context)?; - - // Then convert to Vector, which will check the length - Vector::try_from(list).map_err(|e| { - serde::de::Error::custom(format!("Failed to convert List to Vector: {:?}", e)) - }) - } -} diff --git a/consensus/context_deserialize/context_deserialize/src/impls/mod.rs b/consensus/context_deserialize/context_deserialize/src/impls/mod.rs deleted file mode 100644 index 0225c5e031f..00000000000 --- a/consensus/context_deserialize/context_deserialize/src/impls/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod core; - -#[cfg(feature = "milhouse")] -mod milhouse; - -#[cfg(feature = "ssz")] -mod ssz; diff --git a/consensus/context_deserialize/context_deserialize/src/impls/ssz.rs b/consensus/context_deserialize/context_deserialize/src/impls/ssz.rs deleted file mode 100644 index 26813a96fb7..00000000000 --- a/consensus/context_deserialize/context_deserialize/src/impls/ssz.rs +++ /dev/null @@ -1,51 +0,0 @@ -use crate::ContextDeserialize; -use serde::{ - de::{Deserializer, Error}, - Deserialize, -}; -use ssz_types::{ - length::{Fixed, Variable}, - typenum::Unsigned, - Bitfield, FixedVector, -}; - -impl<'de, C, T, N> ContextDeserialize<'de, C> for FixedVector -where - T: ContextDeserialize<'de, C>, - N: Unsigned, - C: Clone, -{ - fn context_deserialize(deserializer: D, context: C) -> Result - where - D: Deserializer<'de>, - { - let vec = Vec::::context_deserialize(deserializer, context)?; - FixedVector::new(vec).map_err(|e| D::Error::custom(format!("{:?}", e))) - } -} - -impl<'de, C, N> ContextDeserialize<'de, C> for Bitfield> -where - N: Unsigned + Clone, -{ - fn context_deserialize(deserializer: D, _context: C) -> Result - where - D: Deserializer<'de>, - { - Bitfield::>::deserialize(deserializer) - .map_err(|e| D::Error::custom(format!("{:?}", e))) - } -} - -impl<'de, C, N> ContextDeserialize<'de, C> for Bitfield> -where - N: Unsigned + Clone, -{ - fn context_deserialize(deserializer: D, _context: C) -> Result - where - D: Deserializer<'de>, - { - Bitfield::>::deserialize(deserializer) - .map_err(|e| D::Error::custom(format!("{:?}", e))) - } -} diff --git a/consensus/context_deserialize/context_deserialize/src/lib.rs b/consensus/context_deserialize/context_deserialize/src/lib.rs deleted file mode 100644 index e5f2bfdba38..00000000000 --- a/consensus/context_deserialize/context_deserialize/src/lib.rs +++ /dev/null @@ -1,13 +0,0 @@ -mod impls; - -#[cfg(feature = "derive")] -pub use context_deserialize_derive::context_deserialize; - -use serde::de::Deserializer; - -/// General-purpose deserialization trait that accepts extra context `C`. -pub trait ContextDeserialize<'de, C>: Sized { - fn context_deserialize(deserializer: D, context: C) -> Result - where - D: Deserializer<'de>; -} diff --git a/consensus/context_deserialize/context_deserialize_derive/Cargo.toml b/consensus/context_deserialize/context_deserialize_derive/Cargo.toml deleted file mode 100644 index eedae30cdfe..00000000000 --- a/consensus/context_deserialize/context_deserialize_derive/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "context_deserialize_derive" -version = "0.1.0" -edition = "2021" - -[lib] -proc-macro = true - -[dependencies] -quote = { workspace = true } -syn = { workspace = true } - -[dev-dependencies] -context_deserialize = { path = "../context_deserialize" } -serde = { workspace = true } -serde_json = "1.0" diff --git a/consensus/context_deserialize/context_deserialize_derive/src/lib.rs b/consensus/context_deserialize/context_deserialize_derive/src/lib.rs deleted file mode 100644 index 0b73a43b0a4..00000000000 --- a/consensus/context_deserialize/context_deserialize_derive/src/lib.rs +++ /dev/null @@ -1,118 +0,0 @@ -extern crate proc_macro; -extern crate quote; -extern crate syn; - -use proc_macro::TokenStream; -use quote::quote; -use syn::{ - parse_macro_input, AttributeArgs, DeriveInput, GenericParam, LifetimeDef, Meta, NestedMeta, - WhereClause, -}; - -#[proc_macro_attribute] -pub fn context_deserialize(attr: TokenStream, item: TokenStream) -> TokenStream { - let args = parse_macro_input!(attr as AttributeArgs); - let input = parse_macro_input!(item as DeriveInput); - let ident = &input.ident; - - let mut ctx_types = Vec::new(); - let mut explicit_where: Option = None; - - for meta in args { - match meta { - NestedMeta::Meta(Meta::Path(p)) => { - ctx_types.push(p); - } - NestedMeta::Meta(Meta::NameValue(nv)) if nv.path.is_ident("bound") => { - if let syn::Lit::Str(lit_str) = &nv.lit { - let where_string = format!("where {}", lit_str.value()); - match syn::parse_str::(&where_string) { - Ok(where_clause) => { - explicit_where = Some(where_clause); - } - Err(err) => { - return syn::Error::new_spanned( - lit_str, - format!("Invalid where clause '{}': {}", lit_str.value(), err), - ) - .to_compile_error() - .into(); - } - } - } else { - return syn::Error::new_spanned( - &nv, - "Expected a string literal for `bound` value", - ) - .to_compile_error() - .into(); - } - } - _ => { - return syn::Error::new_spanned( - &meta, - "Expected paths or `bound = \"...\"` in #[context_deserialize(...)]", - ) - .to_compile_error() - .into(); - } - } - } - - if ctx_types.is_empty() { - return quote! { - compile_error!("Usage: #[context_deserialize(Type1, Type2, ..., bound = \"...\")]"); - } - .into(); - } - - let original_generics = input.generics.clone(); - - // Clone and clean generics for impl use (remove default params) - let mut impl_generics = input.generics.clone(); - for param in impl_generics.params.iter_mut() { - if let GenericParam::Type(ty) = param { - ty.eq_token = None; - ty.default = None; - } - } - - // Ensure 'de lifetime exists in impl generics - let has_de = impl_generics - .lifetimes() - .any(|LifetimeDef { lifetime, .. }| lifetime.ident == "de"); - - if !has_de { - impl_generics.params.insert(0, syn::parse_quote! { 'de }); - } - - let (_, ty_generics, _) = original_generics.split_for_impl(); - let (impl_gens, _, _) = impl_generics.split_for_impl(); - - // Generate: no `'de` applied to the type name - let mut impls = quote! {}; - for ctx in ctx_types { - impls.extend(quote! { - impl #impl_gens context_deserialize::ContextDeserialize<'de, #ctx> - for #ident #ty_generics - #explicit_where - { - fn context_deserialize( - deserializer: D, - _context: #ctx, - ) -> Result - where - D: serde::de::Deserializer<'de>, - { - ::deserialize(deserializer) - } - } - }); - } - - quote! { - #input - #impls - } - .into() -} diff --git a/consensus/context_deserialize/context_deserialize_derive/tests/context_deserialize_derive.rs b/consensus/context_deserialize/context_deserialize_derive/tests/context_deserialize_derive.rs deleted file mode 100644 index 8fb46da9c65..00000000000 --- a/consensus/context_deserialize/context_deserialize_derive/tests/context_deserialize_derive.rs +++ /dev/null @@ -1,93 +0,0 @@ -use context_deserialize::{context_deserialize, ContextDeserialize}; -use serde::{Deserialize, Serialize}; - -#[test] -fn test_context_deserialize_derive() { - type TestContext = (); - - #[context_deserialize(TestContext)] - #[derive(Debug, PartialEq, Serialize, Deserialize)] - struct Test { - field: String, - } - - let test = Test { - field: "test".to_string(), - }; - let serialized = serde_json::to_string(&test).unwrap(); - let deserialized = - Test::context_deserialize(&mut serde_json::Deserializer::from_str(&serialized), ()) - .unwrap(); - assert_eq!(test, deserialized); -} - -#[test] -fn test_context_deserialize_derive_multiple_types() { - #[allow(dead_code)] - struct TestContext1(u64); - #[allow(dead_code)] - struct TestContext2(String); - - // This will derive: - // - ContextDeserialize for Test - // - ContextDeserialize for Test - // by just leveraging the Deserialize impl - #[context_deserialize(TestContext1, TestContext2)] - #[derive(Debug, PartialEq, Serialize, Deserialize)] - struct Test { - field: String, - } - - let test = Test { - field: "test".to_string(), - }; - let serialized = serde_json::to_string(&test).unwrap(); - let deserialized = Test::context_deserialize( - &mut serde_json::Deserializer::from_str(&serialized), - TestContext1(1), - ) - .unwrap(); - assert_eq!(test, deserialized); - - let deserialized = Test::context_deserialize( - &mut serde_json::Deserializer::from_str(&serialized), - TestContext2("2".to_string()), - ) - .unwrap(); - - assert_eq!(test, deserialized); -} - -#[test] -fn test_context_deserialize_derive_bound() { - use std::fmt::Debug; - - struct TestContext; - - #[derive(Debug, PartialEq, Serialize, Deserialize)] - struct Inner { - value: u64, - } - - #[context_deserialize( - TestContext, - bound = "T: Serialize + for<'a> Deserialize<'a> + Debug + PartialEq" - )] - #[derive(Debug, PartialEq, Serialize, Deserialize)] - struct Wrapper { - inner: T, - } - - let val = Wrapper { - inner: Inner { value: 42 }, - }; - - let serialized = serde_json::to_string(&val).unwrap(); - let deserialized = Wrapper::::context_deserialize( - &mut serde_json::Deserializer::from_str(&serialized), - TestContext, - ) - .unwrap(); - - assert_eq!(val, deserialized); -}