Reformat the source code
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
178
json/src/hash.rs
178
json/src/hash.rs
@@ -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()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
))
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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!(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
),
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")),
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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)))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"))]
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
191
json/src/uint.rs
191
json/src/uint.rs
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user