Moving EVM Factory to Engine

This commit is contained in:
Tomusdrw 2016-01-14 17:24:57 +01:00
parent 9039ed40a9
commit abb4f08eff
8 changed files with 74 additions and 51 deletions

View File

@ -2,6 +2,7 @@ use common::*;
use block::Block; use block::Block;
use spec::Spec; use spec::Spec;
use evm::Schedule; use evm::Schedule;
use evm::Factory;
/// A consensus mechanism for the chain. Generally either proof-of-work or proof-of-stake-based. /// 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. /// 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. /// Get the general parameters of the chain.
fn spec(&self) -> &Spec; fn spec(&self) -> &Spec;
/// Get current EVM factory
fn vm_factory(&self) -> &Factory;
/// Get the EVM schedule for the given `env_info`. /// Get the EVM schedule for the given `env_info`.
fn schedule(&self, env_info: &EnvInfo) -> Schedule; fn schedule(&self, env_info: &EnvInfo) -> Schedule;

View File

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

View File

@ -17,3 +17,4 @@ pub use self::evm::{Evm, Error, Result};
pub use self::ext::Ext; pub use self::ext::Ext;
pub use self::factory::Factory; pub use self::factory::Factory;
pub use self::schedule::Schedule; pub use self::schedule::Schedule;
pub use self::factory::VMType;

View File

