Reformat the source code

This commit is contained in:
Artem Vorotnikov
2020-08-05 07:08:03 +03:00
parent 253ff3f37b
commit 610d9baba4
742 changed files with 175791 additions and 141379 deletions

View File

@@ -16,31 +16,31 @@
//! Blockchain test account deserializer.
use bytes::Bytes;
use std::collections::BTreeMap;
use uint::Uint;
use bytes::Bytes;
/// Blockchain test account deserializer.
#[derive(Debug, PartialEq, Deserialize, Clone)]
pub struct Account {
/// Balance.
pub balance: Uint,
/// Code.
pub code: Bytes,
/// Nonce.
pub nonce: Uint,
/// Storage.
pub storage: BTreeMap<Uint, Uint>,
/// Balance.
pub balance: Uint,
/// Code.
pub code: Bytes,
/// Nonce.
pub nonce: Uint,
/// Storage.
pub storage: BTreeMap<Uint, Uint>,
}
#[cfg(test)]
mod tests {
use serde_json;
use blockchain::account::Account;
use blockchain::account::Account;
use serde_json;
#[test]
fn account_deserialization() {
let s = r#"{
#[test]
fn account_deserialization() {
let s = r#"{
"balance" : "0x09184e72a078",
"code" : "0x600140600155",
"nonce" : "0x00",
@@ -48,7 +48,7 @@ mod tests {
"0x01" : "0x9a10c2b5bb8f3c602e674006d9b21f09167df57c87a78a5ce96d4159ecb76520"
}
}"#;
let _deserialized: Account = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
let _deserialized: Account = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
}

View File

@@ -16,36 +16,35 @@
//! Blockchain test block deserializer.
use blockchain::{header::Header, transaction::Transaction};
use bytes::Bytes;
use blockchain::header::Header;
use blockchain::transaction::Transaction;
/// Blockchain test block deserializer.
#[derive(Debug, PartialEq, Deserialize)]
pub struct Block {
#[serde(rename = "blockHeader")]
header: Option<Header>,
rlp: Bytes,
transactions: Option<Vec<Transaction>>,
#[serde(rename = "uncleHeaders")]
uncles: Option<Vec<Header>>,
#[serde(rename = "blockHeader")]
header: Option<Header>,
rlp: Bytes,
transactions: Option<Vec<Transaction>>,
#[serde(rename = "uncleHeaders")]
uncles: Option<Vec<Header>>,
}
impl Block {
/// Returns block rlp.
pub fn rlp(&self) -> Vec<u8> {
self.rlp.clone().into()
}
/// Returns block rlp.
pub fn rlp(&self) -> Vec<u8> {
self.rlp.clone().into()
}
}
#[cfg(test)]
mod tests {
use serde_json;
use blockchain::block::Block;
use blockchain::block::Block;
use serde_json;
#[test]
fn block_deserialization() {
let s = r#"{
#[test]
fn block_deserialization() {
let s = r#"{
"blockHeader" : {
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
@@ -69,7 +68,7 @@ mod tests {
"transactions" : [],
"uncleHeaders" : []
}"#;
let _deserialized: Block = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
let _deserialized: Block = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
}

View File

@@ -16,91 +16,89 @@
//! Blockchain deserialization.
use blockchain::{block::Block, header::Header, state::State};
use bytes::Bytes;
use hash::H256;
use blockchain::state::State;
use blockchain::header::Header;
use blockchain::block::Block;
use spec::{ForkSpec, Genesis, Seal, Ethereum};
use spec::{Ethereum, ForkSpec, Genesis, Seal};
/// Json Block test possible engine kind.
#[derive(Debug, PartialEq, Deserialize)]
pub enum Engine {
/// Default (old) behaviour.
Ethash,
/// No check of block's difficulty and nonce for tests.
NoProof,
/// Default (old) behaviour.
Ethash,
/// No check of block's difficulty and nonce for tests.
NoProof,
}
impl Default for Engine {
fn default() -> Self {
Engine::Ethash
}
fn default() -> Self {
Engine::Ethash
}
}
/// Blockchain deserialization.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BlockChain {
/// Genesis block header.
#[serde(rename = "genesisBlockHeader")]
pub genesis_block: Header,
/// Genesis block rlp.
#[serde(rename = "genesisRLP")]
pub genesis_rlp: Option<Bytes>,
/// Blocks.
pub blocks: Vec<Block>,
/// Post state.
pub post_state: State,
/// Pre state.
#[serde(rename = "pre")]
pub pre_state: State,
/// Hash of best block.
#[serde(rename = "lastblockhash")]
pub best_block: H256,
/// Network.
pub network: ForkSpec,
#[serde(default)]
#[serde(rename="sealEngine")]
/// Engine
pub engine: Engine,
/// Genesis block header.
#[serde(rename = "genesisBlockHeader")]
pub genesis_block: Header,
/// Genesis block rlp.
#[serde(rename = "genesisRLP")]
pub genesis_rlp: Option<Bytes>,
/// Blocks.
pub blocks: Vec<Block>,
/// Post state.
pub post_state: State,
/// Pre state.
#[serde(rename = "pre")]
pub pre_state: State,
/// Hash of best block.
#[serde(rename = "lastblockhash")]
pub best_block: H256,
/// Network.
pub network: ForkSpec,
#[serde(default)]
#[serde(rename = "sealEngine")]
/// Engine
pub engine: Engine,
}
impl BlockChain {
/// Returns blocks rlp.
pub fn blocks_rlp(&self) -> Vec<Vec<u8>> {
self.blocks.iter().map(|block| block.rlp()).collect()
}
/// Returns blocks rlp.
pub fn blocks_rlp(&self) -> Vec<Vec<u8>> {
self.blocks.iter().map(|block| block.rlp()).collect()
}
/// Returns spec compatible genesis struct.
pub fn genesis(&self) -> Genesis {
Genesis {
seal: Seal::Ethereum(Ethereum {
nonce: self.genesis_block.nonce.clone(),
mix_hash: self.genesis_block.mix_hash.clone(),
}),
difficulty: self.genesis_block.difficulty,
author: Some(self.genesis_block.author.clone()),
timestamp: Some(self.genesis_block.timestamp),
parent_hash: Some(self.genesis_block.parent_hash.clone()),
gas_limit: self.genesis_block.gas_limit,
transactions_root: Some(self.genesis_block.transactions_root.clone()),
receipts_root: Some(self.genesis_block.receipts_root.clone()),
state_root: Some(self.genesis_block.state_root.clone()),
gas_used: Some(self.genesis_block.gas_used),
extra_data: Some(self.genesis_block.extra_data.clone()),
}
}
/// Returns spec compatible genesis struct.
pub fn genesis(&self) -> Genesis {
Genesis {
seal: Seal::Ethereum(Ethereum {
nonce: self.genesis_block.nonce.clone(),
mix_hash: self.genesis_block.mix_hash.clone(),
}),
difficulty: self.genesis_block.difficulty,
author: Some(self.genesis_block.author.clone()),
timestamp: Some(self.genesis_block.timestamp),
parent_hash: Some(self.genesis_block.parent_hash.clone()),
gas_limit: self.genesis_block.gas_limit,
transactions_root: Some(self.genesis_block.transactions_root.clone()),
receipts_root: Some(self.genesis_block.receipts_root.clone()),
state_root: Some(self.genesis_block.state_root.clone()),
gas_used: Some(self.genesis_block.gas_used),
extra_data: Some(self.genesis_block.extra_data.clone()),
}
}
}
#[cfg(test)]
mod tests {
use serde_json;
use blockchain::blockchain::BlockChain;
use blockchain::blockchain::BlockChain;
use serde_json;
#[test]
fn blockchain_deserialization() {
let s = r#"{
#[test]
fn blockchain_deserialization() {
let s = r#"{
"blocks" : [{
"blockHeader" : {
"bloom" : "00000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000040000000000000000000000000000000000000000000000000000000",
@@ -198,7 +196,7 @@ mod tests {
}
}
}"#;
let _deserialized: BlockChain = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
let _deserialized: BlockChain = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
}

View File

@@ -16,60 +16,60 @@
//! Blockchain test header deserializer.
use hash::{H64, Address, H256, Bloom};
use uint::Uint;
use bytes::Bytes;
use hash::{Address, Bloom, H256, H64};
use uint::Uint;
/// Blockchain test header deserializer.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Header {
/// Blocks bloom.
pub bloom: Bloom,
/// Blocks author.
#[serde(rename = "coinbase")]
pub author: Address,
/// Difficulty.
pub difficulty: Uint,
/// Extra data.
pub extra_data: Bytes,
/// Gas limit.
pub gas_limit: Uint,
/// Gas used.
pub gas_used: Uint,
/// Hash.
pub hash: H256,
/// Mix hash.
pub mix_hash: H256,
/// Seal nonce.
pub nonce: H64,
/// Block number.
pub number: Uint,
/// Parent hash.
pub parent_hash: H256,
/// Receipt root.
#[serde(rename = "receiptTrie")]
pub receipts_root: H256,
/// State root.
pub state_root: H256,
/// Timestamp.
pub timestamp: Uint,
/// Transactions root.
#[serde(rename = "transactionsTrie")]
pub transactions_root: H256,
/// Uncles hash.
#[serde(rename = "uncleHash")]
pub uncles_hash: H256,
/// Blocks bloom.
pub bloom: Bloom,
/// Blocks author.
#[serde(rename = "coinbase")]
pub author: Address,
/// Difficulty.
pub difficulty: Uint,
/// Extra data.
pub extra_data: Bytes,
/// Gas limit.
pub gas_limit: Uint,
/// Gas used.
pub gas_used: Uint,
/// Hash.
pub hash: H256,
/// Mix hash.
pub mix_hash: H256,
/// Seal nonce.
pub nonce: H64,
/// Block number.
pub number: Uint,
/// Parent hash.
pub parent_hash: H256,
/// Receipt root.
#[serde(rename = "receiptTrie")]
pub receipts_root: H256,
/// State root.
pub state_root: H256,
/// Timestamp.
pub timestamp: Uint,
/// Transactions root.
#[serde(rename = "transactionsTrie")]
pub transactions_root: H256,
/// Uncles hash.
#[serde(rename = "uncleHash")]
pub uncles_hash: H256,
}
#[cfg(test)]
mod tests {
use serde_json;
use blockchain::header::Header;
use blockchain::header::Header;
use serde_json;
#[test]
fn header_deserialization() {
let s = r#"{
#[test]
fn header_deserialization() {
let s = r#"{
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
"difficulty" : "0x020000",
@@ -87,7 +87,7 @@ mod tests {
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
}"#;
let _deserialized: Header = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
let _deserialized: Header = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
}

View File

@@ -21,14 +21,15 @@ pub mod block;
pub mod blockchain;
pub mod header;
pub mod state;
pub mod transaction;
pub mod test;
pub mod transaction;
pub use self::account::Account;
pub use self::block::Block;
pub use self::blockchain::BlockChain;
pub use self::blockchain::Engine;
pub use self::header::Header;
pub use self::state::State;
pub use self::test::Test;
pub use self::transaction::Transaction;
pub use self::{
account::Account,
block::Block,
blockchain::{BlockChain, Engine},
header::Header,
state::State,
test::Test,
transaction::Transaction,
};

View File

@@ -16,19 +16,19 @@
//! Blockchain test state deserializer.
use std::collections::BTreeMap;
use hash::Address;
use blockchain::account::Account;
use hash::Address;
use std::collections::BTreeMap;
/// Blockchain test state deserializer.
#[derive(Debug, PartialEq, Deserialize, Clone)]
pub struct State(BTreeMap<Address, Account>);
impl IntoIterator for State {
type Item = <BTreeMap<Address, Account> as IntoIterator>::Item;
type IntoIter = <BTreeMap<Address, Account> as IntoIterator>::IntoIter;
type Item = <BTreeMap<Address, Account> as IntoIterator>::Item;
type IntoIter = <BTreeMap<Address, Account> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}

View File

@@ -16,28 +16,29 @@
//! Blockchain test deserializer.
use std::collections::BTreeMap;
use std::io::Read;
use serde_json;
use serde_json::Error;
use blockchain::blockchain::BlockChain;
use serde_json::{self, Error};
use std::{collections::BTreeMap, io::Read};
/// Blockchain test deserializer.
#[derive(Debug, PartialEq, Deserialize)]
pub struct Test(BTreeMap<String, BlockChain>);
impl IntoIterator for Test {
type Item = <BTreeMap<String, BlockChain> as IntoIterator>::Item;
type IntoIter = <BTreeMap<String, BlockChain> as IntoIterator>::IntoIter;
type Item = <BTreeMap<String, BlockChain> as IntoIterator>::Item;
type IntoIter = <BTreeMap<String, BlockChain> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl Test {
/// Loads test from json.
pub fn load<R>(reader: R) -> Result<Self, Error> where R: Read {
serde_json::from_reader(reader)
}
/// Loads test from json.
pub fn load<R>(reader: R) -> Result<Self, Error>
where
R: Read,
{
serde_json::from_reader(reader)
}
}

View File

@@ -16,19 +16,19 @@
//! Blockchain test transaction deserialization.
use uint::Uint;
use bytes::Bytes;
use uint::Uint;
/// Blockchain test transaction deserialization.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Transaction {
data: Bytes,
gas_limit: Uint,
gas_price: Uint,
nonce: Uint,
r: Uint,
s: Uint,
v: Uint,
value: Uint
data: Bytes,
gas_limit: Uint,
gas_price: Uint,
nonce: Uint,
r: Uint,
s: Uint,
v: Uint,
value: Uint,
}

View File

@@ -16,104 +16,115 @@
//! Lenient bytes json deserialization for test json files.
use std::fmt;
use std::str::FromStr;
use std::ops::Deref;
use rustc_hex::FromHex;
use serde::{Deserialize, Deserializer};
use serde::de::{Error, Visitor};
use serde::{
de::{Error, Visitor},
Deserialize, Deserializer,
};
use std::{fmt, ops::Deref, str::FromStr};
/// Lenient bytes json deserialization for test json files.
#[derive(Default, Debug, PartialEq, Eq, Clone, PartialOrd, Ord)]
pub struct Bytes(Vec<u8>);
impl Bytes {
/// Creates bytes struct.
pub fn new(v: Vec<u8>) -> Self {
Bytes(v)
}
/// Creates bytes struct.
pub fn new(v: Vec<u8>) -> Self {
Bytes(v)
}
}
impl Into<Vec<u8>> for Bytes {
fn into(self) -> Vec<u8> {
self.0
}
fn into(self) -> Vec<u8> {
self.0
}
}
impl Deref for Bytes {
type Target = [u8];
type Target = [u8];
fn deref(&self) -> &[u8] {
&self.0
}
fn deref(&self) -> &[u8] {
&self.0
}
}
impl FromStr for Bytes {
type Err = String;
type Err = String;
fn from_str(value: &str) -> Result<Self, Self::Err> {
let v = match value.len() {
0 => vec![],
2 if value.starts_with("0x") => vec![],
_ if value.starts_with("0x") && value.len() % 2 == 1 => {
let v = "0".to_owned() + &value[2..];
FromHex::from_hex(v.as_str()).unwrap_or(vec![])
},
_ if value.starts_with("0x") => FromHex::from_hex(&value[2..]).unwrap_or(vec![]),
_ => FromHex::from_hex(value).unwrap_or(vec![]),
};
fn from_str(value: &str) -> Result<Self, Self::Err> {
let v = match value.len() {
0 => vec![],
2 if value.starts_with("0x") => vec![],
_ if value.starts_with("0x") && value.len() % 2 == 1 => {
let v = "0".to_owned() + &value[2..];
FromHex::from_hex(v.as_str()).unwrap_or(vec![])
}
_ if value.starts_with("0x") => FromHex::from_hex(&value[2..]).unwrap_or(vec![]),
_ => FromHex::from_hex(value).unwrap_or(vec![]),
};
Ok(Bytes(v))
}
Ok(Bytes(v))
}
}
impl<'a> Deserialize<'a> for Bytes {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'a> {
deserializer.deserialize_any(BytesVisitor)
}
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'a>,
{
deserializer.deserialize_any(BytesVisitor)
}
}
struct BytesVisitor;
impl<'a> Visitor<'a> for BytesVisitor {
type Value = Bytes;
type Value = Bytes;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a hex encoded string of bytes")
}
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a hex encoded string of bytes")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> where E: Error {
Bytes::from_str(value).map_err(Error::custom)
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: Error,
{
Bytes::from_str(value).map_err(Error::custom)
}
fn visit_string<E>(self, value: String) -> Result<Self::Value, E> where E: Error {
self.visit_str(value.as_ref())
}
fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
where
E: Error,
{
self.visit_str(value.as_ref())
}
}
#[cfg(test)]
mod test {
use serde_json;
use bytes::Bytes;
use bytes::Bytes;
use serde_json;
#[test]
fn bytes_deserialization() {
let s = r#"["", "0x", "0x12", "1234", "0x001"]"#;
let deserialized: Vec<Bytes> = serde_json::from_str(s).unwrap();
assert_eq!(deserialized, vec![
Bytes(vec![]),
Bytes(vec![]),
Bytes(vec![0x12]),
Bytes(vec![0x12, 0x34]),
Bytes(vec![0, 1])
]);
}
#[test]
fn bytes_deserialization() {
let s = r#"["", "0x", "0x12", "1234", "0x001"]"#;
let deserialized: Vec<Bytes> = serde_json::from_str(s).unwrap();
assert_eq!(
deserialized,
vec![
Bytes(vec![]),
Bytes(vec![]),
Bytes(vec![0x12]),
Bytes(vec![0x12, 0x34]),
Bytes(vec![0, 1])
]
);
}
#[test]
fn bytes_into() {
let bytes = Bytes(vec![0xff, 0x11]);
let v: Vec<u8> = bytes.into();
assert_eq!(vec![0xff, 0x11], v);
}
#[test]
fn bytes_into() {
let bytes = Bytes(vec![0xff, 0x11]);
let v: Vec<u8> = bytes.into();
assert_eq!(vec![0xff, 0x11], v);
}
}

View File

@@ -16,76 +16,95 @@
//! Lenient hash json deserialization for test json files.
use std::str::FromStr;
use std::fmt;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde::de::{Error, Visitor};
use ethereum_types::{
Bloom as Hash2048, H160 as Hash160, H256 as Hash256, H520 as Hash520, H64 as Hash64,
};
use rustc_hex::ToHex;
use ethereum_types::{H64 as Hash64, H160 as Hash160, H256 as Hash256, H520 as Hash520, Bloom as Hash2048};
use serde::{
de::{Error, Visitor},
Deserialize, Deserializer, Serialize, Serializer,
};
use std::{fmt, str::FromStr};
macro_rules! impl_hash {
($name: ident, $inner: ident) => {
/// Lenient hash json deserialization for test json files.
#[derive(Default, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Clone)]
pub struct $name(pub $inner);
($name: ident, $inner: ident) => {
/// Lenient hash json deserialization for test json files.
#[derive(Default, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Clone)]
pub struct $name(pub $inner);
impl From<$name> for $inner {
fn from(other: $name) -> $inner {
other.0
}
}
impl From<$name> for $inner {
fn from(other: $name) -> $inner {
other.0
}
}
impl From<$inner> for $name {
fn from(i: $inner) -> Self {
$name(i)
}
}
impl From<$inner> for $name {
fn from(i: $inner) -> Self {
$name(i)
}
}
impl<'a> Deserialize<'a> for $name {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'a> {
impl<'a> Deserialize<'a> for $name {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'a>,
{
struct HashVisitor;
struct HashVisitor;
impl<'b> Visitor<'b> for HashVisitor {
type Value = $name;
impl<'b> Visitor<'b> for HashVisitor {
type Value = $name;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a 0x-prefixed hex-encoded hash")
}
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a 0x-prefixed hex-encoded hash")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: Error,
{
let value = match value.len() {
0 => $inner::from(0),
2 if value == "0x" => $inner::from(0),
_ if value.starts_with("0x") => {
$inner::from_str(&value[2..]).map_err(|e| {
Error::custom(
format!("Invalid hex value {}: {}", value, e).as_str(),
)
})?
}
_ => $inner::from_str(value).map_err(|e| {
Error::custom(
format!("Invalid hex value {}: {}", value, e).as_str(),
)
})?,
};
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> where E: Error {
let value = match value.len() {
0 => $inner::from(0),
2 if value == "0x" => $inner::from(0),
_ if value.starts_with("0x") => $inner::from_str(&value[2..]).map_err(|e| {
Error::custom(format!("Invalid hex value {}: {}", value, e).as_str())
})?,
_ => $inner::from_str(value).map_err(|e| {
Error::custom(format!("Invalid hex value {}: {}", value, e).as_str())
})?,
};
Ok($name(value))
}
Ok($name(value))
}
fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
where
E: Error,
{
self.visit_str(value.as_ref())
}
}
fn visit_string<E>(self, value: String) -> Result<Self::Value, E> where E: Error {
self.visit_str(value.as_ref())
}
}
deserializer.deserialize_any(HashVisitor)
}
}
deserializer.deserialize_any(HashVisitor)
}
}
impl Serialize for $name {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
let mut hex = "0x".to_owned();
hex.push_str(&self.0.to_hex());
serializer.serialize_str(&hex)
}
}
}
impl Serialize for $name {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut hex = "0x".to_owned();
hex.push_str(&self.0.to_hex());
serializer.serialize_str(&hex)
}
}
};
}
impl_hash!(H64, Hash64);
@@ -96,23 +115,34 @@ impl_hash!(Bloom, Hash2048);
#[cfg(test)]
mod test {
use std::str::FromStr;
use serde_json;
use ethereum_types;
use hash::H256;
use ethereum_types;
use hash::H256;
use serde_json;
use std::str::FromStr;
#[test]
fn hash_deserialization() {
let s = r#"["", "5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae"]"#;
let deserialized: Vec<H256> = serde_json::from_str(s).unwrap();
assert_eq!(deserialized, vec![
H256(ethereum_types::H256::from(0)),
H256(ethereum_types::H256::from_str("5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae").unwrap())
]);
}
#[test]
fn hash_deserialization() {
let s = r#"["", "5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae"]"#;
let deserialized: Vec<H256> = serde_json::from_str(s).unwrap();
assert_eq!(
deserialized,
vec![
H256(ethereum_types::H256::from(0)),
H256(
ethereum_types::H256::from_str(
"5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae"
)
.unwrap()
)
]
);
}
#[test]
fn hash_into() {
assert_eq!(ethereum_types::H256::from(0), H256(ethereum_types::H256::from(0)).into());
}
#[test]
fn hash_into() {
assert_eq!(
ethereum_types::H256::from(0),
H256(ethereum_types::H256::from(0)).into()
);
}
}

View File

@@ -14,23 +14,24 @@
// You should have received a copy of the GNU General Public License
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
extern crate ethereum_types;
extern crate rustc_hex;
extern crate serde;
extern crate serde_json;
extern crate ethereum_types;
#[macro_use] extern crate serde_derive;
#[macro_use]
extern crate serde_derive;
#[cfg(test)]
extern crate macros;
pub mod hash;
pub mod uint;
pub mod bytes;
pub mod blockchain;
pub mod spec;
pub mod trie;
pub mod vm;
pub mod bytes;
pub mod hash;
pub mod maybe;
pub mod spec;
pub mod state;
pub mod transaction;
pub mod test;
pub mod transaction;
pub mod trie;
pub mod uint;
pub mod vm;

View File

@@ -16,85 +16,105 @@
//! Deserializer of empty string values into optionals.
use std::fmt;
use std::marker::PhantomData;
use serde::{Deserialize, Deserializer};
use serde::de::{Error, Visitor, IntoDeserializer};
use serde::{
de::{Error, IntoDeserializer, Visitor},
Deserialize, Deserializer,
};
use std::{fmt, marker::PhantomData};
/// Deserializer of empty string values into optionals.
#[derive(Debug, PartialEq, Clone)]
pub enum MaybeEmpty<T> {
/// Some.
Some(T),
/// None.
None,
/// Some.
Some(T),
/// None.
None,
}
impl<'a, T> Deserialize<'a> for MaybeEmpty<T> where T: Deserialize<'a> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'a> {
deserializer.deserialize_any(MaybeEmptyVisitor::new())
}
impl<'a, T> Deserialize<'a> for MaybeEmpty<T>
where
T: Deserialize<'a>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'a>,
{
deserializer.deserialize_any(MaybeEmptyVisitor::new())
}
}
struct MaybeEmptyVisitor<T> {
_phantom: PhantomData<T>
_phantom: PhantomData<T>,
}
impl<T> MaybeEmptyVisitor<T> {
fn new() -> Self {
MaybeEmptyVisitor {
_phantom: PhantomData
}
}
fn new() -> Self {
MaybeEmptyVisitor {
_phantom: PhantomData,
}
}
}
impl<'a, T> Visitor<'a> for MaybeEmptyVisitor<T> where T: Deserialize<'a> {
type Value = MaybeEmpty<T>;
impl<'a, T> Visitor<'a> for MaybeEmptyVisitor<T>
where
T: Deserialize<'a>,
{
type Value = MaybeEmpty<T>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "an empty string or string-encoded type")
}
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "an empty string or string-encoded type")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> where E: Error {
self.visit_string(value.to_owned())
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: Error,
{
self.visit_string(value.to_owned())
}
fn visit_string<E>(self, value: String) -> Result<Self::Value, E> where E: Error {
match value.is_empty() {
true => Ok(MaybeEmpty::None),
false => {
T::deserialize(value.into_deserializer()).map(MaybeEmpty::Some)
}
}
}
fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
where
E: Error,
{
match value.is_empty() {
true => Ok(MaybeEmpty::None),
false => T::deserialize(value.into_deserializer()).map(MaybeEmpty::Some),
}
}
}
impl<T> Into<Option<T>> for MaybeEmpty<T> {
fn into(self) -> Option<T> {
match self {
MaybeEmpty::Some(s) => Some(s),
MaybeEmpty::None => None
}
}
fn into(self) -> Option<T> {
match self {
MaybeEmpty::Some(s) => Some(s),
MaybeEmpty::None => None,
}
}
}
#[cfg(test)]
mod tests {
use std::str::FromStr;
use serde_json;
use ethereum_types;
use hash::H256;
use maybe::MaybeEmpty;
#[test]
fn maybe_deserialization() {
let s = r#"["", "5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae"]"#;
let deserialized: Vec<MaybeEmpty<H256>> = serde_json::from_str(s).unwrap();
assert_eq!(deserialized, vec![
MaybeEmpty::None,
MaybeEmpty::Some(H256(ethereum_types::H256::from_str("5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae").unwrap()))
]);
}
use ethereum_types;
use hash::H256;
use maybe::MaybeEmpty;
use serde_json;
use std::str::FromStr;
#[test]
fn maybe_deserialization() {
let s = r#"["", "5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae"]"#;
let deserialized: Vec<MaybeEmpty<H256>> = serde_json::from_str(s).unwrap();
assert_eq!(
deserialized,
vec![
MaybeEmpty::None,
MaybeEmpty::Some(H256(
ethereum_types::H256::from_str(
"5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae"
)
.unwrap()
))
]
);
}
}

