use super::*;
impl<N: Network> Serialize for Block<N> {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match serializer.is_human_readable() {
true => {
let mut block = serializer.serialize_struct("Block", 7 + self.solutions.is_some() as usize)?;
block.serialize_field("block_hash", &self.block_hash)?;
block.serialize_field("previous_hash", &self.previous_hash)?;
block.serialize_field("header", &self.header)?;
block.serialize_field("authority", &self.authority)?;
block.serialize_field("ratifications", &self.ratifications)?;
if let Some(solutions) = &self.solutions {
block.serialize_field("solutions", solutions)?;
}
block.serialize_field("transactions", &self.transactions)?;
block.serialize_field("aborted_transaction_ids", &self.aborted_transaction_ids)?;
block.end()
}
false => ToBytesSerializer::serialize_with_size_encoding(self, serializer),
}
}
}
impl<'de, N: Network> Deserialize<'de> for Block<N> {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
match deserializer.is_human_readable() {
true => {
let mut block = serde_json::Value::deserialize(deserializer)?;
let block_hash: N::BlockHash = DeserializeExt::take_from_value::<D>(&mut block, "block_hash")?;
let solutions = block.get_mut("solutions").unwrap_or(&mut serde_json::Value::Null).take();
let block = Self::from(
DeserializeExt::take_from_value::<D>(&mut block, "previous_hash")?,
DeserializeExt::take_from_value::<D>(&mut block, "header")?,
DeserializeExt::take_from_value::<D>(&mut block, "authority")?,
DeserializeExt::take_from_value::<D>(&mut block, "ratifications")?,
serde_json::from_value(solutions).map_err(de::Error::custom)?,
DeserializeExt::take_from_value::<D>(&mut block, "transactions")?,
DeserializeExt::take_from_value::<D>(&mut block, "aborted_transaction_ids")?,
)
.map_err(de::Error::custom)?;
match block_hash == block.hash() {
true => Ok(block),
false => Err(error("Mismatching block hash, possible data corruption")).map_err(de::Error::custom),
}
}
false => FromBytesDeserializer::<Self>::deserialize_with_size_encoding(deserializer, "block"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use console::network::Testnet3;
type CurrentNetwork = Testnet3;
#[test]
fn test_serde_json() -> Result<()> {
let rng = &mut TestRng::default();
for expected in [crate::test_helpers::sample_genesis_block(rng)].into_iter() {
let expected_string = &expected.to_string();
let candidate_string = serde_json::to_string(&expected)?;
assert_eq!(expected, Block::from_str(expected_string)?);
assert_eq!(expected, serde_json::from_str(&candidate_string)?);
}
Ok(())
}
#[test]
fn test_bincode() -> Result<()> {
let rng = &mut TestRng::default();
for expected in [crate::test_helpers::sample_genesis_block(rng)].into_iter() {
let expected_bytes = expected.to_bytes_le()?;
let expected_bytes_with_size_encoding = bincode::serialize(&expected)?;
assert_eq!(&expected_bytes[..], &expected_bytes_with_size_encoding[8..]);
assert_eq!(expected, Block::read_le(&expected_bytes[..])?);
assert_eq!(expected, bincode::deserialize(&expected_bytes_with_size_encoding[..])?);
}
Ok(())
}
#[test]
fn test_genesis_serde_json() -> Result<()> {
let genesis_block = Block::<CurrentNetwork>::read_le(CurrentNetwork::genesis_bytes()).unwrap();
let expected_string = &genesis_block.to_string();
let candidate_string = serde_json::to_string(&genesis_block)?;
assert_eq!(genesis_block, Block::from_str(expected_string)?);
assert_eq!(genesis_block, serde_json::from_str(&candidate_string)?);
Ok(())
}
#[test]
fn test_genesis_bincode() -> Result<()> {
let genesis_block = Block::<CurrentNetwork>::read_le(CurrentNetwork::genesis_bytes()).unwrap();
let expected_bytes = genesis_block.to_bytes_le()?;
let expected_bytes_with_size_encoding = bincode::serialize(&genesis_block)?;
assert_eq!(&expected_bytes[..], &expected_bytes_with_size_encoding[8..]);
assert_eq!(genesis_block, Block::read_le(&expected_bytes[..])?);
assert_eq!(genesis_block, bincode::deserialize(&expected_bytes_with_size_encoding[..])?);
Ok(())
}
}