@ -2,7 +2,7 @@
use common::*; use common::*;
use state::*; use state::*;
use engine::*; use engine::*;
use evm::{self, Schedule, Factory, Ext}; use evm::{self, Schedule, Ext};
/// Returns new address created from address and given nonce. /// Returns new address created from address and given nonce.
pub fn contract_address(address: &Address, nonce: &U256) -> Address { pub fn contract_address(address: &Address, nonce: &U256) -> Address {
@ -74,29 +74,27 @@ pub struct Executive<'a> {
state: &'a mut State, state: &'a mut State,
info: &'a EnvInfo, info: &'a EnvInfo,
engine: &'a Engine, engine: &'a Engine,
factory: &'a Factory,
depth: usize depth: usize
} }
impl<'a> Executive<'a> { impl<'a> Executive<'a> {
/// Basic constructor. /// Basic constructor.
pub fn new(state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine, factory: &'a Factory) -> Self { pub fn new(state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine) -> Self {
Executive::new_with_depth(state, info, engine, factory, 0) Executive::new_with_depth(state, info, engine, 0)
} }
/// Populates executive from parent properties. Increments executive depth. /// 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 { fn from_parent(state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine, depth: usize) -> Self {
Executive::new_with_depth(state, info, engine, factory, depth + 1) Executive::new_with_depth(state, info, engine, depth + 1)
} }
/// Helper constructor. Should be used to create `Executive` with desired depth. /// Helper constructor. Should be used to create `Executive` with desired depth.
/// Private. /// 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 { Executive {
state: state, state: state,
info: info, info: info,
engine: engine, engine: engine,
factory: factory,
depth: depth depth: depth
} }
} }
@ -198,7 +196,7 @@ impl<'a> Executive<'a> {
} else if params.code.len() > 0 { } else if params.code.len() > 0 {
// if destination is a contract, do normal message call // if destination is a contract, do normal message call
let mut ext = Externalities::from_executive(self, params, substate, OutputPolicy::Return(output)); let mut ext = Externalities::from_executive(self, params, substate, OutputPolicy::Return(output));
self.factory.create().exec(&params, &mut ext) self.engine.vm_factory().create().exec(&params, &mut ext)
} else { } else {
// otherwise, nothing // otherwise, nothing
Ok(params.gas) Ok(params.gas)
@ -215,7 +213,7 @@ impl<'a> Executive<'a> {
self.state.transfer_balance(&params.sender, &params.address, &params.value); self.state.transfer_balance(&params.sender, &params.address, &params.value);
let mut ext = Externalities::from_executive(self, params, substate, OutputPolicy::InitContract); let mut ext = Externalities::from_executive(self, params, substate, OutputPolicy::InitContract);
self.factory.create().exec(&params, &mut ext) self.engine.vm_factory().create().exec(&params, &mut ext)
} }
/// Finalizes the transaction (does refunds and suicides). /// Finalizes the transaction (does refunds and suicides).
@ -295,7 +293,6 @@ pub struct Externalities<'a> {
state: &'a mut State, state: &'a mut State,
info: &'a EnvInfo, info: &'a EnvInfo,
engine: &'a Engine, engine: &'a Engine,
factory: &'a Factory,
depth: usize, depth: usize,
#[cfg(test)] #[cfg(test)]
pub params: &'a ActionParams, pub params: &'a ActionParams,
@ -311,7 +308,6 @@ impl<'a> Externalities<'a> {
pub fn new(state: &'a mut State, pub fn new(state: &'a mut State,
info: &'a EnvInfo, info: &'a EnvInfo,
engine: &'a Engine, engine: &'a Engine,
factory: &'a Factory,
depth: usize, depth: usize,
params: &'a ActionParams, params: &'a ActionParams,
substate: &'a mut Substate, substate: &'a mut Substate,
@ -320,7 +316,6 @@ impl<'a> Externalities<'a> {
state: state, state: state,
info: info, info: info,
engine: engine, engine: engine,
factory: factory,
depth: depth, depth: depth,
params: params, params: params,
substate: substate, substate: substate,
@ -331,7 +326,7 @@ impl<'a> Externalities<'a> {
/// Creates `Externalities` from `Executive`. /// Creates `Externalities` from `Executive`.
fn from_executive(e: &'a mut Executive, params: &'a ActionParams, substate: &'a mut Substate, output: OutputPolicy<'a>) -> Self { 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![], 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.state.inc_nonce(&self.params.address);
ex.create(&params, self.substate).map(|gas_left| (gas_left, Some(address))) ex.create(&params, self.substate).map(|gas_left| (gas_left, Some(address)))
} }
@ -425,7 +420,7 @@ impl<'a> Ext for Externalities<'a> {
data: data.to_vec(), 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(&params, self.substate, BytesRef::Fixed(output)).map(|gas_left| gas + gas_left) ex.call(&params, self.substate, BytesRef::Fixed(output)).map(|gas_left| gas + gas_left)
} }
@ -503,13 +498,15 @@ mod tests {
use evm::factory::VMType; use evm::factory::VMType;
struct TestEngine { struct TestEngine {
factory: Factory,
spec: Spec, spec: Spec,
max_depth: usize max_depth: usize
} }
impl TestEngine { impl TestEngine {
fn new(max_depth: usize) -> TestEngine { fn new(max_depth: usize, factory: Factory) -> TestEngine {
TestEngine { TestEngine {
factory: factory,
spec: ethereum::new_frontier_test(), spec: ethereum::new_frontier_test(),
max_depth: max_depth max_depth: max_depth
} }
@ -519,6 +516,9 @@ mod tests {
impl Engine for TestEngine { impl Engine for TestEngine {
fn name(&self) -> &str { "TestEngine" } fn name(&self) -> &str { "TestEngine" }
fn spec(&self) -> &Spec { &self.spec } fn spec(&self) -> &Spec { &self.spec }
fn vm_factory(&self) -> &Factory {
&self.factory
}
fn schedule(&self, _env_info: &EnvInfo) -> Schedule { fn schedule(&self, _env_info: &EnvInfo) -> Schedule {
let mut schedule = Schedule::new_frontier(); let mut schedule = Schedule::new_frontier();
schedule.max_depth = self.max_depth; schedule.max_depth = self.max_depth;
@ -562,11 +562,11 @@ mod tests {
let mut state = State::new_temp(); let mut state = State::new_temp();
state.add_balance(&sender, &U256::from(0x100u64)); state.add_balance(&sender, &U256::from(0x100u64));
let info = EnvInfo::new(); let info = EnvInfo::new();
let engine = TestEngine::new(0); let engine = TestEngine::new(0, factory);
let mut substate = Substate::new(); let mut substate = Substate::new();
let gas_left = { let gas_left = {
let mut ex = Executive::new(&mut state, &info, &engine, &factory); let mut ex = Executive::new(&mut state, &info, &engine);
ex.create(&params, &mut substate).unwrap() ex.create(&params, &mut substate).unwrap()
}; };
@ -620,11 +620,11 @@ mod tests {
let mut state = State::new_temp(); let mut state = State::new_temp();
state.add_balance(&sender, &U256::from(100)); state.add_balance(&sender, &U256::from(100));
let info = EnvInfo::new(); let info = EnvInfo::new();
let engine = TestEngine::new(0); let engine = TestEngine::new(0, factory);
let mut substate = Substate::new(); let mut substate = Substate::new();
let gas_left = { let gas_left = {
let mut ex = Executive::new(&mut state, &info, &engine, &factory); let mut ex = Executive::new(&mut state, &info, &engine);
ex.create(&params, &mut substate).unwrap() ex.create(&params, &mut substate).unwrap()
}; };
@ -673,11 +673,11 @@ mod tests {
let mut state = State::new_temp(); let mut state = State::new_temp();
state.add_balance(&sender, &U256::from(100)); state.add_balance(&sender, &U256::from(100));
let info = EnvInfo::new(); let info = EnvInfo::new();
let engine = TestEngine::new(0); let engine = TestEngine::new(0, factory);
let mut substate = Substate::new(); let mut substate = Substate::new();
let gas_left = { let gas_left = {
let mut ex = Executive::new(&mut state, &info, &engine, &factory); let mut ex = Executive::new(&mut state, &info, &engine);
ex.create(&params, &mut substate).unwrap() ex.create(&params, &mut substate).unwrap()
}; };
@ -724,11 +724,11 @@ mod tests {
let mut state = State::new_temp(); let mut state = State::new_temp();
state.add_balance(&sender, &U256::from(100)); state.add_balance(&sender, &U256::from(100));
let info = EnvInfo::new(); let info = EnvInfo::new();
let engine = TestEngine::new(1024); let engine = TestEngine::new(1024, factory);
let mut substate = Substate::new(); 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(&params, &mut substate).unwrap(); ex.create(&params, &mut substate).unwrap();
} }
@ -782,11 +782,11 @@ mod tests {
state.add_balance(&sender, &U256::from(100_000)); state.add_balance(&sender, &U256::from(100_000));
let info = EnvInfo::new(); let info = EnvInfo::new();
let engine = TestEngine::new(0); let engine = TestEngine::new(0, factory);
let mut substate = Substate::new(); let mut substate = Substate::new();
let gas_left = { let gas_left = {
let mut ex = Executive::new(&mut state, &info, &engine, &factory); let mut ex = Executive::new(&mut state, &info, &engine);
ex.call(&params, &mut substate, BytesRef::Fixed(&mut [])).unwrap() ex.call(&params, &mut substate, BytesRef::Fixed(&mut [])).unwrap()
}; };
@ -824,11 +824,11 @@ mod tests {
let mut state = State::new_temp(); let mut state = State::new_temp();
state.init_code(&address, code.clone()); state.init_code(&address, code.clone());
let info = EnvInfo::new(); let info = EnvInfo::new();
let engine = TestEngine::new(0); let engine = TestEngine::new(0, factory);
let mut substate = Substate::new(); let mut substate = Substate::new();
let gas_left = { let gas_left = {
let mut ex = Executive::new(&mut state, &info, &engine, &factory); let mut ex = Executive::new(&mut state, &info, &engine);
ex.call(&params, &mut substate, BytesRef::Fixed(&mut [])).unwrap() ex.call(&params, &mut substate, BytesRef::Fixed(&mut [])).unwrap()
}; };
@ -849,10 +849,10 @@ mod tests {
state.add_balance(&sender, &U256::from(18)); state.add_balance(&sender, &U256::from(18));
let mut info = EnvInfo::new(); let mut info = EnvInfo::new();
info.gas_limit = U256::from(100_000); info.gas_limit = U256::from(100_000);
let engine = TestEngine::new(0); let engine = TestEngine::new(0, factory);
let executed = { 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() ex.transact(&t).unwrap()
}; };
@ -876,10 +876,10 @@ mod tests {
let mut state = State::new_temp(); let mut state = State::new_temp();
let mut info = EnvInfo::new(); let mut info = EnvInfo::new();
info.gas_limit = U256::from(100_000); info.gas_limit = U256::from(100_000);
let engine = TestEngine::new(0); let engine = TestEngine::new(0, factory);
let res = { let res = {
let mut ex = Executive::new(&mut state, &info, &engine, &factory); let mut ex = Executive::new(&mut state, &info, &engine);
ex.transact(&t) ex.transact(&t)
}; };
@ -900,10 +900,10 @@ mod tests {
state.add_balance(&sender, &U256::from(17)); state.add_balance(&sender, &U256::from(17));
let mut info = EnvInfo::new(); let mut info = EnvInfo::new();
info.gas_limit = U256::from(100_000); info.gas_limit = U256::from(100_000);
let engine = TestEngine::new(0); let engine = TestEngine::new(0, factory);
let res = { let res = {
let mut ex = Executive::new(&mut state, &info, &engine, &factory); let mut ex = Executive::new(&mut state, &info, &engine);
ex.transact(&t) ex.transact(&t)
}; };
@ -926,10 +926,10 @@ mod tests {
let mut info = EnvInfo::new(); let mut info = EnvInfo::new();
info.gas_used = U256::from(20_000); info.gas_used = U256::from(20_000);
info.gas_limit = U256::from(100_000); info.gas_limit = U256::from(100_000);
let engine = TestEngine::new(0); let engine = TestEngine::new(0, factory);
let res = { let res = {
let mut ex = Executive::new(&mut state, &info, &engine, &factory); let mut ex = Executive::new(&mut state, &info, &engine);
ex.transact(&t) ex.transact(&t)
}; };
@ -951,10 +951,10 @@ mod tests {
state.add_balance(&sender, &U256::from(100_017)); state.add_balance(&sender, &U256::from(100_017));
let mut info = EnvInfo::new(); let mut info = EnvInfo::new();
info.gas_limit = U256::from(100_000); info.gas_limit = U256::from(100_000);
let engine = TestEngine::new(0); let engine = TestEngine::new(0, factory);
let res = { let res = {
let mut ex = Executive::new(&mut state, &info, &engine, &factory); let mut ex = Executive::new(&mut state, &info, &engine);
ex.transact(&t) ex.transact(&t)
}; };

View File

@ -1,20 +1,29 @@
use engine::Engine; use engine::Engine;
use spec::Spec; use spec::Spec;
use evm::Schedule; use evm::Schedule;
use evm::Factory;
use env_info::EnvInfo; use env_info::EnvInfo;
/// An engine which does not provide any consensus mechanism. /// An engine which does not provide any consensus mechanism.
pub struct NullEngine { pub struct NullEngine {
spec: Spec, spec: Spec,
factory: Factory
} }
impl NullEngine { impl NullEngine {
pub fn new_boxed(spec: Spec) -> Box<Engine> { 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 { impl Engine for NullEngine {
fn vm_factory(&self) -> &Factory {
&self.factory
}
fn name(&self) -> &str { "NullEngine" } fn name(&self) -> &str { "NullEngine" }
fn spec(&self) -> &Spec { &self.spec } fn spec(&self) -> &Spec { &self.spec }
fn schedule(&self, _env_info: &EnvInfo) -> Schedule { Schedule::new_frontier() } fn schedule(&self, _env_info: &EnvInfo) -> Schedule { Schedule::new_frontier() }

View File

@ -1,7 +1,6 @@
use common::*; use common::*;
use engine::Engine; use engine::Engine;
use executive::Executive; use executive::Executive;
use evm::Factory;
pub type ApplyResult = Result<Receipt, Error>; pub type ApplyResult = Result<Receipt, Error>;
@ -138,8 +137,7 @@ impl State {
/// Execute a given transaction. /// Execute a given transaction.
/// This will change the state accordingly. /// This will change the state accordingly.
pub fn apply(&mut self, env_info: &EnvInfo, engine: &Engine, t: &Transaction) -> ApplyResult { 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).transact(t));
let e = try!(Executive::new(self, env_info, engine, &Factory::default()).transact(t));
self.commit(); self.commit();
Ok(Receipt::new(self.root().clone(), e.gas_used, e.logs)) Ok(Receipt::new(self.root().clone(), e.gas_used, e.logs))
} }

View File

@ -4,17 +4,19 @@ use executive::*;
use spec::*; use spec::*;
use engine::*; use engine::*;
use evm; use evm;
use evm::{Schedule, Ext, Factory}; use evm::{Schedule, Ext, Factory, VMType};
use ethereum; use ethereum;
struct TestEngine { struct TestEngine {
vm_factory: Factory,
spec: Spec, spec: Spec,
max_depth: usize max_depth: usize
} }
impl TestEngine { impl TestEngine {
fn new(max_depth: usize) -> TestEngine { fn new(max_depth: usize, vm_type: VMType) -> TestEngine {
TestEngine { TestEngine {
vm_factory: Factory::new(vm_type),
spec: ethereum::new_frontier_test(), spec: ethereum::new_frontier_test(),
max_depth: max_depth max_depth: max_depth
} }
@ -24,6 +26,7 @@ impl TestEngine {
impl Engine for TestEngine { impl Engine for TestEngine {
fn name(&self) -> &str { "TestEngine" } fn name(&self) -> &str { "TestEngine" }
fn spec(&self) -> &Spec { &self.spec } fn spec(&self) -> &Spec { &self.spec }
fn vm_factory(&self) -> &Factory { &self.vm_factory }
fn schedule(&self, _env_info: &EnvInfo) -> Schedule { fn schedule(&self, _env_info: &EnvInfo) -> Schedule {
let mut schedule = Schedule::new_frontier(); let mut schedule = Schedule::new_frontier();
schedule.max_depth = self.max_depth; schedule.max_depth = self.max_depth;
@ -194,7 +197,7 @@ fn do_json_test(json_data: &[u8]) -> Vec<String> {
info.timestamp = u256_from_json(&env["currentTimestamp"]).low_u64(); info.timestamp = u256_from_json(&env["currentTimestamp"]).low_u64();
}); });
let engine = TestEngine::new(0); let engine = TestEngine::new(0, VMType::Jit);
// params // params
let mut params = ActionParams::new(); let mut params = ActionParams::new();
@ -217,8 +220,7 @@ fn do_json_test(json_data: &[u8]) -> Vec<String> {
// execute // execute
let (res, callcreates) = { let (res, callcreates) = {
let factory = Factory::default(); let ex = Externalities::new(&mut state, &info, &engine, 0, &params, &mut substate, OutputPolicy::Return(BytesRef::Flexible(&mut output)));
let ex = Externalities::new(&mut state, &info, &engine, &factory, 0, &params, &mut substate, OutputPolicy::Return(BytesRef::Flexible(&mut output)));
let mut test_ext = TestExt::new(ex); let mut test_ext = TestExt::new(ex);
let evm = Factory::default().create(); let evm = Factory::default().create();
let res = evm.exec(&params, &mut test_ext); let res = evm.exec(&params, &mut test_ext);

View File

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