From abb4f08effdf629fe5e69f95099ffd6841bf8462 Mon Sep 17 00:00:00 2001 From: Tomusdrw Date: Thu, 14 Jan 2016 17:24:57 +0100 Subject: [PATCH] Moving EVM Factory to Engine --- src/engine.rs | 4 +++ src/ethereum/ethash.rs | 12 ++++++- src/evm/mod.rs | 1 + src/executive.rs | 78 +++++++++++++++++++++--------------------- src/null_engine.rs | 11 +++++- src/state.rs | 4 +-- src/tests/executive.rs | 12 ++++--- src/tests/state.rs | 3 +- 8 files changed, 74 insertions(+), 51 deletions(-) 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/mod.rs b/src/evm/mod.rs index 4b846f28e..5f3f362a2 100644 --- a/src/evm/mod.rs +++ b/src/evm/mod.rs @@ -17,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/executive.rs b/src/executive.rs index 600391915..9173c5444 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 { @@ -74,29 +74,27 @@ pub struct Executive<'a> { state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine, - factory: &'a Factory, depth: usize } impl<'a> Executive<'a> { /// Basic constructor. - pub fn new(state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine, factory: &'a Factory) -> Self { - Executive::new_with_depth(state, info, engine, factory, 0) + pub fn new(state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine) -> Self { + Executive::new_with_depth(state, info, engine, 0) } /// Populates executive from parent properties. Increments executive depth. - fn from_parent(state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine, factory: &'a Factory, depth: usize) -> Self { - Executive::new_with_depth(state, info, engine, factory, depth + 1) + fn from_parent(state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine, depth: usize) -> Self { + Executive::new_with_depth(state, info, engine, depth + 1) } /// Helper constructor. Should be used to create `Executive` with desired depth. /// Private. - fn new_with_depth(state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine, factory: &'a Factory, depth: usize) -> Self { + fn new_with_depth(state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine, depth: usize) -> Self { Executive { state: state, info: info, engine: engine, - factory: factory, depth: depth } } @@ -198,7 +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)); - self.factory.create().exec(¶ms, &mut ext) + self.engine.vm_factory().create().exec(¶ms, &mut ext) } else { // otherwise, nothing Ok(params.gas) @@ -215,7 +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); - self.factory.create().exec(¶ms, &mut ext) + self.engine.vm_factory().create().exec(¶ms, &mut ext) } /// Finalizes the transaction (does refunds and suicides). @@ -295,7 +293,6 @@ pub struct Externalities<'a> { state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine, - factory: &'a Factory, depth: usize, #[cfg(test)] pub params: &'a ActionParams, @@ -311,7 +308,6 @@ impl<'a> Externalities<'a> { pub fn new(state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine, - factory: &'a Factory, depth: usize, params: &'a ActionParams, substate: &'a mut Substate, @@ -320,7 +316,6 @@ impl<'a> Externalities<'a> { state: state, info: info, engine: engine, - factory: factory, depth: depth, params: params, substate: substate, @@ -331,7 +326,7 @@ impl<'a> Externalities<'a> { /// Creates `Externalities` from `Executive`. fn from_executive(e: &'a mut Executive, params: &'a ActionParams, substate: &'a mut Substate, output: OutputPolicy<'a>) -> Self { - Self::new(e.state, e.info, e.engine, e.factory, e.depth, params, substate, output) + Self::new(e.state, e.info, e.engine, e.depth, params, substate, output) } } @@ -383,7 +378,7 @@ impl<'a> Ext for Externalities<'a> { data: vec![], }; - let mut ex = Executive::from_parent(self.state, self.info, self.engine, self.factory, self.depth); + let mut ex = Executive::from_parent(self.state, self.info, self.engine, self.depth); ex.state.inc_nonce(&self.params.address); ex.create(¶ms, self.substate).map(|gas_left| (gas_left, Some(address))) } @@ -425,7 +420,7 @@ impl<'a> Ext for Externalities<'a> { data: data.to_vec(), }; - let mut ex = Executive::from_parent(self.state, self.info, self.engine, self.factory, self.depth); + let mut ex = Executive::from_parent(self.state, self.info, self.engine, self.depth); ex.call(¶ms, self.substate, BytesRef::Fixed(output)).map(|gas_left| gas + gas_left) } @@ -503,13 +498,15 @@ mod tests { 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 } @@ -519,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; @@ -562,11 +562,11 @@ 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 = { - let mut ex = Executive::new(&mut state, &info, &engine, &factory); + let mut ex = Executive::new(&mut state, &info, &engine); ex.create(¶ms, &mut substate).unwrap() }; @@ -620,11 +620,11 @@ 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 = { - let mut ex = Executive::new(&mut state, &info, &engine, &factory); + let mut ex = Executive::new(&mut state, &info, &engine); ex.create(¶ms, &mut substate).unwrap() }; @@ -673,11 +673,11 @@ 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 = { - let mut ex = Executive::new(&mut state, &info, &engine, &factory); + let mut ex = Executive::new(&mut state, &info, &engine); ex.create(¶ms, &mut substate).unwrap() }; @@ -724,11 +724,11 @@ 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(); { - let mut ex = Executive::new(&mut state, &info, &engine, &factory); + let mut ex = Executive::new(&mut state, &info, &engine); ex.create(¶ms, &mut substate).unwrap(); } @@ -782,11 +782,11 @@ 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 = { - let mut ex = Executive::new(&mut state, &info, &engine, &factory); + let mut ex = Executive::new(&mut state, &info, &engine); ex.call(¶ms, &mut substate, BytesRef::Fixed(&mut [])).unwrap() }; @@ -824,11 +824,11 @@ 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 = { - let mut ex = Executive::new(&mut state, &info, &engine, &factory); + let mut ex = Executive::new(&mut state, &info, &engine); ex.call(¶ms, &mut substate, BytesRef::Fixed(&mut [])).unwrap() }; @@ -849,10 +849,10 @@ 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, &factory); + let mut ex = Executive::new(&mut state, &info, &engine); ex.transact(&t).unwrap() }; @@ -876,10 +876,10 @@ mod tests { 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, &factory); + let mut ex = Executive::new(&mut state, &info, &engine); ex.transact(&t) }; @@ -900,10 +900,10 @@ 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, &factory); + let mut ex = Executive::new(&mut state, &info, &engine); ex.transact(&t) }; @@ -926,10 +926,10 @@ 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, &factory); + let mut ex = Executive::new(&mut state, &info, &engine); ex.transact(&t) }; @@ -951,10 +951,10 @@ 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, &factory); + let mut ex = Executive::new(&mut state, &info, &engine); ex.transact(&t) }; 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/state.rs b/src/state.rs index c06337829..1f58f638c 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,7 +1,6 @@ use common::*; use engine::Engine; use executive::Executive; -use evm::Factory; pub type ApplyResult = Result; @@ -138,8 +137,7 @@ impl State { /// Execute a given transaction. /// This will change the state accordingly. pub fn apply(&mut self, env_info: &EnvInfo, engine: &Engine, t: &Transaction) -> ApplyResult { - // TODO [todr] Pass VM factory? - let e = try!(Executive::new(self, env_info, engine, &Factory::default()).transact(t)); + let e = try!(Executive::new(self, env_info, engine).transact(t)); self.commit(); Ok(Receipt::new(self.root().clone(), e.gas_used, e.logs)) } diff --git a/src/tests/executive.rs b/src/tests/executive.rs index bf3815b5c..3f4175b52 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; @@ -194,7 +197,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, VMType::Jit); // params let mut params = ActionParams::new(); @@ -217,8 +220,7 @@ fn do_json_test(json_data: &[u8]) -> Vec { // execute let (res, callcreates) = { - let factory = Factory::default(); - let ex = Externalities::new(&mut state, &info, &engine, &factory, 0, ¶ms, &mut substate, OutputPolicy::Return(BytesRef::Flexible(&mut output))); + 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::default().create(); let res = evm.exec(¶ms, &mut test_ext); 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"}