Merge pull request #111 from gavofyork/evm_factory_parametrized

Parametrizing evm::Factory
This commit is contained in:
Marek Kotewicz 2016-01-15 01:22:43 +01:00
commit 8366c9d44f
10 changed files with 214 additions and 94 deletions

View File

@ -2,6 +2,7 @@ use common::*;
use block::Block;
use spec::Spec;
use evm::Schedule;
use evm::Factory;
/// A consensus mechanism for the chain. Generally either proof-of-work or proof-of-stake-based.
/// Provides hooks into each of the major parts of block import.
@ -22,6 +23,9 @@ pub trait Engine : Sync + Send {
/// Get the general parameters of the chain.
fn spec(&self) -> &Spec;
/// Get current EVM factory
fn vm_factory(&self) -> &Factory;
/// Get the EVM schedule for the given `env_info`.
fn schedule(&self, env_info: &EnvInfo) -> Schedule;

View File

@ -3,16 +3,22 @@ use block::*;
use spec::*;
use engine::*;
use evm::Schedule;
use evm::Factory;
/// Engine using Ethash proof-of-work consensus algorithm, suitable for Ethereum
/// mainnet chains in the Olympic, Frontier and Homestead eras.
pub struct Ethash {
spec: Spec,
factory: Factory
}
impl Ethash {
pub fn new_boxed(spec: Spec) -> Box<Engine> {
Box::new(Ethash{spec: spec})
Box::new(Ethash{
spec: spec,
// TODO [todr] should this return any specific factory?
factory: Factory::default()
})
}
}
@ -27,7 +33,11 @@ impl Engine for Ethash {
/// Additional engine-specific information for the user/developer concerning `header`.
fn extra_info(&self, _header: &Header) -> HashMap<String, String> { HashMap::new() }
fn spec(&self) -> &Spec { &self.spec }
fn schedule(&self, _env_info: &EnvInfo) -> Schedule { Schedule::new_frontier() }
fn vm_factory(&self) -> &Factory {
&self.factory
}
/// Apply the block reward on finalisation of the block.
/// This assumes that all uncles are valid uncles (i.e. of at least one generation before the current).

View File

@ -1,25 +1,99 @@
//! Evm factory.
use std::fmt;
use evm::Evm;
#[derive(Clone)]
pub enum VMType {
Jit,
Interpreter
}
impl fmt::Display for VMType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", match *self {
VMType::Jit => "JIT",
VMType::Interpreter => "INT"
})
}
}
impl VMType {
#[cfg(feature="jit")]
pub fn all() -> Vec<VMType> {
vec![VMType::Jit, VMType::Interpreter]
}
#[cfg(not(feature="jit"))]
pub fn all() -> Vec<VMType> {
vec![VMType::Interpreter]
}
}
/// Evm factory. Creates appropriate Evm.
pub struct Factory;
pub struct Factory {
evm : VMType
}
impl Factory {
/// Returns jit vm
pub fn create(&self) -> Box<Evm> {
match self.evm {
VMType::Jit => {
Factory::jit()
},
VMType::Interpreter => {
Box::new(super::interpreter::Interpreter)
}
}
}
pub fn new(evm: VMType) -> Factory {
Factory {
evm: evm
}
}
#[cfg(feature = "jit")]
pub fn create() -> Box<Evm> {
fn jit() -> Box<Evm> {
Box::new(super::jit::JitEvm)
}
/// Returns native rust evm
#[cfg(not(feature = "jit"))]
pub fn create() -> Box<Evm> {
Box::new(super::interpreter::Interpreter)
fn jit() -> Box<Evm> {
unimplemented!()
}
/// Returns jitvm factory
#[cfg(feature = "jit")]
pub fn default() -> Factory {
Factory {
evm: VMType::Jit
}
}
/// Returns native rust evm factory
#[cfg(not(feature = "jit"))]
pub fn default() -> Factory {
Factory {
evm: VMType::Interpreter
}
}
}
#[test]
fn test_create_vm() {
let _vm = Factory::create();
let _vm = Factory::default().create();
}
#[macro_export]
macro_rules! evm_test(
($name_test: ident: $name_jit: ident, $name_int: ident) => {
#[test]
#[cfg(feature = "jit")]
fn $name_jit() {
$name_test(Factory::new(VMType::Jit));
}
#[test]
fn $name_int() {
$name_test(Factory::new(VMType::Interpreter));
}
}
);

View File

@ -3,6 +3,7 @@
pub mod ext;
pub mod evm;
pub mod interpreter;
#[macro_use]
pub mod factory;
pub mod schedule;
mod instructions;
@ -16,3 +17,4 @@ pub use self::evm::{Evm, Error, Result};
pub use self::ext::Ext;
pub use self::factory::Factory;
pub use self::schedule::Schedule;
pub use self::factory::VMType;

View File

@ -1,6 +1,6 @@
use common::*;
use evm;
use evm::{Ext, Schedule};
use evm::{Ext, Schedule, Factory, VMType};
struct FakeLogEntry {
topics: Vec<H256>,
@ -122,22 +122,8 @@ fn test_stack_underflow() {
};
}
macro_rules! evm_test(
($name_test: ident: $name_jit: ident, $name_int: ident) => {
#[test]
#[cfg(feature = "jit")]
fn $name_jit() {
$name_test(Box::new(super::jit::JitEvm));
}
#[test]
fn $name_int() {
$name_test(Box::new(super::interpreter::Interpreter));
}
}
);
evm_test!{test_add: test_add_jit, test_add_int}
fn test_add(vm : Box<super::Evm>) {
fn test_add(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01600055".from_hex().unwrap();
@ -148,6 +134,7 @@ fn test_add(vm : Box<super::Evm>) {
let mut ext = FakeExt::new();
let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap()
};
@ -156,7 +143,7 @@ fn test_add(vm : Box<super::Evm>) {
}
evm_test!{test_sha3: test_sha3_jit, test_sha3_int}
fn test_sha3(vm: Box<super::Evm>) {
fn test_sha3(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "6000600020600055".from_hex().unwrap();
@ -167,6 +154,7 @@ fn test_sha3(vm: Box<super::Evm>) {
let mut ext = FakeExt::new();
let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap()
};
@ -175,7 +163,7 @@ fn test_sha3(vm: Box<super::Evm>) {
}
evm_test!{test_address: test_address_jit, test_address_int}
fn test_address(vm: Box<super::Evm>) {
fn test_address(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "30600055".from_hex().unwrap();
@ -186,6 +174,7 @@ fn test_address(vm: Box<super::Evm>) {
let mut ext = FakeExt::new();
let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap()
};
@ -194,7 +183,7 @@ fn test_address(vm: Box<super::Evm>) {
}
evm_test!{test_origin: test_origin_jit, test_origin_int}
fn test_origin(vm: Box<super::Evm>) {
fn test_origin(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let origin = Address::from_str("cd1722f2947def4cf144679da39c4c32bdc35681").unwrap();
let code = "32600055".from_hex().unwrap();
@ -207,6 +196,7 @@ fn test_origin(vm: Box<super::Evm>) {
let mut ext = FakeExt::new();
let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap()
};
@ -215,7 +205,7 @@ fn test_origin(vm: Box<super::Evm>) {
}
evm_test!{test_sender: test_sender_jit, test_sender_int}
fn test_sender(vm: Box<super::Evm>) {
fn test_sender(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let sender = Address::from_str("cd1722f2947def4cf144679da39c4c32bdc35681").unwrap();
let code = "33600055".from_hex().unwrap();
@ -228,6 +218,7 @@ fn test_sender(vm: Box<super::Evm>) {
let mut ext = FakeExt::new();
let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap()
};
@ -236,7 +227,7 @@ fn test_sender(vm: Box<super::Evm>) {
}
evm_test!{test_extcodecopy: test_extcodecopy_jit, test_extcodecopy_int}
fn test_extcodecopy(vm: Box<super::Evm>) {
fn test_extcodecopy(factory: super::Factory) {
// 33 - sender
// 3b - extcodesize
// 60 00 - push 0
@ -262,6 +253,7 @@ fn test_extcodecopy(vm: Box<super::Evm>) {
ext.codes.insert(sender, sender_code);
let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap()
};
@ -270,7 +262,7 @@ fn test_extcodecopy(vm: Box<super::Evm>) {
}
evm_test!{test_log_empty: test_log_empty_jit, test_log_empty_int}
fn test_log_empty(vm: Box<super::Evm>) {
fn test_log_empty(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "60006000a0".from_hex().unwrap();
@ -281,6 +273,7 @@ fn test_log_empty(vm: Box<super::Evm>) {
let mut ext = FakeExt::new();
let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap()
};
@ -291,7 +284,7 @@ fn test_log_empty(vm: Box<super::Evm>) {
}
evm_test!{test_log_sender: test_log_sender_jit, test_log_sender_int}
fn test_log_sender(vm: Box<super::Evm>) {
fn test_log_sender(factory: super::Factory) {
// 60 ff - push ff
// 60 00 - push 00
// 53 - mstore
@ -312,6 +305,7 @@ fn test_log_sender(vm: Box<super::Evm>) {
let mut ext = FakeExt::new();
let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap()
};
@ -323,7 +317,7 @@ fn test_log_sender(vm: Box<super::Evm>) {
}
evm_test!{test_blockhash: test_blockhash_jit, test_blockhash_int}
fn test_blockhash(vm: Box<super::Evm>) {
fn test_blockhash(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "600040600055".from_hex().unwrap();
let blockhash = H256::from_str("123400000000000000000000cd1722f2947def4cf144679da39c4c32bdc35681").unwrap();
@ -336,6 +330,7 @@ fn test_blockhash(vm: Box<super::Evm>) {
ext.blockhashes.insert(U256::zero(), blockhash.clone());
let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap()
};
@ -344,7 +339,7 @@ fn test_blockhash(vm: Box<super::Evm>) {
}
evm_test!{test_calldataload: test_calldataload_jit, test_calldataload_int}
fn test_calldataload(vm: Box<super::Evm>) {
fn test_calldataload(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "600135600055".from_hex().unwrap();
let data = "0123ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff23".from_hex().unwrap();
@ -357,6 +352,7 @@ fn test_calldataload(vm: Box<super::Evm>) {
let mut ext = FakeExt::new();
let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap()
};
@ -366,7 +362,7 @@ fn test_calldataload(vm: Box<super::Evm>) {
}
evm_test!{test_author: test_author_jit, test_author_int}
fn test_author(vm: Box<super::Evm>) {
fn test_author(factory: super::Factory) {
let author = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "41600055".from_hex().unwrap();
@ -377,6 +373,7 @@ fn test_author(vm: Box<super::Evm>) {
ext.info.author = author;
let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap()
};
@ -385,7 +382,7 @@ fn test_author(vm: Box<super::Evm>) {
}
evm_test!{test_timestamp: test_timestamp_jit, test_timestamp_int}
fn test_timestamp(vm: Box<super::Evm>) {
fn test_timestamp(factory: super::Factory) {
let timestamp = 0x1234;
let code = "42600055".from_hex().unwrap();
@ -396,6 +393,7 @@ fn test_timestamp(vm: Box<super::Evm>) {
ext.info.timestamp = timestamp;
let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap()
};
@ -404,7 +402,7 @@ fn test_timestamp(vm: Box<super::Evm>) {
}
evm_test!{test_number: test_number_jit, test_number_int}
fn test_number(vm: Box<super::Evm>) {
fn test_number(factory: super::Factory) {
let number = 0x1234;
let code = "43600055".from_hex().unwrap();
@ -415,6 +413,7 @@ fn test_number(vm: Box<super::Evm>) {
ext.info.number = number;
let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap()
};
@ -423,7 +422,7 @@ fn test_number(vm: Box<super::Evm>) {
}
evm_test!{test_difficulty: test_difficulty_jit, test_difficulty_int}
fn test_difficulty(vm: Box<super::Evm>) {
fn test_difficulty(factory: super::Factory) {
let difficulty = U256::from(0x1234);
let code = "44600055".from_hex().unwrap();
@ -434,6 +433,7 @@ fn test_difficulty(vm: Box<super::Evm>) {
ext.info.difficulty = difficulty;
let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap()
};
@ -442,7 +442,7 @@ fn test_difficulty(vm: Box<super::Evm>) {
}
evm_test!{test_gas_limit: test_gas_limit_jit, test_gas_limit_int}
fn test_gas_limit(vm: Box<super::Evm>) {
fn test_gas_limit(factory: super::Factory) {
let gas_limit = U256::from(0x1234);
let code = "45600055".from_hex().unwrap();
@ -453,6 +453,7 @@ fn test_gas_limit(vm: Box<super::Evm>) {
ext.info.gas_limit = gas_limit;
let gas_left = {
let vm = factory.create();
vm.exec(&params, &mut ext).unwrap()
};

View File

@ -2,7 +2,7 @@
use common::*;
use state::*;
use engine::*;
use evm::{self, Schedule, Factory, Ext};
use evm::{self, Schedule, Ext};
/// Returns new address created from address and given nonce.
pub fn contract_address(address: &Address, nonce: &U256) -> Address {
@ -196,8 +196,7 @@ impl<'a> Executive<'a> {
} else if params.code.len() > 0 {
// if destination is a contract, do normal message call
let mut ext = Externalities::from_executive(self, params, substate, OutputPolicy::Return(output));
let evm = Factory::create();
evm.exec(&params, &mut ext)
self.engine.vm_factory().create().exec(&params, &mut ext)
} else {
// otherwise, nothing
Ok(params.gas)
@ -214,8 +213,7 @@ impl<'a> Executive<'a> {
self.state.transfer_balance(&params.sender, &params.address, &params.value);
let mut ext = Externalities::from_executive(self, params, substate, OutputPolicy::InitContract);
let evm = Factory::create();
evm.exec(&params, &mut ext)
self.engine.vm_factory().create().exec(&params, &mut ext)
}
/// Finalizes the transaction (does refunds and suicides).
@ -496,15 +494,19 @@ mod tests {
use engine::*;
use spec::*;
use evm::Schedule;
use evm::Factory;
use evm::factory::VMType;
struct TestEngine {
factory: Factory,
spec: Spec,
max_depth: usize
}
impl TestEngine {
fn new(max_depth: usize) -> TestEngine {
fn new(max_depth: usize, factory: Factory) -> TestEngine {
TestEngine {
factory: factory,
spec: ethereum::new_frontier_test(),
max_depth: max_depth
}
@ -514,6 +516,9 @@ mod tests {
impl Engine for TestEngine {
fn name(&self) -> &str { "TestEngine" }
fn spec(&self) -> &Spec { &self.spec }
fn vm_factory(&self) -> &Factory {
&self.factory
}
fn schedule(&self, _env_info: &EnvInfo) -> Schedule {
let mut schedule = Schedule::new_frontier();
schedule.max_depth = self.max_depth;
@ -528,9 +533,9 @@ mod tests {
assert_eq!(expected_address, contract_address(&address, &U256::from(88)));
}
#[test]
// TODO: replace params with transactions!
fn test_sender_balance() {
evm_test!{test_sender_balance: test_sender_balance_jit, test_sender_balance_int}
fn test_sender_balance(factory: Factory) {
let sender = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let address = contract_address(&sender, &U256::zero());
let mut params = ActionParams::new();
@ -542,7 +547,7 @@ mod tests {
let mut state = State::new_temp();
state.add_balance(&sender, &U256::from(0x100u64));
let info = EnvInfo::new();
let engine = TestEngine::new(0);
let engine = TestEngine::new(0, factory);
let mut substate = Substate::new();
let gas_left = {
@ -560,8 +565,8 @@ mod tests {
// TODO: just test state root.
}
#[test]
fn test_create_contract() {
evm_test!{test_create_contract: test_create_contract_jit, test_create_contract_int}
fn test_create_contract(factory: Factory) {
// code:
//
// 7c 601080600c6000396000f3006000355415600957005b60203560003555 - push 29 bytes?
@ -600,7 +605,7 @@ mod tests {
let mut state = State::new_temp();
state.add_balance(&sender, &U256::from(100));
let info = EnvInfo::new();
let engine = TestEngine::new(0);
let engine = TestEngine::new(0, factory);
let mut substate = Substate::new();
let gas_left = {
@ -613,8 +618,8 @@ mod tests {
assert_eq!(substate.contracts_created.len(), 0);
}
#[test]
fn test_create_contract_value_too_high() {
evm_test!{test_create_contract_value_too_high: test_create_contract_value_too_high_jit, test_create_contract_value_too_high_int}
fn test_create_contract_value_too_high(factory: Factory) {
// code:
//
// 7c 601080600c6000396000f3006000355415600957005b60203560003555 - push 29 bytes?
@ -653,7 +658,7 @@ mod tests {
let mut state = State::new_temp();
state.add_balance(&sender, &U256::from(100));
let info = EnvInfo::new();
let engine = TestEngine::new(0);
let engine = TestEngine::new(0, factory);
let mut substate = Substate::new();
let gas_left = {
@ -665,8 +670,8 @@ mod tests {
assert_eq!(substate.contracts_created.len(), 0);
}
#[test]
fn test_create_contract_without_max_depth() {
evm_test!{test_create_contract_without_max_depth: test_create_contract_without_max_depth_jit, test_create_contract_without_max_depth_int}
fn test_create_contract_without_max_depth(factory: Factory) {
// code:
//
// 7c 601080600c6000396000f3006000355415600957005b60203560003555 - push 29 bytes?
@ -704,7 +709,7 @@ mod tests {
let mut state = State::new_temp();
state.add_balance(&sender, &U256::from(100));
let info = EnvInfo::new();
let engine = TestEngine::new(1024);
let engine = TestEngine::new(1024, factory);
let mut substate = Substate::new();
{
@ -716,8 +721,8 @@ mod tests {
assert_eq!(substate.contracts_created[0], next_address);
}
#[test]
fn test_aba_calls() {
evm_test!{test_aba_calls: test_aba_calls_jit, test_aba_calls_int}
fn test_aba_calls(factory: Factory) {
// 60 00 - push 0
// 60 00 - push 0
// 60 00 - push 0
@ -762,7 +767,7 @@ mod tests {
state.add_balance(&sender, &U256::from(100_000));
let info = EnvInfo::new();
let engine = TestEngine::new(0);
let engine = TestEngine::new(0, factory);
let mut substate = Substate::new();
let gas_left = {
@ -774,8 +779,8 @@ mod tests {
assert_eq!(state.storage_at(&address_a, &H256::from(&U256::from(0x23))), H256::from(&U256::from(1)));
}
#[test]
fn test_recursive_bomb1() {
evm_test!{test_recursive_bomb1: test_recursive_bomb1_jit, test_recursive_bomb1_int}
fn test_recursive_bomb1(factory: Factory) {
// 60 01 - push 1
// 60 00 - push 0
// 54 - sload
@ -804,7 +809,7 @@ mod tests {
let mut state = State::new_temp();
state.init_code(&address, code.clone());
let info = EnvInfo::new();
let engine = TestEngine::new(0);
let engine = TestEngine::new(0, factory);
let mut substate = Substate::new();
let gas_left = {
@ -817,8 +822,8 @@ mod tests {
assert_eq!(state.storage_at(&address, &H256::from(&U256::one())), H256::from(&U256::from(1)));
}
#[test]
fn test_transact_simple() {
evm_test!{test_transact_simple: test_transact_simple_jit, test_transact_simple_int}
fn test_transact_simple(factory: Factory) {
let mut t = Transaction::new_create(U256::from(17), "3331600055".from_hex().unwrap(), U256::from(100_000), U256::zero(), U256::zero());
let keypair = KeyPair::create().unwrap();
t.sign(&keypair.secret());
@ -829,7 +834,7 @@ mod tests {
state.add_balance(&sender, &U256::from(18));
let mut info = EnvInfo::new();
info.gas_limit = U256::from(100_000);
let engine = TestEngine::new(0);
let engine = TestEngine::new(0, factory);
let executed = {
let mut ex = Executive::new(&mut state, &info, &engine);
@ -837,9 +842,9 @@ mod tests {
};
assert_eq!(executed.gas, U256::from(100_000));
assert_eq!(executed.gas_used, U256::from(20_025));
assert_eq!(executed.refunded, U256::from(79_975));
assert_eq!(executed.cumulative_gas_used, U256::from(20_025));
assert_eq!(executed.gas_used, U256::from(41_301));
assert_eq!(executed.refunded, U256::from(58_699));
assert_eq!(executed.cumulative_gas_used, U256::from(41_301));
assert_eq!(executed.logs.len(), 0);
assert_eq!(executed.out_of_gas, false);
assert_eq!(executed.contracts_created.len(), 0);
@ -849,14 +854,14 @@ mod tests {
assert_eq!(state.storage_at(&contract, &H256::new()), H256::from(&U256::from(1)));
}
#[test]
fn test_transact_invalid_sender() {
evm_test!{test_transact_invalid_sender: test_transact_invalid_sender_jit, test_transact_invalid_sender_int}
fn test_transact_invalid_sender(factory: Factory) {
let t = Transaction::new_create(U256::from(17), "3331600055".from_hex().unwrap(), U256::from(100_000), U256::zero(), U256::zero());
let mut state = State::new_temp();
let mut info = EnvInfo::new();
info.gas_limit = U256::from(100_000);
let engine = TestEngine::new(0);
let engine = TestEngine::new(0, factory);
let res = {
let mut ex = Executive::new(&mut state, &info, &engine);
@ -869,8 +874,8 @@ mod tests {
}
}
#[test]
fn test_transact_invalid_nonce() {
evm_test!{test_transact_invalid_nonce: test_transact_invalid_nonce_jit, test_transact_invalid_nonce_int}
fn test_transact_invalid_nonce(factory: Factory) {
let mut t = Transaction::new_create(U256::from(17), "3331600055".from_hex().unwrap(), U256::from(100_000), U256::zero(), U256::one());
let keypair = KeyPair::create().unwrap();
t.sign(&keypair.secret());
@ -880,7 +885,7 @@ mod tests {
state.add_balance(&sender, &U256::from(17));
let mut info = EnvInfo::new();
info.gas_limit = U256::from(100_000);
let engine = TestEngine::new(0);
let engine = TestEngine::new(0, factory);
let res = {
let mut ex = Executive::new(&mut state, &info, &engine);
@ -894,8 +899,8 @@ mod tests {
}
}
#[test]
fn test_transact_gas_limit_reached() {
evm_test!{test_transact_gas_limit_reached: test_transact_gas_limit_reached_jit, test_transact_gas_limit_reached_int}
fn test_transact_gas_limit_reached(factory: Factory) {
let mut t = Transaction::new_create(U256::from(17), "3331600055".from_hex().unwrap(), U256::from(80_001), U256::zero(), U256::zero());
let keypair = KeyPair::create().unwrap();
t.sign(&keypair.secret());
@ -906,7 +911,7 @@ mod tests {
let mut info = EnvInfo::new();
info.gas_used = U256::from(20_000);
info.gas_limit = U256::from(100_000);
let engine = TestEngine::new(0);
let engine = TestEngine::new(0, factory);
let res = {
let mut ex = Executive::new(&mut state, &info, &engine);
@ -920,8 +925,8 @@ mod tests {
}
}
#[test]
fn test_not_enough_cash() {
evm_test!{test_not_enough_cash: test_not_enough_cash_jit, test_not_enough_cash_int}
fn test_not_enough_cash(factory: Factory) {
let mut t = Transaction::new_create(U256::from(18), "3331600055".from_hex().unwrap(), U256::from(100_000), U256::one(), U256::zero());
let keypair = KeyPair::create().unwrap();
t.sign(&keypair.secret());
@ -931,7 +936,7 @@ mod tests {
state.add_balance(&sender, &U256::from(100_017));
let mut info = EnvInfo::new();
info.gas_limit = U256::from(100_000);
let engine = TestEngine::new(0);
let engine = TestEngine::new(0, factory);
let res = {
let mut ex = Executive::new(&mut state, &info, &engine);

View File

@ -88,6 +88,8 @@ extern crate env_logger;
pub mod common;
pub mod basic_types;
#[macro_use]
pub mod evm;
pub mod executive;
pub mod error;
pub mod log_entry;
@ -105,7 +107,6 @@ pub mod spec;
pub mod views;
pub mod blockchain;
pub mod extras;
pub mod evm;
#[cfg(test)]
mod tests;

View File

@ -1,20 +1,29 @@
use engine::Engine;
use spec::Spec;
use evm::Schedule;
use evm::Factory;
use env_info::EnvInfo;
/// An engine which does not provide any consensus mechanism.
pub struct NullEngine {
spec: Spec,
factory: Factory
}
impl NullEngine {
pub fn new_boxed(spec: Spec) -> Box<Engine> {
Box::new(NullEngine{spec: spec})
Box::new(NullEngine{
spec: spec,
// TODO [todr] should this return any specific factory?
factory: Factory::default()
})
}
}
impl Engine for NullEngine {
fn vm_factory(&self) -> &Factory {
&self.factory
}
fn name(&self) -> &str { "NullEngine" }
fn spec(&self) -> &Spec { &self.spec }
fn schedule(&self, _env_info: &EnvInfo) -> Schedule { Schedule::new_frontier() }

View File

@ -4,17 +4,19 @@ use executive::*;
use spec::*;
use engine::*;
use evm;
use evm::{Schedule, Ext, Factory};
use evm::{Schedule, Ext, Factory, VMType};
use ethereum;
struct TestEngine {
vm_factory: Factory,
spec: Spec,
max_depth: usize
}
impl TestEngine {
fn new(max_depth: usize) -> TestEngine {
fn new(max_depth: usize, vm_type: VMType) -> TestEngine {
TestEngine {
vm_factory: Factory::new(vm_type),
spec: ethereum::new_frontier_test(),
max_depth: max_depth
}
@ -24,6 +26,7 @@ impl TestEngine {
impl Engine for TestEngine {
fn name(&self) -> &str { "TestEngine" }
fn spec(&self) -> &Spec { &self.spec }
fn vm_factory(&self) -> &Factory { &self.vm_factory }
fn schedule(&self, _env_info: &EnvInfo) -> Schedule {
let mut schedule = Schedule::new_frontier();
schedule.max_depth = self.max_depth;
@ -153,16 +156,28 @@ impl<'a> Ext for TestExt<'a> {
}
fn do_json_test(json_data: &[u8]) -> Vec<String> {
let vms = VMType::all();
vms
.iter()
.flat_map(|vm| do_json_test_for(vm, json_data))
.collect()
}
fn do_json_test_for(vm: &VMType, 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();
for (name, test) in json.as_object().unwrap() {
// sync io is usefull when something crashes in jit
//::std::io::stdout().write(&name.as_bytes());
//::std::io::stdout().write(b"\n");
//::std::io::stdout().flush();
// ::std::io::stdout().write(&name.as_bytes());
// ::std::io::stdout().write(b"\n");
// ::std::io::stdout().flush();
let mut fail = false;
//let mut fail_unless = |cond: bool| if !cond && !fail { failed.push(name.to_string()); fail = true };
let mut fail_unless = |cond: bool, s: &str | if !cond && !fail { failed.push(name.to_string() + ": "+ s); fail = true };
let mut fail_unless = |cond: bool, s: &str | if !cond && !fail {
failed.push(format!("[{}] {}: {}", vm, name.to_string(), s));
fail = true
};
// test env
let mut state = State::new_temp();
@ -194,7 +209,7 @@ fn do_json_test(json_data: &[u8]) -> Vec<String> {
info.timestamp = u256_from_json(&env["currentTimestamp"]).low_u64();
});
let engine = TestEngine::new(0);
let engine = TestEngine::new(0, vm.clone());
// params
let mut params = ActionParams::new();
@ -219,7 +234,7 @@ fn do_json_test(json_data: &[u8]) -> Vec<String> {
let (res, callcreates) = {
let ex = Externalities::new(&mut state, &info, &engine, 0, &params, &mut substate, OutputPolicy::Return(BytesRef::Flexible(&mut output)));
let mut test_ext = TestExt::new(ex);
let evm = Factory::create();
let evm = engine.vm_factory().create();
let res = evm.exec(&params, &mut test_ext);
(res, test_ext.callcreates)
};

View File

@ -1,6 +1,5 @@
use super::test_common::*;
use state::*;
use executive::*;
use ethereum;
fn do_json_test(json_data: &[u8]) -> Vec<String> {