View File

@@ -18,92 +18,95 @@
use std::collections::BTreeMap;
use uint::Uint;
use bytes::Bytes;
use spec::builtin::BuiltinCompat;
use uint::Uint;
/// Spec account.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct Account {
/// Builtin contract.
pub builtin: Option<BuiltinCompat>,
/// Balance.
pub balance: Option<Uint>,
/// Nonce.
pub nonce: Option<Uint>,
/// Code.
pub code: Option<Bytes>,
/// Storage.
pub storage: Option<BTreeMap<Uint, Uint>>,
/// Constructor.
pub constructor: Option<Bytes>,
/// Builtin contract.
pub builtin: Option<BuiltinCompat>,
/// Balance.
pub balance: Option<Uint>,
/// Nonce.
pub nonce: Option<Uint>,
/// Code.
pub code: Option<Bytes>,
/// Storage.
pub storage: Option<BTreeMap<Uint, Uint>>,
/// Constructor.
pub constructor: Option<Bytes>,
}
impl Account {
/// Returns true if account does not have nonce, balance, code and storage.
pub fn is_empty(&self) -> bool {
self.balance.is_none() && self.nonce.is_none() && self.code.is_none() && self.storage.is_none()
}
/// Returns true if account does not have nonce, balance, code and storage.
pub fn is_empty(&self) -> bool {
self.balance.is_none()
&& self.nonce.is_none()
&& self.code.is_none()
&& self.storage.is_none()
}
}
#[cfg(test)]
mod tests {
use std::collections::BTreeMap;
use serde_json;
use spec::account::Account;
use ethereum_types::U256;
use uint::Uint;
use bytes::Bytes;
use bytes::Bytes;
use ethereum_types::U256;
use serde_json;
use spec::account::Account;
use std::collections::BTreeMap;
use uint::Uint;
#[test]
fn account_balance_missing_not_empty() {
let s = r#"{
#[test]
fn account_balance_missing_not_empty() {
let s = r#"{
"nonce": "0",
"code": "1234",
"storage": { "0x7fffffffffffffff7fffffffffffffff": "0x1" }
}"#;
let deserialized: Account = serde_json::from_str(s).unwrap();
assert!(!deserialized.is_empty());
}
let deserialized: Account = serde_json::from_str(s).unwrap();
assert!(!deserialized.is_empty());
}
#[test]
fn account_nonce_missing_not_empty() {
let s = r#"{
#[test]
fn account_nonce_missing_not_empty() {
let s = r#"{
"balance": "1",
"code": "1234",
"storage": { "0x7fffffffffffffff7fffffffffffffff": "0x1" }
}"#;
let deserialized: Account = serde_json::from_str(s).unwrap();
assert!(!deserialized.is_empty());
}
let deserialized: Account = serde_json::from_str(s).unwrap();
assert!(!deserialized.is_empty());
}
#[test]
fn account_code_missing_not_empty() {
let s = r#"{
#[test]
fn account_code_missing_not_empty() {
let s = r#"{
"balance": "1",
"nonce": "0",
"storage": { "0x7fffffffffffffff7fffffffffffffff": "0x1" }
}"#;
let deserialized: Account = serde_json::from_str(s).unwrap();
assert!(!deserialized.is_empty());
}
let deserialized: Account = serde_json::from_str(s).unwrap();
assert!(!deserialized.is_empty());
}
#[test]
fn account_storage_missing_not_empty() {
let s = r#"{
#[test]
fn account_storage_missing_not_empty() {
let s = r#"{
"balance": "1",
"nonce": "0",
"code": "1234"
}"#;
let deserialized: Account = serde_json::from_str(s).unwrap();
assert!(!deserialized.is_empty());
}
let deserialized: Account = serde_json::from_str(s).unwrap();
assert!(!deserialized.is_empty());
}
#[test]
fn account_empty() {
let s = r#"{
#[test]
fn account_empty() {
let s = r#"{
"builtin": {
"name": "ecrecover",
"pricing": {
@@ -114,13 +117,13 @@ mod tests {
}
}
}"#;
let deserialized: Account = serde_json::from_str(s).unwrap();
assert!(deserialized.is_empty());
}
let deserialized: Account = serde_json::from_str(s).unwrap();
assert!(deserialized.is_empty());
}
#[test]
fn account_deserialization() {
let s = r#"{
#[test]
fn account_deserialization() {
let s = r#"{
"balance": "1",
"nonce": "0",
"code": "1234",
@@ -134,29 +137,32 @@ mod tests {
}
}
}"#;
let deserialized: Account = serde_json::from_str(s).unwrap();
assert!(!deserialized.is_empty());
assert_eq!(deserialized.balance.unwrap(), Uint(U256::from(1)));
assert_eq!(deserialized.nonce.unwrap(), Uint(U256::from(0)));
assert_eq!(deserialized.code.unwrap(), Bytes::new(vec![0x12, 0x34]));
assert!(deserialized.builtin.is_some()); // Further tested in builtin.rs
}
let deserialized: Account = serde_json::from_str(s).unwrap();
assert!(!deserialized.is_empty());
assert_eq!(deserialized.balance.unwrap(), Uint(U256::from(1)));
assert_eq!(deserialized.nonce.unwrap(), Uint(U256::from(0)));
assert_eq!(deserialized.code.unwrap(), Bytes::new(vec![0x12, 0x34]));
assert!(deserialized.builtin.is_some()); // Further tested in builtin.rs
}
#[test]
fn account_storage_deserialization() {
let s = r#"{
#[test]
fn account_storage_deserialization() {
let s = r#"{
"balance": "1",
"nonce": "0",
"code": "1234",
"storage": { "0x7fffffffffffffff7fffffffffffffff": "0x1" }
}"#;
let deserialized: Account = serde_json::from_str(s).unwrap();
assert!(!deserialized.is_empty());
assert_eq!(deserialized.balance.unwrap(), Uint(U256::from(1)));
assert_eq!(deserialized.nonce.unwrap(), Uint(U256::from(0)));
assert_eq!(deserialized.code.unwrap(), Bytes::new(vec![0x12, 0x34]));
let mut storage = BTreeMap::new();
storage.insert(Uint(U256::from("7fffffffffffffff7fffffffffffffff")), Uint(U256::from(1)));
assert_eq!(deserialized.storage.unwrap(), storage);
}
let deserialized: Account = serde_json::from_str(s).unwrap();
assert!(!deserialized.is_empty());
assert_eq!(deserialized.balance.unwrap(), Uint(U256::from(1)));
assert_eq!(deserialized.nonce.unwrap(), Uint(U256::from(0)));
assert_eq!(deserialized.code.unwrap(), Bytes::new(vec![0x12, 0x34]));
let mut storage = BTreeMap::new();
storage.insert(
Uint(U256::from("7fffffffffffffff7fffffffffffffff")),
Uint(U256::from(1)),
);
assert_eq!(deserialized.storage.unwrap(), storage);
}
}

View File

