diff --git a/Cargo.lock b/Cargo.lock index b0c9e5eb3..932b077fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -356,10 +356,15 @@ dependencies = [ "jsonrpc-core 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-http-server 5.1.0 (git+https://github.com/ethcore/jsonrpc-http-server.git)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-idmanager 0.1.3 (git+https://github.com/ethcore/parity-idmanager-rs.git)", - "parity-status 0.4.1 (git+https://github.com/ethcore/parity-status.git)", - "parity-wallet 0.3.0 (git+https://github.com/ethcore/parity-wallet.git)", - "parity-webapp 0.1.0 (git+https://github.com/ethcore/parity-webapp.git)", + "parity-idmanager 0.2.2 (git+https://github.com/ethcore/parity-idmanager-rs.git)", + "parity-status 0.4.3 (git+https://github.com/ethcore/parity-status.git)", + "parity-wallet 0.4.0 (git+https://github.com/ethcore/parity-wallet.git)", + "parity-webapp 0.2.0 (git+https://github.com/ethcore/parity-webapp.git)", + "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -831,32 +836,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "parity-idmanager" -version = "0.1.3" -source = "git+https://github.com/ethcore/parity-idmanager-rs.git#efb69592b87854f41d8882de75982c8f1e748666" +version = "0.2.2" +source = "git+https://github.com/ethcore/parity-idmanager-rs.git#e93ef48a78722561d52ab88c3dfcc5c1465558ac" dependencies = [ - "parity-webapp 0.1.0 (git+https://github.com/ethcore/parity-webapp.git)", + "parity-webapp 0.2.0 (git+https://github.com/ethcore/parity-webapp.git)", ] [[package]] name = "parity-status" -version = "0.4.1" -source = "git+https://github.com/ethcore/parity-status.git#f121ebd1f49986545d9fc262ba210cdf07039e6d" +version = "0.4.3" +source = "git+https://github.com/ethcore/parity-status.git#1d383d74010f6ebcd712b60b8fc5ff547b44f4e5" dependencies = [ - "parity-webapp 0.1.0 (git+https://github.com/ethcore/parity-webapp.git)", + "parity-webapp 0.2.0 (git+https://github.com/ethcore/parity-webapp.git)", ] [[package]] name = "parity-wallet" -version = "0.3.0" -source = "git+https://github.com/ethcore/parity-wallet.git#664fd2b85dd94ca184868bd3965e14a4ba68c03f" +version = "0.4.0" +source = "git+https://github.com/ethcore/parity-wallet.git#5391a89dc5dbf162d1beeba555f03c24bfd619bd" dependencies = [ - "parity-webapp 0.1.0 (git+https://github.com/ethcore/parity-webapp.git)", + "parity-webapp 0.2.0 (git+https://github.com/ethcore/parity-webapp.git)", ] [[package]] name = "parity-webapp" -version = "0.1.0" -source = "git+https://github.com/ethcore/parity-webapp.git#0bf133f193863ba0e88b0b824a5c330037cce3f1" +version = "0.2.0" +source = "git+https://github.com/ethcore/parity-webapp.git#f31681af69631bcadfbef89a7e60dcc49552f7c6" [[package]] name = "primal" diff --git a/ethcore/src/account.rs b/ethcore/src/account.rs index f2942a7e1..66cceda42 100644 --- a/ethcore/src/account.rs +++ b/ethcore/src/account.rs @@ -342,7 +342,6 @@ mod tests { #[test] fn new_account() { - use rustc_serialize::hex::ToHex; let a = Account::new(U256::from(69u8), U256::from(0u8), HashMap::new(), Bytes::new()); assert_eq!(a.rlp().to_hex(), "f8448045a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"); @@ -354,7 +353,6 @@ mod tests { #[test] fn create_account() { - use rustc_serialize::hex::ToHex; let a = Account::new(U256::from(69u8), U256::from(0u8), HashMap::new(), Bytes::new()); assert_eq!(a.rlp().to_hex(), "f8448045a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"); diff --git a/ethcore/src/basic_authority.rs b/ethcore/src/basic_authority.rs index e1dab7c17..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() } @@ -200,7 +196,6 @@ mod tests { use super::*; use common::*; use block::*; - use engine::*; use tests::helpers::*; use util::keys::{TestAccountProvider, TestAccount}; @@ -211,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; @@ -288,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..654cf97f5 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. @@ -430,8 +433,8 @@ impl BlockChainClient for Client where V: Verifier { block.try_seal(self.engine.deref().deref(), seal) } - fn engine(&self) -> &Engine { - self.engine.deref().deref() + fn vm_factory(&self) -> &EvmFactory { + &self.vm_factory } // TODO [todr] Should be moved to miner crate eventually. @@ -443,6 +446,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..97b75547c 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; @@ -33,18 +33,17 @@ use std::collections::HashSet; use util::bytes::Bytes; use util::hash::{Address, H256, H2048}; use util::numbers::U256; -use util::keys::store::AccountProvider; use blockchain::TreeRoute; use block_queue::BlockQueueInfo; -use block::{ExecutedBlock, ClosedBlock, LockedBlock, SealedBlock}; +use block::{ClosedBlock, LockedBlock, SealedBlock}; use header::{BlockNumber, Header}; use transaction::{LocalizedTransaction, SignedTransaction}; use log_entry::LocalizedLogEntry; use filter::Filter; 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 { @@ -134,11 +133,8 @@ pub trait BlockChainClient : Sync + Send { /// Makes a non-persistent transaction call. fn call(&self, t: &SignedTransaction) -> Result; - /// Attempt to seal the block internally. See `Engine`. - fn generate_seal(&self, block: &ExecutedBlock, accounts: Option<&AccountProvider>) -> Option> { self.engine().generate_seal(block, accounts) } - - /// 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..279d4c0bc 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -27,12 +27,12 @@ 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}; use executive::Executed; use error::{ExecutionError}; -use engine::Engine; use trace::LocalizedTrace; /// Test client. @@ -430,7 +430,7 @@ impl BlockChainClient for TestBlockChainClient { } } - fn engine(&self) -> &Engine { + fn vm_factory(&self) -> &EvmFactory { unimplemented!(); } diff --git a/ethcore/src/engine.rs b/ethcore/src/engine.rs index 344144c6e..ed482db89 100644 --- a/ethcore/src/engine.rs +++ b/ethcore/src/engine.rs @@ -14,11 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +//! Consensus engine specification + 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 +39,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 11b13c0c1..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(), } } } @@ -93,10 +91,8 @@ impl Engine for Ethash { } /// Additional engine-specific information for the user/developer concerning `header`. - fn extra_info(&self, _header: &Header) -> HashMap { HashMap::new() } - - fn vm_factory(&self) -> &Factory { - &self.factory + fn extra_info(&self, header: &Header) -> HashMap { + hash_map!["nonce".to_owned() => format!("0x{}", header.nonce().hex()), "mixHash".to_owned() => format!("0x{}", header.mix_hash().hex())] } fn schedule(&self, env_info: &EnvInfo) -> Schedule { @@ -299,7 +295,6 @@ mod tests { use common::*; use block::*; - use engine::*; use tests::helpers::*; use super::super::new_morden; @@ -312,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()); } @@ -326,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(); @@ -344,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/ethereum/mod.rs b/ethcore/src/ethereum/mod.rs index 4cc98ee2b..1f5712c54 100644 --- a/ethcore/src/ethereum/mod.rs +++ b/ethcore/src/ethereum/mod.rs @@ -51,7 +51,6 @@ pub fn new_morden() -> Spec { Spec::load(include_bytes!("../../res/ethereum/mord mod tests { use common::*; use state::*; - use engine::*; use super::*; use tests::helpers::*; 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/lib.rs b/ethcore/src/lib.rs index f443647bd..c5fae168e 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -107,6 +107,7 @@ pub mod trace; pub mod spec; pub mod views; pub mod pod_state; +pub mod engine; mod db; mod common; @@ -116,7 +117,6 @@ mod env_info; mod pod_account; mod account_diff; mod state_diff; -mod engine; mod state; mod account; mod account_db; 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 c44614550..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())); @@ -358,12 +359,9 @@ mod tests { use super::*; use util::common::*; -use util::trie::*; -use util::rlp::*; use account::*; use tests::helpers::*; use devtools::*; -use evm::factory::*; use env_info::*; use spec::*; use transaction::*; @@ -380,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), @@ -392,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 { @@ -440,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), @@ -452,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 { @@ -477,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), @@ -490,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 { @@ -519,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), @@ -531,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 { @@ -571,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, @@ -611,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, @@ -653,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, @@ -698,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, @@ -727,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), @@ -740,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 { @@ -768,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), @@ -782,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 { @@ -825,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), @@ -838,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 { @@ -878,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), @@ -891,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 { @@ -920,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), @@ -934,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 { @@ -974,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), @@ -989,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 { @@ -1046,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), @@ -1061,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/ethcore/src/trace/db.rs b/ethcore/src/trace/db.rs index 5c88ee52b..a69a1ca27 100644 --- a/ethcore/src/trace/db.rs +++ b/ethcore/src/trace/db.rs @@ -22,7 +22,7 @@ use std::sync::{RwLock, Arc}; use std::path::Path; use bloomchain::{Number, Config as BloomConfig}; use bloomchain::group::{BloomGroupDatabase, BloomGroupChain, GroupPosition, BloomGroup}; -use util::{FixedHash, H256, H264, Database, DBTransaction}; +use util::{H256, H264, Database, DBTransaction}; use header::BlockNumber; use trace::{BlockTraces, LocalizedTrace, Config, Switch, Filter, Database as TraceDatabase, ImportRequest, DatabaseExtras}; diff --git a/ethcore/src/types/ids.rs b/ethcore/src/types/ids.rs index 8fffcb8f7..3390f020e 100644 --- a/ethcore/src/types/ids.rs +++ b/ethcore/src/types/ids.rs @@ -19,7 +19,6 @@ use util::hash::H256; use header::BlockNumber; use ipc::binary::BinaryConvertError; -use ipc::binary::BinaryConvertable; use std::mem; use std::collections::VecDeque; diff --git a/ipc/codegen/src/codegen.rs b/ipc/codegen/src/codegen.rs index 6f16994b6..362257fcf 100644 --- a/ipc/codegen/src/codegen.rs +++ b/ipc/codegen/src/codegen.rs @@ -33,7 +33,6 @@ use syntax::ast::{ use syntax::ast; use syntax::codemap::Span; use syntax::ext::base::{Annotatable, ExtCtxt}; -use syntax::ext::build::AstBuilder; use syntax::ptr::P; pub struct Error; diff --git a/ipc/codegen/src/serialization.rs b/ipc/codegen/src/serialization.rs index e8f3d2cd8..8cd9ffdca 100644 --- a/ipc/codegen/src/serialization.rs +++ b/ipc/codegen/src/serialization.rs @@ -252,14 +252,14 @@ fn binary_expr_struct( map_stmts.push(quote_stmt!(cx, map[$field_index] = total;).unwrap()); if ::syntax::print::pprust::ty_to_string(&codegen::strip_ptr(&field.ty)) == "u8" { - map_stmts.push(quote_stmt!(cx, total = total + 1;).unwrap()); + map_stmts.push(quote_stmt!(cx, total += 1;).unwrap()); } else { map_stmts.push(quote_stmt!(cx, let size = match $field_type_ident_qualified::len_params() { 0 => mem::size_of::<$field_type_ident>(), _ => length_stack.pop_front().unwrap(), }).unwrap()); - map_stmts.push(quote_stmt!(cx, total = total + size;).unwrap()); + map_stmts.push(quote_stmt!(cx, total += size;).unwrap()); } }; diff --git a/miner/src/miner.rs b/miner/src/miner.rs index 33d21613f..e989fce90 100644 --- a/miner/src/miner.rs +++ b/miner/src/miner.rs @@ -25,6 +25,8 @@ use ethcore::block::{ClosedBlock, IsBlock}; use ethcore::error::*; use ethcore::client::{Executive, Executed, EnvInfo, TransactOptions}; use ethcore::transaction::SignedTransaction; +use ethcore::spec::Spec; +use ethcore::engine::Engine; use super::{MinerService, MinerStatus, TransactionQueue, AccountDetails, TransactionImportResult, TransactionOrigin}; /// Keeps track of transactions using priority queue and holds currently mined block. @@ -39,6 +41,7 @@ pub struct Miner { gas_floor_target: RwLock, author: RwLock
, extra_data: RwLock, + spec: Spec, accounts: RwLock>>, // TODO: this is horrible since AccountService already contains a single RwLock field. refactor. } @@ -55,13 +58,14 @@ impl Default for Miner { author: RwLock::new(Address::default()), extra_data: RwLock::new(Vec::new()), accounts: RwLock::new(None), + spec: Spec::new_test(), } } } impl Miner { /// Creates new instance of miner - pub fn new(force_sealing: bool) -> Arc { + pub fn new(force_sealing: bool, spec: Spec) -> Arc { Arc::new(Miner { transaction_queue: Mutex::new(TransactionQueue::new()), force_sealing: force_sealing, @@ -72,11 +76,12 @@ impl Miner { author: RwLock::new(Address::default()), extra_data: RwLock::new(Vec::new()), accounts: RwLock::new(None), + spec: spec, }) } /// Creates new instance of miner - pub fn with_accounts(force_sealing: bool, accounts: Arc) -> Arc { + pub fn with_accounts(force_sealing: bool, spec: Spec, accounts: Arc) -> Arc { Arc::new(Miner { transaction_queue: Mutex::new(TransactionQueue::new()), force_sealing: force_sealing, @@ -87,9 +92,14 @@ impl Miner { author: RwLock::new(Address::default()), extra_data: RwLock::new(Vec::new()), accounts: RwLock::new(Some(accounts)), + spec: spec, }) } + fn engine(&self) -> &Engine { + self.spec.engine.deref() + } + /// Prepares new block for sealing including top transactions from queue. #[cfg_attr(feature="dev", allow(match_same_arms))] fn prepare_sealing(&self, chain: &BlockChainClient) { @@ -111,9 +121,9 @@ impl Miner { Some(old_block) => { trace!(target: "miner", "Already have previous work; updating and returning"); // add transactions to old_block - let e = chain.engine(); + let e = self.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. @@ -166,7 +176,7 @@ impl Miner { trace!(target: "miner", "prepare_sealing: block has transaction - attempting internal seal."); // block with transactions - see if we can seal immediately. let a = self.accounts.read().unwrap(); - let s = chain.generate_seal(block.block(), match *a.deref() { + let s = self.engine().generate_seal(block.block(), match *a.deref() { Some(ref x) => Some(x.deref() as &AccountProvider), None => None, }); @@ -267,7 +277,8 @@ 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, self.engine(), chain.vm_factory()).transact(t, options) }, None => { chain.call(t) diff --git a/miner/src/transaction_queue.rs b/miner/src/transaction_queue.rs index 987dfde50..fc62c411e 100644 --- a/miner/src/transaction_queue.rs +++ b/miner/src/transaction_queue.rs @@ -535,12 +535,12 @@ impl TransactionQueue { /// Update height of all transactions in future transactions set. fn update_future(&mut self, sender: &Address, current_nonce: U256) { // We need to drain all transactions for current sender from future and reinsert them with updated height - let all_nonces_from_sender = match self.future.by_address.row(&sender) { + let all_nonces_from_sender = match self.future.by_address.row(sender) { Some(row_map) => row_map.keys().cloned().collect::>(), None => vec![], }; for k in all_nonces_from_sender { - let order = self.future.drop(&sender, &k).unwrap(); + let order = self.future.drop(sender, &k).unwrap(); if k >= current_nonce { self.future.insert(*sender, k, order.update_height(k, current_nonce)); } else { @@ -554,14 +554,14 @@ impl TransactionQueue { /// Drop all transactions from given sender from `current`. /// Either moves them to `future` or removes them from queue completely. fn move_all_to_future(&mut self, sender: &Address, current_nonce: U256) { - let all_nonces_from_sender = match self.current.by_address.row(&sender) { + let all_nonces_from_sender = match self.current.by_address.row(sender) { Some(row_map) => row_map.keys().cloned().collect::>(), None => vec![], }; for k in all_nonces_from_sender { // Goes to future or is removed - let order = self.current.drop(&sender, &k).unwrap(); + let order = self.current.drop(sender, &k).unwrap(); if k >= current_nonce { self.future.insert(*sender, k, order.update_height(k, current_nonce)); } else { @@ -803,7 +803,7 @@ mod test { fn new_tx() -> SignedTransaction { let keypair = KeyPair::create().unwrap(); - new_unsigned_tx(U256::from(123)).sign(&keypair.secret()) + new_unsigned_tx(U256::from(123)).sign(keypair.secret()) } @@ -1173,9 +1173,9 @@ mod test { let mut txq = TransactionQueue::new(); let kp = KeyPair::create().unwrap(); let secret = kp.secret(); - let tx = new_unsigned_tx(U256::from(123)).sign(&secret); - let tx1 = new_unsigned_tx(U256::from(124)).sign(&secret); - let tx2 = new_unsigned_tx(U256::from(125)).sign(&secret); + let tx = new_unsigned_tx(U256::from(123)).sign(secret); + let tx1 = new_unsigned_tx(U256::from(124)).sign(secret); + let tx2 = new_unsigned_tx(U256::from(125)).sign(secret); txq.add(tx, &default_nonce, TransactionOrigin::External).unwrap(); assert_eq!(txq.status().pending, 1); @@ -1403,11 +1403,11 @@ mod test { // given let mut txq = TransactionQueue::new(); let keypair = KeyPair::create().unwrap(); - let tx = new_unsigned_tx(U256::from(123)).sign(&keypair.secret()); + let tx = new_unsigned_tx(U256::from(123)).sign(keypair.secret()); let tx2 = { let mut tx2 = tx.deref().clone(); tx2.gas_price = U256::from(200); - tx2.sign(&keypair.secret()) + tx2.sign(keypair.secret()) }; // when @@ -1426,16 +1426,16 @@ mod test { // given let mut txq = TransactionQueue::new(); let keypair = KeyPair::create().unwrap(); - let tx0 = new_unsigned_tx(U256::from(123)).sign(&keypair.secret()); + let tx0 = new_unsigned_tx(U256::from(123)).sign(keypair.secret()); let tx1 = { let mut tx1 = tx0.deref().clone(); tx1.nonce = U256::from(124); - tx1.sign(&keypair.secret()) + tx1.sign(keypair.secret()) }; let tx2 = { let mut tx2 = tx1.deref().clone(); tx2.gas_price = U256::from(200); - tx2.sign(&keypair.secret()) + tx2.sign(keypair.secret()) }; // when 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 ba7789c08..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; @@ -171,7 +171,7 @@ impl Configuration { let (listen, public) = self.net_addresses(); ret.listen_address = listen; ret.public_address = public; - ret.use_secret = self.args.flag_node_key.as_ref().map(|s| Secret::from_str(&s).unwrap_or_else(|_| s.sha3())); + ret.use_secret = self.args.flag_node_key.as_ref().map(|s| Secret::from_str(s).unwrap_or_else(|_| s.sha3())); ret.discovery_enabled = !self.args.flag_no_discovery && !self.args.flag_nodiscover; ret.ideal_peers = self.max_peers(); let mut net_path = PathBuf::from(&self.path()); @@ -185,7 +185,7 @@ impl Configuration { let mut latest_era = None; let jdb_types = [journaldb::Algorithm::Archive, journaldb::Algorithm::EarlyMerge, journaldb::Algorithm::OverlayRecent, journaldb::Algorithm::RefCounted]; for i in jdb_types.into_iter() { - let db = journaldb::new(&append_path(&get_db_path(&Path::new(&self.path()), *i, spec.genesis_header().hash()), "state"), *i); + let db = journaldb::new(&append_path(&get_db_path(Path::new(&self.path()), *i, spec.genesis_header().hash()), "state"), *i); trace!(target: "parity", "Looking for best DB: {} at {:?}", i, db.latest_era()); match (latest_era, db.latest_era()) { (Some(best), Some(this)) if best >= this => {} @@ -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; @@ -251,7 +259,7 @@ impl Configuration { let account_service = AccountService::with_security(Path::new(&self.keys_path()), self.keys_iterations()); if let Some(ref unlocks) = self.args.flag_unlock { for d in unlocks.split(',') { - let a = Address::from_str(clean_0x(&d)).unwrap_or_else(|_| { + let a = Address::from_str(clean_0x(d)).unwrap_or_else(|_| { die!("{}: Invalid address for --unlock. Must be 40 hex characters, without the 0x at the beginning.", d) }); if passwords.iter().find(|p| account_service.unlock_account_no_expire(&a, p).is_ok()).is_none() { @@ -302,7 +310,7 @@ impl Configuration { pub fn directories(&self) -> Directories { let db_path = Configuration::replace_home( - &self.args.flag_datadir.as_ref().unwrap_or(&self.args.flag_db_path)); + self.args.flag_datadir.as_ref().unwrap_or(&self.args.flag_db_path)); ::std::fs::create_dir_all(&db_path).unwrap_or_else(|e| die_with_io_error("main", e)); let keys_path = Configuration::replace_home(&self.args.flag_keys_path); diff --git a/parity/hypervisor/service.rs.in b/parity/hypervisor/service.rs.in index a8ad90e12..12c39d90a 100644 --- a/parity/hypervisor/service.rs.in +++ b/parity/hypervisor/service.rs.in @@ -18,7 +18,6 @@ use std::sync::{RwLock,Arc}; use std::ops::*; use ipc::IpcConfig; use std::collections::HashMap; -use ipc::BinaryConvertable; use std::mem; use ipc::binary::BinaryConvertError; use std::collections::VecDeque; diff --git a/parity/main.rs b/parity/main.rs index dd70d39cc..a2750dff4 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -138,14 +138,14 @@ fn execute_client(conf: Configuration) { // Build client let mut service = ClientService::start( - client_config, spec, net_settings, &Path::new(&conf.path()) + client_config, spec, net_settings, Path::new(&conf.path()) ).unwrap_or_else(|e| die_with_error("Client", e)); panic_handler.forward_from(&service); let client = service.client(); // Miner - let miner = Miner::with_accounts(conf.args.flag_force_sealing, account_service.clone()); + let miner = Miner::with_accounts(conf.args.flag_force_sealing, conf.spec(), account_service.clone()); miner.set_author(conf.author()); miner.set_gas_floor_target(conf.gas_floor_target()); miner.set_extra_data(conf.extra_data()); diff --git a/parity/price_info.rs b/parity/price_info.rs index 05b89d848..ad25f31da 100644 --- a/parity/price_info.rs +++ b/parity/price_info.rs @@ -37,7 +37,7 @@ impl PriceInfo { .and_then(|json| json.find_path(&["result", "ethusd"]) .and_then(|obj| match *obj { Json::String(ref s) => Some(PriceInfo { - ethusd: FromStr::from_str(&s).unwrap() + ethusd: FromStr::from_str(s).unwrap() }), _ => None })) diff --git a/parity/setup_log.rs b/parity/setup_log.rs index 75cd0f574..0fbc76fb3 100644 --- a/parity/setup_log.rs +++ b/parity/setup_log.rs @@ -31,7 +31,7 @@ pub fn setup_log(init: &Option) -> Arc { if env::var("RUST_LOG").is_ok() { let lvl = &env::var("RUST_LOG").unwrap(); - levels.push_str(&lvl); + levels.push_str(lvl); levels.push_str(","); builder.parse(lvl); } diff --git a/parity/upgrade.rs b/parity/upgrade.rs index 30c977df4..e976535b0 100644 --- a/parity/upgrade.rs +++ b/parity/upgrade.rs @@ -87,7 +87,7 @@ fn upgrade_from_version(previous_version: &Version) -> Result { if upgrade_key.is_applicable(previous_version, ¤t_version) { let upgrade_script = upgrades[upgrade_key]; try!(upgrade_script()); - count = count + 1; + count += 1; } } Ok(count) diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 6fddf7b4f..6222d000d 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -27,7 +27,7 @@ use jsonrpc_core::*; use util::numbers::*; use util::sha3::*; use util::bytes::{ToPretty}; -use util::rlp::{encode, UntrustedRlp, View}; +use util::rlp::{encode, decode, UntrustedRlp, View}; use ethcore::client::*; use ethcore::block::IsBlock; use ethcore::views::*; @@ -97,7 +97,7 @@ impl EthClient timestamp: U256::from(view.timestamp()), difficulty: view.difficulty(), total_difficulty: total_difficulty, - seal_fields: view.seal().into_iter().map(Bytes::new).collect(), + seal_fields: view.seal().into_iter().map(|f| decode(&f)).map(Bytes::new).collect(), uncles: block_view.uncle_hashes(), transactions: { if include_txs { @@ -142,7 +142,7 @@ impl EthClient total_difficulty: uncle.difficulty + parent_difficulty, receipts_root: uncle.receipts_root, extra_data: Bytes::new(uncle.extra_data), - seal_fields: uncle.seal.into_iter().map(Bytes::new).collect(), + seal_fields: uncle.seal.into_iter().map(|f| decode(&f)).map(Bytes::new).collect(), uncles: vec![], transactions: BlockTransactions::Hashes(vec![]), }; diff --git a/sync/src/chain.rs b/sync/src/chain.rs index bd94fb9be..6d7a76572 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -791,8 +791,8 @@ impl ChainSync { self.downloading_hashes.remove(&hash); } for b in &peer.asking_blocks { - self.downloading_headers.remove(&b); - self.downloading_bodies.remove(&b); + self.downloading_headers.remove(b); + self.downloading_bodies.remove(b); } peer.asking_blocks.clear(); } @@ -1255,7 +1255,7 @@ impl ChainSync { self.send_packet(io, peer_id, NEW_BLOCK_PACKET, rlp); self.peers.get_mut(&peer_id).unwrap().latest_hash = chain_info.best_block_hash.clone(); self.peers.get_mut(&peer_id).unwrap().latest_number = Some(chain_info.best_block_number); - sent = sent + 1; + sent += 1; } sent } @@ -1271,7 +1271,7 @@ impl ChainSync { // If we think peer is too far behind just send one latest hash peer_best = last_parent.clone(); } - sent = sent + match ChainSync::create_new_hashes_rlp(io.chain(), &peer_best, &chain_info.best_block_hash) { + sent += match ChainSync::create_new_hashes_rlp(io.chain(), &peer_best, &chain_info.best_block_hash) { Some(rlp) => { { let peer = self.peers.get_mut(&peer_id).unwrap(); @@ -1668,7 +1668,7 @@ mod tests { sync.propagate_new_hashes(&chain_info, &mut io); let data = &io.queue[0].data.clone(); - let result = sync.on_peer_new_hashes(&mut io, 0, &UntrustedRlp::new(&data)); + let result = sync.on_peer_new_hashes(&mut io, 0, &UntrustedRlp::new(data)); assert!(result.is_ok()); } @@ -1686,7 +1686,7 @@ mod tests { sync.propagate_blocks(&chain_info, &mut io); let data = &io.queue[0].data.clone(); - let result = sync.on_peer_new_block(&mut io, 0, &UntrustedRlp::new(&data)); + let result = sync.on_peer_new_block(&mut io, 0, &UntrustedRlp::new(data)); assert!(result.is_ok()); } diff --git a/sync/src/lib.rs b/sync/src/lib.rs index 0b95f0b92..f1b1bb0b2 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -45,7 +45,7 @@ //! let mut service = NetworkService::start(NetworkConfiguration::new()).unwrap(); //! let dir = env::temp_dir(); //! let client = Client::new(ClientConfig::default(), ethereum::new_frontier(), &dir, service.io().channel()); -//! let miner = Miner::new(false); +//! let miner = Miner::new(false, ethereum::new_frontier()); //! EthSync::register(&mut service, SyncConfig::default(), client, miner); //! } //! ``` diff --git a/sync/src/range_collection.rs b/sync/src/range_collection.rs index 0628df401..6b57f0a4b 100644 --- a/sync/src/range_collection.rs +++ b/sync/src/range_collection.rs @@ -70,7 +70,7 @@ impl<'c, K:'c, V:'c> Iterator for RangeIterator<'c, K, V> where K: Add { - Some((*k, &vec)) + Some((*k, vec)) }, None => None } diff --git a/sync/src/tests/chain.rs b/sync/src/tests/chain.rs index eebbdb164..4ed25325b 100644 --- a/sync/src/tests/chain.rs +++ b/sync/src/tests/chain.rs @@ -16,7 +16,6 @@ use util::*; use ethcore::client::{BlockChainClient, BlockId, EachBlockWith}; -use io::SyncIo; use chain::{SyncState}; use super::helpers::*; diff --git a/sync/src/tests/helpers.rs b/sync/src/tests/helpers.rs index 269362064..461553924 100644 --- a/sync/src/tests/helpers.rs +++ b/sync/src/tests/helpers.rs @@ -16,6 +16,7 @@ use util::*; use ethcore::client::{TestBlockChainClient, BlockChainClient}; +use ethcore::spec::Spec; use io::SyncIo; use chain::ChainSync; use ethminer::Miner; @@ -93,7 +94,7 @@ impl TestNet { for _ in 0..n { net.peers.push(TestPeer { chain: TestBlockChainClient::new(), - sync: ChainSync::new(SyncConfig::default(), Miner::new(false)), + sync: ChainSync::new(SyncConfig::default(), Miner::new(false, Spec::new_test())), queue: VecDeque::new(), }); } @@ -147,7 +148,7 @@ impl TestNet { let mut total_steps = 0; while !self.done() { self.sync_step(); - total_steps = total_steps + 1; + total_steps += 1; } total_steps } diff --git a/webapp/Cargo.toml b/webapp/Cargo.toml index fe6fb9bf6..8f9353386 100644 --- a/webapp/Cargo.toml +++ b/webapp/Cargo.toml @@ -4,6 +4,7 @@ name = "ethcore-webapp" version = "1.2.0" license = "GPL-3.0" authors = ["Ethcore . + +#[cfg(not(feature = "serde_macros"))] +mod inner { + extern crate syntex; + extern crate serde_codegen; + + use std::env; + use std::path::Path; + + pub fn main() { + let out_dir = env::var_os("OUT_DIR").unwrap(); + + let src = Path::new("./src/api/mod.rs.in"); + let dst = Path::new(&out_dir).join("mod.rs"); + + let mut registry = syntex::Registry::new(); + + serde_codegen::register(&mut registry); + registry.expand("", &src, &dst).unwrap(); + } +} + +#[cfg(feature = "serde_macros")] +mod inner { + pub fn main() {} +} + +fn main() { + inner::main(); +} diff --git a/webapp/src/api.rs b/webapp/src/api/api.rs similarity index 59% rename from webapp/src/api.rs rename to webapp/src/api/api.rs index 75cdb4c58..fdfef1394 100644 --- a/webapp/src/api.rs +++ b/webapp/src/api/api.rs @@ -14,15 +14,26 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -//! Simple REST API - use std::sync::Arc; -use endpoint::{Endpoint, Endpoints, ContentHandler, Handler, EndpointPath}; +use endpoint::{Endpoint, Endpoints, Handler, EndpointPath}; + +use api::response::as_json; pub struct RestApi { endpoints: Arc, } +#[derive(Debug, PartialEq, Serialize)] +struct App { + pub id: String, + pub name: String, + pub description: String, + pub version: String, + pub author: String, + #[serde(rename="iconUrl")] + pub icon_url: String, +} + impl RestApi { pub fn new(endpoints: Arc) -> Box { Box::new(RestApi { @@ -30,20 +41,23 @@ impl RestApi { }) } - fn list_pages(&self) -> String { - let mut s = "[".to_owned(); - for name in self.endpoints.keys() { - s.push_str(&format!("\"{}\",", name)); - } - s.push_str("\"rpc\""); - s.push_str("]"); - s + fn list_apps(&self) -> Vec { + self.endpoints.iter().filter_map(|(ref k, ref e)| { + e.info().map(|ref info| App { + id: k.to_owned().clone(), + name: info.name.clone(), + description: info.description.clone(), + version: info.version.clone(), + author: info.author.clone(), + icon_url: info.icon_url.clone(), + }) + }).collect() } } impl Endpoint for RestApi { fn to_handler(&self, _path: EndpointPath) -> Box { - Box::new(ContentHandler::new(self.list_pages(), "application/json".to_owned())) + as_json(&self.list_apps()) } } diff --git a/webapp/src/api/mod.rs b/webapp/src/api/mod.rs new file mode 100644 index 000000000..088d7f6b2 --- /dev/null +++ b/webapp/src/api/mod.rs @@ -0,0 +1,28 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! REST API + +#![warn(missing_docs)] +#![cfg_attr(feature="nightly", feature(custom_derive, custom_attribute, plugin))] +#![cfg_attr(feature="nightly", plugin(serde_macros, clippy))] + +#[cfg(feature = "serde_macros")] +include!("mod.rs.in"); + +#[cfg(not(feature = "serde_macros"))] +include!(concat!(env!("OUT_DIR"), "/mod.rs")); + diff --git a/webapp/src/api/mod.rs.in b/webapp/src/api/mod.rs.in new file mode 100644 index 000000000..0eff6b397 --- /dev/null +++ b/webapp/src/api/mod.rs.in @@ -0,0 +1,20 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +mod api; +mod response; + +pub use self::api::RestApi; diff --git a/webapp/src/api/response.rs b/webapp/src/api/response.rs new file mode 100644 index 000000000..345b8a6ee --- /dev/null +++ b/webapp/src/api/response.rs @@ -0,0 +1,23 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use serde::Serialize; +use serde_json; +use endpoint::{ContentHandler, Handler}; + +pub fn as_json(val: &T) -> Box { + Box::new(ContentHandler::new(serde_json::to_string(val).unwrap(), "application/json".to_owned())) +} diff --git a/webapp/src/apps.rs b/webapp/src/apps.rs index 1c9b7e5a8..410a5bc2c 100644 --- a/webapp/src/apps.rs +++ b/webapp/src/apps.rs @@ -30,7 +30,7 @@ pub const API_PATH : &'static str = "api"; pub const UTILS_PATH : &'static str = "parity-utils"; pub fn main_page() -> &'static str { - "/status/" + "/home/" } pub fn utils() -> Box { @@ -43,6 +43,7 @@ pub fn all_endpoints() -> Endpoints { insert::(&mut pages, "status"); insert::(&mut pages, "parity"); + insert::(&mut pages, "home"); wallet_page(&mut pages); pages diff --git a/webapp/src/endpoint.rs b/webapp/src/endpoint.rs index d367734c4..ebb665b9d 100644 --- a/webapp/src/endpoint.rs +++ b/webapp/src/endpoint.rs @@ -30,7 +30,18 @@ pub struct EndpointPath { pub port: u16, } +#[derive(Debug, PartialEq)] +pub struct EndpointInfo { + pub name: String, + pub description: String, + pub version: String, + pub author: String, + pub icon_url: String, +} + pub trait Endpoint : Send + Sync { + fn info(&self) -> Option { None } + fn to_handler(&self, path: EndpointPath) -> Box>; } diff --git a/webapp/src/lib.rs b/webapp/src/lib.rs index 819e9d362..4cf8f0764 100644 --- a/webapp/src/lib.rs +++ b/webapp/src/lib.rs @@ -47,6 +47,8 @@ extern crate log; extern crate url; extern crate hyper; +extern crate serde; +extern crate serde_json; extern crate jsonrpc_core; extern crate jsonrpc_http_server; extern crate parity_webapp; diff --git a/webapp/src/page/mod.rs b/webapp/src/page/mod.rs index 1d987c393..c4e39161c 100644 --- a/webapp/src/page/mod.rs +++ b/webapp/src/page/mod.rs @@ -22,8 +22,8 @@ use hyper::header; use hyper::status::StatusCode; use hyper::net::HttpStream; use hyper::{Decoder, Encoder, Next}; -use endpoint::{Endpoint, EndpointPath}; -use parity_webapp::WebApp; +use endpoint::{Endpoint, EndpointInfo, EndpointPath}; +use parity_webapp::{WebApp, Info}; pub struct PageEndpoint { /// Content of the files @@ -39,6 +39,7 @@ impl PageEndpoint { prefix: None, } } + pub fn with_prefix(app: T, prefix: String) -> Self { PageEndpoint { app: Arc::new(app), @@ -48,6 +49,11 @@ impl PageEndpoint { } impl Endpoint for PageEndpoint { + + fn info(&self) -> Option { + Some(EndpointInfo::from(self.app.info())) + } + fn to_handler(&self, path: EndpointPath) -> Box> { Box::new(PageHandler { app: self.app.clone(), @@ -59,6 +65,18 @@ impl Endpoint for PageEndpoint { } } +impl From for EndpointInfo { + fn from(info: Info) -> Self { + EndpointInfo { + name: info.name, + description: info.description, + author: info.author, + icon_url: info.icon_url, + version: info.version, + } + } +} + struct PageHandler { app: Arc, prefix: Option, diff --git a/webapp/src/router/redirect.rs b/webapp/src/router/redirect.rs index f308635cd..6faf9d0c8 100644 --- a/webapp/src/router/redirect.rs +++ b/webapp/src/router/redirect.rs @@ -16,7 +16,6 @@ //! HTTP Redirection hyper handler -use std::io::Write; use hyper::{header, server, Decoder, Encoder, Next}; use hyper::net::HttpStream; use hyper::status::StatusCode;