diff --git a/src/engine.rs b/src/engine.rs index 59888d12a..61abc9bb3 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -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; diff --git a/src/ethereum/ethash.rs b/src/ethereum/ethash.rs index f2f5eeafd..8a0450e72 100644 --- a/src/ethereum/ethash.rs +++ b/src/ethereum/ethash.rs @@ -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 { - 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 { 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). diff --git a/src/evm/factory.rs b/src/evm/factory.rs index 39019cd8d..25a41afd2 100644 --- a/src/evm/factory.rs +++ b/src/evm/factory.rs @@ -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 { + vec![VMType::Jit, VMType::Interpreter] + } + #[cfg(not(feature="jit"))] + pub fn all() -> Vec { + 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 { + 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 { + fn jit() -> Box { Box::new(super::jit::JitEvm) } - /// Returns native rust evm #[cfg(not(feature = "jit"))] - pub fn create() -> Box { - Box::new(super::interpreter::Interpreter) + fn jit() -> Box { + 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)); + } + } +); diff --git a/src/evm/mod.rs b/src/evm/mod.rs index 118e98f8a..5f3f362a2 100644 --- a/src/evm/mod.rs +++ b/src/evm/mod.rs @@ -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; diff --git a/src/evm/tests.rs b/src/evm/tests.rs index ab5dd9dbd..a818a38fc 100644 --- a/src/evm/tests.rs +++ b/src/evm/tests.rs @@ -1,6 +1,6 @@ use common::*; use evm; -use evm::{Ext, Schedule}; +use evm::{Ext, Schedule, Factory, VMType}; struct FakeLogEntry { topics: Vec, @@ -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) { +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) { let mut ext = FakeExt::new(); let gas_left = { + let vm = factory.create(); vm.exec(¶ms, &mut ext).unwrap() }; @@ -156,7 +143,7 @@ fn test_add(vm : Box) { } evm_test!{test_sha3: test_sha3_jit, test_sha3_int} -fn test_sha3(vm: Box) { +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) { let mut ext = FakeExt::new(); let gas_left = { + let vm = factory.create(); vm.exec(¶ms, &mut ext).unwrap() }; @@ -175,7 +163,7 @@ fn test_sha3(vm: Box) { } evm_test!{test_address: test_address_jit, test_address_int} -fn test_address(vm: Box) { +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) { let mut ext = FakeExt::new(); let gas_left = { + let vm = factory.create(); vm.exec(¶ms, &mut ext).unwrap() }; @@ -194,7 +183,7 @@ fn test_address(vm: Box) { } evm_test!{test_origin: test_origin_jit, test_origin_int} -fn test_origin(vm: Box) { +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) { let mut ext = FakeExt::new(); let gas_left = { + let vm = factory.create(); vm.exec(¶ms, &mut ext).unwrap() }; @@ -215,7 +205,7 @@ fn test_origin(vm: Box) { } evm_test!{test_sender: test_sender_jit, test_sender_int} -fn test_sender(vm: Box) { +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) { let mut ext = FakeExt::new(); let gas_left = { + let vm = factory.create(); vm.exec(¶ms, &mut ext).unwrap() }; @@ -236,7 +227,7 @@ fn test_sender(vm: Box) { } evm_test!{test_extcodecopy: test_extcodecopy_jit, test_extcodecopy_int} -fn test_extcodecopy(vm: Box) { +fn test_extcodecopy(factory: super::Factory) { // 33 - sender // 3b - extcodesize // 60 00 - push 0 @@ -262,6 +253,7 @@ fn test_extcodecopy(vm: Box) { ext.codes.insert(sender, sender_code); let gas_left = { + let vm = factory.create(); vm.exec(¶ms, &mut ext).unwrap() }; @@ -270,7 +262,7 @@ fn test_extcodecopy(vm: Box) { } evm_test!{test_log_empty: test_log_empty_jit, test_log_empty_int} -fn test_log_empty(vm: Box) { +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) { let mut ext = FakeExt::new(); let gas_left = { + let vm = factory.create(); vm.exec(¶ms, &mut ext).unwrap() }; @@ -291,7 +284,7 @@ fn test_log_empty(vm: Box) { } evm_test!{test_log_sender: test_log_sender_jit, test_log_sender_int} -fn test_log_sender(vm: Box) { +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) { let mut ext = FakeExt::new(); let gas_left = { + let vm = factory.create(); vm.exec(¶ms, &mut ext).unwrap() }; @@ -323,7 +317,7 @@ fn test_log_sender(vm: Box) { } evm_test!{test_blockhash: test_blockhash_jit, test_blockhash_int} -fn test_blockhash(vm: Box) { +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) { ext.blockhashes.insert(U256::zero(), blockhash.clone()); let gas_left = { + let vm = factory.create(); vm.exec(¶ms, &mut ext).unwrap() }; @@ -344,7 +339,7 @@ fn test_blockhash(vm: Box) { } evm_test!{test_calldataload: test_calldataload_jit, test_calldataload_int} -fn test_calldataload(vm: Box) { +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) { let mut ext = FakeExt::new(); let gas_left = { + let vm = factory.create(); vm.exec(¶ms, &mut ext).unwrap() }; @@ -366,7 +362,7 @@ fn test_calldataload(vm: Box) { } evm_test!{test_author: test_author_jit, test_author_int} -fn test_author(vm: Box) { +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) { ext.info.author = author; let gas_left = { + let vm = factory.create(); vm.exec(¶ms, &mut ext).unwrap() }; @@ -385,7 +382,7 @@ fn test_author(vm: Box) { } evm_test!{test_timestamp: test_timestamp_jit, test_timestamp_int} -fn test_timestamp(vm: Box) { +fn test_timestamp(factory: super::Factory) { let timestamp = 0x1234; let code = "42600055".from_hex().unwrap(); @@ -396,6 +393,7 @@ fn test_timestamp(vm: Box) { ext.info.timestamp = timestamp; let gas_left = { + let vm = factory.create(); vm.exec(¶ms, &mut ext).unwrap() }; @@ -404,7 +402,7 @@ fn test_timestamp(vm: Box) { } evm_test!{test_number: test_number_jit, test_number_int} -fn test_number(vm: Box) { +fn test_number(factory: super::Factory) { let number = 0x1234; let code = "43600055".from_hex().unwrap(); @@ -415,6 +413,7 @@ fn test_number(vm: Box) { ext.info.number = number; let gas_left = { + let vm = factory.create(); vm.exec(¶ms, &mut ext).unwrap() }; @@ -423,7 +422,7 @@ fn test_number(vm: Box) { } evm_test!{test_difficulty: test_difficulty_jit, test_difficulty_int} -fn test_difficulty(vm: Box) { +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) { ext.info.difficulty = difficulty; let gas_left = { + let vm = factory.create(); vm.exec(¶ms, &mut ext).unwrap() }; @@ -442,7 +442,7 @@ fn test_difficulty(vm: Box) { } evm_test!{test_gas_limit: test_gas_limit_jit, test_gas_limit_int} -fn test_gas_limit(vm: Box) { +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) { ext.info.gas_limit = gas_limit; let gas_left = { + let vm = factory.create(); vm.exec(¶ms, &mut ext).unwrap() }; diff --git a/src/executive.rs b/src/executive.rs index f396d49b1..6fe78f165 100644 --- a/src/executive.rs +++ b/src/executive.rs @@ -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(¶ms, &mut ext) + self.engine.vm_factory().create().exec(¶ms, &mut ext) } else { // otherwise, nothing Ok(params.gas) @@ -214,8 +213,7 @@ impl<'a> Executive<'a> { self.state.transfer_balance(¶ms.sender, ¶ms.address, ¶ms.value); let mut ext = Externalities::from_executive(self, params, substate, OutputPolicy::InitContract); - let evm = Factory::create(); - evm.exec(¶ms, &mut ext) + self.engine.vm_factory().create().exec(¶ms, &mut ext) } /// Finalizes the transaction (does refunds and suicides). @@ -309,7 +307,7 @@ impl<'a> Externalities<'a> { /// Basic `Externalities` constructor. pub fn new(state: &'a mut State, info: &'a EnvInfo, - engine: &'a Engine, + engine: &'a Engine, depth: usize, params: &'a ActionParams, substate: &'a mut Substate, @@ -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); diff --git a/src/lib.rs b/src/lib.rs index 8610404d2..e3c8a5274 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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; diff --git a/src/null_engine.rs b/src/null_engine.rs index bd745365c..e673563b3 100644 --- a/src/null_engine.rs +++ b/src/null_engine.rs @@ -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 { - 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() } diff --git a/src/tests/executive.rs b/src/tests/executive.rs index d49ac5f8b..609ac5f03 100644 --- a/src/tests/executive.rs +++ b/src/tests/executive.rs @@ -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 { + 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 { 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 { 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 { 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 evm = Factory::create(); + let evm = engine.vm_factory().create(); let res = evm.exec(¶ms, &mut test_ext); (res, test_ext.callcreates) }; diff --git a/src/tests/state.rs b/src/tests/state.rs index 080bdf979..8adc885da 100644 --- a/src/tests/state.rs +++ b/src/tests/state.rs @@ -1,6 +1,5 @@ use super::test_common::*; use state::*; -use executive::*; use ethereum; fn do_json_test(json_data: &[u8]) -> Vec { @@ -57,4 +56,4 @@ fn do_json_test(json_data: &[u8]) -> Vec { } declare_test!{StateTests_stExample, "StateTests/stExample"} -declare_test!{StateTests_stLogTests, "StateTests/stLogTests"} \ No newline at end of file +declare_test!{StateTests_stLogTests, "StateTests/stLogTests"}