diff --git a/ethcore/src/basic_authority.rs b/ethcore/src/basic_authority.rs index d56cbb638..fec23cf54 100644 --- a/ethcore/src/basic_authority.rs +++ b/ethcore/src/basic_authority.rs @@ -21,7 +21,7 @@ use util::keys::store::AccountProvider; use block::*; use spec::{CommonParams, Spec}; use engine::*; -use evm::{Schedule, Factory}; +use evm::Schedule; use ethjson; /// `BasicAuthority` params. @@ -51,7 +51,6 @@ pub struct BasicAuthority { params: CommonParams, our_params: BasicAuthorityParams, builtins: BTreeMap, - factory: Factory, } impl BasicAuthority { @@ -61,7 +60,6 @@ impl BasicAuthority { params: params, our_params: our_params, builtins: builtins, - factory: Factory::default(), } } } @@ -78,8 +76,6 @@ impl Engine for BasicAuthority { /// Additional engine-specific information for the user/developer concerning `header`. fn extra_info(&self, _header: &Header) -> HashMap { hash_map!["signature".to_owned() => "TODO".to_owned()] } - fn vm_factory(&self) -> &Factory { &self.factory } - fn schedule(&self, _env_info: &EnvInfo) -> Schedule { Schedule::new_homestead() } @@ -210,12 +206,6 @@ mod tests { assert!(engine.version().major >= 1); } - #[test] - fn can_return_factory() { - let engine = new_test_authority().engine; - engine.vm_factory(); - } - #[test] fn can_return_schedule() { let engine = new_test_authority().engine; @@ -287,7 +277,8 @@ mod tests { let mut db = db_result.take(); spec.ensure_db_good(db.as_hashdb_mut()); let last_hashes = vec![genesis_header.hash()]; - let b = OpenBlock::new(engine.deref(), false, db, &genesis_header, last_hashes, addr.clone(), x!(3141562), vec![]); + let vm_factory = Default::default(); + let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, addr.clone(), x!(3141562), vec![]); let b = b.close_and_lock(); let seal = engine.generate_seal(b.block(), Some(&tap)).unwrap(); diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index 17b0e7071..90d4eec2d 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -23,6 +23,7 @@ use engine::*; use state::*; use verification::PreverifiedBlock; use trace::Trace; +use evm::Factory as EvmFactory; /// A block, encoded as it is on the block chain. #[derive(Default, Debug, Clone)] @@ -190,6 +191,7 @@ impl IsBlock for ExecutedBlock { pub struct OpenBlock<'x> { block: ExecutedBlock, engine: &'x Engine, + vm_factory: &'x EvmFactory, last_hashes: LastHashes, } @@ -226,10 +228,11 @@ pub struct SealedBlock { impl<'x> OpenBlock<'x> { #[cfg_attr(feature="dev", allow(too_many_arguments))] /// Create a new `OpenBlock` ready for transaction pushing. - pub fn new(engine: &'x Engine, tracing: bool, db: Box, parent: &Header, last_hashes: LastHashes, author: Address, gas_floor_target: U256, extra_data: Bytes) -> Self { + pub fn new(engine: &'x Engine, vm_factory: &'x EvmFactory, tracing: bool, db: Box, parent: &Header, last_hashes: LastHashes, author: Address, gas_floor_target: U256, extra_data: Bytes) -> Self { let mut r = OpenBlock { block: ExecutedBlock::new(State::from_existing(db, parent.state_root().clone(), engine.account_start_nonce()), tracing), engine: engine, + vm_factory: vm_factory, last_hashes: last_hashes, }; @@ -308,7 +311,7 @@ impl<'x> OpenBlock<'x> { let env_info = self.env_info(); // info!("env_info says gas_used={}", env_info.gas_used); - match self.block.state.apply(&env_info, self.engine, &t, self.block.traces.is_some()) { + match self.block.state.apply(&env_info, self.engine, self.vm_factory, &t, self.block.traces.is_some()) { Ok(outcome) => { self.block.transactions_set.insert(h.unwrap_or_else(||t.hash())); self.block.base.transactions.push(t); @@ -393,13 +396,14 @@ impl ClosedBlock { } /// Given an engine reference, reopen the `ClosedBlock` into an `OpenBlock`. - pub fn reopen(self, engine: &Engine) -> OpenBlock { + pub fn reopen<'a>(self, engine: &'a Engine, vm_factory: &'a EvmFactory) -> OpenBlock<'a> { // revert rewards (i.e. set state back at last transaction's state). let mut block = self.block; block.state = self.unclosed_state; OpenBlock { block: block, engine: engine, + vm_factory: vm_factory, last_hashes: self.last_hashes, } } @@ -457,7 +461,7 @@ impl IsBlock for SealedBlock { /// Enact the block given by block header, transactions and uncles #[cfg_attr(feature="dev", allow(too_many_arguments))] -pub fn enact(header: &Header, transactions: &[SignedTransaction], uncles: &[Header], engine: &Engine, tracing: bool, db: Box, parent: &Header, last_hashes: LastHashes) -> Result { +pub fn enact(header: &Header, transactions: &[SignedTransaction], uncles: &[Header], engine: &Engine, tracing: bool, db: Box, parent: &Header, last_hashes: LastHashes, vm_factory: &EvmFactory) -> Result { { if ::log::max_log_level() >= ::log::LogLevel::Trace { let s = State::from_existing(db.boxed_clone(), parent.state_root().clone(), engine.account_start_nonce()); @@ -465,7 +469,7 @@ pub fn enact(header: &Header, transactions: &[SignedTransaction], uncles: &[Head } } - let mut b = OpenBlock::new(engine, tracing, db, parent, last_hashes, header.author().clone(), x!(3141562), header.extra_data().clone()); + let mut b = OpenBlock::new(engine, vm_factory, tracing, db, parent, last_hashes, header.author().clone(), x!(3141562), header.extra_data().clone()); b.set_difficulty(*header.difficulty()); b.set_gas_limit(*header.gas_limit()); b.set_timestamp(header.timestamp()); @@ -475,22 +479,22 @@ pub fn enact(header: &Header, transactions: &[SignedTransaction], uncles: &[Head } /// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header -pub fn enact_bytes(block_bytes: &[u8], engine: &Engine, tracing: bool, db: Box, parent: &Header, last_hashes: LastHashes) -> Result { +pub fn enact_bytes(block_bytes: &[u8], engine: &Engine, tracing: bool, db: Box, parent: &Header, last_hashes: LastHashes, vm_factory: &EvmFactory) -> Result { let block = BlockView::new(block_bytes); let header = block.header(); - enact(&header, &block.transactions(), &block.uncles(), engine, tracing, db, parent, last_hashes) + enact(&header, &block.transactions(), &block.uncles(), engine, tracing, db, parent, last_hashes, vm_factory) } /// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header -pub fn enact_verified(block: &PreverifiedBlock, engine: &Engine, tracing: bool, db: Box, parent: &Header, last_hashes: LastHashes) -> Result { +pub fn enact_verified(block: &PreverifiedBlock, engine: &Engine, tracing: bool, db: Box, parent: &Header, last_hashes: LastHashes, vm_factory: &EvmFactory) -> Result { let view = BlockView::new(&block.bytes); - enact(&block.header, &block.transactions, &view.uncles(), engine, tracing, db, parent, last_hashes) + enact(&block.header, &block.transactions, &view.uncles(), engine, tracing, db, parent, last_hashes, vm_factory) } /// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header. Seal the block aferwards -pub fn enact_and_seal(block_bytes: &[u8], engine: &Engine, tracing: bool, db: Box, parent: &Header, last_hashes: LastHashes) -> Result { +pub fn enact_and_seal(block_bytes: &[u8], engine: &Engine, tracing: bool, db: Box, parent: &Header, last_hashes: LastHashes, vm_factory: &EvmFactory) -> Result { let header = BlockView::new(block_bytes).header_view(); - Ok(try!(try!(enact_bytes(block_bytes, engine, tracing, db, parent, last_hashes)).seal(engine, header.seal()))) + Ok(try!(try!(enact_bytes(block_bytes, engine, tracing, db, parent, last_hashes, vm_factory)).seal(engine, header.seal()))) } #[cfg(test)] @@ -509,7 +513,8 @@ mod tests { let mut db = db_result.take(); spec.ensure_db_good(db.as_hashdb_mut()); let last_hashes = vec![genesis_header.hash()]; - let b = OpenBlock::new(engine.deref(), false, db, &genesis_header, last_hashes, Address::zero(), x!(3141562), vec![]); + let vm_factory = Default::default(); + let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, Address::zero(), x!(3141562), vec![]); let b = b.close_and_lock(); let _ = b.seal(engine.deref(), vec![]); } @@ -524,14 +529,15 @@ mod tests { let mut db_result = get_temp_journal_db(); let mut db = db_result.take(); spec.ensure_db_good(db.as_hashdb_mut()); - let b = OpenBlock::new(engine.deref(), false, db, &genesis_header, vec![genesis_header.hash()], Address::zero(), x!(3141562), vec![]).close_and_lock().seal(engine.deref(), vec![]).unwrap(); + let vm_factory = Default::default(); + let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, vec![genesis_header.hash()], Address::zero(), x!(3141562), vec![]).close_and_lock().seal(engine.deref(), vec![]).unwrap(); let orig_bytes = b.rlp_bytes(); let orig_db = b.drain(); let mut db_result = get_temp_journal_db(); let mut db = db_result.take(); spec.ensure_db_good(db.as_hashdb_mut()); - let e = enact_and_seal(&orig_bytes, engine.deref(), false, db, &genesis_header, vec![genesis_header.hash()]).unwrap(); + let e = enact_and_seal(&orig_bytes, engine.deref(), false, db, &genesis_header, vec![genesis_header.hash()], &Default::default()).unwrap(); assert_eq!(e.rlp_bytes(), orig_bytes); @@ -550,7 +556,8 @@ mod tests { let mut db_result = get_temp_journal_db(); let mut db = db_result.take(); spec.ensure_db_good(db.as_hashdb_mut()); - let mut open_block = OpenBlock::new(engine.deref(), false, db, &genesis_header, vec![genesis_header.hash()], Address::zero(), x!(3141562), vec![]); + let vm_factory = Default::default(); + let mut open_block = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, vec![genesis_header.hash()], Address::zero(), x!(3141562), vec![]); let mut uncle1_header = Header::new(); uncle1_header.extra_data = b"uncle1".to_vec(); let mut uncle2_header = Header::new(); @@ -565,7 +572,7 @@ mod tests { let mut db_result = get_temp_journal_db(); let mut db = db_result.take(); spec.ensure_db_good(db.as_hashdb_mut()); - let e = enact_and_seal(&orig_bytes, engine.deref(), false, db, &genesis_header, vec![genesis_header.hash()]).unwrap(); + let e = enact_and_seal(&orig_bytes, engine.deref(), false, db, &genesis_header, vec![genesis_header.hash()], &Default::default()).unwrap(); let bytes = e.rlp_bytes(); assert_eq!(bytes, orig_bytes); diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 0d61325d9..cff9e5323 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -46,6 +46,7 @@ use trace::{TraceDB, ImportRequest as TraceImportRequest, LocalizedTrace, Databa use trace; pub use types::blockchain_info::BlockChainInfo; pub use types::block_status::BlockStatus; +use evm::Factory as EvmFactory; impl fmt::Display for BlockChainInfo { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -87,6 +88,7 @@ pub struct Client where V: Verifier { import_lock: Mutex<()>, panic_handler: Arc, verifier: PhantomData, + vm_factory: Arc, } const HISTORY: u64 = 1200; @@ -151,6 +153,7 @@ impl Client where V: Verifier { import_lock: Mutex::new(()), panic_handler: panic_handler, verifier: PhantomData, + vm_factory: Arc::new(EvmFactory::new(config.vm_type)), }) } @@ -204,7 +207,7 @@ impl Client where V: Verifier { let last_hashes = self.build_last_hashes(header.parent_hash.clone()); let db = self.state_db.lock().unwrap().boxed_clone(); - let enact_result = enact_verified(&block, engine, self.tracedb.tracing_enabled(), db, &parent, last_hashes); + let enact_result = enact_verified(&block, engine, self.tracedb.tracing_enabled(), db, &parent, last_hashes, &self.vm_factory); if let Err(e) = enact_result { warn!(target: "client", "Block import failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); return Err(()); @@ -422,7 +425,7 @@ impl BlockChainClient for Client where V: Verifier { state.sub_balance(&sender, &balance); state.add_balance(&sender, &U256::max_value()); let options = TransactOptions { tracing: false, check_nonce: false }; - Executive::new(&mut state, &env_info, self.engine.deref().deref()).transact(t, options) + Executive::new(&mut state, &env_info, self.engine.deref().deref(), &self.vm_factory).transact(t, options) } // TODO [todr] Should be moved to miner crate eventually. @@ -434,6 +437,10 @@ impl BlockChainClient for Client where V: Verifier { self.engine.deref().deref() } + fn vm_factory(&self) -> &EvmFactory { + &self.vm_factory + } + // TODO [todr] Should be moved to miner crate eventually. fn prepare_sealing(&self, author: Address, gas_floor_target: U256, extra_data: Bytes, transactions: Vec) -> (Option, HashSet) { @@ -443,6 +450,7 @@ impl BlockChainClient for Client where V: Verifier { let mut b = OpenBlock::new( engine, + &self.vm_factory, false, // TODO: this will need to be parameterised once we want to do immediate mining insertion. self.state_db.lock().unwrap().boxed_clone(), match self.chain.block_header(&h) { Some(ref x) => x, None => { return (None, invalid_transactions) } }, diff --git a/ethcore/src/client/config.rs b/ethcore/src/client/config.rs index df685f0d1..7acea0070 100644 --- a/ethcore/src/client/config.rs +++ b/ethcore/src/client/config.rs @@ -17,6 +17,7 @@ pub use block_queue::BlockQueueConfig; pub use blockchain::BlockChainConfig; pub use trace::{Config as TraceConfig, Switch}; +pub use evm::VMType; use util::journaldb; /// Client configuration. Includes configs for all sub-systems. @@ -28,6 +29,8 @@ pub struct ClientConfig { pub blockchain: BlockChainConfig, /// Trace configuration. pub tracing: TraceConfig, + /// VM type. + pub vm_type: VMType, /// The JournalDB ("pruning") algorithm to use. pub pruning: journaldb::Algorithm, /// The name of the client instance. diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index a748ff900..b6f6fde2d 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -22,7 +22,7 @@ mod test_client; mod trace; pub use self::client::*; -pub use self::config::{ClientConfig, BlockQueueConfig, BlockChainConfig, Switch}; +pub use self::config::{ClientConfig, BlockQueueConfig, BlockChainConfig, Switch, VMType}; pub use types::ids::*; pub use self::test_client::{TestBlockChainClient, EachBlockWith}; pub use self::trace::Filter as TraceFilter; @@ -45,6 +45,7 @@ use error::{ImportResult, ExecutionError}; use receipt::LocalizedReceipt; use engine::{Engine}; use trace::LocalizedTrace; +use evm::Factory as EvmFactory; /// Blockchain database client. Owns and manages a blockchain and a block queue. pub trait BlockChainClient : Sync + Send { @@ -140,6 +141,9 @@ pub trait BlockChainClient : Sync + Send { /// Executes a function providing it with a reference to an engine. fn engine(&self) -> &Engine; + /// Returns EvmFactory. + fn vm_factory(&self) -> &EvmFactory; + /// Returns traces matching given filter. fn filter_traces(&self, filter: TraceFilter) -> Option>; diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 4ec993fe5..80bb1d63d 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -27,6 +27,7 @@ use log_entry::LocalizedLogEntry; use receipt::{Receipt, LocalizedReceipt}; use extras::BlockReceipts; use error::{ImportResult}; +use evm::Factory as EvmFactory; use block_queue::BlockQueueInfo; use block::{SealedBlock, ClosedBlock, LockedBlock}; @@ -434,6 +435,10 @@ impl BlockChainClient for TestBlockChainClient { unimplemented!(); } + fn vm_factory(&self) -> &EvmFactory { + unimplemented!(); + } + fn filter_traces(&self, _filter: TraceFilter) -> Option> { unimplemented!(); } diff --git a/ethcore/src/engine.rs b/ethcore/src/engine.rs index 344144c6e..d0c72f26c 100644 --- a/ethcore/src/engine.rs +++ b/ethcore/src/engine.rs @@ -18,7 +18,7 @@ use common::*; use util::keys::store::AccountProvider; use block::ExecutedBlock; use spec::CommonParams; -use evm::{Schedule, Factory}; +use evm::Schedule; /// 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. @@ -37,9 +37,6 @@ pub trait Engine : Sync + Send { /// Get the general parameters of the chain. fn params(&self) -> &CommonParams; - /// 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/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 0cf436d7c..cb06959d0 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -21,7 +21,7 @@ use common::*; use block::*; use spec::CommonParams; use engine::*; -use evm::{Schedule, Factory}; +use evm::Schedule; use ethjson; /// Ethash params. @@ -64,7 +64,6 @@ pub struct Ethash { ethash_params: EthashParams, builtins: BTreeMap, pow: EthashManager, - factory: Factory, } impl Ethash { @@ -75,7 +74,6 @@ impl Ethash { ethash_params: ethash_params, builtins: builtins, pow: EthashManager::new(), - factory: Factory::default(), } } } @@ -97,10 +95,6 @@ impl Engine for Ethash { hash_map!["nonce".to_owned() => format!("0x{}", header.nonce().hex()), "mixHash".to_owned() => format!("0x{}", header.mix_hash().hex())] } - fn vm_factory(&self) -> &Factory { - &self.factory - } - fn schedule(&self, env_info: &EnvInfo) -> Schedule { trace!(target: "client", "Creating schedule. fCML={}", self.ethash_params.frontier_compatibility_mode_limit); @@ -313,7 +307,8 @@ mod tests { let mut db = db_result.take(); spec.ensure_db_good(db.as_hashdb_mut()); let last_hashes = vec![genesis_header.hash()]; - let b = OpenBlock::new(engine.deref(), false, db, &genesis_header, last_hashes, Address::zero(), x!(3141562), vec![]); + let vm_factory = Default::default(); + let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, Address::zero(), x!(3141562), vec![]); let b = b.close(); assert_eq!(b.state().balance(&Address::zero()), U256::from_str("4563918244f40000").unwrap()); } @@ -327,7 +322,8 @@ mod tests { let mut db = db_result.take(); spec.ensure_db_good(db.as_hashdb_mut()); let last_hashes = vec![genesis_header.hash()]; - let mut b = OpenBlock::new(engine.deref(), false, db, &genesis_header, last_hashes, Address::zero(), x!(3141562), vec![]); + let vm_factory = Default::default(); + let mut b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, Address::zero(), x!(3141562), vec![]); let mut uncle = Header::new(); let uncle_author = address_from_hex("ef2d6d194084c2de36e0dabfce45d046b37d1106"); uncle.author = uncle_author.clone(); @@ -345,12 +341,6 @@ mod tests { assert!(engine.version().major >= 1); } - #[test] - fn can_return_factory() { - let engine = new_morden().engine; - engine.vm_factory(); - } - #[test] fn can_return_schedule() { let engine = new_morden().engine; diff --git a/ethcore/src/evm/factory.rs b/ethcore/src/evm/factory.rs index 65add0050..3e60e8808 100644 --- a/ethcore/src/evm/factory.rs +++ b/ethcore/src/evm/factory.rs @@ -17,11 +17,10 @@ //! Evm factory. //! //! TODO: consider spliting it into two separate files. -#[cfg(test)] use std::fmt; use evm::Evm; -#[derive(Clone)] +#[derive(Debug, Clone)] /// Type of EVM to use. pub enum VMType { /// JIT EVM @@ -31,7 +30,6 @@ pub enum VMType { Interpreter } -#[cfg(test)] impl fmt::Display for VMType { #[cfg(feature="jit")] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -48,8 +46,12 @@ impl fmt::Display for VMType { } } -#[cfg(test)] -#[cfg(feature = "json-tests")] +impl Default for VMType { + fn default() -> Self { + VMType::Interpreter + } +} + impl VMType { /// Return all possible VMs (JIT, Interpreter) #[cfg(feature = "jit")] @@ -62,6 +64,18 @@ impl VMType { pub fn all() -> Vec { vec![VMType::Interpreter] } + + /// Return new jit if it's possible + #[cfg(not(feature = "jit"))] + pub fn jit() -> Option { + None + } + + /// Return new jit if it's possible + #[cfg(feature = "jit")] + pub fn jit() -> Option { + Some(VMType::Jit) + } } /// Evm factory. Creates appropriate Evm. @@ -80,7 +94,7 @@ impl Factory { VMType::Interpreter => { Box::new(super::interpreter::Interpreter) } - } + } } /// Create fresh instance of VM @@ -90,17 +104,17 @@ impl Factory { VMType::Interpreter => { Box::new(super::interpreter::Interpreter) } - } + } } /// Create new instance of specific `VMType` factory - #[cfg(test)] - pub fn new(evm: VMType) -> Factory { + pub fn new(evm: VMType) -> Self { Factory { evm: evm } } } + impl Default for Factory { /// Returns jitvm factory #[cfg(feature = "jit")] diff --git a/ethcore/src/evm/mod.rs b/ethcore/src/evm/mod.rs index 3e1dc5ed7..b7816b99c 100644 --- a/ethcore/src/evm/mod.rs +++ b/ethcore/src/evm/mod.rs @@ -31,6 +31,5 @@ mod tests; pub use self::evm::{Evm, Error, Result}; pub use self::ext::{Ext, ContractCreateResult, MessageCallResult}; -pub use self::factory::Factory; +pub use self::factory::{Factory, VMType}; pub use self::schedule::Schedule; -pub use self::factory::VMType; diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index 74e0499c1..320a89cb8 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -18,7 +18,7 @@ use common::*; use state::*; use engine::*; -use evm::{self, Ext}; +use evm::{self, Ext, Factory}; use externalities::*; use substate::*; use trace::{Trace, Tracer, NoopTracer, ExecutiveTracer}; @@ -52,33 +52,36 @@ pub struct Executive<'a> { state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine, + vm_factory: &'a Factory, depth: usize, } impl<'a> Executive<'a> { /// 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, vm_factory: &'a Factory) -> Self { Executive { state: state, info: info, engine: engine, + vm_factory: vm_factory, depth: 0, } } /// Populates executive from parent properties. Increments executive depth. - pub fn from_parent(state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine, parent_depth: usize) -> Self { + pub fn from_parent(state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine, vm_factory: &'a Factory, parent_depth: usize) -> Self { Executive { state: state, info: info, engine: engine, + vm_factory: vm_factory, depth: parent_depth + 1, } } /// Creates `Externalities` from `Executive`. pub fn as_externalities<'_, T>(&'_ mut self, origin_info: OriginInfo, substate: &'_ mut Substate, output: OutputPolicy<'_, '_>, tracer: &'_ mut T) -> Externalities<'_, T> where T: Tracer { - Externalities::new(self.state, self.info, self.engine, self.depth, origin_info, substate, output, tracer) + Externalities::new(self.state, self.info, self.engine, self.vm_factory, self.depth, origin_info, substate, output, tracer) } /// This function should be used to execute transaction. @@ -179,8 +182,8 @@ impl<'a> Executive<'a> { -> evm::Result where T: Tracer { // Ordinary execution - keep VM in same thread if (self.depth + 1) % MAX_VM_DEPTH_FOR_THREAD != 0 { + let vm_factory = self.vm_factory; let mut ext = self.as_externalities(OriginInfo::from(¶ms), unconfirmed_substate, output_policy, tracer); - let vm_factory = self.engine.vm_factory(); trace!(target: "executive", "ext.schedule.have_delegate_call: {}", ext.schedule().have_delegate_call); return vm_factory.create().exec(params, &mut ext); } @@ -189,8 +192,8 @@ impl<'a> Executive<'a> { // TODO [todr] No thread builder yet, so we need to reset once for a while // https://github.com/aturon/crossbeam/issues/16 crossbeam::scope(|scope| { + let vm_factory = self.vm_factory; let mut ext = self.as_externalities(OriginInfo::from(¶ms), unconfirmed_substate, output_policy, tracer); - let vm_factory = self.engine.vm_factory(); scope.spawn(move || { vm_factory.create().exec(params, &mut ext) @@ -458,11 +461,11 @@ mod tests { let mut state = state_result.reference_mut(); state.add_balance(&sender, &U256::from(0x100u64)); let info = EnvInfo::default(); - let engine = TestEngine::new(0, factory); + let engine = TestEngine::new(0); let mut substate = Substate::new(); let gas_left = { - let mut ex = Executive::new(&mut state, &info, &engine); + let mut ex = Executive::new(&mut state, &info, &engine, &factory); ex.create(params, &mut substate, &mut NoopTracer).unwrap() }; @@ -517,11 +520,11 @@ mod tests { let mut state = state_result.reference_mut(); state.add_balance(&sender, &U256::from(100)); let info = EnvInfo::default(); - let engine = TestEngine::new(0, factory); + let engine = TestEngine::new(0); let mut substate = Substate::new(); let gas_left = { - let mut ex = Executive::new(&mut state, &info, &engine); + let mut ex = Executive::new(&mut state, &info, &engine, &factory); ex.create(params, &mut substate, &mut NoopTracer).unwrap() }; @@ -572,12 +575,12 @@ mod tests { let mut state = state_result.reference_mut(); state.add_balance(&sender, &U256::from(100)); let info = EnvInfo::default(); - let engine = TestEngine::new(5, factory); + let engine = TestEngine::new(5); let mut substate = Substate::new(); let mut tracer = ExecutiveTracer::default(); let gas_left = { - let mut ex = Executive::new(&mut state, &info, &engine); + let mut ex = Executive::new(&mut state, &info, &engine, &factory); let output = BytesRef::Fixed(&mut[0u8;0]); ex.call(params, &mut substate, output, &mut tracer).unwrap() }; @@ -644,12 +647,12 @@ mod tests { let mut state = state_result.reference_mut(); state.add_balance(&sender, &U256::from(100)); let info = EnvInfo::default(); - let engine = TestEngine::new(5, factory); + let engine = TestEngine::new(5); let mut substate = Substate::new(); let mut tracer = ExecutiveTracer::default(); let gas_left = { - let mut ex = Executive::new(&mut state, &info, &engine); + let mut ex = Executive::new(&mut state, &info, &engine, &factory); ex.create(params.clone(), &mut substate, &mut tracer).unwrap() }; @@ -714,11 +717,11 @@ mod tests { let mut state = state_result.reference_mut(); state.add_balance(&sender, &U256::from(100)); let info = EnvInfo::default(); - let engine = TestEngine::new(0, factory); + let engine = TestEngine::new(0); let mut substate = Substate::new(); let gas_left = { - let mut ex = Executive::new(&mut state, &info, &engine); + let mut ex = Executive::new(&mut state, &info, &engine, &factory); ex.create(params, &mut substate, &mut NoopTracer).unwrap() }; @@ -766,11 +769,11 @@ mod tests { let mut state = state_result.reference_mut(); state.add_balance(&sender, &U256::from(100)); let info = EnvInfo::default(); - let engine = TestEngine::new(1024, factory); + let engine = TestEngine::new(1024); let mut substate = Substate::new(); { - let mut ex = Executive::new(&mut state, &info, &engine); + let mut ex = Executive::new(&mut state, &info, &engine, &factory); ex.create(params, &mut substate, &mut NoopTracer).unwrap(); } @@ -827,11 +830,11 @@ mod tests { state.add_balance(&sender, &U256::from(100_000)); let info = EnvInfo::default(); - let engine = TestEngine::new(0, factory); + let engine = TestEngine::new(0); let mut substate = Substate::new(); let gas_left = { - let mut ex = Executive::new(&mut state, &info, &engine); + let mut ex = Executive::new(&mut state, &info, &engine, &factory); ex.call(params, &mut substate, BytesRef::Fixed(&mut []), &mut NoopTracer).unwrap() }; @@ -872,11 +875,11 @@ mod tests { let mut state = state_result.reference_mut(); state.init_code(&address, code.clone()); let info = EnvInfo::default(); - let engine = TestEngine::new(0, factory); + let engine = TestEngine::new(0); let mut substate = Substate::new(); let gas_left = { - let mut ex = Executive::new(&mut state, &info, &engine); + let mut ex = Executive::new(&mut state, &info, &engine, &factory); ex.call(params, &mut substate, BytesRef::Fixed(&mut []), &mut NoopTracer).unwrap() }; @@ -906,10 +909,10 @@ mod tests { state.add_balance(&sender, &U256::from(18)); let mut info = EnvInfo::default(); info.gas_limit = U256::from(100_000); - let engine = TestEngine::new(0, factory); + let engine = TestEngine::new(0); let executed = { - let mut ex = Executive::new(&mut state, &info, &engine); + let mut ex = Executive::new(&mut state, &info, &engine, &factory); let opts = TransactOptions { check_nonce: true, tracing: false }; ex.transact(&t, opts).unwrap() }; @@ -940,10 +943,10 @@ mod tests { let mut state = state_result.reference_mut(); let mut info = EnvInfo::default(); info.gas_limit = U256::from(100_000); - let engine = TestEngine::new(0, factory); + let engine = TestEngine::new(0); let res = { - let mut ex = Executive::new(&mut state, &info, &engine); + let mut ex = Executive::new(&mut state, &info, &engine, &factory); let opts = TransactOptions { check_nonce: true, tracing: false }; ex.transact(&t, opts) }; @@ -972,10 +975,10 @@ mod tests { state.add_balance(&sender, &U256::from(17)); let mut info = EnvInfo::default(); info.gas_limit = U256::from(100_000); - let engine = TestEngine::new(0, factory); + let engine = TestEngine::new(0); let res = { - let mut ex = Executive::new(&mut state, &info, &engine); + let mut ex = Executive::new(&mut state, &info, &engine, &factory); let opts = TransactOptions { check_nonce: true, tracing: false }; ex.transact(&t, opts) }; @@ -1006,10 +1009,10 @@ mod tests { let mut info = EnvInfo::default(); info.gas_used = U256::from(20_000); info.gas_limit = U256::from(100_000); - let engine = TestEngine::new(0, factory); + let engine = TestEngine::new(0); let res = { - let mut ex = Executive::new(&mut state, &info, &engine); + let mut ex = Executive::new(&mut state, &info, &engine, &factory); let opts = TransactOptions { check_nonce: true, tracing: false }; ex.transact(&t, opts) }; @@ -1040,10 +1043,10 @@ mod tests { state.add_balance(&sender, &U256::from(100_017)); let mut info = EnvInfo::default(); info.gas_limit = U256::from(100_000); - let engine = TestEngine::new(0, factory); + let engine = TestEngine::new(0); let res = { - let mut ex = Executive::new(&mut state, &info, &engine); + let mut ex = Executive::new(&mut state, &info, &engine, &factory); let opts = TransactOptions { check_nonce: true, tracing: false }; ex.transact(&t, opts) }; @@ -1074,11 +1077,11 @@ mod tests { let mut state = state_result.reference_mut(); state.add_balance(&sender, &U256::from_str("152d02c7e14af6800000").unwrap()); let info = EnvInfo::default(); - let engine = TestEngine::new(0, factory); + let engine = TestEngine::new(0); let mut substate = Substate::new(); let result = { - let mut ex = Executive::new(&mut state, &info, &engine); + let mut ex = Executive::new(&mut state, &info, &engine, &factory); ex.create(params, &mut substate, &mut NoopTracer) }; diff --git a/ethcore/src/externalities.rs b/ethcore/src/externalities.rs index 4d868cba5..c936ac207 100644 --- a/ethcore/src/externalities.rs +++ b/ethcore/src/externalities.rs @@ -19,7 +19,7 @@ use common::*; use state::*; use engine::*; use executive::*; -use evm::{self, Schedule, Ext, ContractCreateResult, MessageCallResult}; +use evm::{self, Schedule, Ext, ContractCreateResult, MessageCallResult, Factory}; use substate::*; use trace::Tracer; @@ -59,6 +59,7 @@ pub struct Externalities<'a, T> where T: 'a + Tracer { state: &'a mut State, env_info: &'a EnvInfo, engine: &'a Engine, + vm_factory: &'a Factory, depth: usize, origin_info: OriginInfo, substate: &'a mut Substate, @@ -74,6 +75,7 @@ impl<'a, T> Externalities<'a, T> where T: 'a + Tracer { pub fn new(state: &'a mut State, env_info: &'a EnvInfo, engine: &'a Engine, + vm_factory: &'a Factory, depth: usize, origin_info: OriginInfo, substate: &'a mut Substate, @@ -84,6 +86,7 @@ impl<'a, T> Externalities<'a, T> where T: 'a + Tracer { state: state, env_info: env_info, engine: engine, + vm_factory: vm_factory, depth: depth, origin_info: origin_info, substate: substate, @@ -146,7 +149,7 @@ impl<'a, T> Ext for Externalities<'a, T> where T: 'a + Tracer { }; self.state.inc_nonce(&self.origin_info.address); - let mut ex = Executive::from_parent(self.state, self.env_info, self.engine, self.depth); + let mut ex = Executive::from_parent(self.state, self.env_info, self.engine, self.vm_factory, self.depth); // TODO: handle internal error separately match ex.create(params, self.substate, self.tracer) { @@ -185,7 +188,7 @@ impl<'a, T> Ext for Externalities<'a, T> where T: 'a + Tracer { params.value = ActionValue::Transfer(value); } - let mut ex = Executive::from_parent(self.state, self.env_info, self.engine, self.depth); + let mut ex = Executive::from_parent(self.state, self.env_info, self.engine, self.vm_factory, self.depth); match ex.call(params, self.substate, BytesRef::Fixed(output), self.tracer) { Ok(gas_left) => MessageCallResult::Success(gas_left), @@ -347,7 +350,8 @@ mod tests { let state = setup.state.reference_mut(); let mut tracer = NoopTracer; - let ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer); + let vm_factory = Default::default(); + let ext = Externalities::new(state, &setup.env_info, &*setup.engine, &vm_factory, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer); assert_eq!(ext.env_info().number, 100); } @@ -358,7 +362,8 @@ mod tests { let state = setup.state.reference_mut(); let mut tracer = NoopTracer; - let ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer); + let vm_factory = Default::default(); + let ext = Externalities::new(state, &setup.env_info, &*setup.engine, &vm_factory, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer); let hash = ext.blockhash(&U256::from_str("0000000000000000000000000000000000000000000000000000000000120000").unwrap()); @@ -379,7 +384,8 @@ mod tests { let state = setup.state.reference_mut(); let mut tracer = NoopTracer; - let ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer); + let vm_factory = Default::default(); + let ext = Externalities::new(state, &setup.env_info, &*setup.engine, &vm_factory, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer); let hash = ext.blockhash(&U256::from_str("0000000000000000000000000000000000000000000000000000000000120000").unwrap()); @@ -393,7 +399,8 @@ mod tests { let state = setup.state.reference_mut(); let mut tracer = NoopTracer; - let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer); + let vm_factory = Default::default(); + let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, &vm_factory, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer); let mut output = vec![]; @@ -418,7 +425,8 @@ mod tests { let mut tracer = NoopTracer; { - let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer); + let vm_factory = Default::default(); + let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, &vm_factory, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer); ext.log(log_topics, &log_data); } @@ -434,7 +442,8 @@ mod tests { let mut tracer = NoopTracer; { - let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer); + let vm_factory = Default::default(); + let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, &vm_factory, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer); ext.suicide(&refund_account); } diff --git a/ethcore/src/json_tests/executive.rs b/ethcore/src/json_tests/executive.rs index ebffdbb15..9e9620169 100644 --- a/ethcore/src/json_tests/executive.rs +++ b/ethcore/src/json_tests/executive.rs @@ -58,6 +58,7 @@ impl<'a, T> TestExt<'a, T> where T: 'a + Tracer { fn new(state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine, + vm_factory: &'a Factory, depth: usize, origin_info: OriginInfo, substate: &'a mut Substate, @@ -66,7 +67,7 @@ impl<'a, T> TestExt<'a, T> where T: 'a + Tracer { tracer: &'a mut T) -> Self { TestExt { contract_address: contract_address(&address, &state.nonce(&address)), - ext: Externalities::new(state, info, engine, depth, origin_info, substate, output, tracer), + ext: Externalities::new(state, info, engine, vm_factory, depth, origin_info, substate, output, tracer), callcreates: vec![] } } @@ -179,7 +180,8 @@ fn do_json_test_for(vm_type: &VMType, json_data: &[u8]) -> Vec { let mut state = state_result.reference_mut(); state.populate_from(From::from(vm.pre_state.clone())); let info = From::from(vm.env); - let engine = TestEngine::new(1, Factory::new(vm_type.clone())); + let engine = TestEngine::new(1); + let vm_factory = Factory::new(vm_type.clone()); let params = ActionParams::from(vm.transaction); let mut substate = Substate::new(); @@ -192,6 +194,7 @@ fn do_json_test_for(vm_type: &VMType, json_data: &[u8]) -> Vec { &mut state, &info, &engine, + &vm_factory, 0, OriginInfo::from(¶ms), &mut substate, @@ -199,7 +202,7 @@ fn do_json_test_for(vm_type: &VMType, json_data: &[u8]) -> Vec { params.address.clone(), &mut tracer, ); - let evm = engine.vm_factory().create(); + let evm = vm_factory.create(); let res = evm.exec(params, &mut ex); (res, ex.callcreates) }; diff --git a/ethcore/src/json_tests/state.rs b/ethcore/src/json_tests/state.rs index cf7f56ce1..5cc611491 100644 --- a/ethcore/src/json_tests/state.rs +++ b/ethcore/src/json_tests/state.rs @@ -63,7 +63,8 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { let mut state = state_result.reference_mut(); state.populate_from(pre); state.commit(); - let res = state.apply(&env, engine.deref(), &transaction, false); + let vm_factory = Default::default(); + let res = state.apply(&env, engine.deref(), &vm_factory, &transaction, false); if fail_unless(state.root() == &post_state_root) { println!("!!! {}: State mismatch (got: {}, expect: {}):", name, state.root(), post_state_root); diff --git a/ethcore/src/null_engine.rs b/ethcore/src/null_engine.rs index 58ae5baa9..a760bea93 100644 --- a/ethcore/src/null_engine.rs +++ b/ethcore/src/null_engine.rs @@ -19,14 +19,13 @@ use util::hash::Address; use builtin::Builtin; use engine::Engine; use spec::CommonParams; -use evm::{Schedule, Factory}; +use evm::Schedule; use env_info::EnvInfo; /// An engine which does not provide any consensus mechanism. pub struct NullEngine { params: CommonParams, builtins: BTreeMap, - factory: Factory, } impl NullEngine { @@ -35,16 +34,11 @@ impl NullEngine { NullEngine{ params: params, builtins: builtins, - factory: Factory::default() } } } impl Engine for NullEngine { - fn vm_factory(&self) -> &Factory { - &self.factory - } - fn name(&self) -> &str { "NullEngine" } diff --git a/ethcore/src/state.rs b/ethcore/src/state.rs index 391730a94..eabca24a8 100644 --- a/ethcore/src/state.rs +++ b/ethcore/src/state.rs @@ -17,6 +17,7 @@ use common::*; use engine::Engine; use executive::{Executive, TransactOptions}; +use evm::Factory as EvmFactory; use account_db::*; use trace::Trace; #[cfg(test)] @@ -218,11 +219,11 @@ impl State { /// Execute a given transaction. /// This will change the state accordingly. - pub fn apply(&mut self, env_info: &EnvInfo, engine: &Engine, t: &SignedTransaction, tracing: bool) -> ApplyResult { + pub fn apply(&mut self, env_info: &EnvInfo, engine: &Engine, vm_factory: &EvmFactory, t: &SignedTransaction, tracing: bool) -> ApplyResult { // let old = self.to_pod(); let options = TransactOptions { tracing: tracing, check_nonce: true }; - let e = try!(Executive::new(self, env_info, engine).transact(t, options)); + let e = try!(Executive::new(self, env_info, engine, vm_factory).transact(t, options)); // TODO uncomment once to_pod() works correctly. // trace!("Applied transaction. Diff:\n{}\n", StateDiff::diff_pod(&old, &self.to_pod())); @@ -361,7 +362,6 @@ use util::common::*; use account::*; use tests::helpers::*; use devtools::*; -use evm::factory::*; use env_info::*; use spec::*; use transaction::*; @@ -378,7 +378,7 @@ fn should_apply_create_transaction() { let mut info = EnvInfo::default(); info.gas_limit = x!(1_000_000); - let engine = TestEngine::new(5, Factory::default()); + let engine = TestEngine::new(5); let t = Transaction { nonce: x!(0), @@ -390,7 +390,8 @@ fn should_apply_create_transaction() { }.sign(&"".sha3()); state.add_balance(t.sender().as_ref().unwrap(), &x!(100)); - let result = state.apply(&info, &engine, &t, true).unwrap(); + let vm_factory = Default::default(); + let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { depth: 0, action: trace::Action::Create(trace::Create { @@ -438,7 +439,7 @@ fn should_trace_failed_create_transaction() { let mut info = EnvInfo::default(); info.gas_limit = x!(1_000_000); - let engine = TestEngine::new(5, Factory::default()); + let engine = TestEngine::new(5); let t = Transaction { nonce: x!(0), @@ -450,7 +451,8 @@ fn should_trace_failed_create_transaction() { }.sign(&"".sha3()); state.add_balance(t.sender().as_ref().unwrap(), &x!(100)); - let result = state.apply(&info, &engine, &t, true).unwrap(); + let vm_factory = Default::default(); + let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { depth: 0, action: trace::Action::Create(trace::Create { @@ -475,7 +477,7 @@ fn should_trace_call_transaction() { let mut info = EnvInfo::default(); info.gas_limit = x!(1_000_000); - let engine = TestEngine::new(5, Factory::default()); + let engine = TestEngine::new(5); let t = Transaction { nonce: x!(0), @@ -488,7 +490,8 @@ fn should_trace_call_transaction() { state.init_code(&x!(0xa), FromHex::from_hex("6000").unwrap()); state.add_balance(t.sender().as_ref().unwrap(), &x!(100)); - let result = state.apply(&info, &engine, &t, true).unwrap(); + let vm_factory = Default::default(); + let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { depth: 0, action: trace::Action::Call(trace::Call { @@ -517,7 +520,7 @@ fn should_trace_basic_call_transaction() { let mut info = EnvInfo::default(); info.gas_limit = x!(1_000_000); - let engine = TestEngine::new(5, Factory::default()); + let engine = TestEngine::new(5); let t = Transaction { nonce: x!(0), @@ -529,7 +532,8 @@ fn should_trace_basic_call_transaction() { }.sign(&"".sha3()); state.add_balance(t.sender().as_ref().unwrap(), &x!(100)); - let result = state.apply(&info, &engine, &t, true).unwrap(); + let vm_factory = Default::default(); + let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { depth: 0, action: trace::Action::Call(trace::Call { @@ -569,7 +573,8 @@ fn should_trace_call_transaction_to_builtin() { data: vec![], }.sign(&"".sha3()); - let result = state.apply(&info, engine.deref(), &t, true).unwrap(); + let vm_factory = Default::default(); + let result = state.apply(&info, engine.deref(), &vm_factory, &t, true).unwrap(); assert_eq!(result.trace, Some(Trace { depth: 0, @@ -609,7 +614,8 @@ fn should_not_trace_subcall_transaction_to_builtin() { }.sign(&"".sha3()); state.init_code(&x!(0xa), FromHex::from_hex("600060006000600060006001610be0f1").unwrap()); - let result = state.apply(&info, engine.deref(), &t, true).unwrap(); + let vm_factory = Default::default(); + let result = state.apply(&info, engine.deref(), &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { depth: 0, @@ -651,7 +657,8 @@ fn should_not_trace_callcode() { state.init_code(&x!(0xa), FromHex::from_hex("60006000600060006000600b611000f2").unwrap()); state.init_code(&x!(0xb), FromHex::from_hex("6000").unwrap()); - let result = state.apply(&info, engine.deref(), &t, true).unwrap(); + let vm_factory = Default::default(); + let result = state.apply(&info, engine.deref(), &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { depth: 0, @@ -696,7 +703,8 @@ fn should_not_trace_delegatecall() { state.init_code(&x!(0xa), FromHex::from_hex("6000600060006000600b618000f4").unwrap()); state.init_code(&x!(0xb), FromHex::from_hex("6000").unwrap()); - let result = state.apply(&info, engine.deref(), &t, true).unwrap(); + let vm_factory = Default::default(); + let result = state.apply(&info, engine.deref(), &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { depth: 0, @@ -725,7 +733,7 @@ fn should_trace_failed_call_transaction() { let mut info = EnvInfo::default(); info.gas_limit = x!(1_000_000); - let engine = TestEngine::new(5, Factory::default()); + let engine = TestEngine::new(5); let t = Transaction { nonce: x!(0), @@ -738,7 +746,8 @@ fn should_trace_failed_call_transaction() { state.init_code(&x!(0xa), FromHex::from_hex("5b600056").unwrap()); state.add_balance(t.sender().as_ref().unwrap(), &x!(100)); - let result = state.apply(&info, &engine, &t, true).unwrap(); + let vm_factory = Default::default(); + let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { depth: 0, action: trace::Action::Call(trace::Call { @@ -766,7 +775,7 @@ fn should_trace_call_with_subcall_transaction() { let mut info = EnvInfo::default(); info.gas_limit = x!(1_000_000); - let engine = TestEngine::new(5, Factory::default()); + let engine = TestEngine::new(5); let t = Transaction { nonce: x!(0), @@ -780,7 +789,8 @@ fn should_trace_call_with_subcall_transaction() { state.init_code(&x!(0xa), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap()); state.init_code(&x!(0xb), FromHex::from_hex("6000").unwrap()); state.add_balance(t.sender().as_ref().unwrap(), &x!(100)); - let result = state.apply(&info, &engine, &t, true).unwrap(); + let vm_factory = Default::default(); + let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { depth: 0, action: trace::Action::Call(trace::Call { @@ -823,7 +833,7 @@ fn should_trace_call_with_basic_subcall_transaction() { let mut info = EnvInfo::default(); info.gas_limit = x!(1_000_000); - let engine = TestEngine::new(5, Factory::default()); + let engine = TestEngine::new(5); let t = Transaction { nonce: x!(0), @@ -836,7 +846,8 @@ fn should_trace_call_with_basic_subcall_transaction() { state.init_code(&x!(0xa), FromHex::from_hex("60006000600060006045600b6000f1").unwrap()); state.add_balance(t.sender().as_ref().unwrap(), &x!(100)); - let result = state.apply(&info, &engine, &t, true).unwrap(); + let vm_factory = Default::default(); + let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { depth: 0, action: trace::Action::Call(trace::Call { @@ -876,7 +887,7 @@ fn should_not_trace_call_with_invalid_basic_subcall_transaction() { let mut info = EnvInfo::default(); info.gas_limit = x!(1_000_000); - let engine = TestEngine::new(5, Factory::default()); + let engine = TestEngine::new(5); let t = Transaction { nonce: x!(0), @@ -889,7 +900,8 @@ fn should_not_trace_call_with_invalid_basic_subcall_transaction() { state.init_code(&x!(0xa), FromHex::from_hex("600060006000600060ff600b6000f1").unwrap()); // not enough funds. state.add_balance(t.sender().as_ref().unwrap(), &x!(100)); - let result = state.apply(&info, &engine, &t, true).unwrap(); + let vm_factory = Default::default(); + let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { depth: 0, action: trace::Action::Call(trace::Call { @@ -918,7 +930,7 @@ fn should_trace_failed_subcall_transaction() { let mut info = EnvInfo::default(); info.gas_limit = x!(1_000_000); - let engine = TestEngine::new(5, Factory::default()); + let engine = TestEngine::new(5); let t = Transaction { nonce: x!(0), @@ -932,7 +944,8 @@ fn should_trace_failed_subcall_transaction() { state.init_code(&x!(0xa), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap()); state.init_code(&x!(0xb), FromHex::from_hex("5b600056").unwrap()); state.add_balance(t.sender().as_ref().unwrap(), &x!(100)); - let result = state.apply(&info, &engine, &t, true).unwrap(); + let vm_factory = Default::default(); + let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { depth: 0, action: trace::Action::Call(trace::Call { @@ -972,7 +985,7 @@ fn should_trace_call_with_subcall_with_subcall_transaction() { let mut info = EnvInfo::default(); info.gas_limit = x!(1_000_000); - let engine = TestEngine::new(5, Factory::default()); + let engine = TestEngine::new(5); let t = Transaction { nonce: x!(0), @@ -987,7 +1000,8 @@ fn should_trace_call_with_subcall_with_subcall_transaction() { state.init_code(&x!(0xb), FromHex::from_hex("60006000600060006000600c602b5a03f1").unwrap()); state.init_code(&x!(0xc), FromHex::from_hex("6000").unwrap()); state.add_balance(t.sender().as_ref().unwrap(), &x!(100)); - let result = state.apply(&info, &engine, &t, true).unwrap(); + let vm_factory = Default::default(); + let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { depth: 0, action: trace::Action::Call(trace::Call { @@ -1044,7 +1058,7 @@ fn should_trace_failed_subcall_with_subcall_transaction() { let mut info = EnvInfo::default(); info.gas_limit = x!(1_000_000); - let engine = TestEngine::new(5, Factory::default()); + let engine = TestEngine::new(5); let t = Transaction { nonce: x!(0), @@ -1059,7 +1073,8 @@ fn should_trace_failed_subcall_with_subcall_transaction() { state.init_code(&x!(0xb), FromHex::from_hex("60006000600060006000600c602b5a03f1505b601256").unwrap()); state.init_code(&x!(0xc), FromHex::from_hex("6000").unwrap()); state.add_balance(t.sender().as_ref().unwrap(), &x!(100)); - let result = state.apply(&info, &engine, &t, true).unwrap(); + let vm_factory = Default::default(); + let result = state.apply(&info, &engine, &vm_factory, &t, true).unwrap(); let expected_trace = Some(Trace { depth: 0, action: trace::Action::Call(trace::Call { diff --git a/ethcore/src/tests/helpers.rs b/ethcore/src/tests/helpers.rs index 56e33d76b..6885a674b 100644 --- a/ethcore/src/tests/helpers.rs +++ b/ethcore/src/tests/helpers.rs @@ -19,7 +19,7 @@ use common::*; use spec::*; use blockchain::{BlockChain, BlockChainConfig}; use state::*; -use evm::{Schedule, Factory}; +use evm::Schedule; use engine::*; use ethereum; use devtools::*; @@ -51,15 +51,13 @@ impl GuardedTempResult { } pub struct TestEngine { - factory: Factory, engine: Box, max_depth: usize } impl TestEngine { - pub fn new(max_depth: usize, factory: Factory) -> TestEngine { + pub fn new(max_depth: usize) -> TestEngine { TestEngine { - factory: factory, engine: ethereum::new_frontier_test().engine, max_depth: max_depth } @@ -79,10 +77,6 @@ impl Engine for TestEngine { self.engine.builtins() } - 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; diff --git a/miner/src/miner.rs b/miner/src/miner.rs index 33d21613f..35056bc03 100644 --- a/miner/src/miner.rs +++ b/miner/src/miner.rs @@ -113,7 +113,7 @@ impl Miner { // add transactions to old_block let e = chain.engine(); let mut invalid_transactions = HashSet::new(); - let mut block = old_block.reopen(e); + let mut block = old_block.reopen(e, chain.vm_factory()); let block_number = block.block().fields().header.number(); // TODO: push new uncles, too. @@ -267,7 +267,7 @@ impl MinerService for Miner { state.sub_balance(&sender, &balance); state.add_balance(&sender, &U256::max_value()); let options = TransactOptions { tracing: false, check_nonce: false }; - Executive::new(&mut state, &env_info, chain.engine()).transact(t, options) + Executive::new(&mut state, &env_info, chain.engine(), chain.vm_factory()).transact(t, options) }, None => { chain.call(t) diff --git a/parity/cli.rs b/parity/cli.rs index 90d7167dc..a33e53aeb 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -140,6 +140,9 @@ Footprint Options: the entire system, overrides other cache and queue options. +Virtual Machine Options: + --jitvm Enable the JIT VM. + Legacy Options: --geth Run in Geth-compatibility mode. Currently just sets the IPC path to be the same as Geth's. Overrides @@ -222,6 +225,7 @@ pub struct Args { pub flag_tx_limit: usize, pub flag_logging: Option, pub flag_version: bool, + pub flag_jitvm: bool, // legacy... pub flag_geth: bool, pub flag_nodekey: Option, diff --git a/parity/configuration.rs b/parity/configuration.rs index 92d69b068..fe9a7131b 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -26,7 +26,7 @@ use die::*; use util::*; use util::keys::store::AccountService; use util::network_settings::NetworkSettings; -use ethcore::client::{append_path, get_db_path, ClientConfig, Switch}; +use ethcore::client::{append_path, get_db_path, ClientConfig, Switch, VMType}; use ethcore::ethereum; use ethcore::spec::Spec; use ethsync::SyncConfig; @@ -201,6 +201,7 @@ impl Configuration { pub fn client_config(&self, spec: &Spec) -> ClientConfig { let mut client_config = ClientConfig::default(); + match self.args.flag_cache { Some(mb) => { client_config.blockchain.max_cache_size = mb * 1024 * 1024; @@ -211,12 +212,14 @@ impl Configuration { client_config.blockchain.max_cache_size = self.args.flag_cache_max_size; } } + client_config.tracing.enabled = match self.args.flag_tracing.as_str() { "auto" => Switch::Auto, "on" => Switch::On, "off" => Switch::Off, _ => { die!("Invalid tracing method given!") } }; + client_config.pruning = match self.args.flag_pruning.as_str() { "archive" => journaldb::Algorithm::Archive, "light" => journaldb::Algorithm::EarlyMerge, @@ -225,6 +228,11 @@ impl Configuration { "auto" => self.find_best_db(spec).unwrap_or(journaldb::Algorithm::OverlayRecent), _ => { die!("Invalid pruning method given."); } }; + + if self.args.flag_jitvm { + client_config.vm_type = VMType::jit().unwrap_or_else(|| die!("Parity built without jit vm.")) + } + trace!(target: "parity", "Using pruning strategy of {}", client_config.pruning); client_config.name = self.args.flag_identity.clone(); client_config.queue.max_mem_use = self.args.flag_queue_max_size;