use std::io; use super::{ReadZcashExt, SerializationError}; /// Consensus-critical serialization for Zcash. /// /// This trait provides a generic deserialization for consensus-critical /// formats, such as network messages, transactions, blocks, etc. It is intended /// for use only in consensus-critical contexts; in other contexts, such as /// internal storage, it would be preferable to use Serde. pub trait ZcashDeserialize: Sized { /// Try to read `self` from the given `reader`. /// /// This function has a `zcash_` prefix to alert the reader that the /// serialization in use is consensus-critical serialization, rather than /// some other kind of serialization. fn zcash_deserialize(reader: R) -> Result; } impl ZcashDeserialize for Vec { fn zcash_deserialize(mut reader: R) -> Result { let len = reader.read_compactsize()?; // We're given len, so we could preallocate. But blindly preallocating // without a size bound can allow DOS attacks, and there's no way to // pass a size bound in a ZcashDeserialize impl, so instead we allocate // as we read from the reader. (The maximum block and transaction sizes // limit the eventual size of these allocations.) let mut vec = Vec::new(); for _ in 0..len { vec.push(T::zcash_deserialize(&mut reader)?); } Ok(vec) } } /// Helper for deserializing more succinctly via type inference pub trait ZcashDeserializeInto { /// Deserialize based on type inference fn zcash_deserialize_into(self) -> Result where T: ZcashDeserialize; } impl ZcashDeserializeInto for R { fn zcash_deserialize_into(self) -> Result where T: ZcashDeserialize, { T::zcash_deserialize(self) } }