use super::*; use crate::case_result::compare_result; use crate::cases::common::SszStaticType; use crate::decode::yaml_decode_file; use cached_tree_hash::CachedTreeHash; use serde_derive::Deserialize; use std::fs; use std::marker::PhantomData; use tree_hash::SignedRoot; use types::Hash256; #[derive(Debug, Clone, Deserialize)] struct SszStaticRoots { root: String, signing_root: Option, } #[derive(Debug, Clone)] pub struct SszStatic { roots: SszStaticRoots, serialized: Vec, value: T, } #[derive(Debug, Clone)] pub struct SszStaticSR { roots: SszStaticRoots, serialized: Vec, value: T, } #[derive(Debug, Clone)] pub struct SszStaticTHC { roots: SszStaticRoots, serialized: Vec, value: T, _phantom: PhantomData, } fn load_from_dir(path: &Path) -> Result<(SszStaticRoots, Vec, T), Error> { let roots = yaml_decode_file(&path.join("roots.yaml"))?; let serialized = fs::read(&path.join("serialized.ssz")).expect("serialized.ssz exists"); let value = yaml_decode_file(&path.join("value.yaml"))?; Ok((roots, serialized, value)) } impl LoadCase for SszStatic { fn load_from_dir(path: &Path) -> Result { load_from_dir(path).map(|(roots, serialized, value)| Self { roots, serialized, value, }) } } impl LoadCase for SszStaticSR { fn load_from_dir(path: &Path) -> Result { load_from_dir(path).map(|(roots, serialized, value)| Self { roots, serialized, value, }) } } impl, C: Debug + Sync> LoadCase for SszStaticTHC { fn load_from_dir(path: &Path) -> Result { load_from_dir(path).map(|(roots, serialized, value)| Self { roots, serialized, value, _phantom: PhantomData, }) } } pub fn check_serialization(value: &T, serialized: &[u8]) -> Result<(), Error> { // Check serialization let serialized_result = value.as_ssz_bytes(); compare_result::(&Ok(value.ssz_bytes_len()), &Some(serialized.len()))?; compare_result::, Error>(&Ok(serialized_result), &Some(serialized.to_vec()))?; // Check deserialization let deserialized_result = T::from_ssz_bytes(serialized); compare_result(&deserialized_result, &Some(value.clone()))?; Ok(()) } pub fn check_tree_hash(expected_str: &str, actual_root: &[u8]) -> Result<(), Error> { let expected_root = hex::decode(&expected_str[2..]) .map_err(|e| Error::FailedToParseTest(format!("{:?}", e)))?; let expected_root = Hash256::from_slice(&expected_root); let tree_hash_root = Hash256::from_slice(actual_root); compare_result::(&Ok(tree_hash_root), &Some(expected_root)) } impl Case for SszStatic { fn result(&self, _case_index: usize) -> Result<(), Error> { check_serialization(&self.value, &self.serialized)?; check_tree_hash(&self.roots.root, &self.value.tree_hash_root())?; Ok(()) } } impl Case for SszStaticSR { fn result(&self, _case_index: usize) -> Result<(), Error> { check_serialization(&self.value, &self.serialized)?; check_tree_hash(&self.roots.root, &self.value.tree_hash_root())?; check_tree_hash( &self .roots .signing_root .as_ref() .expect("signed root exists"), &self.value.signed_root(), )?; Ok(()) } } impl, C: Debug + Sync> Case for SszStaticTHC { fn result(&self, _case_index: usize) -> Result<(), Error> { check_serialization(&self.value, &self.serialized)?; check_tree_hash(&self.roots.root, &self.value.tree_hash_root())?; let mut cache = T::new_tree_hash_cache(); let cached_tree_hash_root = self.value.recalculate_tree_hash_root(&mut cache).unwrap(); check_tree_hash(&self.roots.root, cached_tree_hash_root.as_bytes())?; Ok(()) } }