@@ -16,70 +16,69 @@
//! Authority params deserialization.
use super::ValidatorSet;
use bytes::Bytes;
use hash::Address;
use uint::Uint;
use bytes::Bytes;
use super::ValidatorSet;
/// Authority params deserialization.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct AuthorityRoundParams {
/// Block duration, in seconds.
pub step_duration: Uint,
/// Valid authorities
pub validators: ValidatorSet,
/// Starting step. Determined automatically if not specified.
/// To be used for testing only.
pub start_step: Option<Uint>,
/// Block at which score validation should start.
pub validate_score_transition: Option<Uint>,
/// Block from which monotonic steps start.
pub validate_step_transition: Option<Uint>,
/// Whether transitions should be immediate.
pub immediate_transitions: Option<bool>,
/// Reward per block in wei.
pub block_reward: Option<Uint>,
/// Block at which the block reward contract should start being used.
pub block_reward_contract_transition: Option<Uint>,
/// Block reward contract address (setting the block reward contract
/// overrides the static block reward definition).
pub block_reward_contract_address: Option<Address>,
/// Block reward code. This overrides the block reward contract address.
pub block_reward_contract_code: Option<Bytes>,
/// Block at which maximum uncle count should be considered.
pub maximum_uncle_count_transition: Option<Uint>,
/// Maximum number of accepted uncles.
pub maximum_uncle_count: Option<Uint>,
/// Block at which empty step messages should start.
pub empty_steps_transition: Option<Uint>,
/// Maximum number of accepted empty steps.
pub maximum_empty_steps: Option<Uint>,
/// Strict validation of empty steps transition block.
pub strict_empty_steps_transition: Option<Uint>,
/// Block duration, in seconds.
pub step_duration: Uint,
/// Valid authorities
pub validators: ValidatorSet,
/// Starting step. Determined automatically if not specified.
/// To be used for testing only.
pub start_step: Option<Uint>,
/// Block at which score validation should start.
pub validate_score_transition: Option<Uint>,
/// Block from which monotonic steps start.
pub validate_step_transition: Option<Uint>,
/// Whether transitions should be immediate.
pub immediate_transitions: Option<bool>,
/// Reward per block in wei.
pub block_reward: Option<Uint>,
/// Block at which the block reward contract should start being used.
pub block_reward_contract_transition: Option<Uint>,
/// Block reward contract address (setting the block reward contract
/// overrides the static block reward definition).
pub block_reward_contract_address: Option<Address>,
/// Block reward code. This overrides the block reward contract address.
pub block_reward_contract_code: Option<Bytes>,
/// Block at which maximum uncle count should be considered.
pub maximum_uncle_count_transition: Option<Uint>,
/// Maximum number of accepted uncles.
pub maximum_uncle_count: Option<Uint>,
/// Block at which empty step messages should start.
pub empty_steps_transition: Option<Uint>,
/// Maximum number of accepted empty steps.
pub maximum_empty_steps: Option<Uint>,
/// Strict validation of empty steps transition block.
pub strict_empty_steps_transition: Option<Uint>,
}
/// Authority engine deserialization.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct AuthorityRound {
/// Ethash params.
pub params: AuthorityRoundParams,
/// Ethash params.
pub params: AuthorityRoundParams,
}
#[cfg(test)]
mod tests {
use ethereum_types::{U256, H160};
use uint::Uint;
use serde_json;
use hash::Address;
use spec::validator_set::ValidatorSet;
use spec::authority_round::AuthorityRound;
use ethereum_types::{H160, U256};
use hash::Address;
use serde_json;
use spec::{authority_round::AuthorityRound, validator_set::ValidatorSet};
use uint::Uint;
#[test]
fn authority_round_deserialization() {
let s = r#"{
#[test]
fn authority_round_deserialization() {
let s = r#"{
"params": {
"stepDuration": "0x02",
"validators": {
@@ -93,13 +92,23 @@ mod tests {
}
}"#;
let deserialized: AuthorityRound = serde_json::from_str(s).unwrap();
assert_eq!(deserialized.params.step_duration, Uint(U256::from(0x02)));
assert_eq!(deserialized.params.validators, ValidatorSet::List(vec![Address(H160::from("0xc6d9d2cd449a754c494264e1809c50e34d64562b"))]));
assert_eq!(deserialized.params.start_step, Some(Uint(U256::from(24))));
assert_eq!(deserialized.params.immediate_transitions, None);
assert_eq!(deserialized.params.maximum_uncle_count_transition, Some(Uint(10_000_000.into())));
assert_eq!(deserialized.params.maximum_uncle_count, Some(Uint(5.into())));
}
let deserialized: AuthorityRound = serde_json::from_str(s).unwrap();
assert_eq!(deserialized.params.step_duration, Uint(U256::from(0x02)));
assert_eq!(
deserialized.params.validators,
ValidatorSet::List(vec![Address(H160::from(
"0xc6d9d2cd449a754c494264e1809c50e34d64562b"
))])
);
assert_eq!(deserialized.params.start_step, Some(Uint(U256::from(24))));
assert_eq!(deserialized.params.immediate_transitions, None);
assert_eq!(
deserialized.params.maximum_uncle_count_transition,
Some(Uint(10_000_000.into()))
);
assert_eq!(
deserialized.params.maximum_uncle_count,
Some(Uint(5.into()))
);
}
}

View File

@@ -16,40 +16,39 @@
//! Authority params deserialization.
use uint::Uint;
use super::ValidatorSet;
use uint::Uint;
/// Authority params deserialization.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct BasicAuthorityParams {
/// Block duration.
pub duration_limit: Uint,
/// Valid authorities
pub validators: ValidatorSet,
/// Block duration.
pub duration_limit: Uint,
/// Valid authorities
pub validators: ValidatorSet,
}
/// Authority engine deserialization.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct BasicAuthority {
/// Ethash params.
pub params: BasicAuthorityParams,
/// Ethash params.
pub params: BasicAuthorityParams,
}
#[cfg(test)]
mod tests {
use serde_json;
use uint::Uint;
use ethereum_types::{U256, H160};
use hash::Address;
use spec::basic_authority::BasicAuthority;
use spec::validator_set::ValidatorSet;
use ethereum_types::{H160, U256};
use hash::Address;
use serde_json;
use spec::{basic_authority::BasicAuthority, validator_set::ValidatorSet};
use uint::Uint;
#[test]
fn basic_authority_deserialization() {
let s = r#"{
#[test]
fn basic_authority_deserialization() {
let s = r#"{
"params": {
"durationLimit": "0x0d",
"validators" : {
@@ -58,10 +57,12 @@ mod tests {
}
}"#;
let deserialized: BasicAuthority = serde_json::from_str(s).unwrap();
let deserialized: BasicAuthority = serde_json::from_str(s).unwrap();
assert_eq!(deserialized.params.duration_limit, Uint(U256::from(0x0d)));
let vs = ValidatorSet::List(vec![Address(H160::from("0xc6d9d2cd449a754c494264e1809c50e34d64562b"))]);
assert_eq!(deserialized.params.validators, vs);
}
assert_eq!(deserialized.params.duration_limit, Uint(U256::from(0x0d)));
let vs = ValidatorSet::List(vec![Address(H160::from(
"0xc6d9d2cd449a754c494264e1809c50e34d64562b",
))]);
assert_eq!(deserialized.params.validators, vs);
}
}

View File

@@ -16,43 +16,43 @@
//! Spec builtin deserialization.
use uint::Uint;
use std::collections::BTreeMap;
use uint::Uint;
/// Linear pricing.
#[derive(Debug, PartialEq, Deserialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct Linear {
/// Base price.
pub base: u64,
/// Price for word.
pub word: u64,
/// Base price.
pub base: u64,
/// Price for word.
pub word: u64,
}
/// Pricing for modular exponentiation.
#[derive(Debug, PartialEq, Deserialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct Modexp {
/// Price divisor.
pub divisor: u64,
/// Price divisor.
pub divisor: u64,
}
/// Pricing for constant alt_bn128 operations (ECADD and ECMUL)
#[derive(Debug, PartialEq, Deserialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct AltBn128ConstOperations {
/// price
pub price: u64,
/// price
pub price: u64,
}
/// Pricing for alt_bn128_pairing.
#[derive(Debug, PartialEq, Deserialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct AltBn128Pairing {
/// Base price.
pub base: u64,
/// Price per point pair.
pub pair: u64,
/// Base price.
pub base: u64,
/// Price per point pair.
pub pair: u64,
}
/// Pricing variants.
@@ -60,57 +60,66 @@ pub struct AltBn128Pairing {
#[serde(deny_unknown_fields)]
#[serde(rename_all = "snake_case")]
pub enum Pricing {
/// Pricing for Blake2 compression function: each call costs the same amount per round.
Blake2F {
/// Price per round of Blake2 compression function.
gas_per_round: u64,
},
/// Linear pricing.
Linear(Linear),
/// Pricing for modular exponentiation.
Modexp(Modexp),
/// Pricing for alt_bn128_pairing exponentiation.
AltBn128Pairing(AltBn128Pairing),
/// Pricing for constant alt_bn128 operations
AltBn128ConstOperations(AltBn128ConstOperations),
/// Pricing for Blake2 compression function: each call costs the same amount per round.
Blake2F {
/// Price per round of Blake2 compression function.
gas_per_round: u64,
},
/// Linear pricing.
Linear(Linear),
/// Pricing for modular exponentiation.
Modexp(Modexp),
/// Pricing for alt_bn128_pairing exponentiation.
AltBn128Pairing(AltBn128Pairing),
/// Pricing for constant alt_bn128 operations
AltBn128ConstOperations(AltBn128ConstOperations),
}
/// Builtin compability layer
#[derive(Debug, PartialEq, Deserialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct BuiltinCompat {
/// Builtin name.
name: String,
/// Builtin pricing.
pricing: PricingCompat,
/// Activation block.
activate_at: Option<Uint>,
/// Builtin name.
name: String,
/// Builtin pricing.
pricing: PricingCompat,
/// Activation block.
activate_at: Option<Uint>,
}
/// Spec builtin.
#[derive(Debug, PartialEq, Clone)]
pub struct Builtin {
/// Builtin name.
pub name: String,
/// Builtin pricing.
pub pricing: BTreeMap<u64, PricingAt>,
/// Builtin name.
pub name: String,
/// Builtin pricing.
pub pricing: BTreeMap<u64, PricingAt>,
}
impl From<BuiltinCompat> for Builtin {
fn from(legacy: BuiltinCompat) -> Self {
let pricing = match legacy.pricing {
PricingCompat::Single(pricing) => {
let mut map = BTreeMap::new();
let activate_at: u64 = legacy.activate_at.map_or(0, Into::into);
map.insert(activate_at, PricingAt { info: None, price: pricing });
map
}
PricingCompat::Multi(pricings) => {
pricings.into_iter().map(|(a, p)| (a.into(), p)).collect()
}
};
Self { name: legacy.name, pricing }
}
fn from(legacy: BuiltinCompat) -> Self {
let pricing = match legacy.pricing {
PricingCompat::Single(pricing) => {
let mut map = BTreeMap::new();
let activate_at: u64 = legacy.activate_at.map_or(0, Into::into);
map.insert(
activate_at,
PricingAt {
info: None,
price: pricing,
},
);
map
}
PricingCompat::Multi(pricings) => {
pricings.into_iter().map(|(a, p)| (a.into(), p)).collect()
}
};
Self {
name: legacy.name,
pricing,
}
}
}
/// Compability layer for different pricings
@@ -119,48 +128,54 @@ impl From<BuiltinCompat> for Builtin {
#[serde(deny_unknown_fields)]
#[serde(untagged)]
enum PricingCompat {
/// Single builtin
Single(Pricing),
/// Multiple builtins
Multi(BTreeMap<Uint, PricingAt>),
/// Single builtin
Single(Pricing),
/// Multiple builtins
Multi(BTreeMap<Uint, PricingAt>),
}
/// Price for a builtin, with the block number to activate it on
#[derive(Debug, PartialEq, Deserialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct PricingAt {
/// Description of the activation, e.g. "PunyPony HF, March 12, 2025".
pub info: Option<String>,
/// Builtin pricing.
pub price: Pricing,
/// Description of the activation, e.g. "PunyPony HF, March 12, 2025".
pub info: Option<String>,
/// Builtin pricing.
pub price: Pricing,
}
#[cfg(test)]
mod tests {
use serde_json;
use uint::Uint;
use super::{Builtin, BuiltinCompat, BTreeMap, Pricing, PricingAt, Linear, Modexp, AltBn128ConstOperations};
use macros::map;
use super::{
AltBn128ConstOperations, BTreeMap, Builtin, BuiltinCompat, Linear, Modexp, Pricing,
PricingAt,
};
use macros::map;
use serde_json;
use uint::Uint;
#[test]
fn builtin_deserialization() {
let s = r#"{
#[test]
fn builtin_deserialization() {
let s = r#"{
"name": "ecrecover",
"pricing": { "linear": { "base": 3000, "word": 0 } }
}"#;
let builtin: Builtin = serde_json::from_str::<BuiltinCompat>(s).unwrap().into();
assert_eq!(builtin.name, "ecrecover");
assert_eq!(builtin.pricing, map![
0 => PricingAt {
info: None,
price: Pricing::Linear(Linear { base: 3000, word: 0 })
}
]);
}
let builtin: Builtin = serde_json::from_str::<BuiltinCompat>(s).unwrap().into();
assert_eq!(builtin.name, "ecrecover");
assert_eq!(
builtin.pricing,
map![
0 => PricingAt {
info: None,
price: Pricing::Linear(Linear { base: 3000, word: 0 })
}
]
);
}
#[test]
fn deserialize_multiple_pricings() {
let s = r#"{
#[test]
fn deserialize_multiple_pricings() {
let s = r#"{
"name": "ecrecover",
"pricing": {
"0": {
@@ -172,40 +187,46 @@ mod tests {
}
}
}"#;
let builtin: Builtin = serde_json::from_str::<BuiltinCompat>(s).unwrap().into();
assert_eq!(builtin.name, "ecrecover");
assert_eq!(builtin.pricing, map![
0 => PricingAt {
info: None,
price: Pricing::Linear(Linear { base: 3000, word: 0 })
},
500 => PricingAt {
info: Some(String::from("enable fake EIP at block 500")),
price: Pricing::Linear(Linear { base: 10, word: 0 })
}
]);
}
let builtin: Builtin = serde_json::from_str::<BuiltinCompat>(s).unwrap().into();
assert_eq!(builtin.name, "ecrecover");
assert_eq!(
builtin.pricing,
map![
0 => PricingAt {
info: None,
price: Pricing::Linear(Linear { base: 3000, word: 0 })
},
500 => PricingAt {
info: Some(String::from("enable fake EIP at block 500")),
price: Pricing::Linear(Linear { base: 10, word: 0 })
}
]
);
}
#[test]
fn deserialization_blake2_f_builtin() {
let s = r#"{
#[test]
fn deserialization_blake2_f_builtin() {
let s = r#"{
"name": "blake2_f",
"activate_at": "0xffffff",
"pricing": { "blake2_f": { "gas_per_round": 123 } }
}"#;
let builtin: Builtin = serde_json::from_str::<BuiltinCompat>(s).unwrap().into();
assert_eq!(builtin.name, "blake2_f");
assert_eq!(builtin.pricing, map![
0xffffff => PricingAt {
info: None,
price: Pricing::Blake2F { gas_per_round: 123 }
}
]);
}
let builtin: Builtin = serde_json::from_str::<BuiltinCompat>(s).unwrap().into();
assert_eq!(builtin.name, "blake2_f");
assert_eq!(
builtin.pricing,
map![
0xffffff => PricingAt {
info: None,
price: Pricing::Blake2F { gas_per_round: 123 }
}
]
);
}
#[test]
fn deserialization_alt_bn128_const_operations() {
let s = r#"{
#[test]
fn deserialization_alt_bn128_const_operations() {
let s = r#"{
"name": "alt_bn128_mul",
"pricing": {
"100500": {
@@ -213,33 +234,39 @@ mod tests {
}
}
}"#;
let builtin: Builtin = serde_json::from_str::<BuiltinCompat>(s).unwrap().into();
assert_eq!(builtin.name, "alt_bn128_mul");
assert_eq!(builtin.pricing, map![
100500 => PricingAt {
info: None,
price: Pricing::AltBn128ConstOperations(AltBn128ConstOperations {
price: 123,
}),
}
]);
}
let builtin: Builtin = serde_json::from_str::<BuiltinCompat>(s).unwrap().into();
assert_eq!(builtin.name, "alt_bn128_mul");
assert_eq!(
builtin.pricing,
map![
100500 => PricingAt {
info: None,
price: Pricing::AltBn128ConstOperations(AltBn128ConstOperations {
price: 123,
}),
}
]
);
}
#[test]
fn activate_at() {
let s = r#"{
#[test]
fn activate_at() {
let s = r#"{
"name": "late_start",
"activate_at": 100000,
"pricing": { "modexp": { "divisor": 5 } }
}"#;
let builtin: Builtin = serde_json::from_str::<BuiltinCompat>(s).unwrap().into();
assert_eq!(builtin.name, "late_start");
assert_eq!(builtin.pricing, map![
100_000 => PricingAt {
info: None,
price: Pricing::Modexp(Modexp { divisor: 5 })
}
]);
}
let builtin: Builtin = serde_json::from_str::<BuiltinCompat>(s).unwrap().into();
assert_eq!(builtin.name, "late_start");
assert_eq!(
builtin.pricing,
map![
100_000 => PricingAt {
info: None,
price: Pricing::Modexp(Modexp { divisor: 5 })
}
]
);
}
}

View File

@@ -21,37 +21,37 @@ use std::num::NonZeroU64;
/// Clique params deserialization.
#[derive(Debug, PartialEq, Deserialize)]
pub struct CliqueParams {
/// period as defined in EIP
pub period: Option<u64>,
/// epoch length as defined in EIP
pub epoch: Option<NonZeroU64>
/// period as defined in EIP
pub period: Option<u64>,
/// epoch length as defined in EIP
pub epoch: Option<NonZeroU64>,
}
/// Clique engine deserialization.
#[derive(Debug, PartialEq, Deserialize)]
pub struct Clique {
/// CliqueEngine params
pub params: CliqueParams,
/// CliqueEngine params
pub params: CliqueParams,
}
#[cfg(test)]
mod tests {
use serde_json;
use uint::Uint;
use ethereum_types::U256;
use super::*;
use super::*;
use ethereum_types::U256;
use serde_json;
use uint::Uint;
#[test]
fn clique_deserialization() {
let s = r#"{
#[test]
fn clique_deserialization() {
let s = r#"{
"params": {
"period": 5,
"epoch": 30000
}
}"#;
let deserialized: Clique = serde_json::from_str(s).unwrap();
assert_eq!(deserialized.params.period, Some(5u64));
assert_eq!(deserialized.params.epoch, NonZeroU64::new(30000));
}
let deserialized: Clique = serde_json::from_str(s).unwrap();
assert_eq!(deserialized.params.period, Some(5u64));
assert_eq!(deserialized.params.epoch, NonZeroU64::new(30000));
}
}

View File

@@ -16,36 +16,36 @@
//! Engine deserialization.
use super::{Ethash, BasicAuthority, AuthorityRound, NullEngine, InstantSeal, Clique};
use super::{AuthorityRound, BasicAuthority, Clique, Ethash, InstantSeal, NullEngine};
/// Engine deserialization.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub enum Engine {
/// Null engine.
Null(NullEngine),
/// Instantly sealing engine.
InstantSeal(Option<InstantSeal>),
/// Ethash engine.
#[serde(rename = "Ethash")]
Ethash(Ethash),
/// BasicAuthority engine.
BasicAuthority(BasicAuthority),
/// AuthorityRound engine.
AuthorityRound(AuthorityRound),
/// Clique engine.
Clique(Clique)
/// Null engine.
Null(NullEngine),
/// Instantly sealing engine.
InstantSeal(Option<InstantSeal>),
/// Ethash engine.
#[serde(rename = "Ethash")]
Ethash(Ethash),
/// BasicAuthority engine.
BasicAuthority(BasicAuthority),
/// AuthorityRound engine.
AuthorityRound(AuthorityRound),
/// Clique engine.
Clique(Clique),
}
#[cfg(test)]
mod tests {
use serde_json;
use spec::Engine;
use serde_json;
use spec::Engine;
#[test]
fn engine_deserialization() {
let s = r#"{
#[test]
fn engine_deserialization() {
let s = r#"{
"null": {
"params": {
"blockReward": "0x0d"
@@ -53,33 +53,33 @@ mod tests {
}
}"#;
let deserialized: Engine = serde_json::from_str(s).unwrap();
match deserialized {
Engine::Null(_) => {}, // unit test in its own file.
_ => panic!(),
}
let deserialized: Engine = serde_json::from_str(s).unwrap();
match deserialized {
Engine::Null(_) => {} // unit test in its own file.
_ => panic!(),
}
let s = r#"{
let s = r#"{
"instantSeal": {"params": {}}
}"#;
let deserialized: Engine = serde_json::from_str(s).unwrap();
match deserialized {
Engine::InstantSeal(_) => {}, // instant seal is unit tested in its own file.
_ => panic!(),
};
let deserialized: Engine = serde_json::from_str(s).unwrap();
match deserialized {
Engine::InstantSeal(_) => {} // instant seal is unit tested in its own file.
_ => panic!(),
};
let s = r#"{
let s = r#"{
"instantSeal": null
}"#;
let deserialized: Engine = serde_json::from_str(s).unwrap();
match deserialized {
Engine::InstantSeal(_) => {}, // instant seal is unit tested in its own file.
_ => panic!(),
};
let deserialized: Engine = serde_json::from_str(s).unwrap();
match deserialized {
Engine::InstantSeal(_) => {} // instant seal is unit tested in its own file.
_ => panic!(),
};
let s = r#"{
let s = r#"{
"Ethash": {
"params": {
"minimumDifficulty": "0x020000",
@@ -93,13 +93,13 @@ mod tests {
}
}"#;
let deserialized: Engine = serde_json::from_str(s).unwrap();
match deserialized {
Engine::Ethash(_) => {}, // ethash is unit tested in its own file.
_ => panic!(),
};
let deserialized: Engine = serde_json::from_str(s).unwrap();
match deserialized {
Engine::Ethash(_) => {} // ethash is unit tested in its own file.
_ => panic!(),
};
let s = r#"{
let s = r#"{
"basicAuthority": {
"params": {
"durationLimit": "0x0d",
@@ -109,13 +109,13 @@ mod tests {
}
}
}"#;
let deserialized: Engine = serde_json::from_str(s).unwrap();
match deserialized {
Engine::BasicAuthority(_) => {}, // basicAuthority is unit tested in its own file.
_ => panic!(),
};
let deserialized: Engine = serde_json::from_str(s).unwrap();
match deserialized {
Engine::BasicAuthority(_) => {} // basicAuthority is unit tested in its own file.
_ => panic!(),
};
let s = r#"{
let s = r#"{
"authorityRound": {
"params": {
"stepDuration": "0x02",
@@ -127,13 +127,13 @@ mod tests {
}
}
}"#;
let deserialized: Engine = serde_json::from_str(s).unwrap();
match deserialized {
Engine::AuthorityRound(_) => {}, // AuthorityRound is unit tested in its own file.
_ => panic!(),
};
let deserialized: Engine = serde_json::from_str(s).unwrap();
match deserialized {
Engine::AuthorityRound(_) => {} // AuthorityRound is unit tested in its own file.
_ => panic!(),
};
let s = r#"{
let s = r#"{
"clique": {
"params": {
"period": 15,
@@ -141,10 +141,10 @@ mod tests {
}
}
}"#;
let deserialized: Engine = serde_json::from_str(s).unwrap();
match deserialized {
Engine::Clique(_) => {}, // Clique is unit tested in its own file.
_ => panic!(),
};
}
let deserialized: Engine = serde_json::from_str(s).unwrap();
match deserialized {
Engine::Clique(_) => {} // Clique is unit tested in its own file.
_ => panic!(),
};
}
}

