diff --git a/Cargo.lock b/Cargo.lock index feecc2dd640..b5e388708d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1317,9 +1317,9 @@ name = "ethjson" version = "0.1.0" dependencies = [ "ethereum-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "macros 0.1.0", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/Cargo.toml b/Cargo.toml index 369ff48f4fe..8e39aed2bdb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -92,7 +92,6 @@ default = ["accounts"] accounts = ["ethcore-accounts", "parity-rpc/accounts"] miner-debug = ["ethcore/miner-debug"] json-tests = ["ethcore/json-tests"] -ci-skip-tests = ["ethcore/ci-skip-tests"] test-heavy = ["ethcore/test-heavy"] evm-debug = ["ethcore/evm-debug"] evm-debug-tests = ["ethcore/evm-debug-tests"] diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index c7a0e6063f6..ca79c029b33 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -78,6 +78,8 @@ blooms-db = { path = "../util/blooms-db" } criterion = "0.2" env_logger = "0.5" ethcore-accounts = { path = "../accounts" } +ethjson = { path = "../json", features = ["test-helpers"] } +ethkey = { path = "../accounts/ethkey" } fetch = { path = "../util/fetch" } kvdb-rocksdb = "0.1.3" parity-runtime = { path = "../util/runtime" } @@ -109,8 +111,6 @@ evm-debug-tests = ["evm-debug", "evm/evm-debug-tests"] slow-blocks = [] # Run JSON consensus tests. json-tests = ["env_logger", "test-helpers", "to-pod-full"] -# Skip JSON consensus tests with pending issues. -ci-skip-tests = [] # Run memory/cpu heavy tests. test-heavy = [] # Compile test helpers diff --git a/ethcore/builtin/src/lib.rs b/ethcore/builtin/src/lib.rs index 8e68d2940d7..012d071f163 100644 --- a/ethcore/builtin/src/lib.rs +++ b/ethcore/builtin/src/lib.rs @@ -218,8 +218,8 @@ impl Builtin { impl From for Builtin { fn from(b: ethjson::spec::Builtin) -> Self { let pricer: Box = match b.pricing { - ethjson::spec::Pricing::Blake2F(cost_per_round) => { - Box::new(cost_per_round) + ethjson::spec::Pricing::Blake2F { gas_per_round } => { + Box::new(gas_per_round) }, ethjson::spec::Pricing::Linear(linear) => { Box::new(Linear { diff --git a/ethcore/pod-account/src/lib.rs b/ethcore/pod-account/src/lib.rs index ea004f01715..9f2f0420036 100644 --- a/ethcore/pod-account/src/lib.rs +++ b/ethcore/pod-account/src/lib.rs @@ -82,21 +82,6 @@ impl PodAccount { } } -impl From for PodAccount { - fn from(a: ethjson::blockchain::Account) -> Self { - PodAccount { - balance: a.balance.into(), - nonce: a.nonce.into(), - code: Some(a.code.into()), - storage: a.storage.into_iter().map(|(key, value)| { - let key: U256 = key.into(); - let value: U256 = value.into(); - (BigEndianHash::from_uint(&key), BigEndianHash::from_uint(&value)) - }).collect(), - } - } -} - impl From for PodAccount { fn from(a: ethjson::spec::Account) -> Self { PodAccount { diff --git a/ethcore/res/ethereum/goerli.json b/ethcore/res/ethereum/goerli.json index 2a0fdc0cabd..e7aaa4c485a 100644 --- a/ethcore/res/ethereum/goerli.json +++ b/ethcore/res/ethereum/goerli.json @@ -26,6 +26,11 @@ "eip1052Transition": "0x0", "eip1283Transition": "0x0", "eip1283DisableTransition": "0x0", + "eip1283ReenableTransition": "0x17d433", + "eip1344Transition": "0x17d433", + "eip1706Transition": "0x17d433", + "eip1884Transition": "0x17d433", + "eip2028Transition": "0x17d433", "gasLimitBoundDivisor": "0x400", "maxCodeSize": "0x6000", "maxCodeSizeTransition": "0x0", @@ -126,7 +131,7 @@ "builtin": { "name": "alt_bn128_add", "activate_at": "0x00", - "eip1108_transition": "0x7fffffffffffff", + "eip1108_transition": "0x17d433", "pricing": { "alt_bn128_const_operations": { "price": 500, @@ -140,7 +145,7 @@ "builtin": { "name": "alt_bn128_mul", "activate_at": "0x00", - "eip1108_transition": "0x7fffffffffffff", + "eip1108_transition": "0x17d433", "pricing": { "alt_bn128_const_operations": { "price": 40000, @@ -154,7 +159,7 @@ "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x00", - "eip1108_transition": "0x7fffffffffffff", + "eip1108_transition": "0x17d433", "pricing": { "alt_bn128_pairing": { "base": 100000, @@ -166,7 +171,16 @@ } }, "0x0000000000000000000000000000000000000009": { - "balance": "0x1" + "balance": "0x1", + "builtin": { + "name": "blake2_f", + "activate_at": "0x17d433", + "pricing": { + "blake2_f": { + "gas_per_round": 1 + } + } + } }, "0x000000000000000000000000000000000000000a": { "balance": "0x1" diff --git a/ethcore/res/ethereum/istanbul_test.json b/ethcore/res/ethereum/istanbul_test.json new file mode 100644 index 00000000000..1276dc4c53c --- /dev/null +++ b/ethcore/res/ethereum/istanbul_test.json @@ -0,0 +1,120 @@ +{ + "name": "Istanbul (test)", + "engine": { + "Ethash": { + "params": { + "minimumDifficulty": "0x020000", + "difficultyBoundDivisor": "0x0800", + "durationLimit": "0x0d", + "blockReward": "0x1BC16D674EC80000", + "homesteadTransition": "0x0", + "eip100bTransition": "0x0", + "difficultyBombDelays": { + "0": 5000000 + } + } + } + }, + "params": { + "gasLimitBoundDivisor": "0x0400", + "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", + "accountStartNonce": "0x00", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID" : "0x1", + "maxCodeSize": 24576, + "maxCodeSizeTransition": "0x0", + "eip150Transition": "0x0", + "eip160Transition": "0x0", + "eip161abcTransition": "0x0", + "eip161dTransition": "0x0", + "eip140Transition": "0x0", + "eip211Transition": "0x0", + "eip214Transition": "0x0", + "eip155Transition": "0x0", + "eip658Transition": "0x0", + "eip145Transition": "0x0", + "eip1014Transition": "0x0", + "eip1052Transition": "0x0", + "eip1283Transition": "0x0", + "eip1283DisableTransition": "0x0", + "eip1283ReenableTransition": "0x0", + "eip1344Transition": "0x0", + "eip1706Transition": "0x0", + "eip1884Transition": "0x0", + "eip2028Transition": "0x0" + }, + "genesis": { + "seal": { + "ethereum": { + "nonce": "0x0000000000000042", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "difficulty": "0x400000000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa", + "gasLimit": "0x1388" + }, + "accounts": { + "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 20 } } } }, + "0000000000000000000000000000000000000006": { + "builtin": { + "name": "alt_bn128_add", + "activate_at": "0x00", + "eip1108_transition": "0x0", + "pricing": { + "alt_bn128_const_operations": { + "price": 500, + "eip1108_transition_price": 150 + } + } + } + }, + "0000000000000000000000000000000000000007": { + "builtin": { + "name": "alt_bn128_mul", + "activate_at": "0x00", + "eip1108_transition": "0x0", + "pricing": { + "alt_bn128_const_operations": { + "price": 40000, + "eip1108_transition_price": 6000 + } + } + } + }, + "0000000000000000000000000000000000000008": { + "builtin": { + "name": "alt_bn128_pairing", + "activate_at": "0x00", + "eip1108_transition": "0x0", + "pricing": { + "alt_bn128_pairing": { + "base": 100000, + "pair": 80000, + "eip1108_transition_base": 45000, + "eip1108_transition_pair": 34000 + } + } + } + }, + "0000000000000000000000000000000000000009": { + "builtin": { + "name": "blake2_f", + "activate_at": "0x00", + "pricing": { + "blake2_f": { + "gas_per_round": 1 + } + } + } + } + } +} diff --git a/ethcore/res/ethereum/kovan.json b/ethcore/res/ethereum/kovan.json index 7e9bf761697..34755e3ec2f 100644 --- a/ethcore/res/ethereum/kovan.json +++ b/ethcore/res/ethereum/kovan.json @@ -64,6 +64,11 @@ "eip1052Transition": "0x8c6180", "eip1283Transition": "0x8c6180", "eip1283DisableTransition": "0x9c7b61", + "eip1283ReenableTransition": "0xd751a5", + "eip1344Transition": "0xd751a5", + "eip1706Transition": "0xd751a5", + "eip1884Transition": "0xd751a5", + "eip2028Transition": "0xd751a5", "kip4Transition": "0x8c6180", "kip6Transition": "0x8c6180" }, @@ -5344,7 +5349,7 @@ "builtin": { "name": "alt_bn128_add", "activate_at": "0x4d50f8", - "eip1108_transition": "0x7fffffffffffff", + "eip1108_transition": "0xd751a5", "pricing": { "alt_bn128_const_operations": { "price": 500, @@ -5357,7 +5362,7 @@ "builtin": { "name": "alt_bn128_mul", "activate_at": "0x4d50f8", - "eip1108_transition": "0x7fffffffffffff", + "eip1108_transition": "0xd751a5", "pricing": { "alt_bn128_const_operations": { "price": 40000, @@ -5370,7 +5375,7 @@ "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x4d50f8", - "eip1108_transition": "0x7fffffffffffff", + "eip1108_transition": "0xd751a5", "pricing": { "alt_bn128_pairing": { "base": 100000, @@ -5381,6 +5386,17 @@ } } }, + "0x0000000000000000000000000000000000000009": { + "builtin": { + "name": "blake2_f", + "activate_at": "0xd751a5", + "pricing": { + "blake2_f": { + "gas_per_round": 1 + } + } + } + }, "0x00521965e7bd230323c423d96c657db5b79d099f": { "balance": "1606938044258990275541962092341162602522202993782792835301376" } diff --git a/ethcore/res/ethereum/rinkeby.json b/ethcore/res/ethereum/rinkeby.json index b6c7abe20d7..3945b88118d 100644 --- a/ethcore/res/ethereum/rinkeby.json +++ b/ethcore/res/ethereum/rinkeby.json @@ -26,6 +26,11 @@ "eip1052Transition": "0x37db77", "eip1283Transition": "0x37db77", "eip1283DisableTransition": "0x41efd2", + "eip1283ReenableTransition": "0x52efd1", + "eip1344Transition": "0x52efd1", + "eip1706Transition": "0x52efd1", + "eip1884Transition": "0x52efd1", + "eip2028Transition": "0x52efd1", "gasLimitBoundDivisor": "0x400", "maxCodeSize": "0x6000", "maxCodeSizeTransition": "0x0", @@ -120,7 +125,7 @@ "builtin": { "name": "alt_bn128_add", "activate_at": "0xfcc25", - "eip1108_transition": "0x7fffffffffffff", + "eip1108_transition": "0x52efd1", "pricing": { "alt_bn128_const_operations": { "price": 500, @@ -133,7 +138,7 @@ "builtin": { "name": "alt_bn128_mul", "activate_at": "0xfcc25", - "eip1108_transition": "0x7fffffffffffff", + "eip1108_transition": "0x52efd1", "pricing": { "alt_bn128_const_operations": { "price": 40000, @@ -146,7 +151,7 @@ "builtin": { "name": "alt_bn128_pairing", "activate_at": "0xfcc25", - "eip1108_transition": "0x7fffffffffffff", + "eip1108_transition": "0x52efd1", "pricing": { "alt_bn128_pairing": { "base": 100000, @@ -158,7 +163,16 @@ } }, "0x0000000000000000000000000000000000000009": { - "balance": "0x1" + "balance": "0x1", + "builtin": { + "name": "blake2_f", + "activate_at": "0x52efd1", + "pricing": { + "blake2_f": { + "gas_per_round": 1 + } + } + } }, "0x000000000000000000000000000000000000000a": { "balance": "0x1" diff --git a/ethcore/res/ethereum/ropsten.json b/ethcore/res/ethereum/ropsten.json index 2d23a0a2974..aefca8682cc 100644 --- a/ethcore/res/ethereum/ropsten.json +++ b/ethcore/res/ethereum/ropsten.json @@ -45,7 +45,12 @@ "eip1014Transition": "0x408b70", "eip1052Transition": "0x408b70", "eip1283Transition": "0x408b70", - "eip1283DisableTransition": "0x4b5e82" + "eip1283DisableTransition": "0x4b5e82", + "eip1283ReenableTransition": "0x62f756", + "eip1344Transition": "0x62f756", + "eip1706Transition": "0x62f756", + "eip1884Transition": "0x62f756", + "eip2028Transition": "0x62f756" }, "genesis": { "seal": { @@ -2735,7 +2740,7 @@ "builtin": { "name": "alt_bn128_add", "activate_at": "0x19f0a0", - "eip1108_transition": "0x7fffffffffffff", + "eip1108_transition": "0x62f756", "pricing": { "alt_bn128_const_operations": { "price": 500, @@ -2750,7 +2755,7 @@ "builtin": { "name": "alt_bn128_mul", "activate_at": "0x19f0a0", - "eip1108_transition": "0x7fffffffffffff", + "eip1108_transition": "0x62f756", "pricing": { "alt_bn128_const_operations": { "price": 40000, @@ -2765,7 +2770,7 @@ "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x19f0a0", - "eip1108_transition": "0x7fffffffffffff", + "eip1108_transition": "0x62f756", "pricing": { "alt_bn128_pairing": { "base": 100000, @@ -2777,7 +2782,16 @@ } }, "0x0000000000000000000000000000000000000009": { - "balance": "0x1" + "balance": "0x1", + "builtin": { + "name": "blake2_f", + "activate_at": "0x62f756", + "pricing": { + "blake2_f": { + "gas_per_round": 1 + } + } + } }, "0x000000000000000000000000000000000000000a": { "balance": "0x0" diff --git a/ethcore/res/ethereum/st_peters_test.json b/ethcore/res/ethereum/st_peters_test.json index 9ae2f748949..768e6057fd2 100644 --- a/ethcore/res/ethereum/st_peters_test.json +++ b/ethcore/res/ethereum/st_peters_test.json @@ -36,6 +36,7 @@ "eip145Transition": "0x0", "eip1014Transition": "0x0", "eip1052Transition": "0x0", + "eip1283Transition": "0x0", "eip1283DisableTransition": "0x0" }, "genesis": { diff --git a/ethcore/res/ethereum/tests b/ethcore/res/ethereum/tests index 725dbc73a54..d4f86ecf4aa 160000 --- a/ethcore/res/ethereum/tests +++ b/ethcore/res/ethereum/tests @@ -1 +1 @@ -Subproject commit 725dbc73a54649e22a00330bd0f4d6699a5060e5 +Subproject commit d4f86ecf4aa7c44a40bc0c972fd3e25d63ef5d92 diff --git a/ethcore/res/ethereum/tests-issues/currents.json b/ethcore/res/ethereum/tests-issues/currents.json index d4d3f5e3aae..33759a066f8 100644 --- a/ethcore/res/ethereum/tests-issues/currents.json +++ b/ethcore/res/ethereum/tests-issues/currents.json @@ -1,4 +1,57 @@ { - "block": [], - "state": [] + "block": [ + { + "reference": "Issue https://github.com/paritytech/parity-ethereum/issues/11073 (also see https://github.com/paritytech/parity-ethereum/pull/10923)", + "failing": "stRevertTest", + "subtests": [ + "RevertPrecompiledTouch_d0g0v0_Byzantium", + "RevertPrecompiledTouch_d0g0v0_Constantinople", + "RevertPrecompiledTouch_d0g0v0_ConstantinopleFix", + "RevertPrecompiledTouch_d0g0v0_EIP158", + "RevertPrecompiledTouch_d3g0v0_ConstantinopleFix", + "RevertPrecompiledTouchCC_d0g0v0_Byzantium", + "RevertPrecompiledTouchCC_d0g0v0_Constantinople", + "RevertPrecompiledTouchCC_d0g0v0_EIP158", + "RevertPrecompiledTouchDC_d0g0v0_Byzantium", + "RevertPrecompiledTouchDC_d0g0v0_Constantinople", + "RevertPrecompiledTouchDC_d0g0v0_EIP158", + "RevertPrecompiledTouchExactOOG_d7g1v0_ConstantinopleFix", + "RevertPrecompiledTouchExactOOG_d31g1v0_ConstantinopleFix", + "RevertPrecompiledTouch_storage_d3g0v0_ConstantinopleFix", + "RevertPrecompiledTouch_storage_d0g0v0_ConstantinopleFix" + ] + } + ], + "state": [ + { + "reference": "Issue https://github.com/paritytech/parity-ethereum/issues/11078 (also see https://github.com/paritytech/parity-ethereum/pull/10923)", + "failing": "stRevertTest", + "subtests": { + "RevertPrecompiledTouch_storage": { + "subnumbers": ["1", "2"], + "chain": "St. Peter's (test)" + } + } + }, + { + "reference": "Issue https://github.com/paritytech/parity-ethereum/issues/11079 (also see https://github.com/paritytech/parity-ethereum/pull/10923)", + "failing": "stRevertTest", + "subtests": { + "RevertPrecompiledTouchExactOOG": { + "subnumbers": ["61", "64"], + "chain": "St. Peter's (test)" + } + } + }, + { + "reference": "Issue https://github.com/paritytech/parity-ethereum/issues/11080 (also see https://github.com/paritytech/parity-ethereum/pull/10923)", + "failing": "stRevertTest", + "subtests": { + "RevertPrecompiledTouch": { + "subnumbers": ["1", "2"], + "chain": "St. Peter's (test)" + } + } + } + ] } diff --git a/ethcore/src/client/evm_test_client.rs b/ethcore/src/client/evm_test_client.rs index 1e56e8c2d99..ad08ecef550 100644 --- a/ethcore/src/client/evm_test_client.rs +++ b/ethcore/src/client/evm_test_client.rs @@ -94,6 +94,7 @@ impl<'a> EvmTestClient<'a> { ForkSpec::Byzantium => Some(ethereum::new_byzantium_test()), ForkSpec::Constantinople => Some(ethereum::new_constantinople_test()), ForkSpec::ConstantinopleFix => Some(ethereum::new_constantinople_fix_test()), + ForkSpec::Istanbul => Some(ethereum::new_istanbul_test()), ForkSpec::EIP158ToByzantiumAt5 => Some(ethereum::new_transition_test()), ForkSpec::FrontierToHomesteadAt5 | ForkSpec::HomesteadToDaoAt5 | ForkSpec::HomesteadToEIP150At5 => None, } diff --git a/ethcore/src/ethereum/mod.rs b/ethcore/src/ethereum/mod.rs index ba4138de59f..2185e42df98 100644 --- a/ethcore/src/ethereum/mod.rs +++ b/ethcore/src/ethereum/mod.rs @@ -166,6 +166,9 @@ pub fn new_constantinople_test() -> Spec { load(None, include_bytes!("../../res/ /// Create a new Foundation St. Peter's (Contantinople Fix) era spec. pub fn new_constantinople_fix_test() -> Spec { load(None, include_bytes!("../../res/ethereum/st_peters_test.json")) } +/// Create a new Foundation Istanbul era spec. +pub fn new_istanbul_test() -> Spec { load(None, include_bytes!("../../res/ethereum/istanbul_test.json")) } + /// Create a new Musicoin-MCIP3-era spec. pub fn new_mcip3_test() -> Spec { load(None, include_bytes!("../../res/ethereum/mcip3_test.json")) } diff --git a/ethcore/src/json_tests/chain.rs b/ethcore/src/json_tests/chain.rs index 4488d0f326e..d4cf6cecf75 100644 --- a/ethcore/src/json_tests/chain.rs +++ b/ethcore/src/json_tests/chain.rs @@ -18,49 +18,49 @@ use std::path::Path; use std::sync::Arc; use client::{EvmTestClient, Client, ClientConfig, ChainInfo, ImportBlock}; use spec::Genesis; -use ethjson; +use ethjson::test_helpers::blockchain; use miner::Miner; use io::IoChannel; use test_helpers; -use verification::queue::kind::blocks::Unverified; -use verification::VerifierType; -use super::SKIP_TEST_STATE; +use verification::{VerifierType, queue::kind::BlockLike, queue::kind::blocks::Unverified}; +use super::SKIP_TESTS; use super::HookType; -/// Run chain jsontests on a given folder. -pub fn run_test_path(p: &Path, skip: &[&'static str], h: &mut H) { - ::json_tests::test_common::run_test_path(p, skip, json_chain_test, h) -} - -/// Run chain jsontests on a given file. -pub fn run_test_file(p: &Path, h: &mut H) { - ::json_tests::test_common::run_test_file(p, json_chain_test, h) -} - +#[allow(dead_code)] fn skip_test(name: &String) -> bool { - SKIP_TEST_STATE.block.iter().any(|block_test|block_test.subtests.contains(name)) + SKIP_TESTS + .block + .iter() + .any(|block_test|block_test.subtests.contains(name)) } -pub fn json_chain_test(json_data: &[u8], start_stop_hook: &mut H) -> Vec { +#[allow(dead_code)] +pub fn json_chain_test(path: &Path, json_data: &[u8], start_stop_hook: &mut H) -> Vec { let _ = ::env_logger::try_init(); - let tests = ethjson::blockchain::Test::load(json_data).unwrap(); + let tests = blockchain::Test::load(json_data) + .expect(&format!("Could not parse JSON chain test data from {}", path.display())); let mut failed = Vec::new(); for (name, blockchain) in tests.into_iter() { if skip_test(&name) { - println!(" - {} | {:?} Ignoring tests because in skip list", name, blockchain.network); + println!(" - {} | {:?}: SKIPPED", name, blockchain.network); continue; } + start_stop_hook(&name, HookType::OnStart); let mut fail = false; { - let mut fail_unless = |cond: bool| if !cond && !fail { - failed.push(name.clone()); - flushln!("FAIL"); - fail = true; - true - } else {false}; + let mut fail_unless = |cond: bool| { + if !cond && !fail { + failed.push(name.clone()); + flushln!("FAIL"); + fail = true; + true + } else { + false + } + }; flush!(" - {}...", name); @@ -68,7 +68,7 @@ pub fn json_chain_test(json_data: &[u8], start_stop_ho let mut spec = match EvmTestClient::spec_from_json(&blockchain.network) { Some(spec) => spec, None => { - println!(" - {} | {:?} Ignoring tests because of missing spec", name, blockchain.network); + println!(" - {} | {:?} Ignoring tests because of missing chainspec", name, blockchain.network); continue; } }; @@ -77,30 +77,44 @@ pub fn json_chain_test(json_data: &[u8], start_stop_ho let state = From::from(blockchain.pre_state.clone()); spec.set_genesis_state(state).expect("Failed to overwrite genesis state"); spec.overwrite_genesis_params(genesis); - assert!(spec.is_state_root_valid()); +// assert!(spec.is_state_root_valid()); spec }; { let db = test_helpers::new_db(); let mut config = ClientConfig::default(); - if ethjson::blockchain::Engine::NoProof == blockchain.engine { + if ethjson::test_helpers::blockchain::Engine::NoProof == blockchain.engine { config.verifier_type = VerifierType::CanonNoSeal; config.check_seal = false; } config.history = 8; + config.queue.verifier_settings.num_verifiers = 1; let client = Client::new( config, &spec, db, Arc::new(Miner::new_for_tests(&spec, None)), IoChannel::disconnected(), - ).unwrap(); + ).expect("Failed to instantiate a new Client"); + for b in blockchain.blocks_rlp() { - if let Ok(block) = Unverified::from_rlp(b) { - let _ = client.import_block(block); - client.flush_queue(); - client.import_verified_blocks(); + let bytes_len = b.len(); + let block = Unverified::from_rlp(b); + match block { + Ok(block) => { + let num = block.header.number(); + let hash = block.hash(); + trace!(target: "json-tests", "{} – Importing {} bytes. Block #{}/{}", name, bytes_len, num, hash); + let res = client.import_block(block); + if let Err(e) = res { + warn!(target: "json-tests", "{} – Error importing block #{}/{}: {:?}", name, num, hash, e); + } + client.flush_queue(); + }, + Err(decoder_err) => { + warn!(target: "json-tests", "Error decoding test block: {:?} ({} bytes)", decoder_err, bytes_len); + } } } fail_unless(client.chain_info().best_block_hash == blockchain.best_block.into()); @@ -109,24 +123,31 @@ pub fn json_chain_test(json_data: &[u8], start_stop_ho if !fail { flushln!("ok"); + } else { + flushln!("fail"); } start_stop_hook(&name, HookType::OnStop); } - println!("!!! {:?} tests from failed.", failed.len()); + if failed.len() > 0 { + println!("!!! {:?} tests failed.", failed.len()); + } failed } #[cfg(test)] mod block_tests { + use std::path::Path; + use super::json_chain_test; use json_tests::HookType; - fn do_json_test(json_data: &[u8], h: &mut H) -> Vec { - json_chain_test(json_data, h) + fn do_json_test(path: &Path, json_data: &[u8], h: &mut H) -> Vec { + json_chain_test(path, json_data, h) } - + //todo[dvdplm] do these tests match all folders in `res/` or are there tests we're missing? + //Issue: https://github.com/paritytech/parity-ethereum/issues/11085 declare_test!{BlockchainTests_bcBlockGasLimitTest, "BlockchainTests/bcBlockGasLimitTest"} declare_test!{BlockchainTests_bcExploitTest, "BlockchainTests/bcExploitTest"} declare_test!{BlockchainTests_bcForgedTest, "BlockchainTests/bcForgedTest"} @@ -173,7 +194,12 @@ mod block_tests { declare_test!{BlockchainTests_GeneralStateTest_stRandom2, "BlockchainTests/GeneralStateTests/stRandom2/"} declare_test!{BlockchainTests_GeneralStateTest_stRecursiveCreate, "BlockchainTests/GeneralStateTests/stRecursiveCreate/"} declare_test!{BlockchainTests_GeneralStateTest_stRefundTest, "BlockchainTests/GeneralStateTests/stRefundTest/"} - declare_test!{BlockchainTests_GeneralStateTest_stReturnDataTest, "BlockchainTests/GeneralStateTests/stReturnDataTest/"} + declare_test!{ BlockchainTests_GeneralStateTest_stReturnDataTest, "BlockchainTests/GeneralStateTests/stReturnDataTest/"} + // todo[dvdplm]: + // "RevertPrecompiledTouch_storage" contains 4 tests, only two fails + // "RevertPrecompiledTouchExactOOG" contains a ton of tests, only two fails + // "RevertPrecompiledTouch" has 4 tests, 2 failures + // Ignored in currents.json, issue: https://github.com/paritytech/parity-ethereum/issues/11073 declare_test!{BlockchainTests_GeneralStateTest_stRevertTest, "BlockchainTests/GeneralStateTests/stRevertTest/"} declare_test!{BlockchainTests_GeneralStateTest_stShift, "BlockchainTests/GeneralStateTests/stShift/"} declare_test!{BlockchainTests_GeneralStateTest_stSolidityTest, "BlockchainTests/GeneralStateTests/stSolidityTest/"} diff --git a/ethcore/src/json_tests/difficulty.rs b/ethcore/src/json_tests/difficulty.rs index bf3a48fff19..d7c9a02d9a8 100644 --- a/ethcore/src/json_tests/difficulty.rs +++ b/ethcore/src/json_tests/difficulty.rs @@ -14,16 +14,24 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -use ethjson; -use types::header::Header; +use std::path::Path; + use ethereum_types::U256; +use ethjson::test_helpers::difficulty::DifficultyTest; +use types::header::Header; use spec::Spec; use super::HookType; -pub fn json_difficulty_test(json_data: &[u8], spec: Spec, start_stop_hook: &mut H) -> Vec { - let _ = ::env_logger::try_init(); - let tests = ethjson::test::DifficultyTest::load(json_data).unwrap(); +pub fn json_difficulty_test( + path: &Path, + json_data: &[u8], + spec: Spec, + start_stop_hook: &mut H +) -> Vec { + let _ = env_logger::try_init(); + let tests = DifficultyTest::load(json_data) + .expect(&format!("Could not parse JSON difficulty test data from {}", path.display())); let engine = &spec.engine; for (name, test) in tests.into_iter() { @@ -54,29 +62,28 @@ pub fn json_difficulty_test(json_data: &[u8], spec: Sp macro_rules! difficulty_json_test { ( $spec:ident ) => { - - use super::json_difficulty_test; - use tempdir::TempDir; - use json_tests::HookType; - - fn do_json_test(json_data: &[u8], h: &mut H) -> Vec { - let tempdir = TempDir::new("").unwrap(); - json_difficulty_test(json_data, ::ethereum::$spec(&tempdir.path()), h) - } - + use std::path::Path; + use super::json_difficulty_test; + use tempdir::TempDir; + use json_tests::HookType; + + fn do_json_test(path: &Path, json_data: &[u8], h: &mut H) -> Vec { + let tempdir = TempDir::new("").unwrap(); + json_difficulty_test(path, json_data, ::ethereum::$spec(&tempdir.path()), h) + } } } macro_rules! difficulty_json_test_nopath { ( $spec:ident ) => { + use std::path::Path; - use super::json_difficulty_test; - use json_tests::HookType; - - fn do_json_test(json_data: &[u8], h: &mut H) -> Vec { - json_difficulty_test(json_data, ::ethereum::$spec(), h) - } + use super::json_difficulty_test; + use json_tests::HookType; + fn do_json_test(path: &Path, json_data: &[u8], h: &mut H) -> Vec { + json_difficulty_test(path, json_data, ::ethereum::$spec(), h) + } } } diff --git a/ethcore/src/json_tests/executive.rs b/ethcore/src/json_tests/executive.rs index 6258648d994..239c81f3cf3 100644 --- a/ethcore/src/json_tests/executive.rs +++ b/ethcore/src/json_tests/executive.rs @@ -230,16 +230,22 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for TestExt<'a, T, V, B> } } -fn do_json_test(json_data: &[u8], h: &mut H) -> Vec { +fn do_json_test(path: &Path, json_data: &[u8], h: &mut H) -> Vec { let vms = VMType::all(); vms .iter() - .flat_map(|vm| do_json_test_for(vm, json_data, h)) + .flat_map(|vm| do_json_test_for(path, vm, json_data, h)) .collect() } -fn do_json_test_for(vm_type: &VMType, json_data: &[u8], start_stop_hook: &mut H) -> Vec { - let tests = ethjson::vm::Test::load(json_data).unwrap(); +fn do_json_test_for( + path: &Path, + vm_type: &VMType, + json_data: &[u8], + start_stop_hook: &mut H +) -> Vec { + let tests = ethjson::test_helpers::vm::Test::load(json_data) + .expect(&format!("Could not parse JSON executive test data from {}", path.display())); let mut failed = Vec::new(); for (name, vm) in tests.into_iter() { @@ -331,15 +337,15 @@ fn do_json_test_for(vm_type: &VMType, json_data: &[u8] for (address, account) in vm.post_state.unwrap().into_iter() { let address = address.into(); - let code: Vec = account.code.into(); + let code: Vec = account.code.expect("code is missing from json; test should have code").into(); let found_code = try_fail!(state.code(&address)); let found_balance = try_fail!(state.balance(&address)); let found_nonce = try_fail!(state.nonce(&address)); fail_unless(found_code.as_ref().map_or_else(|| code.is_empty(), |c| &**c == &code), "code is incorrect"); - fail_unless(found_balance == account.balance.into(), "balance is incorrect"); - fail_unless(found_nonce == account.nonce.into(), "nonce is incorrect"); - for (k, v) in account.storage { + fail_unless(account.balance.as_ref().map_or(false, |b| b.0 == found_balance), "balance is incorrect"); + fail_unless(account.nonce.as_ref().map_or(false, |n| n.0 == found_nonce), "nonce is incorrect"); + for (k, v) in account.storage.expect("test should have storage") { let key: U256 = k.into(); let value: U256 = v.into(); let found_storage = try_fail!(state.storage_at(&address, &BigEndianHash::from_uint(&key))); diff --git a/ethcore/src/json_tests/mod.rs b/ethcore/src/json_tests/mod.rs index 99cbdb21eec..d1787e1d3da 100644 --- a/ethcore/src/json_tests/mod.rs +++ b/ethcore/src/json_tests/mod.rs @@ -30,17 +30,7 @@ mod skip; mod difficulty; pub use self::test_common::HookType; - -pub use self::transaction::run_test_path as run_transaction_test_path; -pub use self::transaction::run_test_file as run_transaction_test_file; pub use self::executive::run_test_path as run_executive_test_path; pub use self::executive::run_test_file as run_executive_test_file; -pub use self::state::run_test_path as run_state_test_path; -pub use self::state::run_test_file as run_state_test_file; -pub use self::chain::run_test_path as run_chain_test_path; -pub use self::chain::run_test_file as run_chain_test_file; -pub use self::trie::run_generic_test_path as run_generic_trie_test_path; -pub use self::trie::run_generic_test_file as run_generic_trie_test_file; -pub use self::trie::run_secure_test_path as run_secure_trie_test_path; -pub use self::trie::run_secure_test_file as run_secure_trie_test_file; -use self::skip::SKIP_TEST_STATE; + +use self::skip::SKIP_TESTS; diff --git a/ethcore/src/json_tests/skip.rs b/ethcore/src/json_tests/skip.rs index b6ef9795f69..30ed83e509c 100644 --- a/ethcore/src/json_tests/skip.rs +++ b/ethcore/src/json_tests/skip.rs @@ -14,21 +14,30 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -//! State tests to skip. +//! State or blockchain tests to skip. +//! +//! Looks in the `ethereum/tests/test-issues/currents.json` file. This file contains two +//! collections, `block` and `state`, each with a different format to specify single tests to skip. +//! +//! To skip a blockchain test, add a JSON object to the `block` array, where `failing` names the +//! leaf folder with the tests to skip. The `subtests` array contains the names of the tests to skip. +//! Note that this does not handle duplicate folder names, e.g. `ValidBlocks/funTests/` and +//! `Something/funTests` would both be matched when `failing` is set to `funTests`. +//! +//! To skip a state test, add a JSON object to the `state` array. The `failing` works like for block +//! tests, but the `subtests` key is an object on the form: +//! "testName": {"subnumbers": [INDEX_OF_SKIPPED_SUBTESTS | "*"], "chain": "Blockchain name (informational)"}` +//! +//! Use the `reference` key to point to the github issue tracking to solution to the problem. +//! +//! Note: the `declare_test!` macro can also be use to skip tests, but skips entire files rather +//! than single tests. -use ethjson; +use ethjson::test_helpers::skip::SkipTests; -#[cfg(feature="ci-skip-tests")] -lazy_static!{ - pub static ref SKIP_TEST_STATE: ethjson::test::SkipStates = { +lazy_static! { + pub static ref SKIP_TESTS: SkipTests = { let skip_data = include_bytes!("../../res/ethereum/tests-issues/currents.json"); - ethjson::test::SkipStates::load(&skip_data[..]).expect("No invalid json allowed") - }; -} - -#[cfg(not(feature="ci-skip-tests"))] -lazy_static!{ - pub static ref SKIP_TEST_STATE: ethjson::test::SkipStates = { - ethjson::test::SkipStates::empty() + SkipTests::load(&skip_data[..]).expect("JSON from disk is valid") }; } diff --git a/ethcore/src/json_tests/state.rs b/ethcore/src/json_tests/state.rs index c51a2c361c2..226666c9f0e 100644 --- a/ethcore/src/json_tests/state.rs +++ b/ethcore/src/json_tests/state.rs @@ -22,34 +22,31 @@ use client::{EvmTestClient, EvmTestError, TransactErr, TransactSuccess}; use ethjson; use types::transaction::SignedTransaction; use vm::EnvInfo; -use super::SKIP_TEST_STATE; +use super::SKIP_TESTS; use super::HookType; -/// Run state jsontests on a given folder. -pub fn run_test_path(p: &Path, skip: &[&'static str], h: &mut H) { - ::json_tests::test_common::run_test_path(p, skip, json_chain_test, h) -} - -/// Run state jsontests on a given file. -pub fn run_test_file(p: &Path, h: &mut H) { - ::json_tests::test_common::run_test_file(p, json_chain_test, h) -} - +#[allow(dead_code)] fn skip_test(subname: &str, chain: &String, number: usize) -> bool { - SKIP_TEST_STATE.state.iter().any(|state_test|{ + trace!(target: "json-tests", "[state, skip_test] subname: '{}', chain: '{}', number: {}", subname, chain, number); + SKIP_TESTS.state.iter().any(|state_test|{ if let Some(subtest) = state_test.subtests.get(subname) { + trace!(target: "json-tests", "[state, skip_test] Maybe skipping {:?}", subtest); chain == &subtest.chain && - (subtest.subnumbers[0] == "*" - || subtest.subnumbers.contains(&number.to_string())) + ( + subtest.subnumbers[0] == "*" || + subtest.subnumbers.contains(&number.to_string()) + ) } else { false } }) } -pub fn json_chain_test(json_data: &[u8], start_stop_hook: &mut H) -> Vec { +#[allow(dead_code)] +pub fn json_chain_test(path: &Path, json_data: &[u8], start_stop_hook: &mut H) -> Vec { let _ = ::env_logger::try_init(); - let tests = ethjson::state::test::Test::load(json_data).unwrap(); + let tests = ethjson::test_helpers::state::Test::load(json_data) + .expect(&format!("Could not parse JSON state test data from {}", path.display())); let mut failed = Vec::new(); for (name, test) in tests.into_iter() { @@ -65,7 +62,7 @@ pub fn json_chain_test(json_data: &[u8], start_stop_ho let spec = match EvmTestClient::spec_from_json(&spec_name) { Some(spec) => spec, None => { - println!(" - {} | {:?} Ignoring tests because of missing spec", name, spec_name); + println!(" - {} | {:?} Ignoring tests because of missing chainspec", name, spec_name); continue; } }; @@ -73,7 +70,7 @@ pub fn json_chain_test(json_data: &[u8], start_stop_ho for (i, state) in states.into_iter().enumerate() { let info = format!(" - {} | {:?} ({}/{}) ...", name, spec_name, i + 1, total); if skip_test(&name, &spec.name, i + 1) { - println!("{} in skip list : SKIPPED", info); + println!("{}: SKIPPED", info); continue; } @@ -123,11 +120,13 @@ pub fn json_chain_test(json_data: &[u8], start_stop_ho #[cfg(test)] mod state_tests { + use std::path::Path; + use super::json_chain_test; use json_tests::HookType; - fn do_json_test(json_data: &[u8], h: &mut H) -> Vec { - json_chain_test(json_data, h) + fn do_json_test(path: &Path, json_data: &[u8], h: &mut H) -> Vec { + json_chain_test(path, json_data, h) } declare_test!{GeneralStateTest_stArgsZeroOneBalance, "GeneralStateTests/stArgsZeroOneBalance/"} @@ -164,6 +163,15 @@ mod state_tests { declare_test!{GeneralStateTest_stRecursiveCreate, "GeneralStateTests/stRecursiveCreate/"} declare_test!{GeneralStateTest_stRefundTest, "GeneralStateTests/stRefundTest/"} declare_test!{GeneralStateTest_stReturnDataTest, "GeneralStateTests/stReturnDataTest/"} + // todo[dvdplm]: + // "RevertPrecompiledTouch_storage" contains 4 tests, only two fails + // "RevertPrecompiledTouchExactOOG" contains a ton of tests, only two fails + // "RevertPrecompiledTouch" has 4 tests, 2 failures + // Ignored in `currents.json`. + // Issues: + // https://github.com/paritytech/parity-ethereum/issues/11078 + // https://github.com/paritytech/parity-ethereum/issues/11079 + // https://github.com/paritytech/parity-ethereum/issues/11080 declare_test!{GeneralStateTest_stRevertTest, "GeneralStateTests/stRevertTest/"} declare_test!{GeneralStateTest_stSStoreTest, "GeneralStateTests/stSStoreTest/"} declare_test!{GeneralStateTest_stShift, "GeneralStateTests/stShift/"} diff --git a/ethcore/src/json_tests/test_common.rs b/ethcore/src/json_tests/test_common.rs index 521b6d4eca1..dcbe82327f6 100644 --- a/ethcore/src/json_tests/test_common.rs +++ b/ethcore/src/json_tests/test_common.rs @@ -30,43 +30,61 @@ pub enum HookType { OnStop } +/// Run all tests under the given path (except for the test files named in the skip list) using the +/// provided runner function. pub fn run_test_path( - p: &Path, skip: &[&'static str], - runner: fn(json_data: &[u8], start_stop_hook: &mut H) -> Vec, + path: &Path, + skip: &[&'static str], + runner: fn(path: &Path, json_data: &[u8], start_stop_hook: &mut H) -> Vec, start_stop_hook: &mut H ) { + if !skip.is_empty() { + // todo[dvdplm] it's really annoying to have to use flushln here. Should be `info!(target: + // "json-tests", …)`. Issue https://github.com/paritytech/parity-ethereum/issues/11084 + flushln!("[run_test_path] Skipping tests in {}: {:?}", path.display(), skip); + } let mut errors = Vec::new(); - run_test_path_inner(p, skip, runner, start_stop_hook, &mut errors); + run_test_path_inner(path, skip, runner, start_stop_hook, &mut errors); let empty: [String; 0] = []; - assert_eq!(errors, empty); + assert_eq!(errors, empty, "\nThere were {} tests in '{}' that failed.", errors.len(), path.display()); } fn run_test_path_inner( - p: &Path, skip: &[&'static str], - runner: fn(json_data: &[u8], start_stop_hook: &mut H) -> Vec, + p: &Path, + skip: &[&'static str], + runner: fn(path: &Path, json_data: &[u8], start_stop_hook: &mut H) -> Vec, start_stop_hook: &mut H, errors: &mut Vec ) { let path = Path::new(p); - let s: HashSet = skip.iter().map(|s| { + let extension = path.extension().and_then(|s| s.to_str()); + let skip_list: HashSet = skip.iter().map(|s| { let mut os: OsString = s.into(); os.push(".json"); os }).collect(); - let extension = path.extension().and_then(|s| s.to_str()); + if path.is_dir() { - for p in read_dir(path).unwrap().filter_map(|e| { - let e = e.unwrap(); - if s.contains(&e.file_name()) { - None - } else { - Some(e.path()) - }}) { - run_test_path_inner(&p, skip, runner, start_stop_hook, errors); + trace!(target: "json-tests", "running tests contained in '{}'", path.display()); + let test_files = read_dir(path) + .expect("Directory exists on disk") + .filter_map(|dir_entry| { + let dir_entry = dir_entry.expect("Entry in directory listing exists"); + if skip_list.contains(&dir_entry.file_name()) { + debug!(target: "json-tests", "'{:?}' is on the skip list.", dir_entry.file_name()); + None + } else { + Some(dir_entry.path()) + } + }); + for test_file in test_files { + run_test_path_inner(&test_file, skip, runner, start_stop_hook, errors); } } else if extension == Some("swp") || extension == None { + trace!(target: "json-tests", "ignoring '{}', extension {:?} – Junk?", path.display(), extension); // Ignore junk } else { + trace!(target: "json-tests", "running tests in '{}'", path.display()); let mut path = p.to_path_buf(); path.set_extension("json"); run_test_file_append(&path, runner, start_stop_hook, errors) @@ -75,7 +93,7 @@ fn run_test_path_inner( fn run_test_file_append( path: &Path, - runner: fn(json_data: &[u8], start_stop_hook: &mut H) -> Vec, + runner: fn(path: &Path, json_data: &[u8], start_stop_hook: &mut H) -> Vec, start_stop_hook: &mut H, errors: &mut Vec ) { @@ -85,12 +103,12 @@ fn run_test_file_append( Err(_) => panic!("Error opening test file at: {:?}", path), }; file.read_to_end(&mut data).expect("Error reading test file"); - errors.append(&mut runner(&data, start_stop_hook)); + errors.append(&mut runner(&path, &data, start_stop_hook)); } pub fn run_test_file( path: &Path, - runner: fn(json_data: &[u8], start_stop_hook: &mut H) -> Vec, + runner: fn(path: &Path, json_data: &[u8], start_stop_hook: &mut H) -> Vec, start_stop_hook: &mut H ) { let mut data = Vec::new(); @@ -99,7 +117,7 @@ pub fn run_test_file( Err(_) => panic!("Error opening test file at: {:?}", path), }; file.read_to_end(&mut data).expect("Error reading test file"); - let results = runner(&data, start_stop_hook); + let results = runner(&path, &data, start_stop_hook); let empty: [String; 0] = []; assert_eq!(results, empty); } @@ -107,11 +125,25 @@ pub fn run_test_file( #[cfg(test)] macro_rules! test { ($name: expr, $skip: expr) => { - ::json_tests::test_common::run_test_path(::std::path::Path::new(concat!("res/ethereum/tests/", $name)), &$skip, do_json_test, &mut |_, _| ()); + ::json_tests::test_common::run_test_path( + ::std::path::Path::new(concat!("res/ethereum/tests/", $name)), + &$skip, + do_json_test, + &mut |_, _| () + ); } } -/// Declares a test +/// Declares a test: +/// +/// declare_test!(test_name, "path/to/folder/with/tests"); +/// +/// Declares a test but skip the named test files inside the folder (no extension): +/// +/// declare_test!(skip => ["a-test-file", "other-test-file"], test_name, "path/to/folder/with/tests"); +/// +/// NOTE: a skipped test is considered a passing test as far as `cargo test` is concerned. Normally +/// one test corresponds to a folder full of test files, each of which may contain many tests. #[macro_export] macro_rules! declare_test { (skip => $arr: expr, $id: ident, $name: expr) => { diff --git a/ethcore/src/json_tests/transaction.rs b/ethcore/src/json_tests/transaction.rs index febc61404da..1bb1cd81f05 100644 --- a/ethcore/src/json_tests/transaction.rs +++ b/ethcore/src/json_tests/transaction.rs @@ -23,22 +23,14 @@ use types::header::Header; use types::transaction::UnverifiedTransaction; use transaction_ext::Transaction; -/// Run transaction jsontests on a given folder. -pub fn run_test_path(p: &Path, skip: &[&'static str], h: &mut H) { - ::json_tests::test_common::run_test_path(p, skip, do_json_test, h) -} - -/// Run transaction jsontests on a given file. -pub fn run_test_file(p: &Path, h: &mut H) { - ::json_tests::test_common::run_test_file(p, do_json_test, h) -} - -// Block number used to run the tests. -// Make sure that all the specified features are activated. -const BLOCK_NUMBER: u64 = 0x6ffffffffffffe; - -fn do_json_test(json_data: &[u8], start_stop_hook: &mut H) -> Vec { - let tests = ethjson::transaction::Test::load(json_data).unwrap(); +#[allow(dead_code)] +fn do_json_test(path: &Path, json_data: &[u8], start_stop_hook: &mut H) -> Vec { + // Block number used to run the tests. + // Make sure that all the specified features are activated. + const BLOCK_NUMBER: u64 = 0x6ffffffffffffe; + + let tests = ethjson::test_helpers::transaction::Test::load(json_data) + .expect(&format!("Could not parse JSON transaction test data from {}", path.display())); let mut failed = Vec::new(); for (name, test) in tests.into_iter() { start_stop_hook(&name, HookType::OnStart); diff --git a/ethcore/src/json_tests/trie.rs b/ethcore/src/json_tests/trie.rs index 31ca6135e9d..ce01dac8b5e 100644 --- a/ethcore/src/json_tests/trie.rs +++ b/ethcore/src/json_tests/trie.rs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . +use std::path::Path; + use ethjson; use trie::{TrieFactory, TrieSpec}; use ethtrie::RlpCodec; @@ -21,13 +23,10 @@ use ethereum_types::H256; use super::HookType; -pub use self::generic::run_test_path as run_generic_test_path; -pub use self::generic::run_test_file as run_generic_test_file; -pub use self::secure::run_test_path as run_secure_test_path; -pub use self::secure::run_test_file as run_secure_test_file; - -fn test_trie(json: &[u8], trie: TrieSpec, start_stop_hook: &mut H) -> Vec { - let tests = ethjson::trie::Test::load(json).unwrap(); +#[allow(dead_code)] +fn test_trie(path: &Path, json: &[u8], trie: TrieSpec, start_stop_hook: &mut H) -> Vec { + let tests = ethjson::test_helpers::trie::Test::load(json) + .expect(&format!("Could not parse JSON trie test data from {}", path.display())); let factory = TrieFactory::<_, RlpCodec>::new(trie); let mut result = vec![]; @@ -65,18 +64,9 @@ mod generic { use super::HookType; - /// Run generic trie jsontests on a given folder. - pub fn run_test_path(p: &Path, skip: &[&'static str], h: &mut H) { - ::json_tests::test_common::run_test_path(p, skip, do_json_test, h) - } - - /// Run generic trie jsontests on a given file. - pub fn run_test_file(p: &Path, h: &mut H) { - ::json_tests::test_common::run_test_file(p, do_json_test, h) - } - - fn do_json_test(json: &[u8], h: &mut H) -> Vec { - super::test_trie(json, TrieSpec::Generic, h) + #[allow(dead_code)] + fn do_json_test(path: &Path, json: &[u8], h: &mut H) -> Vec { + super::test_trie(path, json, TrieSpec::Generic, h) } declare_test!{TrieTests_trietest, "TrieTests/trietest"} @@ -89,18 +79,9 @@ mod secure { use super::HookType; - /// Run secure trie jsontests on a given folder. - pub fn run_test_path(p: &Path, skip: &[&'static str], h: &mut H) { - ::json_tests::test_common::run_test_path(p, skip, do_json_test, h) - } - - /// Run secure trie jsontests on a given file. - pub fn run_test_file(p: &Path, h: &mut H) { - ::json_tests::test_common::run_test_file(p, do_json_test, h) - } - - fn do_json_test(json: &[u8], h: &mut H) -> Vec { - super::test_trie(json, TrieSpec::Secure, h) + #[allow(dead_code)] + fn do_json_test(path: &Path, json: &[u8], h: &mut H) -> Vec { + super::test_trie(path, json, TrieSpec::Secure, h) } declare_test!{TrieTests_hex_encoded_secure, "TrieTests/hex_encoded_securetrie_test"} diff --git a/ethcore/src/pod_state.rs b/ethcore/src/pod_state.rs index 406bcc05dc4..4f834b47b51 100644 --- a/ethcore/src/pod_state.rs +++ b/ethcore/src/pod_state.rs @@ -40,13 +40,6 @@ impl PodState { pub fn drain(self) -> BTreeMap { self.0 } } -impl From for PodState { - fn from(s: ethjson::blockchain::State) -> PodState { - let state = s.into_iter().map(|(addr, acc)| (addr.into(), PodAccount::from(acc))).collect(); - PodState(state) - } -} - impl From for PodState { fn from(s: ethjson::spec::State) -> PodState { let state: BTreeMap<_,_> = s.into_iter() diff --git a/ethcore/src/spec/genesis.rs b/ethcore/src/spec/genesis.rs index 96a42178dd4..262db77af2d 100644 --- a/ethcore/src/spec/genesis.rs +++ b/ethcore/src/spec/genesis.rs @@ -20,6 +20,7 @@ use hash::KECCAK_NULL_RLP; use spec::seal::Seal; /// Genesis components. +#[derive(Debug)] pub struct Genesis { /// Seal. pub seal: Seal, diff --git a/ethcore/src/spec/seal.rs b/ethcore/src/spec/seal.rs index ed70ac8b545..b91bed29dfa 100644 --- a/ethcore/src/spec/seal.rs +++ b/ethcore/src/spec/seal.rs @@ -21,6 +21,7 @@ use ethereum_types::{H64, H256, H520}; use ethjson; /// Classic ethereum seal. +#[derive(Debug)] pub struct Ethereum { /// Seal nonce. pub nonce: H64, @@ -37,6 +38,7 @@ impl Into for Ethereum { } /// AuthorityRound seal. +#[derive(Debug)] pub struct AuthorityRound { /// Seal step. pub step: usize, @@ -45,6 +47,7 @@ pub struct AuthorityRound { } /// Tendermint seal. +#[derive(Debug)] pub struct Tendermint { /// Seal round. pub round: usize, @@ -73,9 +76,11 @@ impl Into for Tendermint { } } +#[derive(Debug)] pub struct Generic(pub Vec); /// Genesis seal type. +#[derive(Debug)] pub enum Seal { /// Classic ethereum seal. Ethereum(Ethereum), diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index 3cfc8f4c9da..727cc8baf65 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -21,7 +21,7 @@ use std::io::Read; use std::path::Path; use std::sync::Arc; -use bytes::Bytes; +use bytes::{Bytes, ToPretty}; use ethereum_types::{H256, Bloom, U256, Address}; use ethjson; use hash::{KECCAK_NULL_RLP, keccak}; @@ -691,53 +691,58 @@ impl Spec { let (root, db) = { let mut state = State::from_existing(db, root, start_nonce, factories.clone())?; + if self.constructors.is_empty() { + state.populate_from(self.genesis_state.clone()); + let _ = state.commit()?; + } else { - // Execute contract constructors. - let env_info = EnvInfo { - number: 0, - author: self.author, - timestamp: self.timestamp, - difficulty: self.difficulty, - last_hashes: Default::default(), - gas_used: U256::zero(), - gas_limit: U256::max_value(), - }; - - let from = Address::zero(); - for &(ref address, ref constructor) in self.constructors.iter() { - trace!(target: "spec", "run_constructors: Creating a contract at {}.", address); - trace!(target: "spec", " .. root before = {}", state.root()); - let params = ActionParams { - code_address: address.clone(), - code_hash: Some(keccak(constructor)), - address: address.clone(), - sender: from.clone(), - origin: from.clone(), - gas: U256::max_value(), - gas_price: Default::default(), - value: ActionValue::Transfer(Default::default()), - code: Some(Arc::new(constructor.clone())), - data: None, - call_type: CallType::None, - params_type: ParamsType::Embedded, + // Execute contract constructors. + let env_info = EnvInfo { + number: 0, + author: self.author, + timestamp: self.timestamp, + difficulty: self.difficulty, + last_hashes: Default::default(), + gas_used: U256::zero(), + gas_limit: U256::max_value(), }; - let mut substate = Substate::new(); + let from = Address::zero(); + for &(ref address, ref constructor) in self.constructors.iter() { + trace!(target: "spec", "run_constructors: Creating a contract at {}.", address); + trace!(target: "spec", " .. root before = {}", state.root()); + let params = ActionParams { + code_address: address.clone(), + code_hash: Some(keccak(constructor)), + address: address.clone(), + sender: from.clone(), + origin: from.clone(), + gas: U256::max_value(), + gas_price: Default::default(), + value: ActionValue::Transfer(Default::default()), + code: Some(Arc::new(constructor.clone())), + data: None, + call_type: CallType::None, + params_type: ParamsType::Embedded, + }; + + let mut substate = Substate::new(); + + { + let machine = self.engine.machine(); + let schedule = machine.schedule(env_info.number); + let mut exec = Executive::new(&mut state, &env_info, &machine, &schedule); + if let Err(e) = exec.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer) { + warn!(target: "spec", "Genesis constructor execution at {} failed: {}.", address, e); + } + } - { - let machine = self.engine.machine(); - let schedule = machine.schedule(env_info.number); - let mut exec = Executive::new(&mut state, &env_info, &machine, &schedule); - if let Err(e) = exec.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer) { - warn!(target: "spec", "Genesis constructor execution at {} failed: {}.", address, e); + if let Err(e) = state.commit() { + warn!(target: "spec", "Genesis constructor trie commit at {} failed: {}.", address, e); } - } - if let Err(e) = state.commit() { - warn!(target: "spec", "Genesis constructor trie commit at {} failed: {}.", address, e); + trace!(target: "spec", " .. root after = {}", state.root()); } - - trace!(target: "spec", " .. root after = {}", state.root()); } state.drop() diff --git a/ethcore/src/state/mod.rs b/ethcore/src/state/mod.rs index e085a28a4f3..6804ef93b34 100644 --- a/ethcore/src/state/mod.rs +++ b/ethcore/src/state/mod.rs @@ -2608,7 +2608,7 @@ mod tests { fn should_not_panic_on_state_diff_with_storage() { let mut state = get_temp_state(); let a = Address::from_low_u64_be(0xa); - state.init_code(&a, b"abcdefg".to_vec()).unwrap();; + state.init_code(&a, b"abcdefg".to_vec()).unwrap(); state.add_balance(&a, &256.into(), CleanupMode::NoEmpty).unwrap(); state.set_storage(&a, H256::from_low_u64_be(0xb), H256::from_low_u64_be(0xc).into()).unwrap(); diff --git a/ethcore/types/src/transaction/transaction.rs b/ethcore/types/src/transaction/transaction.rs index 916a58cba39..08fcc3ea914 100644 --- a/ethcore/types/src/transaction/transaction.rs +++ b/ethcore/types/src/transaction/transaction.rs @@ -138,8 +138,8 @@ impl Transaction { } } -impl From for SignedTransaction { - fn from(t: ethjson::state::Transaction) -> Self { +impl From for SignedTransaction { + fn from(t: ethjson::transaction::Transaction) -> Self { let to: Option = t.to.into(); let secret = t.secret.map(|s| Secret::from(s.0)); let tx = Transaction { diff --git a/evmbin/src/main.rs b/evmbin/src/main.rs index ee75f9174d1..ffcea93047a 100644 --- a/evmbin/src/main.rs +++ b/evmbin/src/main.rs @@ -174,7 +174,7 @@ fn run_stats_jsontests_vm(args: Args) { } fn run_state_test(args: Args) { - use ethjson::state::test::Test; + use ethjson::test_helpers::state::Test; let file = args.arg_file.expect("FILE is required"); let mut file = match fs::File::open(&file) { diff --git a/json/Cargo.toml b/json/Cargo.toml index 175155e9d41..4fe094d98ef 100644 --- a/json/Cargo.toml +++ b/json/Cargo.toml @@ -3,10 +3,16 @@ description = "Parity Ethereum JSON Deserialization" name = "ethjson" version = "0.1.0" authors = ["Parity Technologies "] +edition = "2018" [dependencies] ethereum-types = "0.6.0" rustc-hex = "1.0" -serde = "1.0" +serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -serde_derive = "1.0" + +[dev-dependencies] +macros = { path = "../util/macros" } + +[features] +test-helpers = [] diff --git a/json/src/blockchain/state.rs b/json/src/blockchain/state.rs deleted file mode 100644 index e108c937f8a..00000000000 --- a/json/src/blockchain/state.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Ethereum. If not, see . - -//! Blockchain test state deserializer. - -use std::collections::BTreeMap; -use hash::Address; -use blockchain::account::Account; - -/// Blockchain test state deserializer. -#[derive(Debug, PartialEq, Deserialize, Clone)] -pub struct State(BTreeMap); - -impl IntoIterator for State { - type Item = as IntoIterator>::Item; - type IntoIter = as IntoIterator>::IntoIter; - - fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() - } -} diff --git a/json/src/blockchain/test.rs b/json/src/blockchain/test.rs deleted file mode 100644 index d773aa3b510..00000000000 --- a/json/src/blockchain/test.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Ethereum. If not, see . - -//! Blockchain test deserializer. - -use std::collections::BTreeMap; -use std::io::Read; -use serde_json; -use serde_json::Error; -use blockchain::blockchain::BlockChain; - -/// Blockchain test deserializer. -#[derive(Debug, PartialEq, Deserialize)] -pub struct Test(BTreeMap); - -impl IntoIterator for Test { - type Item = as IntoIterator>::Item; - type IntoIter = as IntoIterator>::IntoIter; - - fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() - } -} - -impl Test { - /// Loads test from json. - pub fn load(reader: R) -> Result where R: Read { - serde_json::from_reader(reader) - } -} diff --git a/json/src/blockchain/transaction.rs b/json/src/blockchain/transaction.rs deleted file mode 100644 index 4e519f394ee..00000000000 --- a/json/src/blockchain/transaction.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Ethereum. If not, see . - -//! Blockchain test transaction deserialization. - -use uint::Uint; -use bytes::Bytes; - -/// 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 -} diff --git a/json/src/bytes.rs b/json/src/bytes.rs index 3fbdee2380f..9a93eb28960 100644 --- a/json/src/bytes.rs +++ b/json/src/bytes.rs @@ -57,10 +57,10 @@ impl FromStr for Bytes { 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![]) + FromHex::from_hex(v.as_str()).unwrap_or_default() }, - _ if value.starts_with("0x") => FromHex::from_hex(&value[2..]).unwrap_or(vec![]), - _ => FromHex::from_hex(value).unwrap_or(vec![]), + _ if value.starts_with("0x") => FromHex::from_hex(&value[2..]).unwrap_or_default(), + _ => FromHex::from_hex(value).unwrap_or_default(), }; Ok(Bytes(v)) @@ -94,8 +94,7 @@ impl<'a> Visitor<'a> for BytesVisitor { #[cfg(test)] mod test { - use serde_json; - use bytes::Bytes; + use super::Bytes; #[test] fn bytes_deserialization() { @@ -112,8 +111,7 @@ mod test { #[test] fn bytes_into() { - let bytes = Bytes(vec![0xff, 0x11]); - let v: Vec = bytes.into(); + let v: Vec = Bytes(vec![0xff, 0x11]).into(); assert_eq!(vec![0xff, 0x11], v); } } diff --git a/json/src/hash.rs b/json/src/hash.rs index 3e364b950e2..d6cef24cb89 100644 --- a/json/src/hash.rs +++ b/json/src/hash.rs @@ -94,10 +94,8 @@ impl_hash!(Bloom, Hash2048); #[cfg(test)] mod test { + use super::H256; use std::str::FromStr; - use serde_json; - use ethereum_types; - use hash::H256; #[test] fn hash_deserialization() { diff --git a/json/src/lib.rs b/json/src/lib.rs index af5d93edfa6..39cf728cbbc 100644 --- a/json/src/lib.rs +++ b/json/src/lib.rs @@ -14,20 +14,18 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -extern crate rustc_hex; -extern crate serde; -extern crate serde_json; -extern crate ethereum_types; -#[macro_use] extern crate serde_derive; +//! JSON deserialization library + +#![warn(missing_docs)] -pub mod hash; -pub mod uint; pub mod bytes; -pub mod blockchain; +pub mod hash; +pub mod maybe; pub mod spec; -pub mod trie; +pub mod uint; pub mod vm; -pub mod maybe; -pub mod state; pub mod transaction; -pub mod test; +pub mod state; + +#[cfg(any(test, feature = "test-helpers"))] +pub mod test_helpers; diff --git a/json/src/maybe.rs b/json/src/maybe.rs index 4fd2ca60e49..6e823e8f77e 100644 --- a/json/src/maybe.rs +++ b/json/src/maybe.rs @@ -18,9 +18,13 @@ use std::fmt; use std::marker::PhantomData; + +use ethereum_types::U256; use serde::{Deserialize, Deserializer}; use serde::de::{Error, Visitor, IntoDeserializer}; +use crate::uint::Uint; + /// Deserializer of empty string values into optionals. #[derive(Debug, PartialEq, Clone)] pub enum MaybeEmpty { @@ -32,7 +36,8 @@ pub enum MaybeEmpty { impl<'a, T> Deserialize<'a> for MaybeEmpty where T: Deserialize<'a> { fn deserialize(deserializer: D) -> Result - where D: Deserializer<'a> { + where D: Deserializer<'a> + { deserializer.deserialize_any(MaybeEmptyVisitor::new()) } } @@ -61,11 +66,10 @@ impl<'a, T> Visitor<'a> for MaybeEmptyVisitor where T: Deserialize<'a> { } fn visit_string(self, value: String) -> Result where E: Error { - match value.is_empty() { - true => Ok(MaybeEmpty::None), - false => { - T::deserialize(value.into_deserializer()).map(MaybeEmpty::Some) - } + if value.is_empty() { + Ok(MaybeEmpty::None) + } else { + T::deserialize(value.into_deserializer()).map(MaybeEmpty::Some) } } } @@ -79,13 +83,42 @@ impl Into> for MaybeEmpty { } } +#[cfg(test)] +impl From for MaybeEmpty { + fn from(uint: Uint) -> Self { + MaybeEmpty::Some(uint) + } +} + +impl From> for U256 { + fn from(maybe: MaybeEmpty) -> U256 { + match maybe { + MaybeEmpty::Some(v) => v.0, + MaybeEmpty::None => U256::zero(), + } + } +} + +impl From> for u64 { + fn from(maybe: MaybeEmpty) -> u64 { + match maybe { + MaybeEmpty::Some(v) => v.0.low_u64(), + MaybeEmpty::None => 0u64, + } + } +} + +impl Default for MaybeEmpty { + fn default() -> Self { + MaybeEmpty::Some(Uint::default()) + } +} + #[cfg(test)] mod tests { use std::str::FromStr; - use serde_json; - use ethereum_types; - use hash::H256; - use maybe::MaybeEmpty; + use super::MaybeEmpty; + use crate::hash::H256; #[test] fn maybe_deserialization() { diff --git a/json/src/spec/account.rs b/json/src/spec/account.rs index 3d18ecd6c24..3ab5d69dc67 100644 --- a/json/src/spec/account.rs +++ b/json/src/spec/account.rs @@ -17,11 +17,12 @@ //! Spec account deserialization. use std::collections::BTreeMap; -use uint::Uint; -use bytes::Bytes; -use spec::builtin::Builtin; + +use crate::{bytes::Bytes, spec::builtin::Builtin, uint::Uint}; +use serde::Deserialize; /// Spec account. +#[cfg_attr(any(test, feature = "test-helpers"), derive(Clone))] #[derive(Debug, PartialEq, Deserialize)] #[serde(deny_unknown_fields)] pub struct Account { @@ -48,12 +49,8 @@ impl Account { #[cfg(test)] mod tests { - use std::collections::BTreeMap; - use serde_json; - use spec::account::Account; + use super::{Account, Bytes, BTreeMap, Uint}; use ethereum_types::U256; - use uint::Uint; - use bytes::Bytes; #[test] fn account_balance_missing_not_empty() { diff --git a/json/src/spec/authority_round.rs b/json/src/spec/authority_round.rs index cc437f6b947..7d4512e1508 100644 --- a/json/src/spec/authority_round.rs +++ b/json/src/spec/authority_round.rs @@ -16,9 +16,8 @@ //! Authority params deserialization. -use hash::Address; -use uint::Uint; -use bytes::Bytes; +use crate::{bytes::Bytes, hash::Address, uint::Uint}; +use serde::Deserialize; use super::ValidatorSet; /// Authority params deserialization. @@ -70,12 +69,13 @@ pub struct AuthorityRound { #[cfg(test)] mod tests { + use crate::{bytes::Bytes, hash::Address, uint::Uint}; 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 crate::spec::{ + validator_set::ValidatorSet, + authority_round::AuthorityRound, + }; use std::str::FromStr; #[test] diff --git a/json/src/spec/basic_authority.rs b/json/src/spec/basic_authority.rs index c21333a12ce..2925cbdde3a 100644 --- a/json/src/spec/basic_authority.rs +++ b/json/src/spec/basic_authority.rs @@ -16,8 +16,9 @@ //! Authority params deserialization. -use uint::Uint; +use crate::uint::Uint; use super::ValidatorSet; +use serde::Deserialize; /// Authority params deserialization. #[derive(Debug, PartialEq, Deserialize)] @@ -40,13 +41,10 @@ pub struct BasicAuthority { #[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 std::str::FromStr; + use super::{BasicAuthority, Uint}; + use ethereum_types::{U256, H160}; + use crate::{hash::Address, spec::validator_set::ValidatorSet}; #[test] fn basic_authority_deserialization() { diff --git a/json/src/spec/builtin.rs b/json/src/spec/builtin.rs index 20ebbc3c636..f751750dd25 100644 --- a/json/src/spec/builtin.rs +++ b/json/src/spec/builtin.rs @@ -16,10 +16,9 @@ //! Spec builtin deserialization. -use uint::Uint; +use crate::uint::Uint; +use serde::Deserialize; -/// Price per round of Blake2 compression. -pub type Blake2F = u64; /// Linear pricing. #[derive(Debug, PartialEq, Deserialize, Clone)] @@ -69,7 +68,10 @@ pub struct AltBn128Pairing { #[serde(rename_all = "snake_case")] pub enum Pricing { /// Pricing for Blake2 compression function: each call costs the same amount per round. - Blake2F(Blake2F), + Blake2F { + /// Price per round of Blake2 compression function. + gas_per_round: u64, + }, /// Linear pricing. Linear(Linear), /// Pricing for modular exponentiation. @@ -96,9 +98,7 @@ pub struct Builtin { #[cfg(test)] mod tests { - use serde_json; - use spec::builtin::{Builtin, Pricing, Linear, Modexp}; - use uint::Uint; + use super::{Builtin, Modexp, Linear, Pricing, Uint}; #[test] fn builtin_deserialization() { @@ -117,11 +117,11 @@ mod tests { let s = r#"{ "name": "blake2_f", "activate_at": "0xffffff", - "pricing": { "blake2_f": 123 } + "pricing": { "blake2_f": { "gas_per_round": 123 } } }"#; let deserialized: Builtin = serde_json::from_str(s).unwrap(); assert_eq!(deserialized.name, "blake2_f"); - assert_eq!(deserialized.pricing, Pricing::Blake2F(123)); + assert_eq!(deserialized.pricing, Pricing::Blake2F { gas_per_round: 123 }); assert!(deserialized.activate_at.is_some()); } diff --git a/json/src/spec/clique.rs b/json/src/spec/clique.rs index cef0ebfb81a..4d2c4a99f2f 100644 --- a/json/src/spec/clique.rs +++ b/json/src/spec/clique.rs @@ -17,13 +17,14 @@ //! Clique params deserialization. use std::num::NonZeroU64; +use serde::Deserialize; /// Clique params deserialization. #[derive(Debug, PartialEq, Deserialize)] pub struct CliqueParams { - /// period as defined in EIP + /// period as defined in EIP 225 pub period: Option, - /// epoch length as defined in EIP + /// epoch length as defined in EIP 225 pub epoch: Option } @@ -36,8 +37,7 @@ pub struct Clique { #[cfg(test)] mod tests { - use serde_json; - use super::*; + use super::{Clique, NonZeroU64}; #[test] fn clique_deserialization() { diff --git a/json/src/spec/engine.rs b/json/src/spec/engine.rs index cfa1d8cafd1..1ef517208cd 100644 --- a/json/src/spec/engine.rs +++ b/json/src/spec/engine.rs @@ -17,6 +17,7 @@ //! Engine deserialization. use super::{Ethash, BasicAuthority, AuthorityRound, NullEngine, InstantSeal, Clique}; +use serde::Deserialize; /// Engine deserialization. #[derive(Debug, PartialEq, Deserialize)] @@ -40,8 +41,7 @@ pub enum Engine { #[cfg(test)] mod tests { - use serde_json; - use spec::Engine; + use super::Engine; #[test] fn engine_deserialization() { diff --git a/json/src/spec/ethash.rs b/json/src/spec/ethash.rs index c9748c94459..eee44d02bf1 100644 --- a/json/src/spec/ethash.rs +++ b/json/src/spec/ethash.rs @@ -17,16 +17,21 @@ //! Ethash params deserialization. use std::collections::BTreeMap; -use uint::{self, Uint}; -use bytes::Bytes; -use hash::Address; +use crate::{ + bytes::Bytes, + uint::{self, Uint}, + hash::Address +}; +use serde::Deserialize; /// Deserializable doppelganger of block rewards for EthashParams #[derive(Clone, Debug, PartialEq, Deserialize)] #[serde(deny_unknown_fields)] #[serde(untagged)] pub enum BlockReward { + /// Single block reward Single(Uint), + /// Several block rewards Multi(BTreeMap), } @@ -110,12 +115,9 @@ pub struct Ethash { #[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 std::str::FromStr; + use super::{Address, BlockReward, Ethash, EthashParams, Uint}; + use ethereum_types::{H160, U256}; #[test] fn ethash_deserialization() { diff --git a/json/src/spec/genesis.rs b/json/src/spec/genesis.rs index 6c6def199af..69ce6597ca6 100644 --- a/json/src/spec/genesis.rs +++ b/json/src/spec/genesis.rs @@ -16,10 +16,13 @@ //! Spec genesis deserialization. -use uint::{Uint, self}; -use hash::{Address, H256}; -use bytes::Bytes; -use spec::Seal; +use crate::{ + bytes::Bytes, + hash::{Address, H256}, + spec::Seal, + uint::{self, Uint}, +}; +use serde::Deserialize; /// Spec genesis. #[derive(Debug, PartialEq, Deserialize)] @@ -53,14 +56,13 @@ pub struct Genesis { #[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 super::{Address, Bytes, Genesis, H256, Uint}; + use crate::{ + hash::H64, + spec::{Ethereum, Seal} + }; + use ethereum_types::{U256, H160, H64 as Eth64, H256 as Eth256}; #[test] fn genesis_deserialization() { diff --git a/json/src/spec/hardcoded_sync.rs b/json/src/spec/hardcoded_sync.rs index 262d54312b7..42280b6f71a 100644 --- a/json/src/spec/hardcoded_sync.rs +++ b/json/src/spec/hardcoded_sync.rs @@ -16,8 +16,8 @@ //! Spec hardcoded synchronization deserialization for the light client. -use hash::H256; -use uint::Uint; +use crate::{hash::H256, uint::Uint}; +use serde::{Deserialize, Serialize}; /// Spec hardcoded sync. #[derive(Debug, PartialEq, Serialize, Deserialize)] @@ -36,10 +36,10 @@ pub struct HardcodedSync { #[cfg(test)] mod tests { use serde_json; - use uint::Uint; + use crate::uint::Uint; use ethereum_types::{U256, H256 as Eth256}; - use hash::H256; - use spec::hardcoded_sync::HardcodedSync; + use crate::hash::H256; + use super::HardcodedSync; use std::str::FromStr; #[test] diff --git a/json/src/spec/instant_seal.rs b/json/src/spec/instant_seal.rs index 2f1ad33e9bc..ce03322992b 100644 --- a/json/src/spec/instant_seal.rs +++ b/json/src/spec/instant_seal.rs @@ -16,6 +16,8 @@ //! Instant seal engine params deserialization. +use serde::Deserialize; + /// Instant seal engine params deserialization. #[derive(Debug, PartialEq, Deserialize)] #[serde(deny_unknown_fields)] diff --git a/json/src/spec/mod.rs b/json/src/spec/mod.rs index f1145be2e97..e2569c28685 100644 --- a/json/src/spec/mod.rs +++ b/json/src/spec/mod.rs @@ -40,7 +40,7 @@ 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::state::{State, HashOrMap}; pub use self::ethash::{Ethash, EthashParams, BlockReward}; pub use self::validator_set::ValidatorSet; pub use self::basic_authority::{BasicAuthority, BasicAuthorityParams}; diff --git a/json/src/spec/null_engine.rs b/json/src/spec/null_engine.rs index bf75749808c..76a0868ce70 100644 --- a/json/src/spec/null_engine.rs +++ b/json/src/spec/null_engine.rs @@ -16,7 +16,8 @@ //! Null engine params deserialization. -use uint::Uint; +use crate::uint::Uint; +use serde::Deserialize; /// Authority params deserialization. #[derive(Debug, PartialEq, Deserialize)] @@ -37,10 +38,8 @@ pub struct NullEngine { #[cfg(test)] mod tests { - use serde_json; - use uint::Uint; + use super::{NullEngine, Uint}; use ethereum_types::U256; - use super::*; #[test] fn null_engine_deserialization() { diff --git a/json/src/spec/params.rs b/json/src/spec/params.rs index e8b3ded8a90..711abf519eb 100644 --- a/json/src/spec/params.rs +++ b/json/src/spec/params.rs @@ -16,9 +16,12 @@ //! Spec params deserialization. -use uint::{self, Uint}; -use hash::{H256, Address}; -use bytes::Bytes; +use crate::{ + bytes::Bytes, + hash::{H256, Address}, + uint::{self, Uint} +}; +use serde::Deserialize; /// Spec params. #[derive(Debug, PartialEq, Deserialize)] @@ -138,18 +141,16 @@ pub struct Params { #[cfg(test)] mod tests { - use serde_json; - use uint::Uint; + use super::{Params, Uint}; use ethereum_types::U256; - use spec::params::Params; #[test] fn params_deserialization() { let s = r#"{ "maximumExtraDataSize": "0x20", - "networkID" : "0x1", - "chainID" : "0x15", - "subprotocolName" : "exp", + "networkID": "0x1", + "chainID": "0x15", + "subprotocolName": "exp", "minGasLimit": "0x1388", "accountStartNonce": "0x01", "gasLimitBoundDivisor": "0x20", diff --git a/json/src/spec/seal.rs b/json/src/spec/seal.rs index 67238a5f5c0..04d6c2f5cd1 100644 --- a/json/src/spec/seal.rs +++ b/json/src/spec/seal.rs @@ -16,9 +16,8 @@ //! Spec seal deserialization. -use hash::*; -use uint::Uint; -use bytes::Bytes; +use crate::{bytes::Bytes, hash::{H64, H256, H520}, uint::Uint}; +use serde::Deserialize; /// Ethereum seal. #[derive(Debug, PartialEq, Deserialize)] @@ -70,13 +69,9 @@ pub enum Seal { #[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 std::str::FromStr; + use super::{AuthorityRoundSeal, Bytes, Ethereum, H64, H256, H520, TendermintSeal, Seal, Uint}; + use ethereum_types::{U256, H64 as Eth64, H256 as Eth256, H520 as Eth520}; #[test] fn seal_deserialization() { diff --git a/json/src/spec/spec.rs b/json/src/spec/spec.rs index 68824cad99b..e4813427041 100644 --- a/json/src/spec/spec.rs +++ b/json/src/spec/spec.rs @@ -17,9 +17,9 @@ //! Spec deserialization. use std::io::Read; -use serde_json; +use crate::spec::{Params, Genesis, Engine, State, HardcodedSync}; +use serde::Deserialize; use serde_json::Error; -use spec::{Params, Genesis, Engine, State, HardcodedSync}; /// Fork spec definition #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Deserialize)] @@ -31,6 +31,7 @@ pub enum ForkSpec { Byzantium, Constantinople, ConstantinopleFix, + Istanbul, EIP158ToByzantiumAt5, FrontierToHomesteadAt5, HomesteadToDaoAt5, @@ -69,8 +70,7 @@ impl Spec { #[cfg(test)] mod tests { - use serde_json; - use spec::spec::Spec; + use super::Spec; #[test] fn should_error_on_unknown_fields() { diff --git a/json/src/spec/state.rs b/json/src/spec/state.rs index e8a8663672e..642d9b6eb2a 100644 --- a/json/src/spec/state.rs +++ b/json/src/spec/state.rs @@ -14,33 +14,60 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -//! Blockchain test state deserializer. +//! Blockchain state deserializer. use std::collections::BTreeMap; -use hash::Address; -use bytes::Bytes; -use spec::{Account, Builtin}; +use crate::{ + bytes::Bytes, + hash::{Address, H256}, + spec::{Account, Builtin} +}; +use serde::Deserialize; -/// Blockchain test state deserializer. +/// Recent JSON tests can be either a map or a hash (represented by a string). +/// See https://github.com/ethereum/tests/issues/637 +#[cfg_attr(any(test, feature = "test-helpers"), derive(Clone))] +#[derive(Debug, PartialEq, Deserialize)] +#[serde(untagged)] +pub enum HashOrMap { + /// When the `postState` is large, tests sometimes just include the state root of the last + /// successful block here. + Hash(H256), + /// The expected `postState` of a test + Map(BTreeMap), +} + +/// Blockchain state deserializer. +#[cfg_attr(any(test, feature = "test-helpers"), derive(Clone))] #[derive(Debug, PartialEq, Deserialize)] #[serde(deny_unknown_fields)] -pub struct State(BTreeMap); +pub struct State(pub HashOrMap); impl State { /// Returns all builtins. pub fn builtins(&self) -> BTreeMap { - self.0 - .iter() - .filter_map(|(add, ref acc)| acc.builtin.clone().map(|b| (add.clone(), b))) - .collect() + match &self.0 { + HashOrMap::Hash(_) => BTreeMap::default(), + HashOrMap::Map(map) => { + map.iter().filter_map(|(add, ref acc)| { + acc.builtin.clone().map(|b| (add.clone(), b)) + }).collect() + } + + } } /// Returns all constructors. pub fn constructors(&self) -> BTreeMap { - self.0 - .iter() - .filter_map(|(add, ref acc)| acc.constructor.clone().map(|b| (add.clone(), b))) - .collect() + match &self.0 { + HashOrMap::Hash(_) => BTreeMap::default(), + HashOrMap::Map(map) => { + map.iter().filter_map(|(add, ref acc)| { + acc.constructor.clone().map(|b| (add.clone(), b)) + }).collect() + } + + } } } @@ -49,6 +76,10 @@ impl IntoIterator for State { type IntoIter = as IntoIterator>::IntoIter; fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() + if let HashOrMap::Map(m) = self.0 { + m.into_iter() + } else { + BTreeMap::default().into_iter() + } } } diff --git a/json/src/spec/validator_set.rs b/json/src/spec/validator_set.rs index 4de1d3aa0b5..5dcc5558e60 100644 --- a/json/src/spec/validator_set.rs +++ b/json/src/spec/validator_set.rs @@ -17,8 +17,8 @@ //! Validator set deserialization. use std::collections::BTreeMap; -use uint::Uint; -use hash::Address; +use crate::{hash::Address, uint::Uint}; +use serde::Deserialize; /// Different ways of specifying validators. #[derive(Debug, PartialEq, Deserialize)] @@ -37,12 +37,9 @@ pub enum 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 std::str::FromStr; + use super::{Address, Uint, ValidatorSet}; + use ethereum_types::{H160, U256}; #[test] fn validator_set_deserialization() { diff --git a/json/src/state/log.rs b/json/src/state.rs similarity index 91% rename from json/src/state/log.rs rename to json/src/state.rs index 1a0dda5295a..da05b1f68ac 100644 --- a/json/src/state/log.rs +++ b/json/src/state.rs @@ -14,11 +14,15 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -//! State test log deserialization. -use hash::{Address, H256, Bloom}; -use bytes::Bytes; +//! State deserialization types -/// State test log deserialization. +use crate::{ + bytes::Bytes, + hash::{Address, H256, Bloom}, +}; +use serde::Deserialize; + +/// State log deserialization. #[derive(Debug, PartialEq, Deserialize)] pub struct Log { /// Address. @@ -33,8 +37,7 @@ pub struct Log { #[cfg(test)] mod tests { - use serde_json; - use state::Log; + use super::Log; #[test] fn log_deserialization() { diff --git a/json/src/state/mod.rs b/json/src/state/mod.rs deleted file mode 100644 index 8c2ac287535..00000000000 --- a/json/src/state/mod.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Ethereum. If not, see . - -//! State test deserialization. - -pub mod state; -pub mod transaction; -pub mod test; -pub mod log; - -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 blockchain::State as AccountState; diff --git a/json/src/state/state.rs b/json/src/state/state.rs deleted file mode 100644 index f25dabec798..00000000000 --- a/json/src/state/state.rs +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Ethereum. If not, see . - -//! State test deserialization. - -use bytes::Bytes; -use hash::H256; -use state::{Env, AccountState, Transaction, Log}; - -/// 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 -} - -#[cfg(test)] -mod tests { - use serde_json; - use state::State; - - #[test] - fn state_deserialization() { - let s = r#"{ - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "0x0100", - "currentGasLimit" : "0x01c9c380", - "currentNumber" : "0x00", - "currentTimestamp" : "0x01", - "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" - }, - "logs" : [ - ], - "out" : "0x", - "post" : { - "1000000000000000000000000000000000000000" : { - "balance" : "0x0de0b6b3a763ffff", - "code" : "0x6040600060406000600173100000000000000000000000000000000000000162055730f1600055", - "nonce" : "0x00", - "storage" : { - "0x00" : "0x01" - } - }, - "1000000000000000000000000000000000000001" : { - "balance" : "0x0de0b6b3a763ffff", - "code" : "0x604060006040600060027310000000000000000000000000000000000000026203d090f1600155", - "nonce" : "0x00", - "storage" : { - "0x01" : "0x01" - } - }, - "1000000000000000000000000000000000000002" : { - "balance" : "0x02", - "code" : "0x600160025533600455346007553060e6553260e8553660ec553860ee553a60f055", - "nonce" : "0x00", - "storage" : { - "0x02" : "0x01", - "0x04" : "0x1000000000000000000000000000000000000001", - "0x07" : "0x02", - "0xe6" : "0x1000000000000000000000000000000000000002", - "0xe8" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "0xec" : "0x40", - "0xee" : "0x21", - "0xf0" : "0x01" - } - }, - "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : { - "balance" : "0x039455", - "code" : "0x", - "nonce" : "0x00", - "storage" : { - } - }, - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "0x0de0b6b3a7606bab", - "code" : "0x", - "nonce" : "0x01", - "storage" : { - } - } - }, - "postStateRoot" : "8f8ed2aed2973e159fa5486f47c6ebf15c5058f8e2350286b84b569bc6ce2d25", - "pre" : { - "1000000000000000000000000000000000000000" : { - "balance" : "0x0de0b6b3a7640000", - "code" : "0x6040600060406000600173100000000000000000000000000000000000000162055730f1600055", - "nonce" : "0x00", - "storage" : { - } - }, - "1000000000000000000000000000000000000001" : { - "balance" : "0x0de0b6b3a7640000", - "code" : "0x604060006040600060027310000000000000000000000000000000000000026203d090f1600155", - "nonce" : "0x00", - "storage" : { - } - }, - "1000000000000000000000000000000000000002" : { - "balance" : "0x00", - "code" : "0x600160025533600455346007553060e6553260e8553660ec553860ee553a60f055", - "nonce" : "0x00", - "storage" : { - } - }, - "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { - "balance" : "0x0de0b6b3a7640000", - "code" : "0x", - "nonce" : "0x00", - "storage" : { - } - } - }, - "transaction" : { - "data" : "", - "gasLimit" : "0x2dc6c0", - "gasPrice" : "0x01", - "nonce" : "0x00", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "to" : "1000000000000000000000000000000000000000", - "value" : "0x00" - } - }"#; - let _deserialized: State = serde_json::from_str(s).unwrap(); - // TODO: validate all fields - } -} diff --git a/json/src/state/transaction.rs b/json/src/state/transaction.rs deleted file mode 100644 index 693b976994e..00000000000 --- a/json/src/state/transaction.rs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Ethereum. If not, see . - -//! State test transaction deserialization. - -use uint::Uint; -use bytes::Bytes; -use hash::{Address, H256}; -use maybe::MaybeEmpty; - -/// 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, - /// To. - pub to: MaybeEmpty
, - /// Value. - pub value: Uint, -} - -#[cfg(test)] -mod tests { - use serde_json; - use state::Transaction; - - #[test] - fn transaction_deserialization() { - let s = r#"{ - "data" : "", - "gasLimit" : "0x2dc6c0", - "gasPrice" : "0x01", - "nonce" : "0x00", - "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", - "to" : "1000000000000000000000000000000000000000", - "value" : "0x00" - }"#; - let _deserialized: Transaction = serde_json::from_str(s).unwrap(); - // TODO: validate all fields - } -} diff --git a/json/src/test/mod.rs b/json/src/test/mod.rs deleted file mode 100644 index 355d30d69fc..00000000000 --- a/json/src/test/mod.rs +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Ethereum. If not, see . - -//! Additional test structures deserialization. - -use std::collections::BTreeMap; -use std::io::Read; -use serde_json; -use serde_json::Error; -use hash::H256; -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, -} - -/// Blockchain test deserializer. -#[derive(Debug, PartialEq, Deserialize)] -pub struct DifficultyTest(BTreeMap); - -impl IntoIterator for DifficultyTest { - type Item = as IntoIterator>::Item; - type IntoIter = as IntoIterator>::IntoIter; - - fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() - } -} - -impl DifficultyTest { - /// Loads test from json. - pub fn load(reader: R) -> Result 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, - /// State tests - pub state: Vec, - -} - -/// 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, -} - -/// 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 -} - -/// State subtest to skip. -#[derive(Debug, PartialEq, Deserialize)] -pub struct StateSkipSubStates { - /// State test number of this item. Or '*' for all state. - pub subnumbers: Vec, - /// Chain for this items. - pub chain: String, -} - -impl SkipStates { - /// Loads skip states from json. - pub fn load(reader: R) -> Result where R: Read { - serde_json::from_reader(reader) - } - - /// Empty skip states. - pub fn empty() -> Self { - SkipStates { - block: Vec::new(), - state: Vec::new(), - } - } -} diff --git a/json/src/blockchain/block.rs b/json/src/test_helpers/blockchain/block.rs similarity index 95% rename from json/src/blockchain/block.rs rename to json/src/test_helpers/blockchain/block.rs index 23ba5300dc2..e219fb7bfe8 100644 --- a/json/src/blockchain/block.rs +++ b/json/src/test_helpers/blockchain/block.rs @@ -16,9 +16,9 @@ //! Blockchain test block deserializer. -use bytes::Bytes; -use blockchain::header::Header; -use blockchain::transaction::Transaction; +use crate::{bytes::Bytes, transaction::Transaction}; +use super::header::Header; +use serde::Deserialize; /// Blockchain test block deserializer. #[derive(Debug, PartialEq, Deserialize)] @@ -40,8 +40,7 @@ impl Block { #[cfg(test)] mod tests { - use serde_json; - use blockchain::block::Block; + use super::Block; #[test] fn block_deserialization() { @@ -66,7 +65,7 @@ mod tests { }, "blocknumber" : "1", "rlp" : "0xf901fcf901f7a05a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5aea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0c5c83ff43741f573a0c9b31d0e56fdd745f4e37d193c4e78544f302777aafcf3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefba808456850b7b80a013735ab4156c9b36327224d92e1692fab8fc362f8e0f868c94d421848ef7cd0688931dcc53e5edc514c0c0", - "transactions" : [], + "transaction" : [], "uncleHeaders" : [] }"#; let _deserialized: Block = serde_json::from_str(s).unwrap(); diff --git a/json/src/blockchain/header.rs b/json/src/test_helpers/blockchain/header.rs similarity index 96% rename from json/src/blockchain/header.rs rename to json/src/test_helpers/blockchain/header.rs index 8de5b16edb6..b1144934211 100644 --- a/json/src/blockchain/header.rs +++ b/json/src/test_helpers/blockchain/header.rs @@ -16,9 +16,12 @@ //! Blockchain test header deserializer. -use hash::{H64, Address, H256, Bloom}; -use uint::Uint; -use bytes::Bytes; +use crate::{ + bytes::Bytes, + hash::{H64, Address, H256, Bloom}, + uint::Uint +}; +use serde::Deserialize; /// Blockchain test header deserializer. #[derive(Debug, PartialEq, Deserialize)] @@ -64,8 +67,7 @@ pub struct Header { #[cfg(test)] mod tests { - use serde_json; - use blockchain::header::Header; + use super::Header; #[test] fn header_deserialization() { diff --git a/json/src/blockchain/blockchain.rs b/json/src/test_helpers/blockchain/mod.rs similarity index 96% rename from json/src/blockchain/blockchain.rs rename to json/src/test_helpers/blockchain/mod.rs index b92336f793a..3aac3e8a047 100644 --- a/json/src/blockchain/blockchain.rs +++ b/json/src/test_helpers/blockchain/mod.rs @@ -14,14 +14,24 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -//! Blockchain deserialization. +//! Blockchain test deserialization. -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 crate::{ + bytes::Bytes, + hash::H256, + spec::{Ethereum, ForkSpec, Genesis, Seal, State} + +}; +use serde::Deserialize; + +pub mod block; +pub mod header; + +pub use self::block::Block; +pub use self::header::Header; + +/// Type for running `Blockchain` tests +pub type Test = super::tester::GenericTester; /// Json Block test possible engine kind. #[derive(Debug, PartialEq, Deserialize)] @@ -95,8 +105,7 @@ impl BlockChain { #[cfg(test)] mod tests { - use serde_json; - use blockchain::blockchain::BlockChain; + use super::BlockChain; #[test] fn blockchain_deserialization() { diff --git a/json/src/test_helpers/difficulty.rs b/json/src/test_helpers/difficulty.rs new file mode 100644 index 00000000000..023966c6a22 --- /dev/null +++ b/json/src/test_helpers/difficulty.rs @@ -0,0 +1,23 @@ +use crate::{hash::H256, uint::Uint}; +use serde::Deserialize; + +/// 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, +} + +/// Type for running `Difficulty` tests +pub type DifficultyTest = super::tester::GenericTester; diff --git a/json/src/blockchain/mod.rs b/json/src/test_helpers/mod.rs similarity index 65% rename from json/src/blockchain/mod.rs rename to json/src/test_helpers/mod.rs index 0a3b162e95f..095738a0c48 100644 --- a/json/src/blockchain/mod.rs +++ b/json/src/test_helpers/mod.rs @@ -14,21 +14,24 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -//! Blockchain test deserialization. +//! Test structures for JSON deserialization. -pub mod account; -pub mod block; +/// Blockchain test helpers pub mod blockchain; -pub mod header; +/// Difficulty test helpers +pub mod difficulty; +/// Tests to skip helpers +pub mod skip; +/// State test helpers pub mod state; +/// Test primitives +pub mod tester; +/// Transaction test helpers pub mod transaction; -pub mod test; - -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; +/// Trie test helpers +pub mod trie; +/// Vm test helpers +pub mod vm { + /// Type for running `vm` tests + pub type Test = super::tester::GenericTester; +} diff --git a/json/src/test_helpers/skip.rs b/json/src/test_helpers/skip.rs new file mode 100644 index 00000000000..91067dd36b4 --- /dev/null +++ b/json/src/test_helpers/skip.rs @@ -0,0 +1,58 @@ +use std::collections::BTreeMap; +use serde::Deserialize; + +/// Test to skip (only if issue ongoing) +#[derive(Debug, PartialEq, Deserialize)] +pub struct SkipTests { + /// Block tests + pub block: Vec, + /// State tests + pub state: Vec, + +} + +/// Block test to skip. +#[derive(Debug, PartialEq, Deserialize)] +pub struct SkipBlockchainTest { + /// Issue reference. + pub reference: String, + /// Test failing name. + pub failing: String, + /// Items failing for the test. + pub subtests: Vec, +} + +/// State test to skip. +#[derive(Debug, PartialEq, Deserialize)] +pub struct SkipStateTest { + /// Issue reference. + pub reference: String, + /// Test failing name. + pub failing: String, + /// Items failing for the test. + pub subtests: BTreeMap +} + +/// State subtest to skip. +#[derive(Debug, PartialEq, Deserialize)] +pub struct StateSkipSubStates { + /// State test number of this item. Or '*' for all state. + pub subnumbers: Vec, + /// Chain for this items. + pub chain: String, +} + +impl SkipTests { + /// Empty skip states. + pub fn empty() -> Self { + SkipTests { + block: Vec::new(), + state: Vec::new(), + } + } + + /// Loads test from json. + pub fn load(reader: R) -> Result where R: std::io::Read { + serde_json::from_reader(reader) + } +} diff --git a/json/src/state/test.rs b/json/src/test_helpers/state.rs similarity index 85% rename from json/src/state/test.rs rename to json/src/test_helpers/state.rs index b8e5f35f694..f86257dfa5c 100644 --- a/json/src/state/test.rs +++ b/json/src/test_helpers/state.rs @@ -14,37 +14,22 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -//! General test deserialization. +//! State 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}; - -/// State test deserializer. -#[derive(Debug, PartialEq, Deserialize)] -pub struct Test(BTreeMap); - -impl IntoIterator for Test { - type Item = as IntoIterator>::Item; - type IntoIter = as IntoIterator>::IntoIter; - - fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() - } -} +/// Type for running `State` tests +pub type Test = super::tester::GenericTester; -impl Test { - /// Loads test from json. - pub fn load(reader: R) -> Result where R: Read { - serde_json::from_reader(reader) - } -} +use std::collections::BTreeMap; +use serde::Deserialize; +use crate::{ + bytes::Bytes, + hash::{Address, H256}, + maybe::MaybeEmpty, + uint::Uint, + spec::{ForkSpec, State as AccountState}, + transaction::Transaction, + vm::Env +}; /// State test deserialization. #[derive(Debug, PartialEq, Deserialize)] @@ -87,12 +72,15 @@ impl MultiTransaction { 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(), + gas_limit: self.gas_limit[indexes.gas as usize], + gas_price: self.gas_price, + nonce: self.nonce, to: self.to.clone(), - value: self.value[indexes.value as usize].clone(), + value: self.value[indexes.value as usize], + r: Default::default(), + s: Default::default(), + v: Default::default(), + secret: self.secret.clone(), } } } diff --git a/json/src/test_helpers/tester.rs b/json/src/test_helpers/tester.rs new file mode 100644 index 00000000000..610f5972304 --- /dev/null +++ b/json/src/test_helpers/tester.rs @@ -0,0 +1,27 @@ +use std::collections::BTreeMap; +use serde::Deserialize; +use serde::de::DeserializeOwned; + +/// A genric wrapper over a `BTreeMap` for tests +#[derive(Deserialize)] +pub struct GenericTester(BTreeMap); + +impl IntoIterator for GenericTester { + type Item = as IntoIterator>::Item; + type IntoIter = as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + +impl GenericTester +where + T: DeserializeOwned + Ord, + U: DeserializeOwned +{ + /// Loads test from json. + pub fn load(reader: R) -> Result where R: std::io::Read { + serde_json::from_reader(reader) + } +} diff --git a/json/src/transaction/txtest.rs b/json/src/test_helpers/transaction.rs similarity index 87% rename from json/src/transaction/txtest.rs rename to json/src/test_helpers/transaction.rs index e72e5f60bfa..6aa87545464 100644 --- a/json/src/transaction/txtest.rs +++ b/json/src/test_helpers/transaction.rs @@ -17,16 +17,20 @@ //! Transaction test deserialization. use std::collections::BTreeMap; -use bytes::Bytes; -use hash::Address; -use hash::H256; -use spec::ForkSpec; +use crate::{bytes::Bytes, hash::{Address, H256}, spec::ForkSpec}; +use serde::Deserialize; + +/// Type for running `Transaction` tests +pub type Test = super::tester::GenericTester; /// Transaction test deserialization. #[derive(Debug, Deserialize)] pub struct TransactionTest { + /// RLP of the transaction pub rlp: Bytes, - pub _info: ::serde::de::IgnoredAny, + #[allow(missing_docs)] + pub _info: serde::de::IgnoredAny, + /// State of the transaction after the test runs #[serde(flatten)] pub post_state: BTreeMap, } @@ -43,8 +47,7 @@ pub struct PostState { #[cfg(test)] mod tests { - use serde_json; - use transaction::TransactionTest; + use super::TransactionTest; #[test] fn transaction_deserialization() { diff --git a/json/src/trie/input.rs b/json/src/test_helpers/trie/input.rs similarity index 95% rename from json/src/trie/input.rs rename to json/src/test_helpers/trie/input.rs index 4c56c10d7cd..01d223b59a1 100644 --- a/json/src/trie/input.rs +++ b/json/src/test_helpers/trie/input.rs @@ -19,7 +19,7 @@ use std::fmt; use std::collections::BTreeMap; use std::str::FromStr; -use bytes::Bytes; +use crate::bytes::Bytes; use serde::{Deserialize, Deserializer}; use serde::de::{Error as ErrorTrait, Visitor, MapAccess, SeqAccess}; @@ -89,8 +89,8 @@ impl<'a> Visitor<'a> for InputVisitor { return Err(V::Error::custom("Invalid key value pair.")); } - let ref key_str: Option = keyval[0]; - let ref val_str: Option = keyval[1]; + let key_str = &keyval[0]; + let val_str = &keyval[1]; let key = match *key_str { Some(ref k) if k.starts_with("0x") => Bytes::from_str(k).map_err(V::Error::custom)?, @@ -117,10 +117,7 @@ impl<'a> Visitor<'a> for InputVisitor { #[cfg(test)] mod tests { - use std::collections::BTreeMap; - use serde_json; - use bytes::Bytes; - use super::Input; + use super::{BTreeMap, Bytes, Input}; #[test] fn input_deserialization_from_map() { diff --git a/json/src/trie/trie.rs b/json/src/test_helpers/trie/mod.rs similarity index 84% rename from json/src/trie/trie.rs rename to json/src/test_helpers/trie/mod.rs index 756e54f4351..29bb55531bf 100644 --- a/json/src/trie/trie.rs +++ b/json/src/test_helpers/trie/mod.rs @@ -16,8 +16,15 @@ //! Trie test deserialization. -use hash::H256; -use trie::Input; +mod input; + +pub use self::input::Input; + +/// Type used by `trie` tests +pub type Test = super::tester::GenericTester; + +use serde::Deserialize; +use crate::hash::H256; /// Trie test deserialization. #[derive(Debug, Deserialize, PartialEq)] diff --git a/json/src/transaction/transaction.rs b/json/src/transaction.rs similarity index 51% rename from json/src/transaction/transaction.rs rename to json/src/transaction.rs index 718d3080bd2..48f33d71edb 100644 --- a/json/src/transaction/transaction.rs +++ b/json/src/transaction.rs @@ -14,14 +14,12 @@ // You should have received a copy of the GNU General Public License // along with Parity Ethereum. If not, see . -//! Transaction test transaction deserialization. +//! Transaction deserialization. -use uint::Uint; -use bytes::Bytes; -use hash::Address; -use maybe::MaybeEmpty; +use crate::{bytes::Bytes, hash::{Address, H256}, maybe::MaybeEmpty, uint::Uint}; +use serde::Deserialize; -/// Transaction test transaction deserialization. +/// Unsigned transaction with signing information deserialization. #[derive(Debug, PartialEq, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Transaction { @@ -38,17 +36,23 @@ pub struct Transaction { /// Value. pub value: Uint, /// R. - pub r: Uint, + #[serde(default)] + pub r: MaybeEmpty, /// S. - pub s: Uint, + #[serde(default)] + pub s: MaybeEmpty, /// V. - pub v: Uint, + #[serde(default)] + pub v: MaybeEmpty, + /// Secret + #[serde(rename = "secretKey")] + pub secret: Option, } #[cfg(test)] mod tests { - use serde_json; - use transaction::Transaction; + use super::{Bytes, H256, MaybeEmpty, Transaction, Uint}; + use ethereum_types::{H256 as Eth256, U256}; #[test] fn transaction_deserialization() { @@ -57,13 +61,23 @@ mod tests { "gasLimit" : "0xf388", "gasPrice" : "0x09184e72a000", "nonce" : "0x00", - "r" : "0x2c", - "s" : "0x04", "to" : "", - "v" : "0x1b", - "value" : "0x00" + "value" : "0x00", + "r": "0", + "s": "1", + "v": "2", + "secretKey": "0x0000000000000000000000000000000000000000000000000000000000000000" }"#; - let _deserialized: Transaction = serde_json::from_str(s).unwrap(); - // TODO: validate all fields + let tx: Transaction = serde_json::from_str(s).expect("JSON string is valid"); + assert_eq!(tx.data, Bytes::new(Vec::new())); + assert_eq!(tx.gas_limit, Uint(U256::from(0xf388))); + assert_eq!(tx.gas_price, Uint(U256::from(0x09184e72a000_u64))); + assert_eq!(tx.nonce, Uint(U256::zero())); + assert_eq!(tx.to, MaybeEmpty::None); + assert_eq!(tx.value, Uint(U256::zero())); + assert_eq!(tx.r, Uint(U256::zero()).into()); + assert_eq!(tx.s, Uint(U256::one()).into()); + assert_eq!(tx.v, Uint(U256::from(2)).into()); + assert_eq!(tx.secret, Some(H256(Eth256::zero()))); } } diff --git a/json/src/transaction/mod.rs b/json/src/transaction/mod.rs deleted file mode 100644 index f845fe3340a..00000000000 --- a/json/src/transaction/mod.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Ethereum. If not, see . - -//! Transaction test deserialization. - -mod transaction; -mod txtest; -mod test; - -pub use self::transaction::Transaction; -pub use self::txtest::TransactionTest; -pub use self::test::Test; diff --git a/json/src/transaction/test.rs b/json/src/transaction/test.rs deleted file mode 100644 index ee9d4110f1f..00000000000 --- a/json/src/transaction/test.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Ethereum. If not, see . - -//! TransactionTest test deserializer. - -use std::collections::BTreeMap; -use std::io::Read; -use serde_json; -use serde_json::Error; -use transaction::TransactionTest; - -/// TransactionTest test deserializer. -#[derive(Debug, Deserialize)] -pub struct Test(BTreeMap); - -impl IntoIterator for Test { - type Item = as IntoIterator>::Item; - type IntoIter = as IntoIterator>::IntoIter; - - fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() - } -} - -impl Test { - /// Loads test from json. - pub fn load(reader: R) -> Result where R: Read { - serde_json::from_reader(reader) - } -} diff --git a/json/src/trie/mod.rs b/json/src/trie/mod.rs deleted file mode 100644 index 68fec087617..00000000000 --- a/json/src/trie/mod.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Ethereum. If not, see . - -//! Trie test deserialization. - -mod input; -mod trie; -mod test; - -pub use self::input::Input; -pub use self::trie::Trie; -pub use self::test::Test; diff --git a/json/src/trie/test.rs b/json/src/trie/test.rs deleted file mode 100644 index 39876da0a16..00000000000 --- a/json/src/trie/test.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Ethereum. If not, see . - -//! TransactionTest test deserializer. - -use std::collections::BTreeMap; -use std::io::Read; -use serde_json; -use serde_json::Error; -use trie::Trie; - -/// TransactionTest test deserializer. -#[derive(Debug, PartialEq, Deserialize)] -pub struct Test(BTreeMap); - -impl IntoIterator for Test { - type Item = as IntoIterator>::Item; - type IntoIter = as IntoIterator>::IntoIter; - - fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() - } -} - -impl Test { - /// Loads test from json. - pub fn load(reader: R) -> Result where R: Read { - serde_json::from_reader(reader) - } -} diff --git a/json/src/uint.rs b/json/src/uint.rs index 3428fd56c40..8cba3f1ddef 100644 --- a/json/src/uint.rs +++ b/json/src/uint.rs @@ -92,6 +92,7 @@ impl<'a> Visitor<'a> for UintVisitor { } } +/// Deserialize and validate that the value is non-zero pub fn validate_non_zero<'de, D>(d: D) -> Result where D: Deserializer<'de> { let value = Uint::deserialize(d)?; @@ -102,6 +103,7 @@ pub fn validate_non_zero<'de, D>(d: D) -> Result where D: Deseri Ok(value) } +/// Deserialize and validate that the value is non-zero pub fn validate_optional_non_zero<'de, D>(d: D) -> Result, D::Error> where D: Deserializer<'de> { let value: Option = Option::deserialize(d)?; @@ -116,9 +118,8 @@ pub fn validate_optional_non_zero<'de, D>(d: D) -> Result, D::Error #[cfg(test)] mod test { - use serde_json; + use super::Uint; use ethereum_types::U256; - use uint::Uint; #[test] fn uint_deserialization() { diff --git a/json/src/vm.rs b/json/src/vm.rs new file mode 100644 index 00000000000..8e45fade651 --- /dev/null +++ b/json/src/vm.rs @@ -0,0 +1,275 @@ +// Copyright 2015-2019 Parity Technologies (UK) Ltd. +// This file is part of Parity Ethereum. + +// Parity Ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity Ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity Ethereum. If not, see . + +//! Vm json deserialization + +use crate::{ + bytes::Bytes, + hash::{Address, H256}, + maybe::MaybeEmpty, + spec::State, + uint::Uint, +}; +use serde::Deserialize; + +/// 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>, + /// 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, + /// Hash of logs created during execution of transaction. + pub logs: Option, + /// Transaction output. + #[serde(rename = "out")] + pub output: Option, + /// Post execution vm state. + #[serde(rename = "post")] + pub post_state: Option, + /// 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() + } +} + +/// Call deserialization. +#[derive(Debug, PartialEq, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Call { + /// Call data. + pub data: Bytes, + /// Call destination. + pub destination: MaybeEmpty
, + /// Gas limit. + pub gas_limit: Uint, + /// Call value. + pub value: Uint, +} + +/// 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 code version. + #[serde(default)] + pub code_version: Uint, +} + +/// 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, +} + +#[cfg(test)] +mod tests { + use std::{ + collections::BTreeMap, + str::FromStr + }; + use super::{Address, Bytes, Call, Env, H256, MaybeEmpty, State, Transaction, Uint, Vm}; + + use crate::spec::{Account, HashOrMap}; + use ethereum_types::{U256, H160 as Hash160, H256 as Hash256}; + use macros::map; + use rustc_hex::FromHex; + + const TEST_CODE: &str = "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01600055"; + + #[test] + fn vm_deserialization() { + let s = r#"{ + "callcreates" : [ + ], + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "0x0100", + "currentGasLimit" : "0x0f4240", + "currentNumber" : "0x00", + "currentTimestamp" : "0x01" + }, + "exec" : { + "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01600055", + "data" : "0x", + "gas" : "0x0186a0", + "gasPrice" : "0x5af3107a4000", + "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", + "value" : "0x0de0b6b3a7640000" + }, + "gas" : "0x013874", + "logs" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "out" : "0x", + "post" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "0x0de0b6b3a7640000", + "code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01600055", + "nonce" : "0x00", + "storage" : { + "0x00" : "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe" + } + } + }, + "pre" : { + "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { + "balance" : "0x0de0b6b3a7640000", + "code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01600055", + "nonce" : "0x00", + "storage" : { + } + } + } + }"#; + let vm: Vm = serde_json::from_str(s).expect("JSON is valid"); + assert_eq!(vm.calls, Some(Vec::new())); + assert_eq!(vm.env, Env { + author: Address(Hash160::from_str("2adc25665018aa1fe0e6bc666dac8fc2697ff9ba").unwrap()), + difficulty: Uint(0x0100.into()), + gas_limit: Uint(0x0f4240.into()), + number: Uint(0.into()), + timestamp: Uint(1.into()) + }); + assert_eq!(vm.transaction, Transaction { + address: Address(Hash160::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap()), + sender: Address(Hash160::from_str("cd1722f2947def4cf144679da39c4c32bdc35681").unwrap()), + code: Bytes::new(TEST_CODE.from_hex().unwrap()), + code_version: Uint(0.into()), + data: Bytes::new(Vec::new()), + gas: Uint(0x0186a0.into()), + gas_price: Uint(0x5af3107a4000_u64.into()), + origin: Address(Hash160::from_str("cd1722f2947def4cf144679da39c4c32bdc35681").unwrap()), + value: Uint(0x0de0b6b3a7640000_u64.into()) + }); + assert_eq!(vm.gas_left, Some(Uint(0x013874.into()))); + assert_eq!( + vm.logs, + Some(H256(Hash256::from_str("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").unwrap())) + ); + assert_eq!(vm.output, Some(Bytes::new(Vec::new()))); + assert_eq!(vm.pre_state, State( + HashOrMap::Map( + map![ + Address(Hash160::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap()) => Account { + builtin: None, + balance: Some(Uint(0x0de0b6b3a7640000_u64.into())), + code: Some(Bytes::new(TEST_CODE.from_hex().unwrap())), + constructor: None, + nonce: Some(Uint(0.into())), + storage: Some(map![]), + } + ])) + ); + assert_eq!(vm.post_state, Some( + State( + HashOrMap::Map( + map![ + Address(Hash160::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap()) => Account { + builtin: None, + balance: Some(Uint(0x0de0b6b3a7640000_u64.into())), + code: Some(Bytes::new(TEST_CODE.from_hex().unwrap())), + constructor: None, + nonce: Some(Uint(0.into())), + storage: Some(map![ + Uint(0.into()) => Uint(U256::from_str("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe").unwrap()) + ]), + }])) + ) + ); + } + + #[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(); + + 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))); + } + + #[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(); + + 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))); + } +} diff --git a/json/src/vm/call.rs b/json/src/vm/call.rs deleted file mode 100644 index aa75862f0dd..00000000000 --- a/json/src/vm/call.rs +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Ethereum. If not, see . - -//! Vm call deserialization. - -use bytes::Bytes; -use hash::Address; -use uint::Uint; -use maybe::MaybeEmpty; - -/// Vm call deserialization. -#[derive(Debug, PartialEq, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct Call { - /// Call data. - pub data: Bytes, - /// Call destination. - pub destination: MaybeEmpty
, - /// 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; - - #[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(); - - 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))); - } - - #[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(); - - 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))); - } -} diff --git a/json/src/vm/env.rs b/json/src/vm/env.rs deleted file mode 100644 index e06812c0a87..00000000000 --- a/json/src/vm/env.rs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Ethereum. If not, see . - -//! Vm environment. -use hash::Address; -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, -} - -#[cfg(test)] -mod tests { - use serde_json; - use vm::Env; - - #[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 - } -} diff --git a/json/src/vm/mod.rs b/json/src/vm/mod.rs deleted file mode 100644 index d8f99e20021..00000000000 --- a/json/src/vm/mod.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Ethereum. If not, see . - -//! Vm test loader. - -pub mod env; -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; diff --git a/json/src/vm/test.rs b/json/src/vm/test.rs deleted file mode 100644 index 9dfe814ae82..00000000000 --- a/json/src/vm/test.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Ethereum. If not, see . - -//! Vm test deserializer. - -use std::collections::BTreeMap; -use std::io::Read; -use serde_json; -use serde_json::Error; -use vm::Vm; - -/// Vm test deserializer. -#[derive(Debug, PartialEq, Deserialize)] -pub struct Test(BTreeMap); - -impl IntoIterator for Test { - type Item = as IntoIterator>::Item; - type IntoIter = as IntoIterator>::IntoIter; - - fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() - } -} - -impl Test { - /// Loads test from json. - pub fn load(reader: R) -> Result where R: Read { - serde_json::from_reader(reader) - } -} diff --git a/json/src/vm/vm.rs b/json/src/vm/vm.rs deleted file mode 100644 index 1fbb937cb7f..00000000000 --- a/json/src/vm/vm.rs +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity Ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity Ethereum. If not, see . - -//! Vm execution env. - -use bytes::Bytes; -use uint::Uint; -use hash::H256; -use blockchain::State; -use vm::{Transaction, Call, Env}; - -/// 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>, - /// 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, - /// Hash of logs created during execution of transaction. - pub logs: Option, - /// Transaction output. - #[serde(rename = "out")] - pub output: Option, - /// Post execution vm state. - #[serde(rename = "post")] - pub post_state: Option, - /// 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() - } -} - -#[cfg(test)] -mod tests { - use serde_json; - use vm::Vm; - - #[test] - fn vm_deserialization() { - let s = r#"{ - "callcreates" : [ - ], - "env" : { - "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", - "currentDifficulty" : "0x0100", - "currentGasLimit" : "0x0f4240", - "currentNumber" : "0x00", - "currentTimestamp" : "0x01" - }, - "exec" : { - "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", - "code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01600055", - "data" : "0x", - "gas" : "0x0186a0", - "gasPrice" : "0x5af3107a4000", - "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", - "value" : "0x0de0b6b3a7640000" - }, - "gas" : "0x013874", - "logs" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "out" : "0x", - "network" : "Frontier", - "post" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "0x0de0b6b3a7640000", - "code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01600055", - "nonce" : "0x00", - "storage" : { - "0x00" : "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe" - } - } - }, - "pre" : { - "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { - "balance" : "0x0de0b6b3a7640000", - "code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01600055", - "nonce" : "0x00", - "storage" : { - } - } - } - }"#; - let _deserialized: Vm = serde_json::from_str(s).unwrap(); - // TODO: validate all fields - } -} diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index ec25c9e8b3f..efbd26fdf62 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -68,6 +68,7 @@ ethcore = { path = "../ethcore", features = ["test-helpers"] } ethcore-accounts = { path = "../accounts" } ethcore-io = { path = "../util/io" } ethcore-network = { path = "../util/network" } +ethjson = { path = "../json", features = ["test-helpers"] } fake-fetch = { path = "../util/fake-fetch" } macros = { path = "../util/macros" } pretty_assertions = "0.1" diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index ea9f5b7222f..bdbe12b98f9 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -15,8 +15,8 @@ // along with Parity Ethereum. If not, see . //! rpc integration tests. -use std::env; -use std::sync::Arc; + +use std::{env, sync::Arc}; use accounts::AccountProvider; use ethcore::client::{BlockChainClient, Client, ClientConfig, ChainInfo, ImportBlock}; @@ -27,7 +27,7 @@ use ethcore::test_helpers; use ethcore::verification::VerifierType; use ethcore::verification::queue::kind::blocks::Unverified; use ethereum_types::{Address, H256, U256}; -use ethjson::blockchain::BlockChain; +use ethjson::test_helpers::blockchain::BlockChain; use ethjson::spec::ForkSpec; use io::IoChannel; use miner::external::ExternalMiner; @@ -84,7 +84,7 @@ struct EthTester { impl EthTester { fn from_chain(chain: &BlockChain) -> Self { - let tester = if ::ethjson::blockchain::Engine::NoProof == chain.engine { + let tester = if ethjson::test_helpers::blockchain::Engine::NoProof == chain.engine { let mut config = ClientConfig::default(); config.verifier_type = VerifierType::CanonNoSeal; config.check_seal = false; @@ -174,13 +174,13 @@ impl EthTester { #[test] fn harness_works() { - let chain: BlockChain = extract_chain!("BlockchainTests/bcWalletTest/wallet2outOf3txs"); + let chain: BlockChain = extract_chain!("BlockchainTests/ValidBlocks/bcWalletTest/wallet2outOf3txs"); let _ = EthTester::from_chain(&chain); } #[test] fn eth_get_balance() { - let chain = extract_chain!("BlockchainTests/bcWalletTest/wallet2outOf3txs"); + let chain = extract_chain!("BlockchainTests/ValidBlocks/bcWalletTest/wallet2outOf3txs"); let tester = EthTester::from_chain(&chain); // final account state let req_latest = r#"{ @@ -206,7 +206,7 @@ fn eth_get_balance() { #[test] fn eth_get_proof() { - let chain = extract_chain!("BlockchainTests/bcWalletTest/wallet2outOf3txs"); + let chain = extract_chain!("BlockchainTests/ValidBlocks/bcWalletTest/wallet2outOf3txs"); let tester = EthTester::from_chain(&chain); // final account state let req_latest = r#"{ @@ -233,7 +233,7 @@ fn eth_get_proof() { #[test] fn eth_block_number() { - let chain = extract_chain!("BlockchainTests/bcGasPricerTest/RPC_API_Test"); + let chain = extract_chain!("BlockchainTests/ValidBlocks/bcGasPricerTest/RPC_API_Test"); let tester = EthTester::from_chain(&chain); let req_number = r#"{ "jsonrpc": "2.0", @@ -248,7 +248,7 @@ fn eth_block_number() { #[test] fn eth_get_block() { - let chain = extract_chain!("BlockchainTests/bcGasPricerTest/RPC_API_Test"); + let chain = extract_chain!("BlockchainTests/ValidBlocks/bcGasPricerTest/RPC_API_Test"); let tester = EthTester::from_chain(&chain); let req_block = r#"{"method":"eth_getBlockByNumber","params":["0x0",false],"id":1,"jsonrpc":"2.0"}"#; @@ -258,13 +258,13 @@ fn eth_get_block() { #[test] fn eth_get_block_by_hash() { - let chain = extract_chain!("BlockchainTests/bcGasPricerTest/RPC_API_Test"); + let chain = extract_chain!("BlockchainTests/ValidBlocks/bcGasPricerTest/RPC_API_Test"); let tester = EthTester::from_chain(&chain); // We're looking for block number 4 from "RPC_API_Test_Frontier" - let req_block = r#"{"method":"eth_getBlockByHash","params":["0xaddb9e39795e9e041c936b88a2577802569f34afded0948707b074caa3163a87",false],"id":1,"jsonrpc":"2.0"}"#; + let req_block = r#"{"method":"eth_getBlockByHash","params":["0x75e65fb3bbf5f53afe26dcc72df6a95b0e8ca5f1c450145d8c3915bd0308b75b",false],"id":1,"jsonrpc":"2.0"}"#; - let res_block = r#"{"jsonrpc":"2.0","result":{"author":"0x8888f1f195afa192cfee860698584c030f4c9db1","difficulty":"0x20080","extraData":"0x","gasLimit":"0x1dd7ea0","gasUsed":"0x5458","hash":"0xaddb9e39795e9e041c936b88a2577802569f34afded0948707b074caa3163a87","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0x8888f1f195afa192cfee860698584c030f4c9db1","mixHash":"0x713b0b31f6e72d8cb7367eaf59447ea531f209fc80e6379edd9f8d3bb73931c4","nonce":"0x4534b406bc23b86d","number":"0x4","parentHash":"0x17567aa5995b703736e32972289d68af50543acc4d56d37e8ad1fea7252cac4a","receiptsRoot":"0x7ed8026cf72ed0e98e6fd53ab406e51ffd34397d9da0052494ff41376fda7b5f","sealFields":["0xa0713b0b31f6e72d8cb7367eaf59447ea531f209fc80e6379edd9f8d3bb73931c4","0x884534b406bc23b86d"],"sha3Uncles":"0xe588a44b3e320e72e70b32b531f3ac0d432e756120135ae8fe5fa10895196b40","size":"0x661","stateRoot":"0x68805721294e365020aca15ed56c360d9dc2cf03cbeff84c9b84b8aed023bfb5","timestamp":"0x5bbdf772","totalDifficulty":"0xa00c0","transactions":["0xb094b9dc356dbb8b256402c6d5709288066ad6a372c90c9c516f14277545fd58"],"transactionsRoot":"0x97a593d8d7e15b57f5c6bb25bc6c325463ef99f874bc08a78656c3ab5cb23262","uncles":["0x86b48f5186c4b0882d3dca7977aa37840008832ef092f8ef797019dc74bfa8c7","0x2da9d062c11d536f0f1cc2a4e0111597c79926958d0fc26ae1a2d07d1a3bf47d"]},"id":1}"#; + let res_block = r#"{"jsonrpc":"2.0","result":{"author":"0x8888f1f195afa192cfee860698584c030f4c9db1","difficulty":"0x20000","extraData":"0x","gasLimit":"0x1dd7ea0","gasUsed":"0x5458","hash":"0x75e65fb3bbf5f53afe26dcc72df6a95b0e8ca5f1c450145d8c3915bd0308b75b","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0x8888f1f195afa192cfee860698584c030f4c9db1","mixHash":"0x55553aaef7ee28e3aea539eb784e8cc26646911a19126c242ac682c3fcf22041","nonce":"0xca2904e50ca47ace","number":"0x4","parentHash":"0x58849f66c0ca60054468725cf173b72a2769807152c625aa02e71d67ab2eaed5","receiptsRoot":"0x7ed8026cf72ed0e98e6fd53ab406e51ffd34397d9da0052494ff41376fda7b5f","sealFields":["0xa055553aaef7ee28e3aea539eb784e8cc26646911a19126c242ac682c3fcf22041","0x88ca2904e50ca47ace"],"sha3Uncles":"0x0dbc9711185574f2eee337af18d08c0afe85490304c6bb16b443991b552c5e2c","size":"0x661","stateRoot":"0x68805721294e365020aca15ed56c360d9dc2cf03cbeff84c9b84b8aed023bfb5","timestamp":"0x5c477134","totalDifficulty":"0xa0000","transactions":["0xb094b9dc356dbb8b256402c6d5709288066ad6a372c90c9c516f14277545fd58"],"transactionsRoot":"0x97a593d8d7e15b57f5c6bb25bc6c325463ef99f874bc08a78656c3ab5cb23262","uncles":["0x51b0d7366382926a4f83191af19cb4aa894f6fd9bd1bda6c04de3d5af70eddba","0x9263e0be8311eb79db96171fad3fdd70317bbbdc4081ad6b04c60335db65a3bb"]},"id":1}"#; assert_eq!(tester.handler.handle_request_sync(req_block).unwrap(), res_block); } @@ -510,6 +510,6 @@ fn starting_nonce_test() { assert_eq!(r#"{"jsonrpc":"2.0","result":"0x100","id":15}"#, &sample); } -register_test!(eth_transaction_count_1, verify_transaction_counts, "BlockchainTests/bcWalletTest/wallet2outOf3txs"); -register_test!(eth_transaction_count_2, verify_transaction_counts, "BlockchainTests/bcTotalDifficultyTest/sideChainWithMoreTransactions"); -register_test!(eth_transaction_count_3, verify_transaction_counts, "BlockchainTests/bcGasPricerTest/RPC_API_Test"); +register_test!(eth_transaction_count_1, verify_transaction_counts, "BlockchainTests/ValidBlocks/bcWalletTest/wallet2outOf3txs"); +register_test!(eth_transaction_count_2, verify_transaction_counts, "BlockchainTests/ValidBlocks/bcTotalDifficultyTest/sideChainWithMoreTransactions"); +register_test!(eth_transaction_count_3, verify_transaction_counts, "BlockchainTests/ValidBlocks/bcGasPricerTest/RPC_API_Test"); diff --git a/rpc/src/v1/tests/mod.rs b/rpc/src/v1/tests/mod.rs index 83f9dca905f..76e89e8bc09 100644 --- a/rpc/src/v1/tests/mod.rs +++ b/rpc/src/v1/tests/mod.rs @@ -32,7 +32,7 @@ macro_rules! extract_chain { (iter $file:expr) => {{ const RAW_DATA: &'static [u8] = include_bytes!(concat!("../../../../ethcore/res/ethereum/tests/", $file, ".json")); - ::ethjson::blockchain::Test::load(RAW_DATA).unwrap().into_iter() + ethjson::test_helpers::blockchain::Test::load(RAW_DATA).unwrap().into_iter() }}; ($file:expr) => {{ diff --git a/scripts/gitlab/test-linux.sh b/scripts/gitlab/test-linux.sh index 2ad2ab9be28..2e63240e3f1 100755 --- a/scripts/gitlab/test-linux.sh +++ b/scripts/gitlab/test-linux.sh @@ -5,7 +5,7 @@ echo "________Running test-linux.sh________" set -e # fail on any error set -u # treat unset variables as error -FEATURES="json-tests,ci-skip-tests" +FEATURES="json-tests" OPTIONS="--release" #use nproc `linux only THREADS=$(nproc)