// 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 .
use std::path::Path;
use std::sync::Arc;
use super::test_common::*;
use state::{Backend as StateBackend, State, Substate};
use executive::*;
use evm::{VMType, Finalize};
use vm::{
self, ActionParams, CallType, Schedule, Ext,
ContractCreateResult, EnvInfo, MessageCallResult,
CreateContractAddress, ReturnData,
};
use externalities::*;
use test_helpers::get_temp_state;
use ethjson;
use trace::{Tracer, NoopTracer};
use trace::{VMTracer, NoopVMTracer};
use bytes::Bytes;
use ethtrie;
use rlp::RlpStream;
use hash::keccak;
use machine::EthereumMachine as Machine;
use super::HookType;
/// Run executive 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 executive 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)
}
#[derive(Debug, PartialEq, Clone)]
struct CallCreate {
data: Bytes,
destination: Option,
gas_limit: U256,
value: U256
}
impl From for CallCreate {
fn from(c: ethjson::vm::Call) -> Self {
let dst: Option = c.destination.into();
CallCreate {
data: c.data.into(),
destination: dst.map(Into::into),
gas_limit: c.gas_limit.into(),
value: c.value.into()
}
}
}
/// Tiny wrapper around executive externalities.
/// Stores callcreates.
struct TestExt<'a, T: 'a, V: 'a, B: 'a>
where T: Tracer, V: VMTracer, B: StateBackend
{
ext: Externalities<'a, T, V, B>,
callcreates: Vec,
nonce: U256,
sender: Address,
}
impl<'a, T: 'a, V: 'a, B: 'a> TestExt<'a, T, V, B>
where T: Tracer, V: VMTracer, B: StateBackend,
{
fn new(
state: &'a mut State,
info: &'a EnvInfo,
machine: &'a Machine,
schedule: &'a Schedule,
depth: usize,
origin_info: &'a OriginInfo,
substate: &'a mut Substate,
output: OutputPolicy,
address: Address,
tracer: &'a mut T,
vm_tracer: &'a mut V,
) -> ethtrie::Result {
let static_call = false;
Ok(TestExt {
nonce: state.nonce(&address)?,
ext: Externalities::new(state, info, machine, schedule, depth, 0, origin_info, substate, output, tracer, vm_tracer, static_call),
callcreates: vec![],
sender: address,
})
}
}
impl<'a, T: 'a, V: 'a, B: 'a> Ext for TestExt<'a, T, V, B>
where T: Tracer, V: VMTracer, B: StateBackend
{
fn storage_at(&self, key: &H256) -> vm::Result {
self.ext.storage_at(key)
}
fn initial_storage_at(&self, key: &H256) -> vm::Result {
self.ext.initial_storage_at(key)
}
fn set_storage(&mut self, key: H256, value: H256) -> vm::Result<()> {
self.ext.set_storage(key, value)
}
fn exists(&self, address: &Address) -> vm::Result {
self.ext.exists(address)
}
fn exists_and_not_null(&self, address: &Address) -> vm::Result {
self.ext.exists_and_not_null(address)
}
fn balance(&self, address: &Address) -> vm::Result {
self.ext.balance(address)
}
fn origin_balance(&self) -> vm::Result {
self.ext.origin_balance()
}
fn blockhash(&mut self, number: &U256) -> H256 {
self.ext.blockhash(number)
}
fn create(
&mut self,
gas: &U256,
value: &U256,
code: &[u8],
address: CreateContractAddress,
_trap: bool
) -> Result {
self.callcreates.push(CallCreate {
data: code.to_vec(),
destination: None,
gas_limit: *gas,
value: *value
});
let contract_address = contract_address(address, &self.sender, &self.nonce, &code).0;
Ok(ContractCreateResult::Created(contract_address, *gas))
}
fn call(
&mut self,
gas: &U256,
_sender_address: &Address,
receive_address: &Address,
value: Option,
data: &[u8],
_code_address: &Address,
_call_type: CallType,
_trap: bool
) -> Result {
self.callcreates.push(CallCreate {
data: data.to_vec(),
destination: Some(receive_address.clone()),
gas_limit: *gas,
value: value.unwrap()
});
Ok(MessageCallResult::Success(*gas, ReturnData::empty()))
}
fn extcode(&self, address: &Address) -> vm::Result