Skip to content
This repository was archived by the owner on Nov 6, 2020. It is now read-only.

Commit 79aa179

Browse files
tomusdrwandresilva
authored andcommitted
Update state tests execution model (#9440)
* Update & fix JSON state tests. * Update tests to be able to run ethtest at 021fe3d410773024cd5f0387e62db6e6ec800f32. - Touch user in state - Adjust transaction tests to new json format * Switch to same commit for submodule ethereum/test as geth (next includes constantinople changes). Added test `json_tests::trie::generic::TrieTests_trieanyorder` and a few difficulty tests. * Remove trietestnextprev as it would require to parse differently and implement it. * Support new (shitty) format of transaction tests. * Ignore junk in ethereum/tests repo. * Ignore incorrect test. * Update to a later commit * Move block number to a constant. * Fix ZK2 test - touched account should also be cleared. * Fix conflict resolution
1 parent 4d50c6c commit 79aa179

File tree

16 files changed

+216
-133
lines changed

16 files changed

+216
-133
lines changed

ethcore/res/ethereum/eip161_test.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"eip161abcTransition": "0x0",
2424
"eip161dTransition": "0x0",
2525
"eip98Transition": "0x7fffffffffffffff",
26-
"eip155Transition": "0x7fffffffffffffff",
26+
"eip155Transition": "0x0",
2727
"maxCodeSize": 24576,
2828
"maxCodeSizeTransition": "0x0"
2929
},

ethcore/res/ethereum/tests

Submodule tests updated 19225 files

ethcore/src/client/evm_test_client.rs

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ impl fmt::Display for EvmTestError {
6060
}
6161

6262
use ethereum;
63-
use ethjson::state::test::ForkSpec;
63+
use ethjson::spec::ForkSpec;
6464

6565
/// Simplified, single-block EVM test client.
6666
pub struct EvmTestClient<'a> {
@@ -69,12 +69,12 @@ pub struct EvmTestClient<'a> {
6969
}
7070

7171
impl<'a> fmt::Debug for EvmTestClient<'a> {
72-
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
73-
fmt.debug_struct("EvmTestClient")
74-
.field("state", &self.state)
75-
.field("spec", &self.spec.name)
76-
.finish()
77-
}
72+
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
73+
fmt.debug_struct("EvmTestClient")
74+
.field("state", &self.state)
75+
.field("spec", &self.spec.name)
76+
.finish()
77+
}
7878
}
7979

