diff --git a/substrate/core/sr-primitives/src/generic/block.rs b/substrate/core/sr-primitives/src/generic/block.rs index f0f3c88fe7..736ad0cbbb 100644 --- a/substrate/core/sr-primitives/src/generic/block.rs +++ b/substrate/core/sr-primitives/src/generic/block.rs @@ -20,7 +20,7 @@ use std::fmt; #[cfg(feature = "std")] -use serde::Serialize; +use serde::{Deserialize, Serialize}; use rstd::prelude::*; use crate::codec::{Codec, Encode, Decode}; @@ -62,7 +62,7 @@ impl fmt::Display for BlockId { /// Abstraction over a substrate block. #[derive(PartialEq, Eq, Clone, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug, Serialize))] +#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] #[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] #[cfg_attr(feature = "std", serde(deny_unknown_fields))] pub struct Block { @@ -97,7 +97,7 @@ where /// Abstraction over a substrate block and justification. #[derive(PartialEq, Eq, Clone, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug, Serialize))] +#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] #[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] #[cfg_attr(feature = "std", serde(deny_unknown_fields))] pub struct SignedBlock { diff --git a/substrate/core/sr-primitives/src/generic/digest.rs b/substrate/core/sr-primitives/src/generic/digest.rs index b6d72dddf7..d2974444e2 100644 --- a/substrate/core/sr-primitives/src/generic/digest.rs +++ b/substrate/core/sr-primitives/src/generic/digest.rs @@ -17,7 +17,7 @@ //! Generic implementation of a digest. #[cfg(feature = "std")] -use serde::Serialize; +use serde::{Deserialize, Serialize}; use rstd::prelude::*; @@ -26,7 +26,7 @@ use crate::codec::{Decode, Encode, Input, Error}; /// Generic header digest. #[derive(PartialEq, Eq, Clone, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug, Serialize))] +#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] pub struct Digest { /// A list of logs in the digest. pub logs: Vec>, @@ -102,14 +102,25 @@ pub enum DigestItem { } #[cfg(feature = "std")] -impl ::serde::Serialize for DigestItem { - fn serialize(&self, seq: S) -> Result where S: ::serde::Serializer { +impl serde::Serialize for DigestItem { + fn serialize(&self, seq: S) -> Result where S: serde::Serializer { self.using_encoded(|bytes| { - ::primitives::bytes::serialize(bytes, seq) + primitives::bytes::serialize(bytes, seq) }) } } +#[cfg(feature = "std")] +impl<'a, Hash: Decode> serde::Deserialize<'a> for DigestItem { + fn deserialize(de: D) -> Result where + D: serde::Deserializer<'a>, + { + let r = primitives::bytes::deserialize(de)?; + Decode::decode(&mut &r[..]) + .map_err(|e| serde::de::Error::custom(format!("Decode error: {}", e))) + } +} + /// A 'referencing view' for digest item. Does not own its contents. Used by /// final runtime implementations for encoding/decoding its log items. #[derive(PartialEq, Eq, Clone)] diff --git a/substrate/core/sr-primitives/src/generic/header.rs b/substrate/core/sr-primitives/src/generic/header.rs index e8f40bb7b6..e9a8405fe2 100644 --- a/substrate/core/sr-primitives/src/generic/header.rs +++ b/substrate/core/sr-primitives/src/generic/header.rs @@ -17,7 +17,7 @@ //! Generic implementation of a block header. #[cfg(feature = "std")] -use serde::Serialize; +use serde::{Deserialize, Serialize}; #[cfg(feature = "std")] use log::debug; use crate::codec::{Decode, Encode, Codec, Input, Output, HasCompact, EncodeAsRef, Error}; @@ -26,37 +26,48 @@ use crate::traits::{ MaybeSerializeDebugButNotDeserialize }; use crate::generic::Digest; +use primitives::U256; +use core::convert::TryFrom; /// Abstraction over a block header for a substrate chain. #[derive(PartialEq, Eq, Clone)] -#[cfg_attr(feature = "std", derive(Debug, Serialize))] +#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] #[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] #[cfg_attr(feature = "std", serde(deny_unknown_fields))] -pub struct Header, Hash: HashT> { +pub struct Header + TryFrom, Hash: HashT> { /// The parent hash. - pub parent_hash: ::Output, + pub parent_hash: Hash::Output, /// The block number. - #[cfg_attr(feature = "std", serde(serialize_with = "serialize_number"))] + #[cfg_attr(feature = "std", serde( + serialize_with = "serialize_number", + deserialize_with = "deserialize_number"))] pub number: Number, /// The state trie merkle root - pub state_root: ::Output, + pub state_root: Hash::Output, /// The merkle root of the extrinsics. - pub extrinsics_root: ::Output, + pub extrinsics_root: Hash::Output, /// A chain-specific digest of data useful for light clients or referencing auxiliary data. - pub digest: Digest<::Output>, + pub digest: Digest, } #[cfg(feature = "std")] -pub fn serialize_number>(val: &T, s: S) -> Result where S: ::serde::Serializer { - use primitives::uint::U256; - let v: u128 = (*val).into(); - let lower = U256::from(v as u64); - let upper = U256::from(v.rotate_left(64) as u64) << 64; - ::serde::Serialize::serialize(&(upper + lower), s) +pub fn serialize_number + TryFrom>( + val: &T, s: S, +) -> Result where S: serde::Serializer { + let u256: U256 = (*val).into(); + serde::Serialize::serialize(&u256, s) +} + +#[cfg(feature = "std")] +pub fn deserialize_number<'a, D, T: Copy + Into + TryFrom>( + d: D, +) -> Result where D: serde::Deserializer<'a> { + let u256: U256 = serde::Deserialize::deserialize(d)?; + TryFrom::try_from(u256).map_err(|_| serde::de::Error::custom("Try from failed")) } impl Decode for Header where - Number: HasCompact + Copy + Into, + Number: HasCompact + Copy + Into + TryFrom, Hash: HashT, Hash::Output: Decode, { @@ -72,7 +83,7 @@ impl Decode for Header where } impl Encode for Header where - Number: HasCompact + Copy + Into, + Number: HasCompact + Copy + Into + TryFrom, Hash: HashT, Hash::Output: Encode, { @@ -86,15 +97,17 @@ impl Encode for Header where } impl codec::EncodeLike for Header where - Number: HasCompact + Copy + Into, + Number: HasCompact + Copy + Into + TryFrom, Hash: HashT, Hash::Output: Encode, {} impl traits::Header for Header where - Number: Member + MaybeSerializeDebug + ::rstd::hash::Hash + MaybeDisplay + SimpleArithmetic + Codec + Copy + Into, + Number: Member + MaybeSerializeDebug + rstd::hash::Hash + MaybeDisplay + + SimpleArithmetic + Codec + Copy + Into + TryFrom, Hash: HashT, - Hash::Output: Default + ::rstd::hash::Hash + Copy + Member + MaybeSerializeDebugButNotDeserialize + MaybeDisplay + SimpleBitOps + Codec, + Hash::Output: Default + rstd::hash::Hash + Copy + Member + + MaybeSerializeDebugButNotDeserialize + MaybeDisplay + SimpleBitOps + Codec, { type Number = Number; type Hash = ::Output; @@ -141,9 +154,9 @@ impl traits::Header for Header where } impl Header where - Number: Member + ::rstd::hash::Hash + Copy + MaybeDisplay + SimpleArithmetic + Codec + Into, + Number: Member + rstd::hash::Hash + Copy + MaybeDisplay + SimpleArithmetic + Codec + Into + TryFrom, Hash: HashT, - Hash::Output: Default + ::rstd::hash::Hash + Copy + Member + MaybeDisplay + SimpleBitOps + Codec, + Hash::Output: Default + rstd::hash::Hash + Copy + Member + MaybeDisplay + SimpleBitOps + Codec, { /// Convenience helper for computing the hash of the header without having /// to import the trait. @@ -161,7 +174,7 @@ mod tests { fn serialize(num: u128) -> String { let mut v = vec![]; { - let mut ser = ::serde_json::Serializer::new(::std::io::Cursor::new(&mut v)); + let mut ser = serde_json::Serializer::new(std::io::Cursor::new(&mut v)); serialize_number(&num, &mut ser).unwrap(); } String::from_utf8(v).unwrap() @@ -173,4 +186,16 @@ mod tests { assert_eq!(serialize(u64::max_value() as u128 + 1), "\"0x10000000000000000\"".to_owned()); } + #[test] + fn should_deserialize_number() { + fn deserialize(num: &str) -> u128 { + let mut der = serde_json::Deserializer::new(serde_json::de::StrRead::new(num)); + deserialize_number(&mut der).unwrap() + } + + assert_eq!(deserialize("\"0x0\""), 0); + assert_eq!(deserialize("\"0x1\""), 1); + assert_eq!(deserialize("\"0xffffffffffffffff\""), u64::max_value() as u128); + assert_eq!(deserialize("\"0x10000000000000000\""), u64::max_value() as u128 + 1); + } } diff --git a/substrate/core/sr-primitives/src/lib.rs b/substrate/core/sr-primitives/src/lib.rs index 9246cd3ff6..636a97ce92 100644 --- a/substrate/core/sr-primitives/src/lib.rs +++ b/substrate/core/sr-primitives/src/lib.rs @@ -824,6 +824,15 @@ impl ::serde::Serialize for OpaqueExtrinsic { } } +#[cfg(feature = "std")] +impl<'a> ::serde::Deserialize<'a> for OpaqueExtrinsic { + fn deserialize(de: D) -> Result where D: ::serde::Deserializer<'a> { + let r = ::primitives::bytes::deserialize(de)?; + Decode::decode(&mut &r[..]) + .map_err(|e| ::serde::de::Error::custom(format!("Decode error: {}", e))) + } +} + impl traits::Extrinsic for OpaqueExtrinsic { type Call = ();