diff --git a/ethbloom/Cargo.toml b/ethbloom/Cargo.toml index 16de3c0..0aa6b8f 100644 --- a/ethbloom/Cargo.toml +++ b/ethbloom/Cargo.toml @@ -11,9 +11,8 @@ repository = "https://github.com/paritytech/primitives" [dependencies] tiny-keccak = "1.4" crunchy = { version = "0.2.1", default-features = false, features = ["limit_256"] } -fixed-hash = { version = "0.3", default_features = false } -ethereum-types-serialize = { version = "0.2.1", path = "../serialize", optional = true } -serde = { version = "1.0", optional = true } +fixed-hash = { version = "0.3", default-features = false } +impl-serde = { version = "0.1", default-features = false, optional = true } [dev-dependencies] rand = { version = "0.4" } @@ -23,4 +22,4 @@ hex-literal = "0.1.1" default = ["std", "heapsize", "serialize", "fixed-hash/libc", "fixed-hash/rustc-hex"] std = ["fixed-hash/std", "crunchy/std"] heapsize = ["fixed-hash/heapsize"] -serialize = ["std", "ethereum-types-serialize", "serde"] +serialize = ["std", "impl-serde"] diff --git a/ethbloom/src/lib.rs b/ethbloom/src/lib.rs index cfd5ab6..9734e07 100644 --- a/ethbloom/src/lib.rs +++ b/ethbloom/src/lib.rs @@ -1,4 +1,4 @@ -//! +//! //! ```rust //! extern crate ethbloom; //! #[macro_use] extern crate hex_literal; @@ -26,7 +26,7 @@ //! ).unwrap(); //! let address = hex!("ef2d6d194084c2de36e0dabfce45d046b37d1106"); //! let topic = hex!("02c69be41d0b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc"); -//! +//! //! let mut my_bloom = Bloom::default(); //! assert!(!my_bloom.contains_input(Input::Raw(&address))); //! assert!(!my_bloom.contains_input(Input::Raw(&topic))); @@ -34,7 +34,7 @@ //! my_bloom.accrue(Input::Raw(&address)); //! assert!(my_bloom.contains_input(Input::Raw(&address))); //! assert!(!my_bloom.contains_input(Input::Raw(&topic))); -//! +//! //! my_bloom.accrue(Input::Raw(&topic)); //! assert!(my_bloom.contains_input(Input::Raw(&address))); //! assert!(my_bloom.contains_input(Input::Raw(&topic))); @@ -56,18 +56,13 @@ extern crate crunchy; extern crate fixed_hash; #[cfg(feature="serialize")] -extern crate ethereum_types_serialize; - -#[cfg(feature="serialize")] -extern crate serde; +#[macro_use] +extern crate impl_serde; #[cfg(test)] #[macro_use] extern crate hex_literal; -#[cfg(feature="serialize")] -use serde::{Serialize, Serializer, Deserialize, Deserializer}; - use core::{ops, mem}; use tiny_keccak::keccak256; @@ -227,7 +222,7 @@ impl<'a> BloomRef<'a> { let bloom: Bloom = input.into(); self.contains_bloom(&bloom) } - + pub fn contains_bloom<'b, B>(&self, bloom: B) -> bool where BloomRef<'b>: From { let bloom_ref: BloomRef = bloom.into(); assert_eq!(self.0.len(), BLOOM_SIZE); @@ -259,22 +254,8 @@ impl<'a> From<&'a Bloom> for BloomRef<'a> { } } -#[cfg(feature="serialize")] -impl Serialize for Bloom { - fn serialize(&self, serializer: S) -> Result where S: Serializer { - let mut slice = [0u8; 2 + 2 * BLOOM_SIZE]; - ethereum_types_serialize::serialize(&mut slice, &self.0, serializer) - } -} - -#[cfg(feature="serialize")] -impl<'de> Deserialize<'de> for Bloom { - fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { - let mut bytes = [0; BLOOM_SIZE]; - ethereum_types_serialize::deserialize_check_len(deserializer, ethereum_types_serialize::ExpectedLen::Exact(&mut bytes))?; - Ok(Bloom(bytes)) - } -} +#[cfg(feature = "serialize")] +impl_fixed_hash_serde!(Bloom, BLOOM_SIZE); #[cfg(test)] mod tests { diff --git a/ethereum-types/Cargo.toml b/ethereum-types/Cargo.toml index 8f53d7b..a548395 100644 --- a/ethereum-types/Cargo.toml +++ b/ethereum-types/Cargo.toml @@ -7,18 +7,19 @@ homepage = "https://github.com/paritytech/primitives" description = "Ethereum types" [dependencies] -crunchy = { version = "0.2.1", default-features = false } +crunchy = { version = "0.2", default-features = false } ethbloom = { path = "../ethbloom", version = "0.6", default-features = false } -ethereum-types-serialize = { version = "0.2.1", path = "../serialize", optional = true } -fixed-hash = { version = "0.3", default_features = false } -serde = { version = "1.0", optional = true } -uint = { version = "0.5", default_features = false } +fixed-hash = { version = "0.3", default-features = false, features = ["byteorder", "rustc-hex"] } +uint = { version = "0.5", default-features = false } +primitive-types = { version = "0.1", features = ["rlp", "byteorder", "rustc-hex"], default-features = false } +impl-serde = { version = "0.1", default-features = false, optional = true } +impl-rlp = { version = "0.1", default-features = false } [dev-dependencies] serde_json = "1.0" [features] -default = ["std", "heapsize", "serialize", "fixed-hash/byteorder", "fixed-hash/rustc-hex"] -std = ["uint/std", "fixed-hash/std", "ethbloom/std", "crunchy/std"] -heapsize = ["uint/heapsize", "fixed-hash/heapsize", "ethbloom/heapsize"] -serialize = ["std", "ethereum-types-serialize", "serde", "ethbloom/serialize"] +default = ["std", "heapsize", "serialize"] +std = ["uint/std", "fixed-hash/std", "ethbloom/std", "crunchy/std", "primitive-types/std"] +heapsize = ["uint/heapsize", "primitive-types/heapsize", "fixed-hash/heapsize", "ethbloom/heapsize"] +serialize = ["std", "impl-serde", "primitive-types/serde", "ethbloom/serialize"] diff --git a/ethereum-types/src/hash.rs b/ethereum-types/src/hash.rs index 26410ae..1c4d41c 100644 --- a/ethereum-types/src/hash.rs +++ b/ethereum-types/src/hash.rs @@ -1,115 +1,60 @@ use crate::{U64, U128, U256, U512}; -#[cfg(feature = "serialize")] -use serde::{Serialize, Serializer, Deserialize, Deserializer}; - -#[cfg(feature = "serialize")] -use ethereum_types_serialize; - -macro_rules! impl_serde { - ($name: ident, $len: expr) => { - #[cfg(feature = "serialize")] - impl Serialize for $name { - fn serialize(&self, serializer: S) -> Result where S: Serializer { - let mut slice = [0u8; 2 + 2 * $len]; - ethereum_types_serialize::serialize(&mut slice, &self.0, serializer) - } - } +pub trait BigEndianHash { + type Uint; - #[cfg(feature = "serialize")] - impl<'de> Deserialize<'de> for $name { - fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { - let mut bytes = [0u8; $len]; - ethereum_types_serialize::deserialize_check_len(deserializer, ethereum_types_serialize::ExpectedLen::Exact(&mut bytes))?; - Ok($name(bytes)) - } - } - } + fn from_uint(val: &Self::Uint) -> Self; + fn into_uint(&self) -> Self::Uint; } +construct_fixed_hash!{ pub struct H32(4); } +impl_fixed_hash_rlp!(H32, 4); +#[cfg(feature = "serialize")] impl_fixed_hash_serde!(H32, 4); + +construct_fixed_hash!{ pub struct H64(8); } +impl_fixed_hash_rlp!(H64, 8); +#[cfg(feature = "serialize")] impl_fixed_hash_serde!(H64, 8); + +construct_fixed_hash!{ pub struct H128(16); } +impl_fixed_hash_rlp!(H128, 16); +#[cfg(feature = "serialize")] impl_fixed_hash_serde!(H128, 16); + +pub use primitive_types::H160; +pub use primitive_types::H256; + +construct_fixed_hash!{ pub struct H264(33); } +impl_fixed_hash_rlp!(H264, 33); +#[cfg(feature = "serialize")] impl_fixed_hash_serde!(H264, 33); + +pub use primitive_types::H512; + +construct_fixed_hash!{ pub struct H520(65); } +impl_fixed_hash_rlp!(H520, 65); +#[cfg(feature = "serialize")] impl_fixed_hash_serde!(H520, 65); + macro_rules! impl_uint_conversions { ($hash: ident, $uint: ident) => { - impl From<$uint> for $hash { - fn from(value: $uint) -> Self { - let mut ret = $hash::zero(); - value.to_big_endian(ret.as_bytes_mut()); - ret - } - } + impl BigEndianHash for $hash { + type Uint = $uint; - impl<'a> From<&'a $uint> for $hash { - fn from(value: &'a $uint) -> Self { + fn from_uint(value: &$uint) -> Self { let mut ret = $hash::zero(); value.to_big_endian(ret.as_bytes_mut()); ret } - } - impl From<$hash> for $uint { - fn from(value: $hash) -> Self { - Self::from(&value) - } - } - - impl<'a> From<&'a $hash> for $uint { - fn from(value: &'a $hash) -> Self { - Self::from(value.as_ref() as &[u8]) + fn into_uint(&self) -> $uint { + $uint::from(self.as_ref() as &[u8]) } } } } -impl_serde!(H32, 4); -impl_serde!(H64, 8); -impl_serde!(H128, 16); -impl_serde!(H160, 20); -impl_serde!(H256, 32); -impl_serde!(H264, 33); -impl_serde!(H512, 64); -impl_serde!(H520, 65); - -construct_fixed_hash!{ pub struct H32(4); } -construct_fixed_hash!{ pub struct H64(8); } -construct_fixed_hash!{ pub struct H128(16); } -construct_fixed_hash!{ pub struct H160(20); } -construct_fixed_hash!{ pub struct H256(32); } -construct_fixed_hash!{ pub struct H264(33); } -construct_fixed_hash!{ pub struct H512(64); } -construct_fixed_hash!{ pub struct H520(65); } - impl_uint_conversions!(H64, U64); impl_uint_conversions!(H128, U128); impl_uint_conversions!(H256, U256); impl_uint_conversions!(H512, U512); -impl From for H256 { - fn from(value: H160) -> H256 { - let mut ret = H256::zero(); - ret.0[12..32].copy_from_slice(value.as_bytes()); - ret - } -} - -impl<'a> From<&'a H160> for H256 { - fn from(value: &'a H160) -> H256 { - let mut ret = H256::zero(); - ret.0[12..32].copy_from_slice(value.as_bytes()); - ret - } -} - -impl From for H160 { - fn from(val: u64) -> Self { - H160::from_low_u64_be(val) - } -} - -impl From for H256 { - fn from(val: u64) -> Self { - H256::from_low_u64_be(val) - } -} - #[cfg(test)] mod tests { use super::{H160, H256}; diff --git a/ethereum-types/src/lib.rs b/ethereum-types/src/lib.rs index bcda15b..e724dbe 100644 --- a/ethereum-types/src/lib.rs +++ b/ethereum-types/src/lib.rs @@ -9,11 +9,14 @@ extern crate uint as uint_crate; #[macro_use] extern crate fixed_hash; extern crate ethbloom; +extern crate primitive_types; #[cfg(feature = "serialize")] -extern crate ethereum_types_serialize; -#[cfg(feature = "serialize")] -extern crate serde; +#[macro_use] +extern crate impl_serde; + +#[macro_use] +extern crate impl_rlp; #[cfg(test)] extern crate serde_json; @@ -22,7 +25,7 @@ mod hash; mod uint; pub use uint::{U64, U128, U256, U512}; -pub use hash::{H32, H64, H128, H160, H256, H264, H512, H520}; +pub use hash::{BigEndianHash, H32, H64, H128, H160, H256, H264, H512, H520}; pub use ethbloom::{Bloom, BloomRef, Input as BloomInput}; pub type Address = H160; diff --git a/ethereum-types/src/uint.rs b/ethereum-types/src/uint.rs index 88aeb29..16aeae7 100644 --- a/ethereum-types/src/uint.rs +++ b/ethereum-types/src/uint.rs @@ -1,104 +1,12 @@ -#[cfg(feature = "serialize")] -use serde::{Serialize, Serializer, Deserialize, Deserializer}; - -#[cfg(feature = "serialize")] -use ethereum_types_serialize; - -macro_rules! impl_serde { - ($name: ident, $len: expr) => { - #[cfg(feature = "serialize")] - impl Serialize for $name { - fn serialize(&self, serializer: S) -> Result where S: Serializer { - let mut slice = [0u8; 2 + 2 * $len * 8]; - let mut bytes = [0u8; $len * 8]; - self.to_big_endian(&mut bytes); - ethereum_types_serialize::serialize_uint(&mut slice, &bytes, serializer) - } - } - - #[cfg(feature = "serialize")] - impl<'de> Deserialize<'de> for $name { - fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { - let mut bytes = [0u8; $len * 8]; - let wrote = ethereum_types_serialize::deserialize_check_len(deserializer, ethereum_types_serialize::ExpectedLen::Between(0, &mut bytes))?; - Ok(bytes[0..wrote].into()) - } - } - } -} - construct_uint!(U64, 1); -construct_uint!(U128, 2); -construct_uint!(U256, 4); -construct_uint!(U512, 8); - -impl_serde!(U64, 1); -impl_serde!(U128, 2); -impl_serde!(U256, 4); -impl_serde!(U512, 8); - -impl U256 { - /// Multiplies two 256-bit integers to produce full 512-bit integer - /// No overflow possible - #[inline(always)] - pub fn full_mul(self, other: U256) -> U512 { - U512(uint_full_mul_reg!(U256, 4, self, other)) - } -} +impl_uint_rlp!(U64, 1); +#[cfg(feature = "serialize")] impl_uint_serde!(U64, 1); -impl From for U512 { - fn from(value: U256) -> U512 { - let U256(ref arr) = value; - let mut ret = [0; 8]; - ret[0] = arr[0]; - ret[1] = arr[1]; - ret[2] = arr[2]; - ret[3] = arr[3]; - U512(ret) - } -} - -impl From for U256 { - fn from(value: U512) -> U256 { - let U512(ref arr) = value; - if arr[4] | arr[5] | arr[6] | arr[7] != 0 { - panic!("From for U256: encountered overflow") - } - let mut ret = [0; 4]; - ret[0] = arr[0]; - ret[1] = arr[1]; - ret[2] = arr[2]; - ret[3] = arr[3]; - U256(ret) - } -} - -impl<'a> From<&'a U256> for U512 { - fn from(value: &'a U256) -> U512 { - let U256(ref arr) = *value; - let mut ret = [0; 8]; - ret[0] = arr[0]; - ret[1] = arr[1]; - ret[2] = arr[2]; - ret[3] = arr[3]; - U512(ret) - } -} +construct_uint!(U128, 2); +impl_uint_rlp!(U128, 2); +#[cfg(feature = "serialize")] impl_uint_serde!(U128, 2); -impl<'a> From<&'a U512> for U256 { - fn from(value: &'a U512) -> U256 { - let U512(ref arr) = *value; - if arr[4] | arr[5] | arr[6] | arr[7] != 0 { - panic!("From<&U512> for U256: encountered overflow") - } - let mut ret = [0; 4]; - ret[0] = arr[0]; - ret[1] = arr[1]; - ret[2] = arr[2]; - ret[3] = arr[3]; - U256(ret) - } -} +pub use primitive_types::{U256, U512}; impl From for U128 { fn from(value: U256) -> U128 { @@ -146,18 +54,6 @@ impl From for U256 { } } -impl From for u64 { - fn from(value: U256) -> u64 { - value.as_u64() - } -} - -impl From for u32 { - fn from(value: U256) -> u32 { - value.as_u32() - } -} - #[cfg(test)] mod tests { use super::{U256, U512}; @@ -324,4 +220,4 @@ mod tests { let result = U256([1, 2, 3, 4]).full_mul(U256([5, 6, 7, 8])); assert_eq!(U512([5, 16, 34, 60, 61, 52, 32, 0]), result); } -} \ No newline at end of file +} diff --git a/serialize/Cargo.toml b/serialize/Cargo.toml deleted file mode 100644 index cb160dd..0000000 --- a/serialize/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "ethereum-types-serialize" -version = "0.2.1" -authors = ["Parity Technologies "] -license = "MIT" -homepage = "https://github.com/paritytech/primitives" -description = "Ethereum types" - -[dependencies] -serde = "1.0" diff --git a/serialize/src/lib.rs b/serialize/src/lib.rs deleted file mode 100644 index 7691dd1..0000000 --- a/serialize/src/lib.rs +++ /dev/null @@ -1,144 +0,0 @@ -extern crate serde; - -use std::fmt; -use serde::{de, Serializer, Deserializer}; - -static CHARS: &'static[u8] = b"0123456789abcdef"; - -fn to_hex<'a>(v: &'a mut [u8], bytes: &[u8], skip_leading_zero: bool) -> &'a str { - assert!(v.len() > 1 + bytes.len() * 2); - - v[0] = b'0'; - v[1] = b'x'; - - let mut idx = 2; - let first_nibble = bytes[0] >> 4; - if first_nibble != 0 || !skip_leading_zero { - v[idx] = CHARS[first_nibble as usize]; - idx += 1; - } - v[idx] = CHARS[(bytes[0] & 0xf) as usize]; - idx += 1; - - for &byte in bytes.iter().skip(1) { - v[idx] = CHARS[(byte >> 4) as usize]; - v[idx + 1] = CHARS[(byte & 0xf) as usize]; - idx += 2; - } - - ::std::str::from_utf8(&v[0..idx]).expect("All characters are coming from CHARS") -} - -/// Serializes a slice of bytes. -pub fn serialize(slice: &mut [u8], bytes: &[u8], serializer: S) -> Result where - S: Serializer, -{ - serializer.serialize_str(to_hex(slice, bytes, false)) -} - -/// Serialize a slice of bytes as uint. -/// -/// The representation will have all leading zeros trimmed. -pub fn serialize_uint(slice: &mut [u8], bytes: &[u8], serializer: S) -> Result where - S: Serializer, -{ - let non_zero = bytes.iter().take_while(|b| **b == 0).count(); - let bytes = &bytes[non_zero..]; - if bytes.is_empty() { - return serializer.serialize_str("0x0"); - } - - serializer.serialize_str(to_hex(slice, bytes, true)) -} - -/// Expected length of bytes vector. -#[derive(Debug, PartialEq, Eq)] -pub enum ExpectedLen<'a> { - /// Exact length in bytes. - Exact(&'a mut [u8]), - /// A bytes length between (min; slice.len()]. - Between(usize, &'a mut [u8]), -} - -impl<'a> fmt::Display for ExpectedLen<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - match *self { - ExpectedLen::Exact(ref v) => write!(fmt, "length of {}", v.len() * 2), - ExpectedLen::Between(min, ref v) => write!(fmt, "length between ({}; {}]", min * 2, v.len() * 2), - } - } -} - -/// Deserialize into vector of bytes with additional size check. -/// Returns number of bytes written. -pub fn deserialize_check_len<'a, 'de, D>(deserializer: D, len: ExpectedLen<'a>) -> Result where - D: Deserializer<'de>, -{ - struct Visitor<'a> { - len: ExpectedLen<'a>, - } - - impl<'a, 'b> de::Visitor<'b> for Visitor<'a> { - type Value = usize; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "a 0x-prefixed hex string with {}", self.len) - } - - fn visit_str(self, v: &str) -> Result { - if v.len() < 2 || &v[0..2] != "0x" { - return Err(E::custom("prefix is missing")) - } - - let is_len_valid = match self.len { - ExpectedLen::Exact(ref slice) => v.len() == 2 * slice.len() + 2, - ExpectedLen::Between(min, ref slice) => v.len() <= 2 * slice.len() + 2 && v.len() > 2 * min + 2, - }; - - if !is_len_valid { - return Err(E::invalid_length(v.len() - 2, &self)) - } - - let bytes = match self.len { - ExpectedLen::Exact(slice) => slice, - ExpectedLen::Between(_, slice) => slice, - }; - - let mut modulus = v.len() % 2; - let mut buf = 0; - let mut pos = 0; - for (idx, byte) in v.bytes().enumerate().skip(2) { - buf <<= 4; - - match byte { - b'A'...b'F' => buf |= byte - b'A' + 10, - b'a'...b'f' => buf |= byte - b'a' + 10, - b'0'...b'9' => buf |= byte - b'0', - b' '|b'\r'|b'\n'|b'\t' => { - buf >>= 4; - continue - } - _ => { - let ch = v[idx..].chars().next().unwrap(); - return Err(E::custom(&format!("invalid hex character: {}, at {}", ch, idx))) - } - } - - modulus += 1; - if modulus == 2 { - modulus = 0; - bytes[pos] = buf; - pos += 1; - } - } - - Ok(pos) - } - - fn visit_string(self, v: String) -> Result { - self.visit_str(&v) - } - } - - deserializer.deserialize_str(Visitor { len }) -}