diff --git a/chain-impl-mockchain/src/block/mod.rs b/chain-impl-mockchain/src/block/mod.rs index 73e33a487..46625cf6e 100644 --- a/chain-impl-mockchain/src/block/mod.rs +++ b/chain-impl-mockchain/src/block/mod.rs @@ -145,15 +145,16 @@ impl Readable for Block { let mut contents = ContentsBuilder::new(); while remaining_content_size > 0 { - let message_size = buf.get_u16()?; - let mut message_buf = buf.split_to(message_size as usize)?; + let message_raw = FragmentRaw::read(buf)?; + let message_size = message_raw.size_bytes_plus_size(); // return error here if message serialize sized is bigger than remaining size - let message = Fragment::read(&mut message_buf)?; + let message = Fragment::from_raw(&message_raw) + .map_err(|e| ReadError::StructureInvalid(e.to_string()))?; contents.push(message); - remaining_content_size -= 2 + message_size as u32; + remaining_content_size -= message_size as u32; } Ok(Block { diff --git a/chain-impl-mockchain/src/fragment/raw.rs b/chain-impl-mockchain/src/fragment/raw.rs index 7d046641d..bcbe40ad4 100644 --- a/chain-impl-mockchain/src/fragment/raw.rs +++ b/chain-impl-mockchain/src/fragment/raw.rs @@ -1,7 +1,9 @@ use crate::key::Hash; use chain_core::property; +use chain_ser::mempack::{ReadBuf, ReadError, Readable}; pub type FragmentId = Hash; +pub const FRAGMENT_SIZE_BYTES_LEN: usize = 4; /// A serialized Message #[derive(Debug, Clone, PartialEq, Eq)] @@ -9,7 +11,7 @@ pub struct FragmentRaw(pub(super) Vec); impl FragmentRaw { pub fn size_bytes_plus_size(&self) -> usize { - 2 + self.0.len() + FRAGMENT_SIZE_BYTES_LEN + self.0.len() } pub fn id(&self) -> FragmentId { @@ -23,12 +25,21 @@ impl AsRef<[u8]> for FragmentRaw { } } +impl Readable for FragmentRaw { + fn read(buf: &mut ReadBuf) -> Result { + let size = buf.get_u32()?; + let mut v = vec![0u8; size as usize]; + buf.copy_to_slice_mut(&mut v)?; + Ok(FragmentRaw(v)) + } +} + impl property::Deserialize for FragmentRaw { type Error = std::io::Error; fn deserialize(reader: R) -> Result { use chain_core::packer::*; let mut codec = Codec::new(reader); - let size = codec.get_u16()?; + let size = codec.get_u32()?; let mut v = vec![0u8; size as usize]; codec.into_inner().read_exact(&mut v)?; Ok(FragmentRaw(v)) @@ -41,7 +52,7 @@ impl property::Serialize for FragmentRaw { use chain_core::packer::*; let mut codec = Codec::new(writer); - codec.put_u16(self.0.len() as u16)?; + codec.put_u32(self.0.len() as u32)?; codec.into_inner().write_all(&self.0)?; Ok(()) } diff --git a/chain-impl-mockchain/src/fragment/test.rs b/chain-impl-mockchain/src/fragment/test.rs index 85afd79e2..49f5368b6 100644 --- a/chain-impl-mockchain/src/fragment/test.rs +++ b/chain-impl-mockchain/src/fragment/test.rs @@ -1,7 +1,7 @@ use super::*; use crate::config::ConfigParam; #[cfg(test)] -use crate::testing::serialization::serialization_bijection_r; +use crate::testing::serialization::{serialization_bijection, serialization_bijection_r}; #[cfg(test)] use quickcheck::TestResult; use quickcheck::{Arbitrary, Gen}; @@ -30,11 +30,16 @@ impl Arbitrary for Fragment { } #[quickcheck] -fn fragment_serialization_bijection(b: Fragment) -> TestResult { +fn fragment_raw_bijection(b: Fragment) -> TestResult { let b_got = Fragment::from_raw(&b.to_raw()).unwrap(); TestResult::from_bool(b == b_got) } +#[quickcheck] +fn fragment_serialization_bijection(b: Fragment) -> TestResult { + serialization_bijection(b) +} + quickcheck! { fn initial_ents_serialization_bijection(config_params: ConfigParams) -> TestResult { serialization_bijection_r(config_params)