Moving EVM Factory to Engine
This commit is contained in:
parent
9039ed40a9
commit
abb4f08eff
@ -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;
|
||||
|
||||
|
@ -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).
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
};
|
||||
|
||||
|
@ -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() }
|
||||
|
@ -1,7 +1,6 @@
|
||||
use common::*;
|
||||
use engine::Engine;
|
||||
use executive::Executive;
|
||||
use evm::Factory;
|
||||
|
||||
pub type ApplyResult = Result<Receipt, Error>;
|
||||
|
||||
@ -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))
|
||||
}
|
||||
|
@ -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<String> {
|
||||
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<String> {
|
||||
|
||||
// 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);
|
||||
|
@ -1,6 +1,5 @@
|
||||
use super::test_common::*;
|
||||
use state::*;
|
||||
use executive::*;
|
||||
use ethereum;
|
||||
|
||||
fn do_json_test(json_data: &[u8]) -> Vec<String> {
|
||||
|
Loading…
Reference in New Issue
Block a user