merged with mk
This commit is contained in:
@@ -4,7 +4,7 @@ use executive::*;
|
||||
use spec::*;
|
||||
use engine::*;
|
||||
use evm;
|
||||
use evm::{Schedule, Ext, Factory, VMType};
|
||||
use evm::{Schedule, Ext, Factory, VMType, ContractCreateResult, MessageCallResult};
|
||||
use ethereum;
|
||||
use externalities::*;
|
||||
use substate::*;
|
||||
@@ -39,7 +39,7 @@ impl Engine for TestEngine {
|
||||
struct CallCreate {
|
||||
data: Bytes,
|
||||
destination: Option<Address>,
|
||||
_gas_limit: U256,
|
||||
gas_limit: U256,
|
||||
value: U256
|
||||
}
|
||||
|
||||
@@ -47,13 +47,22 @@ struct CallCreate {
|
||||
/// Stores callcreates.
|
||||
struct TestExt<'a> {
|
||||
ext: Externalities<'a>,
|
||||
callcreates: Vec<CallCreate>
|
||||
callcreates: Vec<CallCreate>,
|
||||
contract_address: Address
|
||||
}
|
||||
|
||||
impl<'a> TestExt<'a> {
|
||||
fn new(ext: Externalities<'a>) -> TestExt {
|
||||
fn new(state: &'a mut State,
|
||||
info: &'a EnvInfo,
|
||||
engine: &'a Engine,
|
||||
depth: usize,
|
||||
origin_info: OriginInfo,
|
||||
substate: &'a mut Substate,
|
||||
output: OutputPolicy<'a>,
|
||||
address: Address) -> Self {
|
||||
TestExt {
|
||||
ext: ext,
|
||||
contract_address: contract_address(&address, &state.nonce(&address)),
|
||||
ext: Externalities::new(state, info, engine, depth, origin_info, substate, output),
|
||||
callcreates: vec![]
|
||||
}
|
||||
}
|
||||
@@ -64,8 +73,12 @@ impl<'a> Ext for TestExt<'a> {
|
||||
self.ext.storage_at(key)
|
||||
}
|
||||
|
||||
fn set_storage_at(&mut self, key: H256, value: H256) {
|
||||
self.ext.set_storage_at(key, value)
|
||||
fn set_storage(&mut self, key: H256, value: H256) {
|
||||
self.ext.set_storage(key, value)
|
||||
}
|
||||
|
||||
fn exists(&self, address: &Address) -> bool {
|
||||
self.ext.exists(address)
|
||||
}
|
||||
|
||||
fn balance(&self, address: &Address) -> U256 {
|
||||
@@ -76,60 +89,30 @@ impl<'a> Ext for TestExt<'a> {
|
||||
self.ext.blockhash(number)
|
||||
}
|
||||
|
||||
fn create(&mut self, gas: &U256, value: &U256, code: &[u8]) -> (U256, Option<Address>) {
|
||||
// in call and create we need to check if we exited with insufficient balance or max limit reached.
|
||||
// in case of reaching max depth, we should store callcreates. Otherwise, ignore.
|
||||
let res = self.ext.create(gas, value, code);
|
||||
let ext = &self.ext;
|
||||
match res {
|
||||
// just record call create
|
||||
(gas_left, Some(address)) => {
|
||||
self.callcreates.push(CallCreate {
|
||||
data: code.to_vec(),
|
||||
destination: Some(address.clone()),
|
||||
_gas_limit: *gas,
|
||||
value: *value
|
||||
});
|
||||
(gas_left, Some(address))
|
||||
},
|
||||
// creation failed only due to reaching max_depth
|
||||
(gas_left, None) if ext.state.balance(&ext.params.address) >= *value => {
|
||||
self.callcreates.push(CallCreate {
|
||||
data: code.to_vec(),
|
||||
// callcreate test does not need an address
|
||||
destination: None,
|
||||
_gas_limit: *gas,
|
||||
value: *value
|
||||
});
|
||||
let address = contract_address(&ext.params.address, &ext.state.nonce(&ext.params.address));
|
||||
(gas_left, Some(address))
|
||||
},
|
||||
other => other
|
||||
}
|
||||
fn create(&mut self, gas: &U256, value: &U256, code: &[u8]) -> ContractCreateResult {
|
||||
self.callcreates.push(CallCreate {
|
||||
data: code.to_vec(),
|
||||
destination: None,
|
||||
gas_limit: *gas,
|
||||
value: *value
|
||||
});
|
||||
ContractCreateResult::Created(self.contract_address.clone(), *gas)
|
||||
}
|
||||
|
||||
fn call(&mut self,
|
||||
gas: &U256,
|
||||
call_gas: &U256,
|
||||
receive_address: &Address,
|
||||
value: &U256,
|
||||
data: &[u8],
|
||||
code_address: &Address,
|
||||
output: &mut [u8]) -> Result<(U256, bool), evm::Error> {
|
||||
let res = self.ext.call(gas, call_gas, receive_address, value, data, code_address, output);
|
||||
let ext = &self.ext;
|
||||
if let &Ok((gas_left, _)) = &res {
|
||||
if ext.state.balance(&ext.params.address) >= *value {
|
||||
self.callcreates.push(CallCreate {
|
||||
data: data.to_vec(),
|
||||
destination: Some(receive_address.clone()),
|
||||
_gas_limit: *call_gas,
|
||||
value: *value
|
||||
});
|
||||
return Ok((gas_left, true))
|
||||
}
|
||||
}
|
||||
res
|
||||
_code_address: &Address,
|
||||
_output: &mut [u8]) -> MessageCallResult {
|
||||
self.callcreates.push(CallCreate {
|
||||
data: data.to_vec(),
|
||||
destination: Some(receive_address.clone()),
|
||||
gas_limit: *gas,
|
||||
value: *value
|
||||
});
|
||||
MessageCallResult::Success(*gas)
|
||||
}
|
||||
|
||||
fn extcode(&self, address: &Address) -> Bytes {
|
||||
@@ -155,6 +138,14 @@ impl<'a> Ext for TestExt<'a> {
|
||||
fn env_info(&self) -> &EnvInfo {
|
||||
self.ext.env_info()
|
||||
}
|
||||
|
||||
fn depth(&self) -> usize {
|
||||
0
|
||||
}
|
||||
|
||||
fn inc_sstore_clears(&mut self) {
|
||||
self.ext.inc_sstore_clears()
|
||||
}
|
||||
}
|
||||
|
||||
fn do_json_test(json_data: &[u8]) -> Vec<String> {
|
||||
@@ -206,7 +197,7 @@ fn do_json_test_for(vm: &VMType, json_data: &[u8]) -> Vec<String> {
|
||||
info.timestamp = xjson!(&env["currentTimestamp"]);
|
||||
});
|
||||
|
||||
let engine = TestEngine::new(0, vm.clone());
|
||||
let engine = TestEngine::new(1, vm.clone());
|
||||
|
||||
// params
|
||||
let mut params = ActionParams::new();
|
||||
@@ -229,11 +220,17 @@ fn do_json_test_for(vm: &VMType, json_data: &[u8]) -> Vec<String> {
|
||||
|
||||
// execute
|
||||
let (res, callcreates) = {
|
||||
let ex = Externalities::new(&mut state, &info, &engine, 0, ¶ms, &mut substate, OutputPolicy::Return(BytesRef::Flexible(&mut output)));
|
||||
let mut test_ext = TestExt::new(ex);
|
||||
let mut ex = TestExt::new(&mut state,
|
||||
&info,
|
||||
&engine,
|
||||
0,
|
||||
OriginInfo::from(¶ms),
|
||||
&mut substate,
|
||||
OutputPolicy::Return(BytesRef::Flexible(&mut output)),
|
||||
params.address.clone());
|
||||
let evm = engine.vm_factory().create();
|
||||
let res = evm.exec(¶ms, &mut test_ext);
|
||||
(res, test_ext.callcreates)
|
||||
let res = evm.exec(params, &mut ex);
|
||||
(res, ex.callcreates)
|
||||
};
|
||||
|
||||
// then validate
|
||||
@@ -262,11 +259,7 @@ fn do_json_test_for(vm: &VMType, json_data: &[u8]) -> Vec<String> {
|
||||
fail_unless(callcreate.data == Bytes::from_json(&expected["data"]), "callcreates data is incorrect");
|
||||
fail_unless(callcreate.destination == xjson!(&expected["destination"]), "callcreates destination is incorrect");
|
||||
fail_unless(callcreate.value == xjson!(&expected["value"]), "callcreates value is incorrect");
|
||||
|
||||
// TODO: call_gas is calculated in externalities and is not exposed to TestExt.
|
||||
// maybe move it to it's own function to simplify calculation?
|
||||
//println!("name: {:?}, callcreate {:?}, expected: {:?}", name, callcreate.gas_limit, U256::from(&expected["gasLimit"]));
|
||||
//fail_unless(callcreate.gas_limit == U256::from(&expected["gasLimit"]), "callcreates gas_limit is incorrect");
|
||||
fail_unless(callcreate.gas_limit == xjson!(&expected["gasLimit"]), "callcreates gas_limit is incorrect");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,15 +4,26 @@ use pod_state::*;
|
||||
use state_diff::*;
|
||||
use ethereum;
|
||||
|
||||
const HOMESTEAD_BLOCK : u64 = 0x0dbba0;
|
||||
|
||||
fn do_json_test(json_data: &[u8]) -> Vec<String> {
|
||||
let json = Json::from_str(::std::str::from_utf8(json_data).unwrap()).expect("Json is invalid");
|
||||
let mut failed = Vec::new();
|
||||
|
||||
let engine = ethereum::new_frontier_test().to_engine().unwrap();
|
||||
let engine = |block_number: u64| {
|
||||
if block_number >= HOMESTEAD_BLOCK {
|
||||
ethereum::new_homestead_test().to_engine().unwrap()
|
||||
} else {
|
||||
ethereum::new_frontier_test().to_engine().unwrap()
|
||||
}
|
||||
};
|
||||
|
||||
flush(format!("\n"));
|
||||
|
||||
for (name, test) in json.as_object().unwrap() {
|
||||
if name != "createNameRegistratorPerTxsAt" {
|
||||
continue;
|
||||
}
|
||||
let mut fail = false;
|
||||
{
|
||||
let mut fail_unless = |cond: bool| if !cond && !fail {
|
||||
@@ -24,8 +35,9 @@ fn do_json_test(json_data: &[u8]) -> Vec<String> {
|
||||
|
||||
flush(format!(" - {}...", name));
|
||||
|
||||
let t = Transaction::from_json(&test["transaction"]);
|
||||
let env = EnvInfo::from_json(&test["env"]);
|
||||
let engine = engine(env.number);
|
||||
let t = Transaction::from_json(&test["transaction"]);
|
||||
let _out = Bytes::from_json(&test["out"]);
|
||||
let post_state_root = xjson!(&test["postStateRoot"]);
|
||||
let pre = PodState::from_json(&test["pre"]);
|
||||
|
||||
Reference in New Issue
Block a user