View File

@@ -16,18 +16,18 @@
//! Ethash params deserialization.
use std::collections::BTreeMap;
use uint::{self, Uint};
use bytes::Bytes;
use hash::Address;
use std::collections::BTreeMap;
use uint::{self, Uint};
/// Deserializable doppelganger of block rewards for EthashParams
#[derive(Clone, Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(untagged)]
pub enum BlockReward {
Single(Uint),
Multi(BTreeMap<Uint, Uint>),
Single(Uint),
Multi(BTreeMap<Uint, Uint>),
}
/// Deserializable doppelganger of EthashParams.
@@ -35,90 +35,90 @@ pub enum BlockReward {
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct EthashParams {
/// See main EthashParams docs.
#[serde(deserialize_with="uint::validate_non_zero")]
pub minimum_difficulty: Uint,
/// See main EthashParams docs.
#[serde(deserialize_with="uint::validate_non_zero")]
pub difficulty_bound_divisor: Uint,
/// See main EthashParams docs.
#[serde(default, deserialize_with="uint::validate_optional_non_zero")]
pub difficulty_increment_divisor: Option<Uint>,
/// See main EthashParams docs.
#[serde(default, deserialize_with="uint::validate_optional_non_zero")]
pub metropolis_difficulty_increment_divisor: Option<Uint>,
/// See main EthashParams docs.
pub duration_limit: Option<Uint>,
/// See main EthashParams docs.
#[serde(deserialize_with = "uint::validate_non_zero")]
pub minimum_difficulty: Uint,
/// See main EthashParams docs.
#[serde(deserialize_with = "uint::validate_non_zero")]
pub difficulty_bound_divisor: Uint,
/// See main EthashParams docs.
#[serde(default, deserialize_with = "uint::validate_optional_non_zero")]
pub difficulty_increment_divisor: Option<Uint>,
/// See main EthashParams docs.
#[serde(default, deserialize_with = "uint::validate_optional_non_zero")]
pub metropolis_difficulty_increment_divisor: Option<Uint>,
/// See main EthashParams docs.
pub duration_limit: Option<Uint>,
/// See main EthashParams docs.
pub homestead_transition: Option<Uint>,
/// Reward per block in wei.
pub block_reward: Option<BlockReward>,
/// Block at which the block reward contract should start being used.
pub block_reward_contract_transition: Option<Uint>,
/// Block reward contract address (setting the block reward contract
/// overrides all other block reward parameters).
pub block_reward_contract_address: Option<Address>,
/// Block reward code. This overrides the block reward contract address.
pub block_reward_contract_code: Option<Bytes>,
/// See main EthashParams docs.
pub homestead_transition: Option<Uint>,
/// Reward per block in wei.
pub block_reward: Option<BlockReward>,
/// Block at which the block reward contract should start being used.
pub block_reward_contract_transition: Option<Uint>,
/// Block reward contract address (setting the block reward contract
/// overrides all other block reward parameters).
pub block_reward_contract_address: Option<Address>,
/// Block reward code. This overrides the block reward contract address.
pub block_reward_contract_code: Option<Bytes>,
/// See main EthashParams docs.
pub dao_hardfork_transition: Option<Uint>,
/// See main EthashParams docs.
pub dao_hardfork_beneficiary: Option<Address>,
/// See main EthashParams docs.
pub dao_hardfork_accounts: Option<Vec<Address>>,
/// See main EthashParams docs.
pub dao_hardfork_transition: Option<Uint>,
/// See main EthashParams docs.
pub dao_hardfork_beneficiary: Option<Address>,
/// See main EthashParams docs.
pub dao_hardfork_accounts: Option<Vec<Address>>,
/// See main EthashParams docs.
pub difficulty_hardfork_transition: Option<Uint>,
/// See main EthashParams docs.
#[serde(default, deserialize_with="uint::validate_optional_non_zero")]
pub difficulty_hardfork_bound_divisor: Option<Uint>,
/// See main EthashParams docs.
pub bomb_defuse_transition: Option<Uint>,
/// See main EthashParams docs.
pub difficulty_hardfork_transition: Option<Uint>,
/// See main EthashParams docs.
#[serde(default, deserialize_with = "uint::validate_optional_non_zero")]
pub difficulty_hardfork_bound_divisor: Option<Uint>,
/// See main EthashParams docs.
pub bomb_defuse_transition: Option<Uint>,
/// See main EthashParams docs.
pub eip100b_transition: Option<Uint>,
/// See main EthashParams docs.
pub eip100b_transition: Option<Uint>,
/// See main EthashParams docs.
pub ecip1010_pause_transition: Option<Uint>,
/// See main EthashParams docs.
pub ecip1010_continue_transition: Option<Uint>,
/// See main EthashParams docs.
pub ecip1010_pause_transition: Option<Uint>,
/// See main EthashParams docs.
pub ecip1010_continue_transition: Option<Uint>,
/// See main EthashParams docs.
pub ecip1017_era_rounds: Option<Uint>,
/// See main EthashParams docs.
pub ecip1017_era_rounds: Option<Uint>,
/// Delays of difficulty bombs.
pub difficulty_bomb_delays: Option<BTreeMap<Uint, Uint>>,
/// Delays of difficulty bombs.
pub difficulty_bomb_delays: Option<BTreeMap<Uint, Uint>>,
/// EXPIP-2 block height
pub expip2_transition: Option<Uint>,
/// EXPIP-2 duration limit
pub expip2_duration_limit: Option<Uint>,
/// Block to transition to progpow
#[serde(rename="progpowTransition")]
pub progpow_transition: Option<Uint>,
/// EXPIP-2 block height
pub expip2_transition: Option<Uint>,
/// EXPIP-2 duration limit
pub expip2_duration_limit: Option<Uint>,
/// Block to transition to progpow
#[serde(rename = "progpowTransition")]
pub progpow_transition: Option<Uint>,
}
/// Ethash engine deserialization.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Ethash {
/// Ethash params.
pub params: EthashParams,
/// Ethash params.
pub params: EthashParams,
}
#[cfg(test)]
mod tests {
use serde_json;
use uint::Uint;
use ethereum_types::{H160, U256};
use hash::Address;
use spec::ethash::{Ethash, EthashParams, BlockReward};
use ethereum_types::{H160, U256};
use hash::Address;
use serde_json;
use spec::ethash::{BlockReward, Ethash, EthashParams};
use uint::Uint;
#[test]
fn ethash_deserialization() {
let s = r#"{
#[test]
fn ethash_deserialization() {
let s = r#"{
"params": {
"minimumDifficulty": "0x020000",
"difficultyBoundDivisor": "0x0800",
@@ -156,109 +156,117 @@ mod tests {
}
}"#;
let deserialized: Ethash = serde_json::from_str(s).unwrap();
let deserialized: Ethash = serde_json::from_str(s).unwrap();
assert_eq!(deserialized, Ethash {
params: EthashParams {
minimum_difficulty: Uint(U256::from(0x020000)),
difficulty_bound_divisor: Uint(U256::from(0x0800)),
difficulty_increment_divisor: None,
metropolis_difficulty_increment_divisor: None,
duration_limit: Some(Uint(U256::from(0x0d))),
homestead_transition: Some(Uint(U256::from(0x42))),
block_reward: Some(BlockReward::Single(Uint(U256::from(0x100)))),
block_reward_contract_address: None,
block_reward_contract_code: None,
block_reward_contract_transition: None,
dao_hardfork_transition: Some(Uint(U256::from(0x08))),
dao_hardfork_beneficiary: Some(Address(H160::from("0xabcabcabcabcabcabcabcabcabcabcabcabcabca"))),
dao_hardfork_accounts: Some(vec![
Address(H160::from("0x304a554a310c7e546dfe434669c62820b7d83490")),
Address(H160::from("0x914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79")),
Address(H160::from("0xfe24cdd8648121a43a7c86d289be4dd2951ed49f")),
Address(H160::from("0x17802f43a0137c506ba92291391a8a8f207f487d")),
Address(H160::from("0xb136707642a4ea12fb4bae820f03d2562ebff487")),
Address(H160::from("0xdbe9b615a3ae8709af8b93336ce9b477e4ac0940")),
Address(H160::from("0xf14c14075d6c4ed84b86798af0956deef67365b5")),
Address(H160::from("0xca544e5c4687d109611d0f8f928b53a25af72448")),
Address(H160::from("0xaeeb8ff27288bdabc0fa5ebb731b6f409507516c")),
Address(H160::from("0xcbb9d3703e651b0d496cdefb8b92c25aeb2171f7")),
Address(H160::from("0xaccc230e8a6e5be9160b8cdf2864dd2a001c28b6")),
Address(H160::from("0x2b3455ec7fedf16e646268bf88846bd7a2319bb2")),
Address(H160::from("0x4613f3bca5c44ea06337a9e439fbc6d42e501d0a")),
Address(H160::from("0xd343b217de44030afaa275f54d31a9317c7f441e")),
Address(H160::from("0x84ef4b2357079cd7a7c69fd7a37cd0609a679106")),
Address(H160::from("0xda2fef9e4a3230988ff17df2165440f37e8b1708")),
Address(H160::from("0xf4c64518ea10f995918a454158c6b61407ea345c")),
Address(H160::from("0x7602b46df5390e432ef1c307d4f2c9ff6d65cc97")),
Address(H160::from("0xbb9bc244d798123fde783fcc1c72d3bb8c189413")),
Address(H160::from("0x807640a13483f8ac783c557fcdf27be11ea4ac7a")),
]),
difficulty_hardfork_transition: Some(Uint(U256::from(0x59d9))),
difficulty_hardfork_bound_divisor: Some(Uint(U256::from(0x0200))),
bomb_defuse_transition: Some(Uint(U256::from(0x41))),
eip100b_transition: Some(Uint(U256::from(0x42))),
ecip1010_pause_transition: None,
ecip1010_continue_transition: None,
ecip1017_era_rounds: None,
expip2_transition: None,
expip2_duration_limit: None,
progpow_transition: None,
difficulty_bomb_delays: None,
}
});
}
assert_eq!(
deserialized,
Ethash {
params: EthashParams {
minimum_difficulty: Uint(U256::from(0x020000)),
difficulty_bound_divisor: Uint(U256::from(0x0800)),
difficulty_increment_divisor: None,
metropolis_difficulty_increment_divisor: None,
duration_limit: Some(Uint(U256::from(0x0d))),
homestead_transition: Some(Uint(U256::from(0x42))),
block_reward: Some(BlockReward::Single(Uint(U256::from(0x100)))),
block_reward_contract_address: None,
block_reward_contract_code: None,
block_reward_contract_transition: None,
dao_hardfork_transition: Some(Uint(U256::from(0x08))),
dao_hardfork_beneficiary: Some(Address(H160::from(
"0xabcabcabcabcabcabcabcabcabcabcabcabcabca"
))),
dao_hardfork_accounts: Some(vec![
Address(H160::from("0x304a554a310c7e546dfe434669c62820b7d83490")),
Address(H160::from("0x914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79")),
Address(H160::from("0xfe24cdd8648121a43a7c86d289be4dd2951ed49f")),
Address(H160::from("0x17802f43a0137c506ba92291391a8a8f207f487d")),
Address(H160::from("0xb136707642a4ea12fb4bae820f03d2562ebff487")),
Address(H160::from("0xdbe9b615a3ae8709af8b93336ce9b477e4ac0940")),
Address(H160::from("0xf14c14075d6c4ed84b86798af0956deef67365b5")),
Address(H160::from("0xca544e5c4687d109611d0f8f928b53a25af72448")),
Address(H160::from("0xaeeb8ff27288bdabc0fa5ebb731b6f409507516c")),
Address(H160::from("0xcbb9d3703e651b0d496cdefb8b92c25aeb2171f7")),
Address(H160::from("0xaccc230e8a6e5be9160b8cdf2864dd2a001c28b6")),
Address(H160::from("0x2b3455ec7fedf16e646268bf88846bd7a2319bb2")),
Address(H160::from("0x4613f3bca5c44ea06337a9e439fbc6d42e501d0a")),
Address(H160::from("0xd343b217de44030afaa275f54d31a9317c7f441e")),
Address(H160::from("0x84ef4b2357079cd7a7c69fd7a37cd0609a679106")),
Address(H160::from("0xda2fef9e4a3230988ff17df2165440f37e8b1708")),
Address(H160::from("0xf4c64518ea10f995918a454158c6b61407ea345c")),
Address(H160::from("0x7602b46df5390e432ef1c307d4f2c9ff6d65cc97")),
Address(H160::from("0xbb9bc244d798123fde783fcc1c72d3bb8c189413")),
Address(H160::from("0x807640a13483f8ac783c557fcdf27be11ea4ac7a")),
]),
difficulty_hardfork_transition: Some(Uint(U256::from(0x59d9))),
difficulty_hardfork_bound_divisor: Some(Uint(U256::from(0x0200))),
bomb_defuse_transition: Some(Uint(U256::from(0x41))),
eip100b_transition: Some(Uint(U256::from(0x42))),
ecip1010_pause_transition: None,
ecip1010_continue_transition: None,
ecip1017_era_rounds: None,
expip2_transition: None,
expip2_duration_limit: None,
progpow_transition: None,
difficulty_bomb_delays: None,
}
}
);
}
#[test]
fn ethash_deserialization_missing_optionals() {
let s = r#"{
#[test]
fn ethash_deserialization_missing_optionals() {
let s = r#"{
"params": {
"difficultyBoundDivisor": "0x0800",
"minimumDifficulty": "0x020000"
}
}"#;
let deserialized: Ethash = serde_json::from_str(s).unwrap();
assert_eq!(deserialized, Ethash {
params: EthashParams {
minimum_difficulty: Uint(U256::from(0x020000)),
difficulty_bound_divisor: Uint(U256::from(0x0800)),
difficulty_increment_divisor: None,
metropolis_difficulty_increment_divisor: None,
duration_limit: None,
homestead_transition: None,
block_reward: None,
block_reward_contract_address: None,
block_reward_contract_code: None,
block_reward_contract_transition: None,
dao_hardfork_transition: None,
dao_hardfork_beneficiary: None,
dao_hardfork_accounts: None,
difficulty_hardfork_transition: None,
difficulty_hardfork_bound_divisor: None,
bomb_defuse_transition: None,
eip100b_transition: None,
ecip1010_pause_transition: None,
ecip1010_continue_transition: None,
ecip1017_era_rounds: None,
expip2_transition: None,
expip2_duration_limit: None,
progpow_transition: None,
difficulty_bomb_delays: None,
}
});
}
let deserialized: Ethash = serde_json::from_str(s).unwrap();
assert_eq!(
deserialized,
Ethash {
params: EthashParams {
minimum_difficulty: Uint(U256::from(0x020000)),
difficulty_bound_divisor: Uint(U256::from(0x0800)),
difficulty_increment_divisor: None,
metropolis_difficulty_increment_divisor: None,
duration_limit: None,
homestead_transition: None,
block_reward: None,
block_reward_contract_address: None,
block_reward_contract_code: None,
block_reward_contract_transition: None,
dao_hardfork_transition: None,
dao_hardfork_beneficiary: None,
dao_hardfork_accounts: None,
difficulty_hardfork_transition: None,
difficulty_hardfork_bound_divisor: None,
bomb_defuse_transition: None,
eip100b_transition: None,
ecip1010_pause_transition: None,
ecip1010_continue_transition: None,
ecip1017_era_rounds: None,
expip2_transition: None,
expip2_duration_limit: None,
progpow_transition: None,
difficulty_bomb_delays: None,
}
}
);
}
#[test]
#[should_panic(expected = "a non-zero value")]
fn test_zero_value_divisor() {
let s = r#"{
#[test]
#[should_panic(expected = "a non-zero value")]
fn test_zero_value_divisor() {
let s = r#"{
"params": {
"difficultyBoundDivisor": "0x0",
"minimumDifficulty": "0x020000"
}
}"#;
let _deserialized: Ethash = serde_json::from_str(s).unwrap();
}
let _deserialized: Ethash = serde_json::from_str(s).unwrap();
}
}

View File