8080
impl<'a> EvmTestClient<'a> {
@@ -217,9 +217,27 @@ impl<'a> EvmTestClient<'a> {
217217
let result = self.state.apply_with_tracing(&env_info, self.spec.engine.machine(), &transaction, tracer, vm_tracer);
218218
let scheme = self.spec.engine.machine().create_address_scheme(env_info.number);
219219

220+
// Touch the coinbase at the end of the test to simulate
221+
// miner reward.
222+
// Details: https://github.com/paritytech/parity-ethereum/issues/9431
223+
let schedule = self.spec.engine.machine().schedule(env_info.number);
224+
self.state.add_balance(&env_info.author, &0.into(), if schedule.no_empty {
225+
state::CleanupMode::NoEmpty
226+
} else {
227+
state::CleanupMode::ForceCreate
228+
}).ok();
229+
// Touching also means that we should remove the account if it's within eip161
230+
// conditions.
231+
self.state.kill_garbage(
232+
&vec![env_info.author].into_iter().collect(),
233+
schedule.kill_empty,
234+
&None,
235+
false
236+
).ok();
237+
self.state.commit().ok();
238+
220239
match result {
221240
Ok(result) => {
222-
self.state.commit().ok();
223241
TransactResult::Ok {
224242
state_root: *self.state.root(),
225243
gas_left: initial_gas - result.receipt.gas_used,

ethcore/src/json_tests/difficulty.rs

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,26 +52,61 @@ pub fn json_difficulty_test<H: FnMut(&str, HookType)>(json_data: &[u8], spec: Sp
5252
vec![]
5353
}
5454

55-
mod difficulty_test_byzantium {
55+
macro_rules! difficulty_json_test {
56+
( $spec:ident ) => {
57+
5658
use super::json_difficulty_test;
59+
use tempdir::TempDir;
5760
use json_tests::HookType;
5861

5962
fn do_json_test<H: FnMut(&str, HookType)>(json_data: &[u8], h: &mut H) -> Vec<String> {
60-
json_difficulty_test(json_data, ::ethereum::new_byzantium_test(), h)
63+
let tempdir = TempDir::new("").unwrap();
64+
json_difficulty_test(json_data, ::ethereum::$spec(&tempdir.path()), h)
6165
}
6266

63-
declare_test!{DifficultyTests_difficultyByzantium, "BasicTests/difficultyByzantium.json"}
67+
}
6468
}
6569

66-
mod difficulty_test_foundation {
70+
macro_rules! difficulty_json_test_nopath {
71+
( $spec:ident ) => {
72+
6773
use super::json_difficulty_test;
68-
use tempdir::TempDir;
6974
use json_tests::HookType;
7075

7176
fn do_json_test<H: FnMut(&str, HookType)>(json_data: &[u8], h: &mut H) -> Vec<String> {
72-
let tempdir = TempDir::new("").unwrap();
73-
json_difficulty_test(json_data, ::ethereum::new_foundation(&tempdir.path()), h)
77+
json_difficulty_test(json_data, ::ethereum::$spec(), h)
7478
}
7579

80+
}
81+
}
82+
83+
mod difficulty_test {
84+
difficulty_json_test!(new_foundation);
85+
declare_test!{DifficultyTests_difficulty, "BasicTests/difficulty.json"}
86+
}
87+
88+
mod difficulty_test_byzantium {
89+
difficulty_json_test_nopath!(new_byzantium_test);
90+
declare_test!{DifficultyTests_difficultyByzantium, "BasicTests/difficultyByzantium.json"}
91+
}
92+
93+
mod difficulty_test_foundation {
94+
difficulty_json_test!(new_foundation);
7695
declare_test!{DifficultyTests_difficultyMainNetwork, "BasicTests/difficultyMainNetwork.json"}
7796
}
97+
98+
mod difficulty_test_ropsten {
99+
difficulty_json_test_nopath!(new_ropsten_test);
100+
declare_test!{DifficultyTests_difficultyRopsten, "BasicTests/difficultyRopsten.json"}
101+
}
102+
103+
mod difficulty_test_frontier {
104+
difficulty_json_test_nopath!(new_frontier_test);
105+
declare_test!{DifficultyTests_difficultyFrontier, "BasicTests/difficultyFrontier.json"}
106+
}
107+
108+
mod difficulty_test_homestead {
109+
difficulty_json_test_nopath!(new_homestead_test);
110+
declare_test!{DifficultyTests_difficultyHomestead, "BasicTests/difficultyHomestead.json"}
111+
}
112+

ethcore/src/json_tests/state.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,16 @@ mod state_tests {
114114
json_chain_test(json_data, h)
115115
}
116116

117+
declare_test!{GeneralStateTest_stArgsZeroOneBalance, "GeneralStateTests/stArgsZeroOneBalance/"}
117118
declare_test!{GeneralStateTest_stAttackTest, "GeneralStateTests/stAttackTest/"}
118119
declare_test!{GeneralStateTest_stBadOpcodeTest, "GeneralStateTests/stBadOpcode/"}
120+
declare_test!{GeneralStateTest_stBugs, "GeneralStateTests/stBugs/"}
119121
declare_test!{GeneralStateTest_stCallCodes, "GeneralStateTests/stCallCodes/"}
122+
declare_test!{GeneralStateTest_stCallCreateCallCodeTest, "GeneralStateTests/stCallCreateCallCodeTest/"}
120123
declare_test!{GeneralStateTest_stCallDelegateCodesCallCodeHomestead, "GeneralStateTests/stCallDelegateCodesCallCodeHomestead/"}
121124
declare_test!{GeneralStateTest_stCallDelegateCodesHomestead, "GeneralStateTests/stCallDelegateCodesHomestead/"}
122125
declare_test!{GeneralStateTest_stChangedEIP150, "GeneralStateTests/stChangedEIP150/"}
126+
declare_test!{GeneralStateTest_stCodeCopyTest, "GeneralStateTests/stCodeCopyTest/"}
123127
declare_test!{GeneralStateTest_stCodeSizeLimit, "GeneralStateTests/stCodeSizeLimit/"}
124128
declare_test!{GeneralStateTest_stCreateTest, "GeneralStateTests/stCreateTest/"}
125129
declare_test!{GeneralStateTest_stDelegatecallTestHomestead, "GeneralStateTests/stDelegatecallTestHomestead/"}
@@ -135,12 +139,15 @@ mod state_tests {
135139
declare_test!{GeneralStateTest_stMemoryTest, "GeneralStateTests/stMemoryTest/"}
136140
declare_test!{GeneralStateTest_stNonZeroCallsTest, "GeneralStateTests/stNonZeroCallsTest/"}
137141
declare_test!{GeneralStateTest_stPreCompiledContracts, "GeneralStateTests/stPreCompiledContracts/"}
142+
declare_test!{GeneralStateTest_stPreCompiledContracts2, "GeneralStateTests/stPreCompiledContracts2/"}
138143
declare_test!{heavy => GeneralStateTest_stQuadraticComplexityTest, "GeneralStateTests/stQuadraticComplexityTest/"}
139144
declare_test!{GeneralStateTest_stRandom, "GeneralStateTests/stRandom/"}
145+
declare_test!{GeneralStateTest_stRandom2, "GeneralStateTests/stRandom2/"}
140146
declare_test!{GeneralStateTest_stRecursiveCreate, "GeneralStateTests/stRecursiveCreate/"}
141147
declare_test!{GeneralStateTest_stRefundTest, "GeneralStateTests/stRefundTest/"}
142148
declare_test!{GeneralStateTest_stReturnDataTest, "GeneralStateTests/stReturnDataTest/"}
143149
declare_test!{GeneralStateTest_stRevertTest, "GeneralStateTests/stRevertTest/"}
150+
declare_test!{GeneralStateTest_stShift, "GeneralStateTests/stShift/"}
144151
declare_test!{GeneralStateTest_stSolidityTest, "GeneralStateTests/stSolidityTest/"}
145152
declare_test!{GeneralStateTest_stSpecialTest, "GeneralStateTests/stSpecialTest/"}
146153
declare_test!{GeneralStateTest_stStackTests, "GeneralStateTests/stStackTests/"}
@@ -152,4 +159,11 @@ mod state_tests {
152159
declare_test!{GeneralStateTest_stZeroCallsRevert, "GeneralStateTests/stZeroCallsRevert/"}
153160
declare_test!{GeneralStateTest_stZeroCallsTest, "GeneralStateTests/stZeroCallsTest/"}
154161
declare_test!{GeneralStateTest_stZeroKnowledge, "GeneralStateTests/stZeroKnowledge/"}
162+
163+
// Attempts to send a transaction that requires more than current balance:
164+
// Tx:
165+
// https://github.com/ethereum/tests/blob/726b161ba8a739691006cc1ba080672bb50a9d49/GeneralStateTests/stZeroKnowledge2/ecmul_0-3_5616_28000_96.json#L170
166+
// Balance:
167+
// https://github.com/ethereum/tests/blob/726b161ba8a739691006cc1ba080672bb50a9d49/GeneralStateTests/stZeroKnowledge2/ecmul_0-3_5616_28000_96.json#L126
168+
declare_test!{GeneralStateTest_stZeroKnowledge2, "GeneralStateTests/stZeroKnowledge2/"}
155169
}

ethcore/src/json_tests/test_common.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ pub fn run_test_path<H: FnMut(&str, HookType)>(
4141
os.push(".json");
4242
os
4343
}).collect();
44+
let extension = path.extension().and_then(|s| s.to_str());
4445
if path.is_dir() {
4546
for p in read_dir(path).unwrap().filter_map(|e| {
4647
let e = e.unwrap();
@@ -51,6 +52,8 @@ pub fn run_test_path<H: FnMut(&str, HookType)>(
5152
}}) {
5253
run_test_path(&p, skip, runner, start_stop_hook)
5354
}
55+
} else if extension == Some("swp") || extension == None {
56+
// Ignore junk
5457
} else {
5558
let mut path = p.to_path_buf();
5659
path.set_extension("json");
@@ -64,7 +67,10 @@ pub fn run_test_file<H: FnMut(&str, HookType)>(
6467
start_stop_hook: &mut H
6568
) {
6669
let mut data = Vec::new();
67-
let mut file = File::open(&path).expect("Error opening test file");
70+
let mut file = match File::open(&path) {
71+
Ok(file) => file,
72+
Err(_) => panic!("Error opening test file at: {:?}", path),
73+
};
6874
file.read_to_end(&mut data).expect("Error reading test file");
6975
let results = runner(&data, start_stop_hook);
7076
let empty: [String; 0] = [];

ethcore/src/json_tests/transaction.rs

Lines changed: 62 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@
1616

1717
use std::path::Path;
1818
use super::test_common::*;
19-
use evm;
19+
use client::EvmTestClient;
20+
use header::Header;
2021
use ethjson;
2122
use rlp::Rlp;
22-
use transaction::{Action, UnverifiedTransaction, SignedTransaction};
23+
use transaction::UnverifiedTransaction;
2324

2425
/// Run transaction jsontests on a given folder.
2526
pub fn run_test_path<H: FnMut(&str, HookType)>(p: &Path, skip: &[&'static str], h: &mut H) {
@@ -31,55 +32,61 @@ pub fn run_test_file<H: FnMut(&str, HookType)>(p: &Path, h: &mut H) {
3132
::json_tests::test_common::run_test_file(p, do_json_test, h)
3233
}
3334

35+
// Block number used to run the tests.
36+
// Make sure that all the specified features are activated.
37+
const BLOCK_NUMBER: u64 = 0x6ffffffffffffe;
38+
3439
fn do_json_test<H: FnMut(&str, HookType)>(json_data: &[u8], start_stop_hook: &mut H) -> Vec<String> {
3540
let tests = ethjson::transaction::Test::load(json_data).unwrap();
3641
let mut failed = Vec::new();
37-
let frontier_schedule = evm::Schedule::new_frontier();
38-
let homestead_schedule = evm::Schedule::new_homestead();
39-
let byzantium_schedule = evm::Schedule::new_byzantium();
4042
for (name, test) in tests.into_iter() {
4143
start_stop_hook(&name, HookType::OnStart);
4244

43-
let mut fail_unless = |cond: bool, title: &str| if !cond { failed.push(name.clone()); println!("Transaction failed: {:?}: {:?}", name, title); };
44-
45-
let number: Option<u64> = test.block_number.map(Into::into);
46-
let schedule = match number {
47-
None => &frontier_schedule,
48-
Some(x) if x < 1_150_000 => &frontier_schedule,
49-
Some(x) if x < 3_000_000 => &homestead_schedule,
50-
Some(_) => &byzantium_schedule
51-
};
52-
let allow_chain_id_of_one = number.map_or(false, |n| n >= 2_675_000);
53-
let allow_unsigned = number.map_or(false, |n| n >= 3_000_000);
54-
55-
let rlp: Vec<u8> = test.rlp.into();
56-
let res = Rlp::new(&rlp)
57-
.as_val()
58-
.map_err(::error::Error::from)
59-
.and_then(|t: UnverifiedTransaction| {
60-
t.validate(schedule, schedule.have_delegate_call, allow_chain_id_of_one, allow_unsigned).map_err(Into::into)
61-
});
62-
63-
fail_unless(test.transaction.is_none() == res.is_err(), "Validity different");
64-
if let (Some(tx), Some(sender)) = (test.transaction, test.sender) {
65-
let t = res.unwrap();
66-
fail_unless(SignedTransaction::new(t.clone()).unwrap().sender() == sender.into(), "sender mismatch");
67-
let is_acceptable_chain_id = match t.chain_id() {
68-
None => true,
69-
Some(1) if allow_chain_id_of_one => true,
70-
_ => false,
45+
for (spec_name, result) in test.post_state {
46+
let spec = match EvmTestClient::spec_from_json(&spec_name) {
47+
Some(spec) => spec,
48+
None => {
49+
println!(" - {} | {:?} Ignoring tests because of missing spec", name, spec_name);
50+
continue;
51+
}
52+
};
53+
54+
let mut fail_unless = |cond: bool, title: &str| if !cond {
55+
failed.push(format!("{}-{:?}", name, spec_name));
56+
println!("Transaction failed: {:?}-{:?}: {:?}", name, spec_name, title);
7157
};
72-
fail_unless(is_acceptable_chain_id, "Network ID unacceptable");
73-
let data: Vec<u8> = tx.data.into();
74-
fail_unless(t.data == data, "data mismatch");
75-
fail_unless(t.gas_price == tx.gas_price.into(), "gas_price mismatch");
76-
fail_unless(t.nonce == tx.nonce.into(), "nonce mismatch");
77-
fail_unless(t.value == tx.value.into(), "value mismatch");
78-
let to: Option<ethjson::hash::Address> = tx.to.into();
79-
let to: Option<Address> = to.map(Into::into);
80-
match t.action {
81-
Action::Call(dest) => fail_unless(Some(dest) == to, "call/destination mismatch"),
82-
Action::Create => fail_unless(None == to, "create mismatch"),
58+
59+
let rlp: Vec<u8> = test.rlp.clone().into();
60+
let res = Rlp::new(&rlp)
61+
.as_val()
62+
.map_err(::error::Error::from)
63+
.and_then(|t: UnverifiedTransaction| {
64+
let mut header: Header = Default::default();
65+
// Use high enough number to activate all required features.
66+
header.set_number(BLOCK_NUMBER);
67+
68+
let minimal = t.gas_required(&spec.engine.schedule(header.number())).into();
69+
if t.gas < minimal {
70+
return Err(::transaction::Error::InsufficientGas {
71+
minimal, got: t.gas,
72+
}.into());
73+
}
74+
spec.engine.verify_transaction_basic(&t, &header)?;
75+
Ok(spec.engine.verify_transaction_unordered(t, &header)?)
76+
});
77+
78+
match (res, result.hash, result.sender) {
79+
(Ok(t), Some(hash), Some(sender)) => {
80+
fail_unless(t.sender() == sender.into(), "sender mismatch");
81+
fail_unless(t.hash() == hash.into(), "hash mismatch");
82+
},
83+
(Err(_), None, None) => {},
84+
data => {
85+
fail_unless(
86+
false,
87+
&format!("Validity different: {:?}", data)
88+
);
89+
}
8390
}
8491
}
8592

@@ -92,13 +99,14 @@ fn do_json_test<H: FnMut(&str, HookType)>(json_data: &[u8], start_stop_hook: &mu
9299
failed
93100
}
94101

95-
declare_test!{TransactionTests_ttEip155VitaliksHomesead, "TransactionTests/ttEip155VitaliksHomesead"}
96-
declare_test!{TransactionTests_ttEip155VitaliksEip158, "TransactionTests/ttEip155VitaliksEip158"}
97-
declare_test!{TransactionTests_ttEip158, "TransactionTests/ttEip158"}
98-
declare_test!{TransactionTests_ttFrontier, "TransactionTests/ttFrontier"}
99-
declare_test!{TransactionTests_ttHomestead, "TransactionTests/ttHomestead"}
100-
declare_test!{TransactionTests_ttVRuleEip158, "TransactionTests/ttVRuleEip158"}
101-
declare_test!{TransactionTests_ttWrongRLPFrontier, "TransactionTests/ttWrongRLPFrontier"}
102-
declare_test!{TransactionTests_ttWrongRLPHomestead, "TransactionTests/ttWrongRLPHomestead"}
103-
declare_test!{TransactionTests_ttConstantinople, "TransactionTests/ttConstantinople"}
104-
declare_test!{TransactionTests_ttSpecConstantinople, "TransactionTests/ttSpecConstantinople"}
102+
declare_test!{TransactionTests_ttAddress, "TransactionTests/ttAddress"}
103+
declare_test!{TransactionTests_ttData, "TransactionTests/ttData"}
104+
declare_test!{TransactionTests_ttGasLimit, "TransactionTests/ttGasLimit"}
105+
declare_test!{TransactionTests_ttGasPrice, "TransactionTests/ttGasPrice"}
106+
declare_test!{TransactionTests_ttNonce, "TransactionTests/ttNonce"}
107+
declare_test!{TransactionTests_ttRSValue, "TransactionTests/ttRSValue"}
108+
declare_test!{TransactionTests_ttSignature, "TransactionTests/ttSignature"}
109+
declare_test!{TransactionTests_ttValue, "TransactionTests/ttValue"}
110+
declare_test!{TransactionTests_ttVValue, "TransactionTests/ttVValue"}
111+
declare_test!{TransactionTests_ttWrongRLP, "TransactionTests/ttWrongRLP"}
112+

ethcore/transaction/src/transaction.rs

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -387,23 +387,6 @@ impl UnverifiedTransaction {
387387
Ok(recover(&self.signature(), &self.unsigned.hash(self.chain_id()))?)
388388
}
389389

390-
/// Do basic validation, checking for valid signature and minimum gas,
391-
// TODO: consider use in block validation.
392-
#[cfg(feature = "json-tests")]
393-
pub fn validate(self, schedule: &Schedule, require_low: bool, allow_chain_id_of_one: bool, allow_empty_signature: bool)
394-
-> Result<UnverifiedTransaction, error::Error>
395-
{
396-
let chain_id = if allow_chain_id_of_one { Some(1) } else { None };
397-
self.verify_basic(require_low, chain_id, allow_empty_signature)?;
398-
if !allow_empty_signature || !self.is_unsigned() {
399-
self.recover_public()?;
400-
}
401-
if self.gas < U256::from(self.gas_required(&schedule)) {
402-
return Err(error::Error::InvalidGasLimit(::unexpected::OutOfBounds{min: Some(U256::from(self.gas_required(&schedule))), max: None, found: self.gas}).into())
403-
}
404-
Ok(self)
405-
}
406-
407390
/// Verify basic signature params. Does not attempt sender recovery.
408391
pub fn verify_basic(&self, check_low_s: bool, chain_id: Option<u64>, allow_empty_signature: bool) -> Result<(), error::Error> {
409392
if check_low_s && !(allow_empty_signature && self.is_unsigned()) {

evmbin/src/info.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ pub fn run_action<T: Informant>(
8484
pub fn run_transaction<T: Informant>(
8585
name: &str,
8686
idx: usize,
87-
spec: &ethjson::state::test::ForkSpec,
87+
spec: &ethjson::spec::ForkSpec,
8888
pre_state: &pod_state::PodState,
8989
post_root: H256,
9090
env_info: &client::EnvInfo,

json/src/blockchain/blockchain.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ use hash::H256;
2121
use blockchain::state::State;
2222
use blockchain::header::Header;
2323
use blockchain::block::Block;
24-
use state::test::ForkSpec;
25-
use spec::{Genesis, Seal, Ethereum};
24+
use spec::{ForkSpec, Genesis, Seal, Ethereum};
2625

2726
/// Blockchain deserialization.
2827
#[derive(Debug, PartialEq, Deserialize)]

0 commit comments

Comments
 (0)