Parametrizing evm::Factory

This commit is contained in:
Tomusdrw 2016-01-14 13:36:45 +01:00
parent eebcd0f35b
commit 81720d6617
5 changed files with 93 additions and 36 deletions

View File

@ -2,24 +2,63 @@
use evm::Evm; use evm::Evm;
pub enum VMType {
Jit,
Interpreter
}
/// Evm factory. Creates appropriate Evm. /// Evm factory. Creates appropriate Evm.
pub struct Factory; pub struct Factory {
evm : VMType
}
impl Factory { 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")] #[cfg(feature = "jit")]
pub fn create() -> Box<Evm> { fn jit() -> Box<Evm> {
Box::new(super::jit::JitEvm) Box::new(super::jit::JitEvm)
} }
/// Returns native rust evm
#[cfg(not(feature = "jit"))] #[cfg(not(feature = "jit"))]
pub fn create() -> Box<Evm> { fn jit() -> Box<Evm> {
Box::new(super::interpreter::Interpreter) 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] #[test]
fn test_create_vm() { fn test_create_vm() {
let _vm = Factory::create(); let _vm = Factory::default().create();
} }

View File

@ -127,11 +127,11 @@ macro_rules! evm_test(
#[test] #[test]
#[cfg(feature = "jit")] #[cfg(feature = "jit")]
fn $name_jit() { fn $name_jit() {
$name_test(Box::new(super::jit::JitEvm)); $name_test(super::Factory::new(super::factory::VMType::Jit).create());
} }
#[test] #[test]
fn $name_int() { fn $name_int() {
$name_test(Box::new(super::interpreter::Interpreter)); $name_test(super::Factory::new(super::factory::VMType::Interpreter).create());
} }
} }
); );

View File