@@ -16,55 +16,54 @@
//! Spec genesis deserialization.
use uint::{Uint, self};
use hash::{Address, H256};
use bytes::Bytes;
use hash::{Address, H256};
use spec::Seal;
use uint::{self, Uint};
/// Spec genesis.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct Genesis {
/// Seal.
pub seal: Seal,
/// Difficulty.
pub difficulty: Uint,
/// Block author, defaults to 0.
pub author: Option<Address>,
/// Block timestamp, defaults to 0.
pub timestamp: Option<Uint>,
/// Parent hash, defaults to 0.
pub parent_hash: Option<H256>,
/// Gas limit.
#[serde(deserialize_with="uint::validate_non_zero")]
pub gas_limit: Uint,
/// Transactions root.
pub transactions_root: Option<H256>,
/// Receipts root.
pub receipts_root: Option<H256>,
/// State root.
pub state_root: Option<H256>,
/// Gas used.
pub gas_used: Option<Uint>,
/// Extra data.
pub extra_data: Option<Bytes>,
/// Seal.
pub seal: Seal,
/// Difficulty.
pub difficulty: Uint,
/// Block author, defaults to 0.
pub author: Option<Address>,
/// Block timestamp, defaults to 0.
pub timestamp: Option<Uint>,
/// Parent hash, defaults to 0.
pub parent_hash: Option<H256>,
/// Gas limit.
#[serde(deserialize_with = "uint::validate_non_zero")]
pub gas_limit: Uint,
/// Transactions root.
pub transactions_root: Option<H256>,
/// Receipts root.
pub receipts_root: Option<H256>,
/// State root.
pub state_root: Option<H256>,
/// Gas used.
pub gas_used: Option<Uint>,
/// Extra data.
pub extra_data: Option<Bytes>,
}
#[cfg(test)]
mod tests {
use serde_json;
use bytes::Bytes;
use uint::Uint;
use ethereum_types::{U256, H160, H64 as Eth64, H256 as Eth256};
use hash::{H64, H256, Address};
use spec::genesis::Genesis;
use spec::{Ethereum, Seal};
use std::str::FromStr;
use bytes::Bytes;
use ethereum_types::{H160, H256 as Eth256, H64 as Eth64, U256};
use hash::{Address, H256, H64};
use serde_json;
use spec::{genesis::Genesis, Ethereum, Seal};
use std::str::FromStr;
use uint::Uint;
#[test]
fn genesis_deserialization() {
let s = r#"{
#[test]
fn genesis_deserialization() {
let s = r#"{
"difficulty": "0x400000000",
"seal": {
"ethereum": {
@@ -79,22 +78,38 @@ mod tests {
"gasLimit": "0x1388",
"stateRoot": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544"
}"#;
let deserialized: Genesis = serde_json::from_str(s).unwrap();
assert_eq!(deserialized, Genesis {
seal: Seal::Ethereum(Ethereum {
nonce: H64(Eth64::from("0x00006d6f7264656e")),
mix_hash: H256(Eth256::from("0x0000000000000000000000000000000000000000000000000000000000000000"))
}),
difficulty: Uint(U256::from(0x400000000u64)),
author: Some(Address(H160::from("0x1000000000000000000000000000000000000001"))),
timestamp: Some(Uint(U256::from(0x07))),
parent_hash: Some(H256(Eth256::from("0x9000000000000000000000000000000000000000000000000000000000000000"))),
gas_limit: Uint(U256::from(0x1388)),
transactions_root: None,
receipts_root: None,
state_root: Some(H256(Eth256::from("0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544"))),
gas_used: None,
extra_data: Some(Bytes::from_str("0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa").unwrap()),
});
}
let deserialized: Genesis = serde_json::from_str(s).unwrap();
assert_eq!(
deserialized,
Genesis {
seal: Seal::Ethereum(Ethereum {
nonce: H64(Eth64::from("0x00006d6f7264656e")),
mix_hash: H256(Eth256::from(
"0x0000000000000000000000000000000000000000000000000000000000000000"
))
}),
difficulty: Uint(U256::from(0x400000000u64)),
author: Some(Address(H160::from(
"0x1000000000000000000000000000000000000001"
))),
timestamp: Some(Uint(U256::from(0x07))),
parent_hash: Some(H256(Eth256::from(
"0x9000000000000000000000000000000000000000000000000000000000000000"
))),
gas_limit: Uint(U256::from(0x1388)),
transactions_root: None,
receipts_root: None,
state_root: Some(H256(Eth256::from(
"0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544"
))),
gas_used: None,
extra_data: Some(
Bytes::from_str(
"0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa"
)
.unwrap()
),
}
);
}
}

View File

@@ -24,26 +24,26 @@ use uint::Uint;
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct HardcodedSync {
/// Hexadecimal of the RLP encoding of the header of the block to start synchronization from.
pub header: String,
/// Total difficulty including the block of `header`.
pub total_difficulty: Uint,
/// Ordered trie roots of blocks before and including `header`.
#[serde(rename = "CHTs")]
pub chts: Vec<H256>,
/// Hexadecimal of the RLP encoding of the header of the block to start synchronization from.
pub header: String,
/// Total difficulty including the block of `header`.
pub total_difficulty: Uint,
/// Ordered trie roots of blocks before and including `header`.
#[serde(rename = "CHTs")]
pub chts: Vec<H256>,
}
#[cfg(test)]
mod tests {
use serde_json;
use uint::Uint;
use ethereum_types::{U256, H256 as Eth256};
use hash::H256;
use spec::hardcoded_sync::HardcodedSync;
use ethereum_types::{H256 as Eth256, U256};
use hash::H256;
use serde_json;
use spec::hardcoded_sync::HardcodedSync;
use uint::Uint;
#[test]
fn hardcoded_sync_deserialization() {
let s = r#"{
#[test]
fn hardcoded_sync_deserialization() {
let s = r#"{
"header": "f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23",
"totalDifficulty": "0x400000000",
"CHTs": [
@@ -51,8 +51,8 @@ mod tests {
"0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544"
]
}"#;
let deserialized: HardcodedSync = serde_json::from_str(s).unwrap();
assert_eq!(deserialized, HardcodedSync {
let deserialized: HardcodedSync = serde_json::from_str(s).unwrap();
assert_eq!(deserialized, HardcodedSync {
header: String::from("f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23"),
total_difficulty: Uint(U256::from(0x400000000u64)),
chts: vec![
@@ -60,5 +60,5 @@ mod tests {
H256(Eth256::from("0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544")),
]
});
}
}
}

View File

@@ -21,15 +21,15 @@
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct InstantSealParams {
/// Whether to enable millisecond timestamp.
#[serde(default)]
pub millisecond_timestamp: bool,
/// Whether to enable millisecond timestamp.
#[serde(default)]
pub millisecond_timestamp: bool,
}
/// Instant seal engine descriptor.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct InstantSeal {
/// Instant seal parameters.
pub params: InstantSealParams,
/// Instant seal parameters.
pub params: InstantSealParams,
}

View File

@@ -17,35 +17,37 @@
//! Spec deserialization.
pub mod account;
pub mod builtin;
pub mod genesis;
pub mod params;
pub mod spec;
pub mod seal;
pub mod engine;
pub mod state;
pub mod ethash;
pub mod validator_set;
pub mod basic_authority;
pub mod authority_round;
pub mod null_engine;
pub mod instant_seal;
pub mod hardcoded_sync;
pub mod basic_authority;
pub mod builtin;
pub mod clique;
pub mod engine;
pub mod ethash;
pub mod genesis;
pub mod hardcoded_sync;
pub mod instant_seal;
pub mod null_engine;
pub mod params;
pub mod seal;
pub mod spec;
pub mod state;
pub mod validator_set;
pub use self::account::Account;
pub use self::builtin::{Builtin, Pricing, Linear};
pub use self::genesis::Genesis;
pub use self::params::Params;
pub use self::spec::{Spec, ForkSpec};
pub use self::seal::{Seal, Ethereum, AuthorityRoundSeal, TendermintSeal};
pub use self::engine::Engine;
pub use self::state::State;
pub use self::ethash::{Ethash, EthashParams, BlockReward};
pub use self::validator_set::ValidatorSet;
pub use self::basic_authority::{BasicAuthority, BasicAuthorityParams};
pub use self::authority_round::{AuthorityRound, AuthorityRoundParams};
pub use self::clique::{Clique, CliqueParams};
pub use self::null_engine::{NullEngine, NullEngineParams};
pub use self::instant_seal::{InstantSeal, InstantSealParams};
pub use self::hardcoded_sync::HardcodedSync;
pub use self::{
account::Account,
authority_round::{AuthorityRound, AuthorityRoundParams},
basic_authority::{BasicAuthority, BasicAuthorityParams},
builtin::{Builtin, Linear, Pricing},
clique::{Clique, CliqueParams},
engine::Engine,
ethash::{BlockReward, Ethash, EthashParams},
genesis::Genesis,
hardcoded_sync::HardcodedSync,
instant_seal::{InstantSeal, InstantSealParams},
null_engine::{NullEngine, NullEngineParams},
params::Params,
seal::{AuthorityRoundSeal, Ethereum, Seal, TendermintSeal},
spec::{ForkSpec, Spec},
state::State,
validator_set::ValidatorSet,
};

View File

@@ -23,36 +23,39 @@ use uint::Uint;
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct NullEngineParams {
/// Block reward.
pub block_reward: Option<Uint>,
/// Immediate finalization.
pub immediate_finalization: Option<bool>
/// Block reward.
pub block_reward: Option<Uint>,
/// Immediate finalization.
pub immediate_finalization: Option<bool>,
}
/// Null engine descriptor
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct NullEngine {
/// Ethash params.
pub params: NullEngineParams,
/// Ethash params.
pub params: NullEngineParams,
}
#[cfg(test)]
mod tests {
use serde_json;
use uint::Uint;
use ethereum_types::U256;
use super::*;
use super::*;
use ethereum_types::U256;
use serde_json;
use uint::Uint;
#[test]
fn null_engine_deserialization() {
let s = r#"{
#[test]
fn null_engine_deserialization() {
let s = r#"{
"params": {
"blockReward": "0x0d"
}
}"#;
let deserialized: NullEngine = serde_json::from_str(s).unwrap();
assert_eq!(deserialized.params.block_reward, Some(Uint(U256::from(0x0d))));
}
let deserialized: NullEngine = serde_json::from_str(s).unwrap();
assert_eq!(
deserialized.params.block_reward,
Some(Uint(U256::from(0x0d)))
);
}
}

View File

@@ -16,136 +16,136 @@
//! Spec params deserialization.
use uint::{self, Uint};
use hash::{H256, Address};
use bytes::Bytes;
use hash::{Address, H256};
use uint::{self, Uint};
/// Spec params.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct Params {
/// Account start nonce, defaults to 0.
pub account_start_nonce: Option<Uint>,
/// Maximum size of extra data.
pub maximum_extra_data_size: Uint,
/// Minimum gas limit.
pub min_gas_limit: Uint,
/// Account start nonce, defaults to 0.
pub account_start_nonce: Option<Uint>,
/// Maximum size of extra data.
pub maximum_extra_data_size: Uint,
/// Minimum gas limit.
pub min_gas_limit: Uint,
/// Network id.
#[serde(rename = "networkID")]
pub network_id: Uint,
/// Chain id.
#[serde(rename = "chainID")]
pub chain_id: Option<Uint>,
/// Network id.
#[serde(rename = "networkID")]
pub network_id: Uint,
/// Chain id.
#[serde(rename = "chainID")]
pub chain_id: Option<Uint>,
/// Name of the main ("eth") subprotocol.
pub subprotocol_name: Option<String>,
/// Name of the main ("eth") subprotocol.
pub subprotocol_name: Option<String>,
/// Option fork block number to check.
pub fork_block: Option<Uint>,
/// Expected fork block hash.
#[serde(rename = "forkCanonHash")]
pub fork_hash: Option<H256>,
/// Option fork block number to check.
pub fork_block: Option<Uint>,
/// Expected fork block hash.
#[serde(rename = "forkCanonHash")]
pub fork_hash: Option<H256>,
/// See main EthashParams docs.
pub eip150_transition: Option<Uint>,
/// See main EthashParams docs.
pub eip150_transition: Option<Uint>,
/// See main EthashParams docs.
pub eip160_transition: Option<Uint>,
/// See main EthashParams docs.
pub eip160_transition: Option<Uint>,
/// See main EthashParams docs.
pub eip161abc_transition: Option<Uint>,
/// See main EthashParams docs.
pub eip161d_transition: Option<Uint>,
/// See main EthashParams docs.
pub eip161abc_transition: Option<Uint>,
/// See main EthashParams docs.
pub eip161d_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip98_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip155_transition: Option<Uint>,
/// See `CommonParams` docs.
pub validate_chain_id_transition: Option<Uint>,
/// See `CommonParams` docs.
pub validate_receipts_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip140_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip210_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip210_contract_address: Option<Address>,
/// See `CommonParams` docs.
pub eip210_contract_code: Option<Bytes>,
/// See `CommonParams` docs.
pub eip210_contract_gas: Option<Uint>,
/// See `CommonParams` docs.
pub eip211_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip145_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip214_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip658_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip1052_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip1283_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip1283_disable_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip1283_reenable_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip1014_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip1706_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip1344_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip1884_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip2028_transition: Option<Uint>,
/// See `CommonParams` docs.
pub dust_protection_transition: Option<Uint>,
/// See `CommonParams` docs.
pub nonce_cap_increment: Option<Uint>,
/// See `CommonParams` docs.
pub remove_dust_contracts : Option<bool>,
/// See `CommonParams` docs.
#[serde(deserialize_with="uint::validate_non_zero")]
pub gas_limit_bound_divisor: Uint,
/// See `CommonParams` docs.
pub registrar: Option<Address>,
/// Apply reward flag
pub apply_reward: Option<bool>,
/// Node permission contract address.
pub node_permission_contract: Option<Address>,
/// See main EthashParams docs.
pub max_code_size: Option<Uint>,
/// Maximum size of transaction RLP payload.
pub max_transaction_size: Option<Uint>,
/// See main EthashParams docs.
pub max_code_size_transition: Option<Uint>,
/// Transaction permission contract address.
pub transaction_permission_contract: Option<Address>,
/// Block at which the transaction permission contract should start being used.
pub transaction_permission_contract_transition: Option<Uint>,
/// Wasm activation block height, if not activated from start
pub wasm_activation_transition: Option<Uint>,
/// KIP4 activiation block height.
pub kip4_transition: Option<Uint>,
/// KIP6 activiation block height.
pub kip6_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip98_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip155_transition: Option<Uint>,
/// See `CommonParams` docs.
pub validate_chain_id_transition: Option<Uint>,
/// See `CommonParams` docs.
pub validate_receipts_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip140_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip210_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip210_contract_address: Option<Address>,
/// See `CommonParams` docs.
pub eip210_contract_code: Option<Bytes>,
/// See `CommonParams` docs.
pub eip210_contract_gas: Option<Uint>,
/// See `CommonParams` docs.
pub eip211_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip145_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip214_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip658_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip1052_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip1283_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip1283_disable_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip1283_reenable_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip1014_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip1706_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip1344_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip1884_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip2028_transition: Option<Uint>,
/// See `CommonParams` docs.
pub dust_protection_transition: Option<Uint>,
/// See `CommonParams` docs.
pub nonce_cap_increment: Option<Uint>,
/// See `CommonParams` docs.
pub remove_dust_contracts: Option<bool>,
/// See `CommonParams` docs.
#[serde(deserialize_with = "uint::validate_non_zero")]
pub gas_limit_bound_divisor: Uint,
/// See `CommonParams` docs.
pub registrar: Option<Address>,
/// Apply reward flag
pub apply_reward: Option<bool>,
/// Node permission contract address.
pub node_permission_contract: Option<Address>,
/// See main EthashParams docs.
pub max_code_size: Option<Uint>,
/// Maximum size of transaction RLP payload.
pub max_transaction_size: Option<Uint>,
/// See main EthashParams docs.
pub max_code_size_transition: Option<Uint>,
/// Transaction permission contract address.
pub transaction_permission_contract: Option<Address>,
/// Block at which the transaction permission contract should start being used.
pub transaction_permission_contract_transition: Option<Uint>,
/// Wasm activation block height, if not activated from start
pub wasm_activation_transition: Option<Uint>,
/// KIP4 activiation block height.
pub kip4_transition: Option<Uint>,
/// KIP6 activiation block height.
pub kip6_transition: Option<Uint>,
}
#[cfg(test)]
mod tests {
use serde_json;
use uint::Uint;
use ethereum_types::U256;
use spec::params::Params;
use ethereum_types::U256;
use serde_json;
use spec::params::Params;
use uint::Uint;
#[test]
fn params_deserialization() {
let s = r#"{
#[test]
fn params_deserialization() {
let s = r#"{
"maximumExtraDataSize": "0x20",
"networkID" : "0x1",
"chainID" : "0x15",
@@ -157,22 +157,28 @@ mod tests {
"wasmActivationTransition": "0x1010"
}"#;
let deserialized: Params = serde_json::from_str(s).unwrap();
assert_eq!(deserialized.maximum_extra_data_size, Uint(U256::from(0x20)));
assert_eq!(deserialized.network_id, Uint(U256::from(0x1)));
assert_eq!(deserialized.chain_id, Some(Uint(U256::from(0x15))));
assert_eq!(deserialized.subprotocol_name, Some("exp".to_owned()));
assert_eq!(deserialized.min_gas_limit, Uint(U256::from(0x1388)));
assert_eq!(deserialized.account_start_nonce, Some(Uint(U256::from(0x01))));
assert_eq!(deserialized.gas_limit_bound_divisor, Uint(U256::from(0x20)));
assert_eq!(deserialized.max_code_size, Some(Uint(U256::from(0x1000))));
assert_eq!(deserialized.wasm_activation_transition, Some(Uint(U256::from(0x1010))));
}
let deserialized: Params = serde_json::from_str(s).unwrap();
assert_eq!(deserialized.maximum_extra_data_size, Uint(U256::from(0x20)));
assert_eq!(deserialized.network_id, Uint(U256::from(0x1)));
assert_eq!(deserialized.chain_id, Some(Uint(U256::from(0x15))));
assert_eq!(deserialized.subprotocol_name, Some("exp".to_owned()));
assert_eq!(deserialized.min_gas_limit, Uint(U256::from(0x1388)));
assert_eq!(
deserialized.account_start_nonce,
Some(Uint(U256::from(0x01)))
);
assert_eq!(deserialized.gas_limit_bound_divisor, Uint(U256::from(0x20)));
assert_eq!(deserialized.max_code_size, Some(Uint(U256::from(0x1000))));
assert_eq!(
deserialized.wasm_activation_transition,
Some(Uint(U256::from(0x1010)))
);
}
#[test]
#[should_panic(expected = "a non-zero value")]
fn test_zero_value_divisor() {
let s = r#"{
#[test]
#[should_panic(expected = "a non-zero value")]
fn test_zero_value_divisor() {
let s = r#"{
"maximumExtraDataSize": "0x20",
"networkID" : "0x1",
"chainID" : "0x15",
@@ -183,6 +189,6 @@ mod tests {
"maxCodeSize": "0x1000"
}"#;
let _deserialized: Params = serde_json::from_str(s).unwrap();
}
let _deserialized: Params = serde_json::from_str(s).unwrap();
}
}

View File

@@ -16,41 +16,41 @@
//! Spec seal deserialization.
use bytes::Bytes;
use hash::*;
use uint::Uint;
use bytes::Bytes;
/// Ethereum seal.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct Ethereum {
/// Seal nonce.
pub nonce: H64,
/// Seal mix hash.
pub mix_hash: H256,
/// Seal nonce.
pub nonce: H64,
/// Seal mix hash.
pub mix_hash: H256,
}
/// AuthorityRound seal.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct AuthorityRoundSeal {
/// Seal step.
pub step: Uint,
/// Seal signature.
pub signature: H520,
/// Seal step.
pub step: Uint,
/// Seal signature.
pub signature: H520,
}
/// Tendermint seal.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct TendermintSeal {
/// Seal round.
pub round: Uint,
/// Proposal seal signature.
pub proposal: H520,
/// Proposal seal signature.
pub precommits: Vec<H520>,
/// Seal round.
pub round: Uint,
/// Proposal seal signature.
pub proposal: H520,
/// Proposal seal signature.
pub precommits: Vec<H520>,
}
/// Seal variants.
@@ -58,28 +58,28 @@ pub struct TendermintSeal {
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub enum Seal {
/// Ethereum seal.
Ethereum(Ethereum),
/// AuthorityRound seal.
AuthorityRound(AuthorityRoundSeal),
/// Tendermint seal.
Tendermint(TendermintSeal),
/// Generic seal.
Generic(Bytes),
/// Ethereum seal.
Ethereum(Ethereum),
/// AuthorityRound seal.
AuthorityRound(AuthorityRoundSeal),
/// Tendermint seal.
Tendermint(TendermintSeal),
/// Generic seal.
Generic(Bytes),
}
#[cfg(test)]
mod tests {
use serde_json;
use hash::*;
use bytes::Bytes;
use uint::Uint;
use ethereum_types::{U256, H64 as Eth64, H256 as Eth256, H520 as Eth520};
use spec::{Ethereum, AuthorityRoundSeal, TendermintSeal, Seal};
use bytes::Bytes;
use ethereum_types::{H256 as Eth256, H520 as Eth520, H64 as Eth64, U256};
use hash::*;
use serde_json;
use spec::{AuthorityRoundSeal, Ethereum, Seal, TendermintSeal};
use uint::Uint;
#[test]
fn seal_deserialization() {
let s = r#"[{
#[test]
fn seal_deserialization() {
let s = r#"[{
"ethereum": {
"nonce": "0x0000000000000042",
"mixHash": "0x1000000000000000000000000000000000000000000000000000000000000001"
@@ -101,31 +101,41 @@ mod tests {
}
}]"#;
let deserialized: Vec<Seal> = serde_json::from_str(s).unwrap();
assert_eq!(deserialized.len(), 4);
let deserialized: Vec<Seal> = serde_json::from_str(s).unwrap();
assert_eq!(deserialized.len(), 4);
// [0]
assert_eq!(deserialized[0], Seal::Ethereum(Ethereum {
nonce: H64(Eth64::from("0x0000000000000042")),
mix_hash: H256(Eth256::from("0x1000000000000000000000000000000000000000000000000000000000000001"))
}));
// [0]
assert_eq!(
deserialized[0],
Seal::Ethereum(Ethereum {
nonce: H64(Eth64::from("0x0000000000000042")),
mix_hash: H256(Eth256::from(
"0x1000000000000000000000000000000000000000000000000000000000000001"
))
})
);
// [1]
assert_eq!(deserialized[1], Seal::Generic(Bytes::new(vec![
0xe0, 0x11, 0xbb, 0xe8, 0xdb, 0x4e, 0x34, 0x7b, 0x4e, 0x8c, 0x93, 0x7c, 0x1c, 0x83, 0x70, 0xe4,
0xb5, 0xed, 0x33, 0xad, 0xb3, 0xdb, 0x69, 0xcb, 0xdb, 0x7a, 0x38, 0xe1, 0xe5, 0x0b, 0x1b, 0x82, 0xfa])));
// [1]
assert_eq!(
deserialized[1],
Seal::Generic(Bytes::new(vec![
0xe0, 0x11, 0xbb, 0xe8, 0xdb, 0x4e, 0x34, 0x7b, 0x4e, 0x8c, 0x93, 0x7c, 0x1c, 0x83,
0x70, 0xe4, 0xb5, 0xed, 0x33, 0xad, 0xb3, 0xdb, 0x69, 0xcb, 0xdb, 0x7a, 0x38, 0xe1,
0xe5, 0x0b, 0x1b, 0x82, 0xfa
]))
);
// [2]
assert_eq!(deserialized[2], Seal::AuthorityRound(AuthorityRoundSeal {
// [2]
assert_eq!(deserialized[2], Seal::AuthorityRound(AuthorityRoundSeal {
step: Uint(U256::from(0x0)),
signature: H520(Eth520::from("0x2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002"))
}));
// [3]
assert_eq!(deserialized[3], Seal::Tendermint(TendermintSeal {
// [3]
assert_eq!(deserialized[3], Seal::Tendermint(TendermintSeal {
round: Uint(U256::from(0x3)),
proposal: H520(Eth520::from("0x3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003")),
precommits: vec![H520(Eth520::from("0x4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004"))]
}));
}
}
}

View File

@@ -16,26 +16,25 @@
//! Spec deserialization.
use serde_json::{self, Error};
use spec::{Engine, Genesis, HardcodedSync, Params, State};
use std::io::Read;
use serde_json;
use serde_json::Error;
use spec::{Params, Genesis, Engine, State, HardcodedSync};
/// Fork spec definition
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Deserialize)]
pub enum ForkSpec {
EIP150,
EIP158,
Frontier,
Homestead,
Byzantium,
Constantinople,
ConstantinopleFix,
Istanbul,
EIP158ToByzantiumAt5,
FrontierToHomesteadAt5,
HomesteadToDaoAt5,
HomesteadToEIP150At5,
EIP150,
EIP158,
Frontier,
Homestead,
Byzantium,
Constantinople,
ConstantinopleFix,
Istanbul,
EIP158ToByzantiumAt5,
FrontierToHomesteadAt5,
HomesteadToDaoAt5,
HomesteadToEIP150At5,
}
/// Spec deserialization.
@@ -43,39 +42,42 @@ pub enum ForkSpec {
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct Spec {
/// Spec name.
pub name: String,
/// Special fork name.
pub data_dir: Option<String>,
/// Engine.
pub engine: Engine,
/// Spec params.
pub params: Params,
/// Genesis header.
pub genesis: Genesis,
/// Genesis state.
pub accounts: State,
/// Boot nodes.
pub nodes: Option<Vec<String>>,
/// Hardcoded synchronization for the light client.
pub hardcoded_sync: Option<HardcodedSync>,
/// Spec name.
pub name: String,
/// Special fork name.
pub data_dir: Option<String>,
/// Engine.
pub engine: Engine,
/// Spec params.
pub params: Params,
/// Genesis header.
pub genesis: Genesis,
/// Genesis state.
pub accounts: State,
/// Boot nodes.
pub nodes: Option<Vec<String>>,
/// Hardcoded synchronization for the light client.
pub hardcoded_sync: Option<HardcodedSync>,
}
impl Spec {
/// Loads test from json.
pub fn load<R>(reader: R) -> Result<Self, Error> where R: Read {
serde_json::from_reader(reader)
}
/// Loads test from json.
pub fn load<R>(reader: R) -> Result<Self, Error>
where
R: Read,
{
serde_json::from_reader(reader)
}
}
#[cfg(test)]
mod tests {
use serde_json;
use spec::spec::Spec;
use serde_json;
use spec::spec::Spec;
#[test]
fn should_error_on_unknown_fields() {
let s = r#"{
#[test]
fn should_error_on_unknown_fields() {
let s = r#"{
"name": "Morden",
"dataDir": "morden",
"engine": {
@@ -134,13 +136,13 @@ mod tests {
]
}
}"#;
let result: Result<Spec, _> = serde_json::from_str(s);
assert!(result.is_err());
}
let result: Result<Spec, _> = serde_json::from_str(s);
assert!(result.is_err());
}
#[test]
fn spec_deserialization() {
let s = r#"{
#[test]
fn spec_deserialization() {
let s = r#"{
"name": "Morden",
"dataDir": "morden",
"engine": {
@@ -246,7 +248,7 @@ mod tests {
]
}
}"#;
let _deserialized: Spec = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
let _deserialized: Spec = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
}

View File

@@ -16,10 +16,10 @@
//! Blockchain test state deserializer.
use std::collections::BTreeMap;
use hash::Address;
use bytes::Bytes;
use hash::Address;
use spec::{Account, Builtin};
use std::collections::BTreeMap;
/// Blockchain test state deserializer.
#[derive(Debug, PartialEq, Deserialize)]
@@ -27,28 +27,28 @@ use spec::{Account, Builtin};
pub struct State(BTreeMap<Address, Account>);
impl State {
/// Returns all builtins.
pub fn builtins(&self) -> BTreeMap<Address, Builtin> {
self.0
.iter()
.filter_map(|(add, ref acc)| acc.builtin.clone().map(|b| (add.clone(), b.into())))
.collect()
}
/// Returns all builtins.
pub fn builtins(&self) -> BTreeMap<Address, Builtin> {
self.0
.iter()
.filter_map(|(add, ref acc)| acc.builtin.clone().map(|b| (add.clone(), b.into())))
.collect()
}
/// Returns all constructors.
pub fn constructors(&self) -> BTreeMap<Address, Bytes> {
self.0
.iter()
.filter_map(|(add, ref acc)| acc.constructor.clone().map(|b| (add.clone(), b)))
.collect()
}
/// Returns all constructors.
pub fn constructors(&self) -> BTreeMap<Address, Bytes> {
self.0
.iter()
.filter_map(|(add, ref acc)| acc.constructor.clone().map(|b| (add.clone(), b)))
.collect()
}
}
impl IntoIterator for State {
type Item = <BTreeMap<Address, Account> as IntoIterator>::Item;
type IntoIter = <BTreeMap<Address, Account> as IntoIterator>::IntoIter;
type Item = <BTreeMap<Address, Account> as IntoIterator>::Item;
type IntoIter = <BTreeMap<Address, Account> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}

View File

@@ -16,36 +16,36 @@
//! Validator set deserialization.
use hash::Address;
use std::collections::BTreeMap;
use uint::Uint;
use hash::Address;
/// Different ways of specifying validators.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub enum ValidatorSet {
/// A simple list of authorities.
List(Vec<Address>),
/// Address of a contract that indicates the list of authorities.
SafeContract(Address),
/// Address of a contract that indicates the list of authorities and enables reporting of theor misbehaviour using transactions.
Contract(Address),
/// A map of starting blocks for each validator set.
Multi(BTreeMap<Uint, ValidatorSet>),
/// A simple list of authorities.
List(Vec<Address>),
/// Address of a contract that indicates the list of authorities.
SafeContract(Address),
/// Address of a contract that indicates the list of authorities and enables reporting of theor misbehaviour using transactions.
Contract(Address),
/// A map of starting blocks for each validator set.
Multi(BTreeMap<Uint, ValidatorSet>),
}
#[cfg(test)]
mod tests {
use serde_json;
use uint::Uint;
use ethereum_types::{H160, U256};
use hash::Address;
use spec::validator_set::ValidatorSet;
use ethereum_types::{H160, U256};
use hash::Address;
use serde_json;
use spec::validator_set::ValidatorSet;
use uint::Uint;
#[test]
fn validator_set_deserialization() {
let s = r#"[{
#[test]
fn validator_set_deserialization() {
let s = r#"[{
"list": ["0xc6d9d2cd449a754c494264e1809c50e34d64562b"]
}, {
"safeContract": "0xc6d9d2cd449a754c494264e1809c50e34d64562b"
@@ -59,20 +59,35 @@ mod tests {
}
}]"#;
let deserialized: Vec<ValidatorSet> = serde_json::from_str(s).unwrap();
assert_eq!(deserialized.len(), 4);
let deserialized: Vec<ValidatorSet> = serde_json::from_str(s).unwrap();
assert_eq!(deserialized.len(), 4);
assert_eq!(deserialized[0], ValidatorSet::List(vec![Address(H160::from("0xc6d9d2cd449a754c494264e1809c50e34d64562b"))]));
assert_eq!(deserialized[1], ValidatorSet::SafeContract(Address(H160::from("0xc6d9d2cd449a754c494264e1809c50e34d64562b"))));
assert_eq!(deserialized[2], ValidatorSet::Contract(Address(H160::from("0xc6d9d2cd449a754c494264e1809c50e34d64562b"))));
match deserialized[3] {
ValidatorSet::Multi(ref map) => {
assert_eq!(map.len(), 3);
assert!(map.contains_key(&Uint(U256::from(0))));
assert!(map.contains_key(&Uint(U256::from(10))));
assert!(map.contains_key(&Uint(U256::from(20))));
},
_ => assert!(false),
}
}
assert_eq!(
deserialized[0],
ValidatorSet::List(vec![Address(H160::from(
"0xc6d9d2cd449a754c494264e1809c50e34d64562b"
))])
);
assert_eq!(
deserialized[1],
ValidatorSet::SafeContract(Address(H160::from(
"0xc6d9d2cd449a754c494264e1809c50e34d64562b"
)))
);
assert_eq!(
deserialized[2],
ValidatorSet::Contract(Address(H160::from(
"0xc6d9d2cd449a754c494264e1809c50e34d64562b"
)))
);
match deserialized[3] {
ValidatorSet::Multi(ref map) => {
assert_eq!(map.len(), 3);
assert!(map.contains_key(&Uint(U256::from(0))));
assert!(map.contains_key(&Uint(U256::from(10))));
assert!(map.contains_key(&Uint(U256::from(20))));
}
_ => assert!(false),
}
}
}

View File

@@ -15,30 +15,30 @@
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
//! State test log deserialization.
use hash::{Address, H256, Bloom};
use bytes::Bytes;
use hash::{Address, Bloom, H256};
/// State test log deserialization.
#[derive(Debug, PartialEq, Deserialize)]
pub struct Log {
/// Address.
pub address: Address,
/// Topics.
pub topics: Vec<H256>,
/// Data.
pub data: Bytes,
/// Bloom.
pub bloom: Bloom,
/// Address.
pub address: Address,
/// Topics.
pub topics: Vec<H256>,
/// Data.
pub data: Bytes,
/// Bloom.
pub bloom: Bloom,
}
#[cfg(test)]
mod tests {
use serde_json;
use state::Log;
use serde_json;
use state::Log;
#[test]
fn log_deserialization() {
let s = r#"{
#[test]
fn log_deserialization() {
let s = r#"{
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008800000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000",
"data" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
@@ -46,7 +46,7 @@ mod tests {
"0000000000000000000000000000000000000000000000000000000000000000"
]
}"#;
let _deserialized: Log = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
let _deserialized: Log = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
}

View File

@@ -16,14 +16,11 @@
//! State test deserialization.
pub mod state;
pub mod transaction;
pub mod test;
pub mod log;
pub mod state;
pub mod test;
pub mod transaction;
pub use self::state::State;
pub use self::transaction::Transaction;
pub use self::test::Test;
pub use self::log::Log;
pub use vm::Env as Env;
pub use self::{log::Log, state::State, test::Test, transaction::Transaction};
pub use blockchain::State as AccountState;
pub use vm::Env;

View File

@@ -18,39 +18,39 @@
use bytes::Bytes;
use hash::H256;
use state::{Env, AccountState, Transaction, Log};
use state::{AccountState, Env, Log, Transaction};
/// State test deserialization.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct State {
/// Environment.
pub env: Env,
/// Output.
#[serde(rename = "out")]
pub output: Bytes,
/// Pre state.
#[serde(rename = "pre")]
pub pre_state: AccountState,
/// Post state.
#[serde(rename = "post")]
pub post_state: AccountState,
/// Post state root.
pub post_state_root: H256,
/// Transaction.
pub transaction: Transaction,
/// Logs.
pub logs: Vec<Log>
/// Environment.
pub env: Env,
/// Output.
#[serde(rename = "out")]
pub output: Bytes,
/// Pre state.
#[serde(rename = "pre")]
pub pre_state: AccountState,
/// Post state.
#[serde(rename = "post")]
pub post_state: AccountState,
/// Post state root.
pub post_state_root: H256,
/// Transaction.
pub transaction: Transaction,
/// Logs.
pub logs: Vec<Log>,
}
#[cfg(test)]
mod tests {
use serde_json;
use state::State;
use serde_json;
use state::State;
#[test]
fn state_deserialization() {
let s = r#"{
#[test]
fn state_deserialization() {
let s = r#"{
"env" : {
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
"currentDifficulty" : "0x0100",
@@ -150,7 +150,7 @@ mod tests {
"value" : "0x00"
}
}"#;
let _deserialized: State = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
let _deserialized: State = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
}

View File

@@ -16,115 +16,117 @@
//! General test deserialization.
use std::io::Read;
use std::collections::BTreeMap;
use uint::Uint;
use bytes::Bytes;
use hash::{Address, H256};
use spec::ForkSpec;
use state::{Env, AccountState, Transaction};
use maybe::MaybeEmpty;
use serde_json::{self, Error};
use spec::ForkSpec;
use state::{AccountState, Env, Transaction};
use std::{collections::BTreeMap, io::Read};
use uint::Uint;
/// State test deserializer.
#[derive(Debug, PartialEq, Deserialize)]
pub struct Test(BTreeMap<String, State>);
impl IntoIterator for Test {
type Item = <BTreeMap<String, State> as IntoIterator>::Item;
type IntoIter = <BTreeMap<String, State> as IntoIterator>::IntoIter;
type Item = <BTreeMap<String, State> as IntoIterator>::Item;
type IntoIter = <BTreeMap<String, State> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl Test {
/// Loads test from json.
pub fn load<R>(reader: R) -> Result<Self, Error> where R: Read {
serde_json::from_reader(reader)
}
/// Loads test from json.
pub fn load<R>(reader: R) -> Result<Self, Error>
where
R: Read,
{
serde_json::from_reader(reader)
}
}
/// State test deserialization.
#[derive(Debug, PartialEq, Deserialize)]
pub struct State {
/// Environment.
pub env: Env,
/// Pre state.
#[serde(rename = "pre")]
pub pre_state: AccountState,
/// Post state.
#[serde(rename = "post")]
pub post_states: BTreeMap<ForkSpec, Vec<PostStateResult>>,
/// Transaction.
pub transaction: MultiTransaction,
/// Environment.
pub env: Env,
/// Pre state.
#[serde(rename = "pre")]
pub pre_state: AccountState,
/// Post state.
#[serde(rename = "post")]
pub post_states: BTreeMap<ForkSpec, Vec<PostStateResult>>,
/// Transaction.
pub transaction: MultiTransaction,
}
/// State test transaction deserialization.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MultiTransaction {
/// Transaction data set.
pub data: Vec<Bytes>,
/// Gas limit set.
pub gas_limit: Vec<Uint>,
/// Gas price.
pub gas_price: Uint,
/// Nonce.
pub nonce: Uint,
/// Secret key.
#[serde(rename = "secretKey")]
pub secret: Option<H256>,
/// To.
pub to: MaybeEmpty<Address>,
/// Value set.
pub value: Vec<Uint>,
/// Transaction data set.
pub data: Vec<Bytes>,
/// Gas limit set.
pub gas_limit: Vec<Uint>,
/// Gas price.
pub gas_price: Uint,
/// Nonce.
pub nonce: Uint,
/// Secret key.
#[serde(rename = "secretKey")]
pub secret: Option<H256>,
/// To.
pub to: MaybeEmpty<Address>,
/// Value set.
pub value: Vec<Uint>,
}
impl MultiTransaction {
/// Build transaction with given indexes.
pub fn select(&self, indexes: &PostStateIndexes) -> Transaction {
Transaction {
data: self.data[indexes.data as usize].clone(),
gas_limit: self.gas_limit[indexes.gas as usize].clone(),
gas_price: self.gas_price.clone(),
nonce: self.nonce.clone(),
secret: self.secret.clone(),
to: self.to.clone(),
value: self.value[indexes.value as usize].clone(),
}
}
/// Build transaction with given indexes.
pub fn select(&self, indexes: &PostStateIndexes) -> Transaction {
Transaction {
data: self.data[indexes.data as usize].clone(),
gas_limit: self.gas_limit[indexes.gas as usize].clone(),
gas_price: self.gas_price.clone(),
nonce: self.nonce.clone(),
secret: self.secret.clone(),
to: self.to.clone(),
value: self.value[indexes.value as usize].clone(),
}
}
}
/// State test indexes deserialization.
#[derive(Debug, PartialEq, Deserialize)]
pub struct PostStateIndexes {
/// Index into transaction data set.
pub data: u64,
/// Index into transaction gas limit set.
pub gas: u64,
/// Index into transaction value set.
pub value: u64,
/// Index into transaction data set.
pub data: u64,
/// Index into transaction gas limit set.
pub gas: u64,
/// Index into transaction value set.
pub value: u64,
}
/// State test indexed state result deserialization.
#[derive(Debug, PartialEq, Deserialize)]
pub struct PostStateResult {
/// Post state hash
pub hash: H256,
/// Indexes
pub indexes: PostStateIndexes,
/// Post state hash
pub hash: H256,
/// Indexes
pub indexes: PostStateIndexes,
}
#[cfg(test)]
mod tests {
use serde_json;
use super::{MultiTransaction, State};
use super::{MultiTransaction, State};
use serde_json;
#[test]
fn multi_transaction_deserialization() {
let s = r#"{
#[test]
fn multi_transaction_deserialization() {
let s = r#"{
"data" : [ "" ],
"gasLimit" : [ "0x2dc6c0", "0x222222" ],
"gasPrice" : "0x01",
@@ -133,12 +135,12 @@ mod tests {
"to" : "1000000000000000000000000000000000000000",
"value" : [ "0x00", "0x01", "0x02" ]
}"#;
let _deserialized: MultiTransaction = serde_json::from_str(s).unwrap();
}
let _deserialized: MultiTransaction = serde_json::from_str(s).unwrap();
}
#[test]
fn state_deserialization() {
let s = r#"{
#[test]
fn state_deserialization() {
let s = r#"{
"env" : {
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
"currentDifficulty" : "0x0100",
@@ -209,7 +211,7 @@ mod tests {
"value" : [ "10", "0" ]
}
}"#;
let _deserialized: State = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
let _deserialized: State = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
}

View File

@@ -16,40 +16,40 @@
//! State test transaction deserialization.
use uint::Uint;
use bytes::Bytes;
use hash::{Address, H256};
use maybe::MaybeEmpty;
use uint::Uint;
/// State test transaction deserialization.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Transaction {
/// Transaction data.
pub data: Bytes,
/// Gas limit.
pub gas_limit: Uint,
/// Gas price.
pub gas_price: Uint,
/// Nonce.
pub nonce: Uint,
/// Secret key.
#[serde(rename = "secretKey")]
pub secret: Option<H256>,
/// To.
pub to: MaybeEmpty<Address>,
/// Value.
pub value: Uint,
/// Transaction data.
pub data: Bytes,
/// Gas limit.
pub gas_limit: Uint,
/// Gas price.
pub gas_price: Uint,
/// Nonce.
pub nonce: Uint,
/// Secret key.
#[serde(rename = "secretKey")]
pub secret: Option<H256>,
/// To.
pub to: MaybeEmpty<Address>,
/// Value.
pub value: Uint,
}
#[cfg(test)]
mod tests {
use serde_json;
use state::Transaction;
use serde_json;
use state::Transaction;
#[test]
fn transaction_deserialization() {
let s = r#"{
#[test]
fn transaction_deserialization() {
let s = r#"{
"data" : "",
"gasLimit" : "0x2dc6c0",
"gasPrice" : "0x01",
@@ -58,7 +58,7 @@ mod tests {
"to" : "1000000000000000000000000000000000000000",
"value" : "0x00"
}"#;
let _deserialized: Transaction = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
let _deserialized: Transaction = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
}

View File

@@ -16,29 +16,27 @@
//! Additional test structures deserialization.
use std::collections::BTreeMap;
use std::io::Read;
use serde_json;
use serde_json::Error;
use hash::H256;
use serde_json::{self, Error};
use std::{collections::BTreeMap, io::Read};
use uint::Uint;
/// Blockchain test header deserializer.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DifficultyTestCase {
/// Parent timestamp.
pub parent_timestamp: Uint,
/// Parent difficulty.
pub parent_difficulty: Uint,
/// Parent uncle hash.
pub parent_uncles: H256,
/// Current timestamp.
pub current_timestamp: Uint,
/// Current difficulty.
pub current_difficulty: Uint,
/// Current block number.
pub current_block_number: Uint,
/// Parent timestamp.
pub parent_timestamp: Uint,
/// Parent difficulty.
pub parent_difficulty: Uint,
/// Parent uncle hash.
pub parent_uncles: H256,
/// Current timestamp.
pub current_timestamp: Uint,
/// Current difficulty.
pub current_difficulty: Uint,
/// Current block number.
pub current_block_number: Uint,
}
/// Blockchain test deserializer.
@@ -46,73 +44,78 @@ pub struct DifficultyTestCase {
pub struct DifficultyTest(BTreeMap<String, DifficultyTestCase>);
impl IntoIterator for DifficultyTest {
type Item = <BTreeMap<String, DifficultyTestCase> as IntoIterator>::Item;
type IntoIter = <BTreeMap<String, DifficultyTestCase> as IntoIterator>::IntoIter;
type Item = <BTreeMap<String, DifficultyTestCase> as IntoIterator>::Item;
type IntoIter = <BTreeMap<String, DifficultyTestCase> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl DifficultyTest {
/// Loads test from json.
pub fn load<R>(reader: R) -> Result<Self, Error> where R: Read {
serde_json::from_reader(reader)
}
/// Loads test from json.
pub fn load<R>(reader: R) -> Result<Self, Error>
where
R: Read,
{
serde_json::from_reader(reader)
}
}
/// Test to skip (only if issue ongoing)
#[derive(Debug, PartialEq, Deserialize)]
pub struct SkipStates {
/// Block tests
pub block: Vec<BlockSkipStates>,
/// State tests
pub state: Vec<StateSkipStates>,
/// Block tests
pub block: Vec<BlockSkipStates>,
/// State tests
pub state: Vec<StateSkipStates>,
}
/// Block test to skip.
#[derive(Debug, PartialEq, Deserialize)]
pub struct BlockSkipStates {
/// Issue reference.
pub reference: String,
/// Test failing name.
pub failing: String,
/// Items failing for the test.
pub subtests: Vec<String>,
/// Issue reference.
pub reference: String,
/// Test failing name.
pub failing: String,
/// Items failing for the test.
pub subtests: Vec<String>,
}
/// State test to skip.
#[derive(Debug, PartialEq, Deserialize)]
pub struct StateSkipStates {
/// Issue reference.
pub reference: String,
/// Test failing name.
pub failing: String,
/// Items failing for the test.
pub subtests: BTreeMap<String, StateSkipSubStates>
/// Issue reference.
pub reference: String,
/// Test failing name.
pub failing: String,
/// Items failing for the test.
pub subtests: BTreeMap<String, StateSkipSubStates>,
}
/// State subtest to skip.
#[derive(Debug, PartialEq, Deserialize)]
pub struct StateSkipSubStates {
/// State test number of this item. Or '*' for all state.
pub subnumbers: Vec<String>,
/// Chain for this items.
pub chain: String,
/// State test number of this item. Or '*' for all state.
pub subnumbers: Vec<String>,
/// Chain for this items.
pub chain: String,
}
impl SkipStates {
/// Loads skip states from json.
pub fn load<R>(reader: R) -> Result<Self, Error> where R: Read {
serde_json::from_reader(reader)
}
/// Loads skip states from json.
pub fn load<R>(reader: R) -> Result<Self, Error>
where
R: Read,
{
serde_json::from_reader(reader)
}
/// Empty skip states.
pub fn empty() -> Self {
SkipStates {
block: Vec::new(),
state: Vec::new(),
}
}
/// Empty skip states.
pub fn empty() -> Self {
SkipStates {
block: Vec::new(),
state: Vec::new(),
}
}
}

View File

@@ -16,10 +16,8 @@
//! Transaction test deserialization.
mod test;
mod transaction;
mod txtest;
mod test;
pub use self::transaction::Transaction;
pub use self::txtest::TransactionTest;
pub use self::test::Test;
pub use self::{test::Test, transaction::Transaction, txtest::TransactionTest};

View File

@@ -16,10 +16,8 @@
//! TransactionTest test deserializer.
use std::collections::BTreeMap;
use std::io::Read;
use serde_json;
use serde_json::Error;
use serde_json::{self, Error};
use std::{collections::BTreeMap, io::Read};
use transaction::TransactionTest;
/// TransactionTest test deserializer.
@@ -27,17 +25,20 @@ use transaction::TransactionTest;
pub struct Test(BTreeMap<String, TransactionTest>);
impl IntoIterator for Test {
type Item = <BTreeMap<String, TransactionTest> as IntoIterator>::Item;
type IntoIter = <BTreeMap<String, TransactionTest> as IntoIterator>::IntoIter;
type Item = <BTreeMap<String, TransactionTest> as IntoIterator>::Item;
type IntoIter = <BTreeMap<String, TransactionTest> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl Test {
/// Loads test from json.
pub fn load<R>(reader: R) -> Result<Self, Error> where R: Read {
serde_json::from_reader(reader)
}
/// Loads test from json.
pub fn load<R>(reader: R) -> Result<Self, Error>
where
R: Read,
{
serde_json::from_reader(reader)
}
}

View File

@@ -16,43 +16,43 @@
//! Transaction test transaction deserialization.
use uint::Uint;
use bytes::Bytes;
use hash::Address;
use maybe::MaybeEmpty;
use uint::Uint;
/// Transaction test transaction deserialization.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Transaction {
/// Transaction data.
pub data: Bytes,
/// Gas limit.
pub gas_limit: Uint,
/// Gas price.
pub gas_price: Uint,
/// Nonce.
pub nonce: Uint,
/// To.
pub to: MaybeEmpty<Address>,
/// Value.
pub value: Uint,
/// R.
pub r: Uint,
/// S.
pub s: Uint,
/// V.
pub v: Uint,
/// Transaction data.
pub data: Bytes,
/// Gas limit.
pub gas_limit: Uint,
/// Gas price.
pub gas_price: Uint,
/// Nonce.
pub nonce: Uint,
/// To.
pub to: MaybeEmpty<Address>,
/// Value.
pub value: Uint,
/// R.
pub r: Uint,
/// S.
pub s: Uint,
/// V.
pub v: Uint,
}
#[cfg(test)]
mod tests {
use serde_json;
use transaction::Transaction;
use serde_json;
use transaction::Transaction;
#[test]
fn transaction_deserialization() {
let s = r#"{
#[test]
fn transaction_deserialization() {
let s = r#"{
"data" : "0x",
"gasLimit" : "0xf388",
"gasPrice" : "0x09184e72a000",
@@ -63,7 +63,7 @@ mod tests {
"v" : "0x1b",
"value" : "0x00"
}"#;
let _deserialized: Transaction = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
let _deserialized: Transaction = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
}

View File

@@ -16,39 +16,38 @@
//! Transaction test deserialization.
use std::collections::BTreeMap;
use bytes::Bytes;
use hash::Address;
use hash::H256;
use hash::{Address, H256};
use spec::ForkSpec;
use std::collections::BTreeMap;
/// Transaction test deserialization.
#[derive(Debug, Deserialize)]
pub struct TransactionTest {
pub rlp: Bytes,
pub _info: ::serde::de::IgnoredAny,
#[serde(flatten)]
pub post_state: BTreeMap<ForkSpec, PostState>,
pub rlp: Bytes,
pub _info: ::serde::de::IgnoredAny,
#[serde(flatten)]
pub post_state: BTreeMap<ForkSpec, PostState>,
}
/// TransactionTest post state.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct PostState {
/// Transaction sender.
pub sender: Option<Address>,
/// Transaction hash.
pub hash: Option<H256>,
/// Transaction sender.
pub sender: Option<Address>,
/// Transaction hash.
pub hash: Option<H256>,
}
#[cfg(test)]
mod tests {
use serde_json;
use transaction::TransactionTest;
use serde_json;
use transaction::TransactionTest;
#[test]
fn transaction_deserialization() {
let s = r#"{
#[test]
fn transaction_deserialization() {
let s = r#"{
"Byzantium" : {
"hash" : "4782cb5edcaeda1f0aef204b161214f124cefade9e146245183abbb9ca01bca5",
"sender" : "2ea991808ba979ba103147edfd72304ebd95c028"
@@ -77,7 +76,7 @@ mod tests {
"rlp" : "0xf865808698852840a46f82d6d894095e7baea6a6c7c4c2dfeb977efac326af552d87808025a098ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4aa01887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3"
}"#;
let _deserialized: TransactionTest = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
let _deserialized: TransactionTest = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
}

View File

@@ -16,141 +16,164 @@
//! Trie test input deserialization.
use std::fmt;
use std::collections::BTreeMap;
use std::str::FromStr;
use bytes::Bytes;
use serde::{Deserialize, Deserializer};
use serde::de::{Error as ErrorTrait, Visitor, MapAccess, SeqAccess};
use serde::{
de::{Error as ErrorTrait, MapAccess, SeqAccess, Visitor},
Deserialize, Deserializer,
};
use std::{collections::BTreeMap, fmt, str::FromStr};
/// Trie test input.
#[derive(Debug, PartialEq)]
pub struct Input {
/// Input params.
pub data: BTreeMap<Bytes, Option<Bytes>>,
/// Input params.
pub data: BTreeMap<Bytes, Option<Bytes>>,
}
impl<'a> Deserialize<'a> for Input {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'a>
{
deserializer.deserialize_any(InputVisitor)
}
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'a>,
{
deserializer.deserialize_any(InputVisitor)
}
}
struct InputVisitor;
impl<'a> Visitor<'a> for InputVisitor {
type Value = Input;
type Value = Input;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a map of bytes into bytes")
}
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a map of bytes into bytes")
}
fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error> where V: MapAccess<'a> {
let mut result = BTreeMap::new();
fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
where
V: MapAccess<'a>,
{
let mut result = BTreeMap::new();
loop {
let key_str: Option<String> = visitor.next_key()?;
let key = match key_str {
Some(ref k) if k.starts_with("0x") => Bytes::from_str(k).map_err(V::Error::custom)?,
Some(k) => Bytes::new(k.into_bytes()),
None => { break; }
};
loop {
let key_str: Option<String> = visitor.next_key()?;
let key = match key_str {
Some(ref k) if k.starts_with("0x") => {
Bytes::from_str(k).map_err(V::Error::custom)?
}
Some(k) => Bytes::new(k.into_bytes()),
None => {
break;
}
};
let val_str: Option<String> = visitor.next_value()?;
let val = match val_str {
Some(ref v) if v.starts_with("0x") => Some(Bytes::from_str(v).map_err(V::Error::custom)?),
Some(v) => Some(Bytes::new(v.into_bytes())),
None => None,
};
let val_str: Option<String> = visitor.next_value()?;
let val = match val_str {
Some(ref v) if v.starts_with("0x") => {
Some(Bytes::from_str(v).map_err(V::Error::custom)?)
}
Some(v) => Some(Bytes::new(v.into_bytes())),
None => None,
};
result.insert(key, val);
}
result.insert(key, val);
}
let input = Input {
data: result
};
let input = Input { data: result };
Ok(input)
}
Ok(input)
}
fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error> where V: SeqAccess<'a> {
let mut result = BTreeMap::new();
fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
where
V: SeqAccess<'a>,
{
let mut result = BTreeMap::new();
loop {
let keyval: Option<Vec<Option<String>>> = visitor.next_element()?;
let keyval = match keyval {
Some(k) => k,
_ => { break; },
};
loop {
let keyval: Option<Vec<Option<String>>> = visitor.next_element()?;
let keyval = match keyval {
Some(k) => k,
_ => {
break;
}
};
if keyval.len() != 2 {
return Err(V::Error::custom("Invalid key value pair."));
}
if keyval.len() != 2 {
return Err(V::Error::custom("Invalid key value pair."));
}
let ref key_str: Option<String> = keyval[0];
let ref val_str: Option<String> = keyval[1];
let ref key_str: Option<String> = keyval[0];
let ref val_str: Option<String> = keyval[1];
let key = match *key_str {
Some(ref k) if k.starts_with("0x") => Bytes::from_str(k).map_err(V::Error::custom)?,
Some(ref k) => Bytes::new(k.clone().into_bytes()),
None => { break; }
};
let key = match *key_str {
Some(ref k) if k.starts_with("0x") => {
Bytes::from_str(k).map_err(V::Error::custom)?
}
Some(ref k) => Bytes::new(k.clone().into_bytes()),
None => {
break;
}
};
let val = match *val_str {
Some(ref v) if v.starts_with("0x") => Some(Bytes::from_str(v).map_err(V::Error::custom)?),
Some(ref v) => Some(Bytes::new(v.clone().into_bytes())),
None => None,
};
let val = match *val_str {
Some(ref v) if v.starts_with("0x") => {
Some(Bytes::from_str(v).map_err(V::Error::custom)?)
}
Some(ref v) => Some(Bytes::new(v.clone().into_bytes())),
None => None,
};
result.insert(key, val);
}
result.insert(key, val);
}
let input = Input {
data: result
};
let input = Input { data: result };
Ok(input)
}
Ok(input)
}
}
#[cfg(test)]
mod tests {
use std::collections::BTreeMap;
use serde_json;
use bytes::Bytes;
use super::Input;
use super::Input;
use bytes::Bytes;
use serde_json;
use std::collections::BTreeMap;
#[test]
fn input_deserialization_from_map() {
let s = r#"{
#[test]
fn input_deserialization_from_map() {
let s = r#"{
"0x0045" : "0x0123456789",
"be" : "e",
"0x0a" : null
}"#;
let input: Input = serde_json::from_str(s).unwrap();
let mut map = BTreeMap::new();
map.insert(Bytes::new(vec![0, 0x45]), Some(Bytes::new(vec![0x01, 0x23, 0x45, 0x67, 0x89])));
map.insert(Bytes::new(vec![0x62, 0x65]), Some(Bytes::new(vec![0x65])));
map.insert(Bytes::new(vec![0x0a]), None);
assert_eq!(input.data, map);
}
let input: Input = serde_json::from_str(s).unwrap();
let mut map = BTreeMap::new();
map.insert(
Bytes::new(vec![0, 0x45]),
Some(Bytes::new(vec![0x01, 0x23, 0x45, 0x67, 0x89])),
);
map.insert(Bytes::new(vec![0x62, 0x65]), Some(Bytes::new(vec![0x65])));
map.insert(Bytes::new(vec![0x0a]), None);
assert_eq!(input.data, map);
}
#[test]
fn input_deserialization_from_array() {
let s = r#"[
#[test]
fn input_deserialization_from_array() {
let s = r#"[
["0x0045", "0x0123456789"],
["be", "e"],
["0x0a", null]
]"#;
let input: Input = serde_json::from_str(s).unwrap();
let mut map = BTreeMap::new();
map.insert(Bytes::new(vec![0, 0x45]), Some(Bytes::new(vec![0x01, 0x23, 0x45, 0x67, 0x89])));
map.insert(Bytes::new(vec![0x62, 0x65]), Some(Bytes::new(vec![0x65])));
map.insert(Bytes::new(vec![0x0a]), None);
assert_eq!(input.data, map);
}
let input: Input = serde_json::from_str(s).unwrap();
let mut map = BTreeMap::new();
map.insert(
Bytes::new(vec![0, 0x45]),
Some(Bytes::new(vec![0x01, 0x23, 0x45, 0x67, 0x89])),
);
map.insert(Bytes::new(vec![0x62, 0x65]), Some(Bytes::new(vec![0x65])));
map.insert(Bytes::new(vec![0x0a]), None);
assert_eq!(input.data, map);
}
}

View File

@@ -17,9 +17,7 @@
//! Trie test deserialization.
mod input;
mod trie;
mod test;
mod trie;
pub use self::input::Input;
pub use self::trie::Trie;
pub use self::test::Test;
pub use self::{input::Input, test::Test, trie::Trie};

View File

@@ -16,10 +16,8 @@
//! TransactionTest test deserializer.
use std::collections::BTreeMap;
use std::io::Read;
use serde_json;
use serde_json::Error;
use serde_json::{self, Error};
use std::{collections::BTreeMap, io::Read};
use trie::Trie;
/// TransactionTest test deserializer.
@@ -27,17 +25,20 @@ use trie::Trie;
pub struct Test(BTreeMap<String, Trie>);
impl IntoIterator for Test {
type Item = <BTreeMap<String, Trie> as IntoIterator>::Item;
type IntoIter = <BTreeMap<String, Trie> as IntoIterator>::IntoIter;
type Item = <BTreeMap<String, Trie> as IntoIterator>::Item;
type IntoIter = <BTreeMap<String, Trie> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl Test {
/// Loads test from json.
pub fn load<R>(reader: R) -> Result<Self, Error> where R: Read {
serde_json::from_reader(reader)
}
/// Loads test from json.
pub fn load<R>(reader: R) -> Result<Self, Error>
where
R: Read,
{
serde_json::from_reader(reader)
}
}

View File

@@ -22,9 +22,9 @@ use trie::Input;
/// Trie test deserialization.
#[derive(Debug, Deserialize, PartialEq)]
pub struct Trie {
/// Trie test input.
#[serde(rename = "in")]
pub input: Input,
/// Trie root hash.
pub root: H256,
/// Trie test input.
#[serde(rename = "in")]
pub input: Input,
/// Trie root hash.
pub root: H256,
}

View File

@@ -16,132 +16,161 @@
//! Lenient uint json deserialization for test json files.
use std::fmt;
use std::str::FromStr;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde::de::{Error, Visitor, Unexpected};
use ethereum_types::U256;
use serde::{
de::{Error, Unexpected, Visitor},
Deserialize, Deserializer, Serialize, Serializer,
};
use std::{fmt, str::FromStr};
/// Lenient uint json deserialization for test json files.
#[derive(Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
pub struct Uint(pub U256);
impl Into<U256> for Uint {
fn into(self) -> U256 {
self.0
}
fn into(self) -> U256 {
self.0
}
}
impl Into<u64> for Uint {
fn into(self) -> u64 {
u64::from(self.0)
}
fn into(self) -> u64 {
u64::from(self.0)
}
}
impl Into<usize> for Uint {
fn into(self) -> usize {
// TODO: clean it after util conversions refactored.
u64::from(self.0) as usize
}
fn into(self) -> usize {
// TODO: clean it after util conversions refactored.
u64::from(self.0) as usize
}
}
impl Into<u8> for Uint {
fn into(self) -> u8 {
u64::from(self.0) as u8
}
fn into(self) -> u8 {
u64::from(self.0) as u8
}
}
impl Serialize for Uint {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer {
self.0.to_string().serialize(serializer)
}
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.to_string().serialize(serializer)
}
}
impl<'a> Deserialize<'a> for Uint {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'a> {
deserializer.deserialize_any(UintVisitor)
}
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'a>,
{
deserializer.deserialize_any(UintVisitor)
}
}
struct UintVisitor;
impl<'a> Visitor<'a> for UintVisitor {
type Value = Uint;
type Value = Uint;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a hex encoded or decimal uint")
}
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a hex encoded or decimal uint")
}
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E> where E: Error {
Ok(Uint(U256::from(value)))
}
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
where
E: Error,
{
Ok(Uint(U256::from(value)))
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> where E: Error {
let value = match value.len() {
0 => U256::from(0),
2 if value.starts_with("0x") => U256::from(0),
_ if value.starts_with("0x") => U256::from_str(&value[2..]).map_err(|e| {
Error::custom(format!("Invalid hex value {}: {}", value, e).as_str())
})?,
_ => U256::from_dec_str(value).map_err(|e| {
Error::custom(format!("Invalid decimal value {}: {:?}", value, e).as_str())
})?
};
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: Error,
{
let value = match value.len() {
0 => U256::from(0),
2 if value.starts_with("0x") => U256::from(0),
_ if value.starts_with("0x") => U256::from_str(&value[2..]).map_err(|e| {
Error::custom(format!("Invalid hex value {}: {}", value, e).as_str())
})?,
_ => U256::from_dec_str(value).map_err(|e| {
Error::custom(format!("Invalid decimal value {}: {:?}", value, e).as_str())
})?,
};
Ok(Uint(value))
}
Ok(Uint(value))
}
fn visit_string<E>(self, value: String) -> Result<Self::Value, E> where E: Error {
self.visit_str(value.as_ref())
}
fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
where
E: Error,
{
self.visit_str(value.as_ref())
}
}
/// Deserialize and validate that the value is non-zero
pub fn validate_non_zero<'de, D>(d: D) -> Result<Uint, D::Error> where D: Deserializer<'de> {
let value = Uint::deserialize(d)?;
pub fn validate_non_zero<'de, D>(d: D) -> Result<Uint, D::Error>
where
D: Deserializer<'de>,
{
let value = Uint::deserialize(d)?;
if value == Uint(U256::from(0)) {
return Err(Error::invalid_value(Unexpected::Unsigned(value.into()), &"a non-zero value"))
}
if value == Uint(U256::from(0)) {
return Err(Error::invalid_value(
Unexpected::Unsigned(value.into()),
&"a non-zero value",
));
}
Ok(value)
Ok(value)
}
/// Deserialize and validate that the value is non-zero
pub fn validate_optional_non_zero<'de, D>(d: D) -> Result<Option<Uint>, D::Error> where D: Deserializer<'de> {
let value: Option<Uint> = Option::deserialize(d)?;
pub fn validate_optional_non_zero<'de, D>(d: D) -> Result<Option<Uint>, D::Error>
where
D: Deserializer<'de>,
{
let value: Option<Uint> = Option::deserialize(d)?;
if let Some(value) = value {
if value == Uint(U256::from(0)) {
return Err(Error::invalid_value(Unexpected::Unsigned(value.into()), &"a non-zero value"))
}
}
if let Some(value) = value {
if value == Uint(U256::from(0)) {
return Err(Error::invalid_value(
Unexpected::Unsigned(value.into()),
&"a non-zero value",
));
}
}
Ok(value)
Ok(value)
}
#[cfg(test)]
mod test {
use serde_json;
use ethereum_types::U256;
use uint::Uint;
use ethereum_types::U256;
use serde_json;
use uint::Uint;
#[test]
fn uint_deserialization() {
let s = r#"["0xa", "10", "", "0x", 0]"#;
let deserialized: Vec<Uint> = serde_json::from_str(s).unwrap();
assert_eq!(deserialized, vec![
Uint(U256::from(10)),
Uint(U256::from(10)),
Uint(U256::from(0)),
Uint(U256::from(0)),
Uint(U256::from(0))
]);
}
#[test]
fn uint_deserialization() {
let s = r#"["0xa", "10", "", "0x", 0]"#;
let deserialized: Vec<Uint> = serde_json::from_str(s).unwrap();
assert_eq!(
deserialized,
vec![
Uint(U256::from(10)),
Uint(U256::from(10)),
Uint(U256::from(0)),
Uint(U256::from(0)),
Uint(U256::from(0))
]
);
}
#[test]
fn uint_into() {
assert_eq!(U256::from(10), Uint(U256::from(10)).into());
}
#[test]
fn uint_into() {
assert_eq!(U256::from(10), Uint(U256::from(10)).into());
}
}

View File

@@ -18,67 +18,76 @@
use bytes::Bytes;
use hash::Address;
use uint::Uint;
use maybe::MaybeEmpty;
use uint::Uint;
/// Vm call deserialization.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Call {
/// Call data.
pub data: Bytes,
/// Call destination.
pub destination: MaybeEmpty<Address>,
/// Gas limit.
pub gas_limit: Uint,
/// Call value.
pub value: Uint,
/// Call data.
pub data: Bytes,
/// Call destination.
pub destination: MaybeEmpty<Address>,
/// Gas limit.
pub gas_limit: Uint,
/// Call value.
pub value: Uint,
}
#[cfg(test)]
mod tests {
use serde_json;
use vm::Call;
use ethereum_types::{U256, H160 as Hash160};
use uint::Uint;
use hash::Address;
use maybe::MaybeEmpty;
use std::str::FromStr;
use ethereum_types::{H160 as Hash160, U256};
use hash::Address;
use maybe::MaybeEmpty;
use serde_json;
use std::str::FromStr;
use uint::Uint;
use vm::Call;
#[test]
fn call_deserialization_empty_dest() {
let s = r#"{
#[test]
fn call_deserialization_empty_dest() {
let s = r#"{
"data" : "0x1111222233334444555566667777888899990000aaaabbbbccccddddeeeeffff",
"destination" : "",
"gasLimit" : "0x1748766aa5",
"value" : "0x00"
}"#;
let call: Call = serde_json::from_str(s).unwrap();
let call: Call = serde_json::from_str(s).unwrap();
assert_eq!(&call.data[..],
&[0x11, 0x11, 0x22, 0x22, 0x33, 0x33, 0x44, 0x44, 0x55, 0x55, 0x66, 0x66, 0x77, 0x77,
0x88, 0x88, 0x99, 0x99, 0x00, 0x00, 0xaa, 0xaa, 0xbb, 0xbb, 0xcc, 0xcc, 0xdd, 0xdd,
0xee, 0xee, 0xff, 0xff]);
assert_eq!(
&call.data[..],
&[
0x11, 0x11, 0x22, 0x22, 0x33, 0x33, 0x44, 0x44, 0x55, 0x55, 0x66, 0x66, 0x77, 0x77,
0x88, 0x88, 0x99, 0x99, 0x00, 0x00, 0xaa, 0xaa, 0xbb, 0xbb, 0xcc, 0xcc, 0xdd, 0xdd,
0xee, 0xee, 0xff, 0xff
]
);
assert_eq!(call.destination, MaybeEmpty::None);
assert_eq!(call.gas_limit, Uint(U256::from(0x1748766aa5u64)));
assert_eq!(call.value, Uint(U256::from(0)));
}
assert_eq!(call.destination, MaybeEmpty::None);
assert_eq!(call.gas_limit, Uint(U256::from(0x1748766aa5u64)));
assert_eq!(call.value, Uint(U256::from(0)));
}
#[test]
fn call_deserialization_full_dest() {
let s = r#"{
#[test]
fn call_deserialization_full_dest() {
let s = r#"{
"data" : "0x1234",
"destination" : "5a39ed1020c04d4d84539975b893a4e7c53eab6c",
"gasLimit" : "0x1748766aa5",
"value" : "0x00"
}"#;
let call: Call = serde_json::from_str(s).unwrap();
let call: Call = serde_json::from_str(s).unwrap();
assert_eq!(&call.data[..], &[0x12, 0x34]);
assert_eq!(call.destination, MaybeEmpty::Some(Address(Hash160::from_str("5a39ed1020c04d4d84539975b893a4e7c53eab6c").unwrap())));
assert_eq!(call.gas_limit, Uint(U256::from(0x1748766aa5u64)));
assert_eq!(call.value, Uint(U256::from(0)));
}
assert_eq!(&call.data[..], &[0x12, 0x34]);
assert_eq!(
call.destination,
MaybeEmpty::Some(Address(
Hash160::from_str("5a39ed1020c04d4d84539975b893a4e7c53eab6c").unwrap()
))
);
assert_eq!(call.gas_limit, Uint(U256::from(0x1748766aa5u64)));
assert_eq!(call.value, Uint(U256::from(0)));
}
}

View File

@@ -21,38 +21,38 @@ use uint::Uint;
/// Vm environment.
#[derive(Debug, PartialEq, Deserialize)]
pub struct Env {
/// Address.
#[serde(rename = "currentCoinbase")]
pub author: Address,
/// Difficulty
#[serde(rename = "currentDifficulty")]
pub difficulty: Uint,
/// Gas limit.
#[serde(rename = "currentGasLimit")]
pub gas_limit: Uint,
/// Number.
#[serde(rename = "currentNumber")]
pub number: Uint,
/// Timestamp.
#[serde(rename = "currentTimestamp")]
pub timestamp: Uint,
/// Address.
#[serde(rename = "currentCoinbase")]
pub author: Address,
/// Difficulty
#[serde(rename = "currentDifficulty")]
pub difficulty: Uint,
/// Gas limit.
#[serde(rename = "currentGasLimit")]
pub gas_limit: Uint,
/// Number.
#[serde(rename = "currentNumber")]
pub number: Uint,
/// Timestamp.
#[serde(rename = "currentTimestamp")]
pub timestamp: Uint,
}
#[cfg(test)]
mod tests {
use serde_json;
use vm::Env;
use serde_json;
use vm::Env;
#[test]
fn env_deserialization() {
let s = r#"{
#[test]
fn env_deserialization() {
let s = r#"{
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
"currentDifficulty" : "0x0100",
"currentGasLimit" : "0x0f4240",
"currentNumber" : "0x00",
"currentTimestamp" : "0x01"
}"#;
let _deserialized: Env = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
let _deserialized: Env = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
}

View File

@@ -16,14 +16,10 @@
//! Vm test loader.
pub mod call;
pub mod env;
pub mod test;
pub mod transaction;
pub mod vm;
pub mod call;
pub mod test;
pub use self::env::Env;
pub use self::transaction::Transaction;
pub use self::vm::Vm;
pub use self::call::Call;
pub use self::test::Test;
pub use self::{call::Call, env::Env, test::Test, transaction::Transaction, vm::Vm};

View File

@@ -16,10 +16,8 @@
//! Vm test deserializer.
use std::collections::BTreeMap;
use std::io::Read;
use serde_json;
use serde_json::Error;
use serde_json::{self, Error};
use std::{collections::BTreeMap, io::Read};
use vm::Vm;
/// Vm test deserializer.
@@ -27,17 +25,20 @@ use vm::Vm;
pub struct Test(BTreeMap<String, Vm>);
impl IntoIterator for Test {
type Item = <BTreeMap<String, Vm> as IntoIterator>::Item;
type IntoIter = <BTreeMap<String, Vm> as IntoIterator>::IntoIter;
type Item = <BTreeMap<String, Vm> as IntoIterator>::Item;
type IntoIter = <BTreeMap<String, Vm> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl Test {
/// Loads test from json.
pub fn load<R>(reader: R) -> Result<Self, Error> where R: Read {
serde_json::from_reader(reader)
}
/// Loads test from json.
pub fn load<R>(reader: R) -> Result<Self, Error>
where
R: Read,
{
serde_json::from_reader(reader)
}
}

View File

@@ -15,41 +15,41 @@
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
//! Executed transaction.
use bytes::Bytes;
use hash::Address;
use uint::Uint;
use bytes::Bytes;
/// Executed transaction.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Transaction {
/// Contract address.
pub address: Address,
/// Transaction sender.
#[serde(rename = "caller")]
pub sender: Address,
/// Contract code.
pub code: Bytes,
/// Input data.
pub data: Bytes,
/// Gas.
pub gas: Uint,
/// Gas price.
pub gas_price: Uint,
/// Transaction origin.
pub origin: Address,
/// Sent value.
pub value: Uint,
/// Contract address.
pub address: Address,
/// Transaction sender.
#[serde(rename = "caller")]
pub sender: Address,
/// Contract code.
pub code: Bytes,
/// Input data.
pub data: Bytes,
/// Gas.
pub gas: Uint,
/// Gas price.
pub gas_price: Uint,
/// Transaction origin.
pub origin: Address,
/// Sent value.
pub value: Uint,
}
#[cfg(test)]
mod tests {
use serde_json;
use vm::Transaction;
use serde_json;
use vm::Transaction;
#[test]
fn transaction_deserialization() {
let s = r#"{
#[test]
fn transaction_deserialization() {
let s = r#"{
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"caller" : "cd1722f2947def4cf144679da39c4c32bdc35681",
"code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01600055",
@@ -59,6 +59,6 @@ mod tests {
"origin" : "cd1722f2947def4cf144679da39c4c32bdc35681",
"value" : "0x0de0b6b3a7640000"
}"#;
let _deserialized: Transaction = serde_json::from_str(s).unwrap();
}
let _deserialized: Transaction = serde_json::from_str(s).unwrap();
}
}

View File

@@ -16,54 +16,54 @@
//! Vm execution env.
use bytes::Bytes;
use uint::Uint;
use hash::H256;
use blockchain::State;
use vm::{Transaction, Call, Env};
use bytes::Bytes;
use hash::H256;
use uint::Uint;
use vm::{Call, Env, Transaction};
/// Represents vm execution environment before and after execution of transaction.
#[derive(Debug, PartialEq, Deserialize)]
pub struct Vm {
/// Contract calls made internaly by executed transaction.
#[serde(rename = "callcreates")]
pub calls: Option<Vec<Call>>,
/// Env info.
pub env: Env,
/// Executed transaction
#[serde(rename = "exec")]
pub transaction: Transaction,
/// Gas left after transaction execution.
#[serde(rename = "gas")]
pub gas_left: Option<Uint>,
/// Hash of logs created during execution of transaction.
pub logs: Option<H256>,
/// Transaction output.
#[serde(rename = "out")]
pub output: Option<Bytes>,
/// Post execution vm state.
#[serde(rename = "post")]
pub post_state: Option<State>,
/// Pre execution vm state.
#[serde(rename = "pre")]
pub pre_state: State,
/// Contract calls made internaly by executed transaction.
#[serde(rename = "callcreates")]
pub calls: Option<Vec<Call>>,
/// Env info.
pub env: Env,
/// Executed transaction
#[serde(rename = "exec")]
pub transaction: Transaction,
/// Gas left after transaction execution.
#[serde(rename = "gas")]
pub gas_left: Option<Uint>,
/// Hash of logs created during execution of transaction.
pub logs: Option<H256>,
/// Transaction output.
#[serde(rename = "out")]
pub output: Option<Bytes>,
/// Post execution vm state.
#[serde(rename = "post")]
pub post_state: Option<State>,
/// Pre execution vm state.
#[serde(rename = "pre")]
pub pre_state: State,
}
impl Vm {
/// Returns true if transaction execution run out of gas.
pub fn out_of_gas(&self) -> bool {
self.calls.is_none()
}
/// Returns true if transaction execution run out of gas.
pub fn out_of_gas(&self) -> bool {
self.calls.is_none()
}
}
#[cfg(test)]
mod tests {
use serde_json;
use vm::Vm;
use serde_json;
use vm::Vm;
#[test]
fn vm_deserialization() {
let s = r#"{
#[test]
fn vm_deserialization() {
let s = r#"{
"callcreates" : [
],
"env" : {
@@ -107,7 +107,7 @@ mod tests {
}
}
}"#;
let _deserialized: Vm = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
let _deserialized: Vm = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
}