Merge pull request #817 from ethcore/state_tests
refactored loading of state tests
This commit is contained in:
commit
8bb49f05d0
@ -19,6 +19,7 @@ use tests::helpers::*;
|
||||
use pod_state::*;
|
||||
use state_diff::*;
|
||||
use ethereum;
|
||||
use ethjson;
|
||||
|
||||
fn do_json_test(json_data: &[u8]) -> Vec<String> {
|
||||
json_chain_test(json_data, ChainEra::Frontier)
|
||||
@ -26,18 +27,14 @@ fn do_json_test(json_data: &[u8]) -> Vec<String> {
|
||||
|
||||
pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> {
|
||||
init_log();
|
||||
|
||||
let json = Json::from_str(::std::str::from_utf8(json_data).unwrap()).expect("Json is invalid");
|
||||
let tests = ethjson::state::Test::load(json_data).unwrap();
|
||||
let mut failed = Vec::new();
|
||||
|
||||
let engine = match era {
|
||||
ChainEra::Frontier => ethereum::new_mainnet_like(),
|
||||
ChainEra::Homestead => ethereum::new_homestead_test(),
|
||||
}.to_engine().unwrap();
|
||||
|
||||
flushln!("");
|
||||
|
||||
for (name, test) in json.as_object().unwrap() {
|
||||
for (name, test) in tests.into_iter() {
|
||||
let mut fail = false;
|
||||
{
|
||||
let mut fail_unless = |cond: bool| if !cond && !fail {
|
||||
@ -49,16 +46,13 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> {
|
||||
|
||||
flush!(" - {}...", name);
|
||||
|
||||
let t = SignedTransaction::from_json(&test["transaction"]);
|
||||
let env = EnvInfo::from_json(&test["env"]);
|
||||
let _out = Bytes::from_json(&test["out"]);
|
||||
let post_state_root = xjson!(&test["postStateRoot"]);
|
||||
let pre = PodState::from_json(&test["pre"]);
|
||||
let post = PodState::from_json(&test["post"]);
|
||||
let logs: Vec<_> = test["logs"].as_array().unwrap().iter().map(&LogEntry::from_json).collect();
|
||||
let transaction = test.transaction.into();
|
||||
let post_state_root = test.post_state_root.into();
|
||||
let env = test.env.into();
|
||||
let pre: PodState = test.pre_state.into();
|
||||
let post: PodState = test.post_state.into();
|
||||
let logs: Vec<LogEntry> = test.logs.into_iter().map(Into::into).collect();
|
||||
|
||||
//println!("Transaction: {:?}", t);
|
||||
//println!("Env: {:?}", env);
|
||||
let calc_post = sec_trie_root(post.get().iter().map(|(k, v)| (k.to_vec(), v.rlp())).collect());
|
||||
|
||||
if fail_unless(post_state_root == calc_post) {
|
||||
@ -69,7 +63,7 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> {
|
||||
let mut state = state_result.reference_mut();
|
||||
state.populate_from(pre);
|
||||
state.commit();
|
||||
let res = state.apply(&env, engine.deref(), &t, false);
|
||||
let res = state.apply(&env, engine.deref(), &transaction, false);
|
||||
|
||||
if fail_unless(state.root() == &post_state_root) {
|
||||
println!("!!! {}: State mismatch (got: {}, expect: {}):", name, state.root(), post_state_root);
|
||||
@ -88,12 +82,12 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !fail {
|
||||
flushln!("ok");
|
||||
}
|
||||
// TODO: Add extra APIs for output
|
||||
//if fail_unless(out == r.)
|
||||
}
|
||||
|
||||
println!("!!! {:?} tests from failed.", failed.len());
|
||||
failed
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
use util::*;
|
||||
use basic_types::LogBloom;
|
||||
use header::BlockNumber;
|
||||
use ethjson;
|
||||
|
||||
/// A record of execution for a `LOG` operation.
|
||||
#[derive(Default, Debug, Clone, PartialEq, Eq)]
|
||||
@ -65,6 +66,16 @@ impl LogEntry {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ethjson::state::Log> for LogEntry {
|
||||
fn from(l: ethjson::state::Log) -> Self {
|
||||
LogEntry {
|
||||
address: l.address.into(),
|
||||
topics: l.topics.into_iter().map(Into::into).collect(),
|
||||
data: l.data.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromJson for LogEntry {
|
||||
/// Convert given JSON object to a LogEntry.
|
||||
fn from_json(json: &Json) -> LogEntry {
|
||||
|
@ -20,6 +20,7 @@ use util::*;
|
||||
use error::*;
|
||||
use evm::Schedule;
|
||||
use header::BlockNumber;
|
||||
use ethjson;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
/// Transaction action type.
|
||||
@ -79,6 +80,23 @@ impl Transaction {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ethjson::state::Transaction> for SignedTransaction {
|
||||
fn from(t: ethjson::state::Transaction) -> Self {
|
||||
let to: Option<_> = t.to.into();
|
||||
Transaction {
|
||||
nonce: t.nonce.into(),
|
||||
gas_price: t.gas_price.into(),
|
||||
gas: t.gas_limit.into(),
|
||||
action: match to {
|
||||
Some(to) => Action::Call(to.into()),
|
||||
None => Action::Create
|
||||
},
|
||||
value: t.value.into(),
|
||||
data: t.data.into(),
|
||||
}.sign(&t.secret.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl FromJson for SignedTransaction {
|
||||
#[cfg_attr(feature="dev", allow(single_char_pattern))]
|
||||
fn from_json(json: &Json) -> SignedTransaction {
|
||||
|
@ -26,3 +26,4 @@ pub mod blockchain;
|
||||
pub mod spec;
|
||||
pub mod vm;
|
||||
pub mod maybe;
|
||||
pub mod state;
|
||||
|
52
json/src/state/log.rs
Normal file
52
json/src/state/log.rs
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity 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 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. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! State test log deserialization.
|
||||
use hash::{Address, H256, Bloom};
|
||||
use bytes::Bytes;
|
||||
|
||||
/// State test log deserialization.
|
||||
#[derive(Debug, PartialEq, Deserialize)]
|
||||
pub struct Log {
|
||||
/// Address.
|
||||
pub address: Address,
|
||||
/// Topics.
|
||||
pub topics: Vec<H256>,
|
||||
/// Data.
|
||||
pub data: Bytes,
|
||||
/// Bloom.
|
||||
pub bloom: Bloom,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use serde_json;
|
||||
use state::Log;
|
||||
|
||||
#[test]
|
||||
fn log_deserialization() {
|
||||
let s = r#"{
|
||||
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008800000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"data" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
"topics" : [
|
||||
"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
]
|
||||
}"#;
|
||||
let _deserialized: Log = serde_json::from_str(s).unwrap();
|
||||
// TODO: validate all fields
|
||||
}
|
||||
}
|
29
json/src/state/mod.rs
Normal file
29
json/src/state/mod.rs
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity 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 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. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! 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;
|
156
json/src/state/state.rs
Normal file
156
json/src/state/state.rs
Normal file
@ -0,0 +1,156 @@
|
||||
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity 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 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. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! State test deserialization.
|
||||
|
||||
use bytes::Bytes;
|
||||
use hash::H256;
|
||||
use state::{Env, AccountState, Transaction, Log};
|
||||
|
||||
/// State test deserialization.
|
||||
#[derive(Debug, PartialEq, Deserialize)]
|
||||
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.
|
||||
#[serde(rename="postStateRoot")]
|
||||
pub post_state_root: H256,
|
||||
/// Transaction.
|
||||
pub transaction: Transaction,
|
||||
/// Logs.
|
||||
pub logs: Vec<Log>
|
||||
}
|
||||
|
||||
#[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
|
||||
}
|
||||
}
|
43
json/src/state/test.rs
Normal file
43
json/src/state/test.rs
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity 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 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. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! State test deserializer.
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::io::Read;
|
||||
use serde_json;
|
||||
use serde_json::Error;
|
||||
use state::State;
|
||||
|
||||
/// State test deserializer.
|
||||
#[derive(Debug, PartialEq, Deserialize)]
|
||||
pub struct Test(BTreeMap<String, State>);
|
||||
|
||||
impl IntoIterator for Test {
|
||||
type Item = <BTreeMap<String, State> as IntoIterator>::Item;
|
||||
type IntoIter = <BTreeMap<String, State> as IntoIterator>::IntoIter;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.0.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl Test {
|
||||
/// Loads test from json.
|
||||
pub fn load<R>(reader: R) -> Result<Self, Error> where R: Read {
|
||||
serde_json::from_reader(reader)
|
||||
}
|
||||
}
|
65
json/src/state/transaction.rs
Normal file
65
json/src/state/transaction.rs
Normal file
@ -0,0 +1,65 @@
|
||||
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity 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 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. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! 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)]
|
||||
pub struct Transaction {
|
||||
/// Transaction data.
|
||||
pub data: Bytes,
|
||||
/// Gas limit.
|
||||
#[serde(rename="gasLimit")]
|
||||
pub gas_limit: Uint,
|
||||
/// Gas price.
|
||||
#[serde(rename="gasPrice")]
|
||||
pub gas_price: Uint,
|
||||
/// Nonce.
|
||||
pub nonce: Uint,
|
||||
/// Secret key.
|
||||
#[serde(rename="secretKey")]
|
||||
pub secret: H256,
|
||||
/// To.
|
||||
pub to: MaybeEmpty<Address>,
|
||||
/// 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
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user