2020-09-22 14:53:52 +02:00
|
|
|
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
|
|
|
// This file is part of OpenEthereum.
|
2016-02-05 13:40:41 +01:00
|
|
|
|
2020-09-22 14:53:52 +02:00
|
|
|
// OpenEthereum is free software: you can redistribute it and/or modify
|
2016-02-05 13:40:41 +01:00
|
|
|
// 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.
|
|
|
|
|
2020-09-22 14:53:52 +02:00
|
|
|
// OpenEthereum is distributed in the hope that it will be useful,
|
2016-02-05 13:40:41 +01:00
|
|
|
// 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
|
2020-09-22 14:53:52 +02:00
|
|
|
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
|
2016-02-05 13:40:41 +01:00
|
|
|
|
2016-01-13 01:23:01 +01:00
|
|
|
use super::test_common::*;
|
2018-08-13 23:27:13 +02:00
|
|
|
use bytes::Bytes;
|
2016-03-24 01:25:59 +01:00
|
|
|
use ethjson;
|
2018-07-02 18:50:05 +02:00
|
|
|
use ethtrie;
|
2020-09-08 02:48:09 +02:00
|
|
|
use evm::Finalize;
|
2016-01-13 01:23:01 +01:00
|
|
|
use executive::*;
|
2016-01-15 14:22:46 +01:00
|
|
|
use externalities::*;
|
2017-09-15 21:07:54 +02:00
|
|
|
use hash::keccak;
|
2017-09-26 14:19:08 +02:00
|
|
|
use machine::EthereumMachine as Machine;
|
2017-09-15 21:07:54 +02:00
|
|
|
use rlp::RlpStream;
|
2017-02-22 10:52:58 +01:00
|
|
|
use state::{Backend as StateBackend, State, Substate};
|
2018-06-25 11:21:45 +02:00
|
|
|
use std::{path::Path, sync::Arc};
|
2018-04-09 16:14:33 +02:00
|
|
|
use test_helpers::get_temp_state;
|
2016-06-02 12:40:31 +02:00
|
|
|
use trace::{NoopTracer, NoopVMTracer, Tracer, VMTracer};
|
2017-08-01 12:37:57 +02:00
|
|
|
use vm::{
|
|
|
|
self, ActionParams, CallType, ContractCreateResult, CreateContractAddress, EnvInfo, Ext,
|
2018-10-02 16:33:19 +02:00
|
|
|
MessageCallResult, ReturnData, Schedule,
|
2020-08-05 06:08:03 +02:00
|
|
|
};
|
2016-01-13 01:23:01 +01:00
|
|
|
|
2018-06-25 11:21:45 +02:00
|
|
|
use super::HookType;
|
|
|
|
|
2016-06-02 19:04:15 +02:00
|
|
|
#[derive(Debug, PartialEq, Clone)]
|
2016-01-13 13:16:53 +01:00
|
|
|
struct CallCreate {
|
|
|
|
data: Bytes,
|
2016-01-14 23:36:35 +01:00
|
|
|
destination: Option<Address>,
|
2016-01-16 20:11:12 +01:00
|
|
|
gas_limit: U256,
|
2016-01-13 13:16:53 +01:00
|
|
|
value: U256,
|
|
|
|
}
|
|
|
|
|
2016-03-24 01:25:59 +01:00
|
|
|
impl From<ethjson::vm::Call> for CallCreate {
|
|
|
|
fn from(c: ethjson::vm::Call) -> Self {
|
2016-07-28 23:46:24 +02:00
|
|
|
let dst: Option<ethjson::hash::Address> = c.destination.into();
|
2016-03-24 01:25:59 +01:00
|
|
|
CallCreate {
|
|
|
|
data: c.data.into(),
|
|
|
|
destination: dst.map(Into::into),
|
|
|
|
gas_limit: c.gas_limit.into(),
|
|
|
|
value: c.value.into(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-13 13:16:53 +01:00
|
|
|
/// Tiny wrapper around executive externalities.
|
|
|
|
/// Stores callcreates.
|
2017-09-26 14:19:08 +02:00
|
|
|
struct TestExt<'a, T: 'a, V: 'a, B: 'a>
|
|
|
|
where
|
|
|
|
T: Tracer,
|
|
|
|
V: VMTracer,
|
|
|
|
B: StateBackend,
|
2017-02-22 10:52:58 +01:00
|
|
|
{
|
2017-09-26 14:19:08 +02:00
|
|
|
ext: Externalities<'a, T, V, B>,
|
2016-01-16 20:11:12 +01:00
|
|
|
callcreates: Vec<CallCreate>,
|
2017-04-19 14:30:00 +02:00
|
|
|
nonce: U256,
|
|
|
|
sender: Address,
|
2016-01-13 13:16:53 +01:00
|
|
|
}
|
|
|
|
|
2017-09-26 14:19:08 +02:00
|
|
|
impl<'a, T: 'a, V: 'a, B: 'a> TestExt<'a, T, V, B>
|
|
|
|
where
|
|
|
|
T: Tracer,
|
|
|
|
V: VMTracer,
|
|
|
|
B: StateBackend,
|
2017-02-22 10:52:58 +01:00
|
|
|
{
|
2016-06-02 12:40:31 +02:00
|
|
|
fn new(
|
2017-02-22 10:52:58 +01:00
|
|
|
state: &'a mut State<B>,
|
2016-06-02 12:40:31 +02:00
|
|
|
info: &'a EnvInfo,
|
2017-09-26 14:19:08 +02:00
|
|
|
machine: &'a Machine,
|
2018-07-23 15:48:01 +02:00
|
|
|
schedule: &'a Schedule,
|
2016-06-02 12:40:31 +02:00
|
|
|
depth: usize,
|
2018-10-02 16:33:19 +02:00
|
|
|
origin_info: &'a OriginInfo,
|
2016-06-02 12:40:31 +02:00
|
|
|
substate: &'a mut Substate,
|
2018-08-13 23:27:13 +02:00
|
|
|
output: OutputPolicy,
|
2016-06-02 12:40:31 +02:00
|
|
|
address: Address,
|
|
|
|
tracer: &'a mut T,
|
|
|
|
vm_tracer: &'a mut V,
|
2018-07-02 18:50:05 +02:00
|
|
|
) -> ethtrie::Result<Self> {
|
2017-06-19 11:41:46 +02:00
|
|
|
let static_call = false;
|
2017-02-26 13:10:50 +01:00
|
|
|
Ok(TestExt {
|
2017-04-19 14:30:00 +02:00
|
|
|
nonce: state.nonce(&address)?,
|
2018-10-02 16:33:19 +02:00
|
|
|
ext: Externalities::new(
|
|
|
|
state,
|
|
|
|
info,
|
|
|
|
machine,
|
|
|
|
schedule,
|
|
|
|
depth,
|
|
|
|
0,
|
|
|
|
origin_info,
|
|
|
|
substate,
|
|
|
|
output,
|
|
|
|
tracer,
|
|
|
|
vm_tracer,
|
|
|
|
static_call,
|
|
|
|
),
|
2017-04-19 14:30:00 +02:00
|
|
|
callcreates: vec![],
|
|
|
|
sender: address,
|
2017-02-26 13:10:50 +01:00
|
|
|
})
|
2016-01-13 13:16:53 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-26 14:19:08 +02:00
|
|
|
impl<'a, T: 'a, V: 'a, B: 'a> Ext for TestExt<'a, T, V, B>
|
|
|
|
where
|
|
|
|
T: Tracer,
|
|
|
|
V: VMTracer,
|
|
|
|
B: StateBackend,
|
2017-02-22 10:52:58 +01:00
|
|
|
{
|
2017-08-01 12:37:57 +02:00
|
|
|
fn storage_at(&self, key: &H256) -> vm::Result<H256> {
|
2016-01-15 18:56:28 +01:00
|
|
|
self.ext.storage_at(key)
|
2016-01-13 13:16:53 +01:00
|
|
|
}
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2018-09-07 12:51:08 +02:00
|
|
|
fn initial_storage_at(&self, key: &H256) -> vm::Result<H256> {
|
|
|
|
self.ext.initial_storage_at(key)
|
|
|
|
}
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2017-08-01 12:37:57 +02:00
|
|
|
fn set_storage(&mut self, key: H256, value: H256) -> vm::Result<()> {
|
2016-01-16 20:11:12 +01:00
|
|
|
self.ext.set_storage(key, value)
|
|
|
|
}
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2017-08-01 12:37:57 +02:00
|
|
|
fn exists(&self, address: &Address) -> vm::Result<bool> {
|
2016-01-16 20:11:12 +01:00
|
|
|
self.ext.exists(address)
|
2016-01-13 13:16:53 +01:00
|
|
|
}
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2017-08-01 12:37:57 +02:00
|
|
|
fn exists_and_not_null(&self, address: &Address) -> vm::Result<bool> {
|
2016-11-03 22:22:25 +01:00
|
|
|
self.ext.exists_and_not_null(address)
|
|
|
|
}
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2017-08-01 12:37:57 +02:00
|
|
|
fn balance(&self, address: &Address) -> vm::Result<U256> {
|
2016-01-13 13:16:53 +01:00
|
|
|
self.ext.balance(address)
|
|
|
|
}
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2017-08-01 12:37:57 +02:00
|
|
|
fn origin_balance(&self) -> vm::Result<U256> {
|
2016-11-03 22:22:25 +01:00
|
|
|
self.ext.origin_balance()
|
|
|
|
}
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2017-05-30 11:52:33 +02:00
|
|
|
fn blockhash(&mut self, number: &U256) -> H256 {
|
2016-01-13 13:16:53 +01:00
|
|
|
self.ext.blockhash(number)
|
|
|
|
}
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2018-10-02 16:33:19 +02:00
|
|
|
fn create(
|
|
|
|
&mut self,
|
|
|
|
gas: &U256,
|
|
|
|
value: &U256,
|
|
|
|
code: &[u8],
|
|
|
|
address: CreateContractAddress,
|
|
|
|
_trap: bool,
|
|
|
|
) -> Result<ContractCreateResult, vm::TrapKind> {
|
2016-01-16 20:11:12 +01:00
|
|
|
self.callcreates.push(CallCreate {
|
|
|
|
data: code.to_vec(),
|
|
|
|
destination: None,
|
|
|
|
gas_limit: *gas,
|
|
|
|
value: *value,
|
|
|
|
});
|
2017-06-30 11:30:32 +02:00
|
|
|
let contract_address = contract_address(address, &self.sender, &self.nonce, &code).0;
|
2018-10-02 16:33:19 +02:00
|
|
|
Ok(ContractCreateResult::Created(contract_address, *gas))
|
2016-01-13 13:16:53 +01:00
|
|
|
}
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2018-10-02 16:33:19 +02:00
|
|
|
fn call(
|
|
|
|
&mut self,
|
2016-07-27 17:41:21 +02:00
|
|
|
gas: &U256,
|
|
|
|
_sender_address: &Address,
|
|
|
|
receive_address: &Address,
|
|
|
|
value: Option<U256>,
|
|
|
|
data: &[u8],
|
|
|
|
_code_address: &Address,
|
2018-10-02 16:33:19 +02:00
|
|
|
_call_type: CallType,
|
|
|
|
_trap: bool,
|
|
|
|
) -> Result<MessageCallResult, vm::TrapKind> {
|
2016-01-16 20:11:12 +01:00
|
|
|
self.callcreates.push(CallCreate {
|
|
|
|
data: data.to_vec(),
|
|
|
|
destination: Some(receive_address.clone()),
|
|
|
|
gas_limit: *gas,
|
2016-01-25 23:59:50 +01:00
|
|
|
value: value.unwrap(),
|
2016-01-20 16:52:22 +01:00
|
|
|
});
|
2018-10-02 16:33:19 +02:00
|
|
|
Ok(MessageCallResult::Success(*gas, ReturnData::empty()))
|
2016-01-20 16:52:22 +01:00
|
|
|
}
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2018-07-31 07:27:57 +02:00
|
|
|
fn extcode(&self, address: &Address) -> vm::Result<Option<Arc<Bytes>>> {
|
2016-01-13 13:16:53 +01:00
|
|
|
self.ext.extcode(address)
|
|
|
|
}
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2018-07-31 07:27:57 +02:00
|
|
|
fn extcodesize(&self, address: &Address) -> vm::Result<Option<usize>> {
|
2016-09-22 19:58:42 +02:00
|
|
|
self.ext.extcodesize(address)
|
|
|
|
}
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2018-07-31 07:27:57 +02:00
|
|
|
fn extcodehash(&self, address: &Address) -> vm::Result<Option<H256>> {
|
|
|
|
self.ext.extcodehash(address)
|
|
|
|
}
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2017-08-01 12:37:57 +02:00
|
|
|
fn log(&mut self, topics: Vec<H256>, data: &[u8]) -> vm::Result<()> {
|
2016-01-13 13:16:53 +01:00
|
|
|
self.ext.log(topics, data)
|
|
|
|
}
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2017-09-15 21:07:54 +02:00
|
|
|
fn ret(self, gas: &U256, data: &ReturnData, apply_state: bool) -> Result<U256, vm::Error> {
|
|
|
|
self.ext.ret(gas, data, apply_state)
|
2016-01-13 13:16:53 +01:00
|
|
|
}
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2017-08-01 12:37:57 +02:00
|
|
|
fn suicide(&mut self, refund_address: &Address) -> vm::Result<()> {
|
2016-01-13 16:16:21 +01:00
|
|
|
self.ext.suicide(refund_address)
|
2016-01-13 13:16:53 +01:00
|
|
|
}
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2016-01-13 13:16:53 +01:00
|
|
|
fn schedule(&self) -> &Schedule {
|
|
|
|
self.ext.schedule()
|
|
|
|
}
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2016-01-13 13:16:53 +01:00
|
|
|
fn env_info(&self) -> &EnvInfo {
|
|
|
|
self.ext.env_info()
|
|
|
|
}
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2019-09-12 18:43:53 +02:00
|
|
|
fn chain_id(&self) -> u64 {
|
|
|
|
0
|
|
|
|
}
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2016-01-16 20:11:12 +01:00
|
|
|
fn depth(&self) -> usize {
|
|
|
|
0
|
|
|
|
}
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2017-09-15 21:07:54 +02:00
|
|
|
fn is_static(&self) -> bool {
|
|
|
|
false
|
|
|
|
}
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2018-10-15 11:09:55 +02:00
|
|
|
fn add_sstore_refund(&mut self, value: usize) {
|
2018-09-07 12:51:08 +02:00
|
|
|
self.ext.add_sstore_refund(value)
|
|
|
|
}
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2018-10-15 11:09:55 +02:00
|
|
|
fn sub_sstore_refund(&mut self, value: usize) {
|
2018-09-07 12:51:08 +02:00
|
|
|
self.ext.sub_sstore_refund(value)
|
2016-01-16 20:11:12 +01:00
|
|
|
}
|
2016-01-13 13:16:53 +01:00
|
|
|
}
|
|
|
|
|
2020-09-30 13:10:54 +02:00
|
|
|
/// run an json executive test
|
2020-09-08 02:48:09 +02:00
|
|
|
pub fn json_executive_test<H: FnMut(&str, HookType)>(
|
|
|
|
path: &Path,
|
2018-06-25 11:21:45 +02:00
|
|
|
json_data: &[u8],
|
|
|
|
start_stop_hook: &mut H,
|
|
|
|
) -> Vec<String> {
|
2020-09-08 02:48:09 +02:00
|
|
|
let tests = ethjson::vm::Test::load(json_data).expect(&format!(
|
|
|
|
"Could not parse JSON executive test data from {}",
|
|
|
|
path.display()
|
|
|
|
));
|
2016-01-13 01:23:01 +01:00
|
|
|
let mut failed = Vec::new();
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2016-03-24 01:25:59 +01:00
|
|
|
for (name, vm) in tests.into_iter() {
|
2020-09-10 08:04:14 +02:00
|
|
|
if !super::debug_include_test(&name) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-09-08 02:48:09 +02:00
|
|
|
start_stop_hook(&format!("{}", name), HookType::OnStart);
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2016-01-13 01:23:01 +01:00
|
|
|
let mut fail = false;
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2016-02-10 00:20:36 +01:00
|
|
|
let mut fail_unless = |cond: bool, s: &str| {
|
|
|
|
if !cond && !fail {
|
2020-09-08 02:48:09 +02:00
|
|
|
failed.push(format!("{}: {}", name, s));
|
2016-02-10 00:20:36 +01:00
|
|
|
fail = true
|
2020-08-05 06:08:03 +02:00
|
|
|
}
|
2016-01-14 18:29:18 +01:00
|
|
|
};
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2017-02-26 13:10:50 +01:00
|
|
|
macro_rules! try_fail {
|
|
|
|
($e: expr) => {
|
|
|
|
match $e {
|
|
|
|
Ok(x) => x,
|
|
|
|
Err(e) => {
|
|
|
|
let msg = format!("Internal error: {}", e);
|
|
|
|
fail_unless(false, &msg);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2020-08-05 06:08:03 +02:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2016-03-24 01:25:59 +01:00
|
|
|
let out_of_gas = vm.out_of_gas();
|
2017-04-06 19:26:17 +02:00
|
|
|
let mut state = get_temp_state();
|
2016-03-24 01:25:59 +01:00
|
|
|
state.populate_from(From::from(vm.pre_state.clone()));
|
2018-07-23 15:48:01 +02:00
|
|
|
let info: EnvInfo = From::from(vm.env);
|
2017-09-26 14:19:08 +02:00
|
|
|
let machine = {
|
|
|
|
let mut machine = ::ethereum::new_frontier_test_machine();
|
|
|
|
machine.set_schedule_creation_rules(Box::new(move |s, _| s.max_depth = 1));
|
|
|
|
machine
|
|
|
|
};
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2016-03-24 01:25:59 +01:00
|
|
|
let params = ActionParams::from(vm.transaction);
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2016-04-08 11:48:37 +02:00
|
|
|
let mut substate = Substate::new();
|
|
|
|
let mut tracer = NoopTracer;
|
2016-06-02 12:40:31 +02:00
|
|
|
let mut vm_tracer = NoopVMTracer;
|
2017-05-30 11:52:33 +02:00
|
|
|
let vm_factory = state.vm_factory();
|
2018-10-02 16:33:19 +02:00
|
|
|
let origin_info = OriginInfo::from(¶ms);
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2016-01-13 01:23:01 +01:00
|
|
|
// execute
|
2016-01-13 17:26:04 +01:00
|
|
|
let (res, callcreates) = {
|
2018-07-23 15:48:01 +02:00
|
|
|
let schedule = machine.schedule(info.number);
|
2017-02-26 13:10:50 +01:00
|
|
|
let mut ex = try_fail!(TestExt::new(
|
2016-03-19 14:10:32 +01:00
|
|
|
&mut state,
|
|
|
|
&info,
|
2017-09-26 14:19:08 +02:00
|
|
|
&machine,
|
2018-07-23 15:48:01 +02:00
|
|
|
&schedule,
|
2016-03-19 14:10:32 +01:00
|
|
|
0,
|
2018-10-02 16:33:19 +02:00
|
|
|
&origin_info,
|
2016-03-19 14:10:32 +01:00
|
|
|
&mut substate,
|
2018-08-13 23:27:13 +02:00
|
|
|
OutputPolicy::Return,
|
2016-04-08 11:48:37 +02:00
|
|
|
params.address.clone(),
|
|
|
|
&mut tracer,
|
2016-06-02 12:40:31 +02:00
|
|
|
&mut vm_tracer,
|
2017-02-26 13:10:50 +01:00
|
|
|
));
|
2020-07-29 11:00:04 +02:00
|
|
|
let evm = vm_factory.create(params, &schedule, 0);
|
2018-10-02 16:33:19 +02:00
|
|
|
let res = evm
|
|
|
|
.exec(&mut ex)
|
|
|
|
.ok()
|
|
|
|
.expect("TestExt never trap; resume error never happens; qed");
|
2016-06-02 19:04:15 +02:00
|
|
|
// a return in finalize will not alter callcreates
|
|
|
|
let callcreates = ex.callcreates.clone();
|
|
|
|
(res.finalize(ex), callcreates)
|
2016-01-13 01:23:01 +01:00
|
|
|
};
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2018-08-13 23:27:13 +02:00
|
|
|
let output = match &res {
|
|
|
|
Ok(res) => res.return_data.to_vec(),
|
|
|
|
Err(_) => Vec::new(),
|
|
|
|
};
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2017-09-15 21:07:54 +02:00
|
|
|
let log_hash = {
|
|
|
|
let mut rlp = RlpStream::new_list(substate.logs.len());
|
|
|
|
for l in &substate.logs {
|
|
|
|
rlp.append(l);
|
|
|
|
}
|
|
|
|
keccak(&rlp.drain())
|
|
|
|
};
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2016-01-13 01:23:01 +01:00
|
|
|
match res {
|
|
|
|
Err(_) => fail_unless(out_of_gas, "didn't expect to run out of gas."),
|
2017-05-23 15:49:17 +02:00
|
|
|
Ok(res) => {
|
2016-01-13 01:23:01 +01:00
|
|
|
fail_unless(!out_of_gas, "expected to run out of gas.");
|
2017-05-23 15:49:17 +02:00
|
|
|
fail_unless(
|
|
|
|
Some(res.gas_left) == vm.gas_left.map(Into::into),
|
|
|
|
"gas_left is incorrect",
|
|
|
|
);
|
2016-03-24 01:25:59 +01:00
|
|
|
let vm_output: Option<Vec<u8>> = vm.output.map(Into::into);
|
|
|
|
fail_unless(Some(output) == vm_output, "output is incorrect");
|
2017-09-15 21:07:54 +02:00
|
|
|
fail_unless(Some(log_hash) == vm.logs.map(|h| h.0), "logs are incorrect");
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2016-03-24 16:40:52 +01:00
|
|
|
for (address, account) in vm.post_state.unwrap().into_iter() {
|
|
|
|
let address = address.into();
|
2020-09-08 02:48:09 +02:00
|
|
|
if let Some(code) = account.code {
|
|
|
|
let code: Vec<u8> = code.into();
|
|
|
|
let found_code = try_fail!(state.code(&address));
|
|
|
|
fail_unless(
|
|
|
|
found_code
|
|
|
|
.as_ref()
|
|
|
|
.map_or_else(|| code.is_empty(), |c| &**c == &code),
|
|
|
|
"code is incorrect",
|
|
|
|
);
|
|
|
|
}
|
2017-02-26 13:10:50 +01:00
|
|
|
let found_balance = try_fail!(state.balance(&address));
|
|
|
|
let found_nonce = try_fail!(state.nonce(&address));
|
2020-09-08 02:48:09 +02:00
|
|
|
if let Some(balance) = account.balance {
|
|
|
|
fail_unless(found_balance == balance.into(), "balance is incorrect");
|
|
|
|
}
|
|
|
|
if let Some(nonce) = account.nonce {
|
|
|
|
fail_unless(found_nonce == nonce.into(), "nonce is incorrect");
|
|
|
|
}
|
|
|
|
if let Some(storage) = account.storage {
|
|
|
|
for (k, v) in storage {
|
|
|
|
let key: U256 = k.into();
|
|
|
|
let value: U256 = v.into();
|
|
|
|
let found_storage =
|
|
|
|
try_fail!(state.storage_at(&address, &From::from(&key)));
|
|
|
|
fail_unless(
|
|
|
|
found_storage == From::from(&value),
|
|
|
|
"storage is incorrect",
|
|
|
|
);
|
|
|
|
}
|
2016-03-24 16:40:52 +01:00
|
|
|
}
|
2020-08-05 06:08:03 +02:00
|
|
|
}
|
|
|
|
|
2016-03-24 01:25:59 +01:00
|
|
|
let calls: Option<Vec<CallCreate>> =
|
|
|
|
vm.calls.map(|c| c.into_iter().map(From::from).collect());
|
|
|
|
fail_unless(Some(callcreates) == calls, "callcreates does not match");
|
2016-01-13 01:23:01 +01:00
|
|
|
}
|
2016-03-24 01:25:59 +01:00
|
|
|
};
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2020-09-08 02:48:09 +02:00
|
|
|
if fail {
|
|
|
|
println!(" - vm: {:?}...FAILED", name);
|
|
|
|
} else {
|
|
|
|
println!(" - vm: {:?}...OK", name);
|
|
|
|
}
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2020-09-08 02:48:09 +02:00
|
|
|
start_stop_hook(&format!("{}", name), HookType::OnStop);
|
2016-01-13 01:23:01 +01:00
|
|
|
}
|
2020-08-05 06:08:03 +02:00
|
|
|
|
2016-01-13 01:23:01 +01:00
|
|
|
failed
|
|
|
|
}
|