@ -74,27 +74,29 @@ 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) -> Self { pub fn new(state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine, factory: &'a Factory) -> Self {
Executive::new_with_depth(state, info, engine, 0) Executive::new_with_depth(state, info, engine, factory, 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, depth: usize) -> Self { 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, depth + 1) Executive::new_with_depth(state, info, engine, factory, 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, depth: usize) -> Self { fn new_with_depth(state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine, factory: &'a Factory, depth: usize) -> Self {
Executive { Executive {
state: state, state: state,
info: info, info: info,
engine: engine, engine: engine,
factory: factory,
depth: depth depth: depth
} }
} }
@ -191,8 +193,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));
let evm = Factory::create(); self.factory.create().exec(&params, &mut ext)
evm.exec(&params, &mut ext)
} else { } else {
// otherwise, nothing // otherwise, nothing
Ok(params.gas) Ok(params.gas)
@ -209,8 +210,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);
let evm = Factory::create(); self.factory.create().exec(&params, &mut ext)
evm.exec(&params, &mut ext)
} }
/// Finalizes the transaction (does refunds and suicides). /// Finalizes the transaction (does refunds and suicides).
@ -290,6 +290,7 @@ 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,
@ -304,7 +305,8 @@ impl<'a> Externalities<'a> {
/// Basic `Externalities` constructor. /// Basic `Externalities` constructor.
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,
@ -313,6 +315,7 @@ 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,
@ -323,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.depth, params, substate, output) Self::new(e.state, e.info, e.engine, e.factory, e.depth, params, substate, output)
} }
} }
@ -375,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.depth); let mut ex = Executive::from_parent(self.state, self.info, self.engine, self.factory, 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)))
} }
@ -417,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.depth); let mut ex = Executive::from_parent(self.state, self.info, self.engine, self.factory, self.depth);
ex.call(&params, self.substate, BytesRef::Fixed(output)) ex.call(&params, self.substate, BytesRef::Fixed(output))
} }
@ -491,6 +494,7 @@ mod tests {
use engine::*; use engine::*;
use spec::*; use spec::*;
use evm::Schedule; use evm::Schedule;
use evm::Factory;
struct TestEngine { struct TestEngine {
spec: Spec, spec: Spec,
@ -541,7 +545,8 @@ mod tests {
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); let factory = Factory::default();
let mut ex = Executive::new(&mut state, &info, &engine, &factory);
ex.create(&params, &mut substate).unwrap() ex.create(&params, &mut substate).unwrap()
}; };
@ -599,7 +604,8 @@ mod tests {
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); let factory = Factory::default();
let mut ex = Executive::new(&mut state, &info, &engine, &factory);
ex.create(&params, &mut substate).unwrap() ex.create(&params, &mut substate).unwrap()
}; };
@ -652,7 +658,8 @@ mod tests {
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); let factory = Factory::default();
let mut ex = Executive::new(&mut state, &info, &engine, &factory);
ex.create(&params, &mut substate).unwrap() ex.create(&params, &mut substate).unwrap()
}; };
@ -703,7 +710,8 @@ mod tests {
let mut substate = Substate::new(); let mut substate = Substate::new();
{ {
let mut ex = Executive::new(&mut state, &info, &engine); let factory = Factory::default();
let mut ex = Executive::new(&mut state, &info, &engine, &factory);
ex.create(&params, &mut substate).unwrap(); ex.create(&params, &mut substate).unwrap();
} }
@ -761,7 +769,8 @@ mod tests {
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); let factory = Factory::default();
let mut ex = Executive::new(&mut state, &info, &engine, &factory);
ex.call(&params, &mut substate, BytesRef::Fixed(&mut [])).unwrap() ex.call(&params, &mut substate, BytesRef::Fixed(&mut [])).unwrap()
}; };
@ -803,7 +812,8 @@ mod tests {
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); let factory = Factory::default();
let mut ex = Executive::new(&mut state, &info, &engine, &factory);
ex.call(&params, &mut substate, BytesRef::Fixed(&mut [])).unwrap() ex.call(&params, &mut substate, BytesRef::Fixed(&mut [])).unwrap()
}; };
@ -827,7 +837,8 @@ mod tests {
let engine = TestEngine::new(0); let engine = TestEngine::new(0);
let executed = { let executed = {
let mut ex = Executive::new(&mut state, &info, &engine); let factory = Factory::default();
let mut ex = Executive::new(&mut state, &info, &engine, &factory);
ex.transact(&t).unwrap() ex.transact(&t).unwrap()
}; };
@ -854,7 +865,8 @@ mod tests {
let engine = TestEngine::new(0); let engine = TestEngine::new(0);
let res = { let res = {
let mut ex = Executive::new(&mut state, &info, &engine); let factory = Factory::default();
let mut ex = Executive::new(&mut state, &info, &engine, &factory);
ex.transact(&t) ex.transact(&t)
}; };
@ -878,7 +890,8 @@ mod tests {
let engine = TestEngine::new(0); let engine = TestEngine::new(0);
let res = { let res = {
let mut ex = Executive::new(&mut state, &info, &engine); let factory = Factory::default();
let mut ex = Executive::new(&mut state, &info, &engine, &factory);
ex.transact(&t) ex.transact(&t)
}; };
@ -904,7 +917,8 @@ mod tests {
let engine = TestEngine::new(0); let engine = TestEngine::new(0);
let res = { let res = {
let mut ex = Executive::new(&mut state, &info, &engine); let factory = Factory::default();
let mut ex = Executive::new(&mut state, &info, &engine, &factory);
ex.transact(&t) ex.transact(&t)
}; };
@ -929,7 +943,8 @@ mod tests {
let engine = TestEngine::new(0); let engine = TestEngine::new(0);
let res = { let res = {
let mut ex = Executive::new(&mut state, &info, &engine); let factory = Factory::default();
let mut ex = Executive::new(&mut state, &info, &engine, &factory);
ex.transact(&t) ex.transact(&t)
}; };

View File

@ -1,6 +1,7 @@
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>;
@ -137,7 +138,8 @@ 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 {
let e = try!(Executive::new(self, env_info, engine).transact(t)); // TODO [todr] Pass VM factory?
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

@ -217,9 +217,10 @@ fn do_json_test(json_data: &[u8]) -> Vec<String> {
// execute // execute
let (res, callcreates) = { let (res, callcreates) = {
let ex = Externalities::new(&mut state, &info, &engine, 0, &params, &mut substate, OutputPolicy::Return(BytesRef::Flexible(&mut output))); let factory = Factory::default();
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::create(); let evm = Factory::default().create();
let res = evm.exec(&params, &mut test_ext); let res = evm.exec(&params, &mut test_ext);
(res, test_ext.callcreates) (res, test_ext.callcreates)
}; };