diff --git a/Cargo.lock b/Cargo.lock index e9edecc88..d8561cd11 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -784,8 +784,7 @@ name = "ethstore" version = "0.1.0" dependencies = [ "docopt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore-devtools 1.7.0", - "ethcore-util 1.7.0", + "ethcore-bigint 0.1.2", "ethcrypto 0.1.0", "ethkey 0.2.0", "itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -800,6 +799,7 @@ dependencies = [ "serde_derive 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1761,7 +1761,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/paritytech/js-precompiled.git#b4c41885c6e02c64fb773546b2f135f56ea7022f" +source = "git+https://github.com/paritytech/js-precompiled.git#fb346e5f2925d1b2d533eb986bd2cefb962c7a88" dependencies = [ "parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/ethcore/light/src/cache.rs b/ethcore/light/src/cache.rs index 185007a1b..67ba11ce0 100644 --- a/ethcore/light/src/cache.rs +++ b/ethcore/light/src/cache.rs @@ -61,6 +61,7 @@ impl Default for CacheSizes { /// /// Note that almost all getter methods take `&mut self` due to the necessity to update /// the underlying LRU-caches on read. +/// [LRU-cache](https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_Recently_Used_.28LRU.29) pub struct Cache { headers: MemoryLruCache, canon_hashes: MemoryLruCache, diff --git a/ethcore/light/src/cht.rs b/ethcore/light/src/cht.rs index 7c749b44f..91a5496f6 100644 --- a/ethcore/light/src/cht.rs +++ b/ethcore/light/src/cht.rs @@ -15,7 +15,7 @@ //! //! Each CHT is a trie mapping block numbers to canonical hashes and total difficulty. //! One is generated for every `SIZE` blocks, allowing us to discard those blocks in -//! favor the the trie root. When the "ancient" blocks need to be accessed, we simply +//! favor of the trie root. When the "ancient" blocks need to be accessed, we simply //! request an inclusion proof of a specific block number against the trie with the //! root has. A correct proof implies that the claimed block is identical to the one //! we discarded. diff --git a/ethcore/light/src/client/header_chain.rs b/ethcore/light/src/client/header_chain.rs index 77881446b..35e6d996c 100644 --- a/ethcore/light/src/client/header_chain.rs +++ b/ethcore/light/src/client/header_chain.rs @@ -39,6 +39,9 @@ use rlp::{Encodable, Decodable, DecoderError, RlpStream, Rlp, UntrustedRlp}; use util::{H256, U256, HeapSizeOf, RwLock}; use util::kvdb::{DBTransaction, KeyValueDB}; +use cache::Cache; +use util::Mutex; + use smallvec::SmallVec; /// Store at least this many candidate headers at all times. @@ -138,11 +141,12 @@ pub struct HeaderChain { best_block: RwLock, db: Arc, col: Option, + cache: Arc>, } impl HeaderChain { /// Create a new header chain given this genesis block and database to read from. - pub fn new(db: Arc, col: Option, genesis: &[u8]) -> Result { + pub fn new(db: Arc, col: Option, genesis: &[u8], cache: Arc>) -> Result { use ethcore::views::HeaderView; let chain = if let Some(current) = db.get(col, CURRENT_KEY)? { @@ -186,6 +190,7 @@ impl HeaderChain { candidates: RwLock::new(candidates), db: db, col: col, + cache: cache, } } else { let g_view = HeaderView::new(genesis); @@ -199,6 +204,7 @@ impl HeaderChain { candidates: RwLock::new(BTreeMap::new()), db: db, col: col, + cache: cache, } }; @@ -375,11 +381,24 @@ impl HeaderChain { /// will be returned. pub fn block_header(&self, id: BlockId) -> Option { let load_from_db = |hash: H256| { - match self.db.get(self.col, &hash) { - Ok(val) => val.map(|x| x.to_vec()).map(encoded::Header::new), - Err(e) => { - warn!(target: "chain", "Failed to read from database: {}", e); - None + let mut cache = self.cache.lock(); + + match cache.block_header(&hash) { + Some(header) => Some(header), + None => { + match self.db.get(self.col, &hash) { + Ok(db_value) => { + db_value.map(|x| x.to_vec()).map(encoded::Header::new) + .and_then(|header| { + cache.insert_block_header(hash.clone(), header.clone()); + Some(header) + }) + }, + Err(e) => { + warn!(target: "chain", "Failed to read from database: {}", e); + None + } + } } } }; @@ -531,6 +550,10 @@ mod tests { use ethcore::ids::BlockId; use ethcore::header::Header; use ethcore::spec::Spec; + use cache::Cache; + + use time::Duration; + use util::Mutex; fn make_db() -> Arc<::util::KeyValueDB> { Arc::new(::util::kvdb::in_memory(0)) @@ -542,7 +565,9 @@ mod tests { let genesis_header = spec.genesis_header(); let db = make_db(); - let chain = HeaderChain::new(db.clone(), None, &::rlp::encode(&genesis_header)).unwrap(); + let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::hours(6)))); + + let chain = HeaderChain::new(db.clone(), None, &::rlp::encode(&genesis_header), cache).unwrap(); let mut parent_hash = genesis_header.hash(); let mut rolling_timestamp = genesis_header.timestamp(); @@ -572,9 +597,10 @@ mod tests { fn reorganize() { let spec = Spec::new_test(); let genesis_header = spec.genesis_header(); - let db = make_db(); - let chain = HeaderChain::new(db.clone(), None, &::rlp::encode(&genesis_header)).unwrap(); + let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::hours(6)))); + + let chain = HeaderChain::new(db.clone(), None, &::rlp::encode(&genesis_header), cache).unwrap(); let mut parent_hash = genesis_header.hash(); let mut rolling_timestamp = genesis_header.timestamp(); @@ -655,8 +681,10 @@ mod tests { let spec = Spec::new_test(); let genesis_header = spec.genesis_header(); let db = make_db(); + let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::hours(6)))); + + let chain = HeaderChain::new(db.clone(), None, &::rlp::encode(&genesis_header), cache).unwrap(); - let chain = HeaderChain::new(db.clone(), None, &::rlp::encode(&genesis_header)).unwrap(); assert!(chain.block_header(BlockId::Earliest).is_some()); assert!(chain.block_header(BlockId::Latest).is_some()); @@ -668,9 +696,10 @@ mod tests { let spec = Spec::new_test(); let genesis_header = spec.genesis_header(); let db = make_db(); + let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::hours(6)))); { - let chain = HeaderChain::new(db.clone(), None, &::rlp::encode(&genesis_header)).unwrap(); + let chain = HeaderChain::new(db.clone(), None, &::rlp::encode(&genesis_header), cache.clone()).unwrap(); let mut parent_hash = genesis_header.hash(); let mut rolling_timestamp = genesis_header.timestamp(); for i in 1..10000 { @@ -690,7 +719,7 @@ mod tests { } } - let chain = HeaderChain::new(db.clone(), None, &::rlp::encode(&genesis_header)).unwrap(); + let chain = HeaderChain::new(db.clone(), None, &::rlp::encode(&genesis_header), cache.clone()).unwrap(); assert!(chain.block_header(BlockId::Number(10)).is_none()); assert!(chain.block_header(BlockId::Number(9000)).is_some()); assert!(chain.cht_root(2).is_some()); @@ -703,9 +732,10 @@ mod tests { let spec = Spec::new_test(); let genesis_header = spec.genesis_header(); let db = make_db(); + let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::hours(6)))); { - let chain = HeaderChain::new(db.clone(), None, &::rlp::encode(&genesis_header)).unwrap(); + let chain = HeaderChain::new(db.clone(), None, &::rlp::encode(&genesis_header), cache.clone()).unwrap(); let mut parent_hash = genesis_header.hash(); let mut rolling_timestamp = genesis_header.timestamp(); @@ -747,7 +777,7 @@ mod tests { } // after restoration, non-canonical eras should still be loaded. - let chain = HeaderChain::new(db.clone(), None, &::rlp::encode(&genesis_header)).unwrap(); + let chain = HeaderChain::new(db.clone(), None, &::rlp::encode(&genesis_header), cache.clone()).unwrap(); assert_eq!(chain.block_header(BlockId::Latest).unwrap().number(), 10); assert!(chain.candidates.read().get(&100).is_some()) } diff --git a/ethcore/light/src/client/mod.rs b/ethcore/light/src/client/mod.rs index 81dd5a175..6d241f7fd 100644 --- a/ethcore/light/src/client/mod.rs +++ b/ethcore/light/src/client/mod.rs @@ -36,6 +36,8 @@ use util::kvdb::{KeyValueDB, CompactionProfile}; use self::header_chain::{AncestryIter, HeaderChain}; +use cache::Cache; + pub use self::service::Service; mod header_chain; @@ -133,13 +135,13 @@ pub struct Client { impl Client { /// Create a new `Client`. - pub fn new(config: Config, db: Arc, chain_col: Option, spec: &Spec, io_channel: IoChannel) -> Result { + pub fn new(config: Config, db: Arc, chain_col: Option, spec: &Spec, io_channel: IoChannel, cache: Arc>) -> Result { let gh = ::rlp::encode(&spec.genesis_header()); Ok(Client { queue: HeaderQueue::new(config.queue, spec.engine.clone(), io_channel, true), engine: spec.engine.clone(), - chain: HeaderChain::new(db.clone(), chain_col, &gh)?, + chain: HeaderChain::new(db.clone(), chain_col, &gh, cache)?, report: RwLock::new(ClientReport::default()), import_lock: Mutex::new(()), db: db, @@ -148,10 +150,10 @@ impl Client { /// Create a new `Client` backed purely in-memory. /// This will ignore all database options in the configuration. - pub fn in_memory(config: Config, spec: &Spec, io_channel: IoChannel) -> Self { + pub fn in_memory(config: Config, spec: &Spec, io_channel: IoChannel, cache: Arc>) -> Self { let db = ::util::kvdb::in_memory(0); - Client::new(config, Arc::new(db), None, spec, io_channel).expect("New DB creation infallible; qed") + Client::new(config, Arc::new(db), None, spec, io_channel, cache).expect("New DB creation infallible; qed") } /// Import a header to the queue for additional verification. diff --git a/ethcore/light/src/client/service.rs b/ethcore/light/src/client/service.rs index 55795d870..83949a2f1 100644 --- a/ethcore/light/src/client/service.rs +++ b/ethcore/light/src/client/service.rs @@ -27,6 +27,9 @@ use ethcore::spec::Spec; use io::{IoContext, IoError, IoHandler, IoService}; use util::kvdb::{Database, DatabaseConfig}; +use cache::Cache; +use util::Mutex; + use super::{Client, Config as ClientConfig}; /// Errors on service initialization. @@ -55,7 +58,8 @@ pub struct Service { impl Service { /// Start the service: initialize I/O workers and client itself. - pub fn start(config: ClientConfig, spec: &Spec, path: &Path) -> Result { + pub fn start(config: ClientConfig, spec: &Spec, path: &Path, cache: Arc>) -> Result { + // initialize database. let mut db_config = DatabaseConfig::with_columns(db::NUM_COLUMNS); @@ -78,6 +82,7 @@ impl Service { db::COL_LIGHT_CHAIN, spec, io_service.channel(), + cache, ).map_err(Error::Database)?); io_service.register_handler(Arc::new(ImportBlocks(client.clone()))).map_err(Error::Io)?; Ok(Service { @@ -112,11 +117,18 @@ mod tests { use super::Service; use devtools::RandomTempPath; use ethcore::spec::Spec; + + use std::sync::Arc; + use cache::Cache; + use time::Duration; + use util::Mutex; #[test] fn it_works() { let spec = Spec::new_test(); let temp_path = RandomTempPath::new(); - Service::start(Default::default(), &spec, temp_path.as_path()).unwrap(); + let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::hours(6)))); + + Service::start(Default::default(), &spec, temp_path.as_path(), cache).unwrap(); } } diff --git a/ethcore/light/src/net/mod.rs b/ethcore/light/src/net/mod.rs index 917ef9049..798f68fe5 100644 --- a/ethcore/light/src/net/mod.rs +++ b/ethcore/light/src/net/mod.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -//! PIP Protocol Version 1 implementation. +//! PLP Protocol Version 1 implementation. //! //! This uses a "Provider" to answer requests. diff --git a/ethcore/res/ethereum/eip150_test.json b/ethcore/res/ethereum/eip150_test.json index f43abea4b..8331c8fc2 100644 --- a/ethcore/res/ethereum/eip150_test.json +++ b/ethcore/res/ethereum/eip150_test.json @@ -14,7 +14,8 @@ "eip155Transition": "0x7fffffffffffffff", "eip160Transition": "0x7fffffffffffffff", "eip161abcTransition": "0x7fffffffffffffff", - "eip161dTransition": "0x7fffffffffffffff" + "eip161dTransition": "0x7fffffffffffffff", + "maxCodeSize": 24576 } } }, diff --git a/ethcore/res/ethereum/eip161_test.json b/ethcore/res/ethereum/eip161_test.json index b51d052c9..00885bae1 100644 --- a/ethcore/res/ethereum/eip161_test.json +++ b/ethcore/res/ethereum/eip161_test.json @@ -14,7 +14,8 @@ "eip155Transition": "0x7fffffffffffffff", "eip160Transition": "0x0", "eip161abcTransition": "0x0", - "eip161dTransition": "0x0" + "eip161dTransition": "0x0", + "maxCodeSize": 24576 } } }, diff --git a/ethcore/src/engines/tendermint/message.rs b/ethcore/src/engines/tendermint/message.rs index 0649ea050..304aa2671 100644 --- a/ethcore/src/engines/tendermint/message.rs +++ b/ethcore/src/engines/tendermint/message.rs @@ -61,6 +61,11 @@ pub fn consensus_view(header: &Header) -> Result { UntrustedRlp::new(view_rlp.as_slice()).as_val() } +/// Proposal signature. +pub fn proposal_signature(header: &Header) -> Result { + UntrustedRlp::new(header.seal().get(1).expect("seal passed basic verification; seal has 3 fields; qed").as_slice()).as_val() +} + impl Message for ConsensusMessage { type Round = VoteStep; @@ -84,34 +89,18 @@ impl ConsensusMessage { pub fn new_proposal(header: &Header) -> Result { Ok(ConsensusMessage { + signature: proposal_signature(header)?, vote_step: VoteStep::new(header.number() as Height, consensus_view(header)?, Step::Propose), - signature: UntrustedRlp::new(header.seal().get(1).expect("seal passed basic verification; seal has 3 fields; qed").as_slice()).as_val()?, block_hash: Some(header.bare_hash()), }) } - pub fn new_commit(proposal: &ConsensusMessage, signature: H520) -> Self { - let mut vote_step = proposal.vote_step.clone(); - vote_step.step = Step::Precommit; - ConsensusMessage { - vote_step: vote_step, - block_hash: proposal.block_hash, - signature: signature, - } - } - pub fn verify(&self) -> Result { let full_rlp = ::rlp::encode(self); let block_info = Rlp::new(&full_rlp).at(1); let public_key = recover(&self.signature.into(), &block_info.as_raw().sha3())?; Ok(public_to_address(&public_key)) } - - pub fn precommit_hash(&self) -> H256 { - let mut vote_step = self.vote_step.clone(); - vote_step.step = Step::Precommit; - message_info_rlp(&vote_step, self.block_hash).sha3() - } } impl Default for VoteStep { @@ -203,6 +192,10 @@ pub fn message_full_rlp(signature: &H520, vote_info: &Bytes) -> Bytes { s.out() } +pub fn message_hash(vote_step: VoteStep, block_hash: H256) -> H256 { + message_info_rlp(&vote_step, Some(block_hash)).sha3() +} + #[cfg(test)] mod tests { use util::*; @@ -294,19 +287,6 @@ mod tests { ); } - #[test] - fn message_info_from_header() { - let header = Header::default(); - let pro = ConsensusMessage { - signature: Default::default(), - vote_step: VoteStep::new(0, 0, Step::Propose), - block_hash: Some(header.bare_hash()) - }; - let pre = message_info_rlp(&VoteStep::new(0, 0, Step::Precommit), Some(header.bare_hash())); - - assert_eq!(pro.precommit_hash(), pre.sha3()); - } - #[test] fn step_ordering() { assert!(VoteStep::new(10, 123, Step::Precommit) < VoteStep::new(11, 123, Step::Precommit)); diff --git a/ethcore/src/engines/tendermint/mod.rs b/ethcore/src/engines/tendermint/mod.rs index 464e102de..8c8094117 100644 --- a/ethcore/src/engines/tendermint/mod.rs +++ b/ethcore/src/engines/tendermint/mod.rs @@ -97,6 +97,8 @@ pub struct Tendermint { proposal: RwLock>, /// Hash of the proposal parent block. proposal_parent: RwLock, + /// Last block proposed by this validator. + last_proposed: RwLock, /// Set used to determine the current validators. validators: Box, } @@ -122,6 +124,7 @@ impl Tendermint { last_lock: AtomicUsize::new(0), proposal: RwLock::new(None), proposal_parent: Default::default(), + last_proposed: Default::default(), validators: new_validator_set(our_params.validators), }); let handler = TransitionHandler::new(Arc::downgrade(&engine) as Weak, Box::new(our_params.timeouts)); @@ -196,6 +199,7 @@ impl Tendermint { self.height.store(new_height, AtomicOrdering::SeqCst); self.view.store(0, AtomicOrdering::SeqCst); *self.lock_change.write() = None; + *self.proposal.write() = None; } /// Use via step_service to transition steps. @@ -206,7 +210,6 @@ impl Tendermint { *self.step.write() = step; match step { Step::Propose => { - *self.proposal.write() = None; self.update_sealing() }, Step::Prevote => { @@ -230,28 +233,6 @@ impl Tendermint { }, Step::Commit => { trace!(target: "engine", "to_step: Commit."); - // Commit the block using a complete signature set. - let view = self.view.load(AtomicOrdering::SeqCst); - let height = self.height.load(AtomicOrdering::SeqCst); - if let Some(block_hash) = *self.proposal.read() { - // Generate seal and remove old votes. - if self.is_signer_proposer(&*self.proposal_parent.read()) { - let proposal_step = VoteStep::new(height, view, Step::Propose); - let precommit_step = VoteStep::new(proposal_step.height, proposal_step.view, Step::Precommit); - if let Some(seal) = self.votes.seal_signatures(proposal_step, precommit_step, &block_hash) { - trace!(target: "engine", "Collected seal: {:?}", seal); - let seal = vec![ - ::rlp::encode(&view).to_vec(), - ::rlp::encode(&seal.proposal).to_vec(), - ::rlp::encode_list(&seal.votes).to_vec() - ]; - self.submit_seal(block_hash, seal); - self.to_next_height(height); - } else { - warn!(target: "engine", "Not enough votes found!"); - } - } - } }, } } @@ -260,8 +241,17 @@ impl Tendermint { self.validators.contains(&*self.proposal_parent.read(), address) } - fn is_above_threshold(&self, n: usize) -> bool { - n > self.validators.count(&*self.proposal_parent.read()) * 2/3 + fn check_above_threshold(&self, n: usize) -> Result<(), EngineError> { + let threshold = self.validators.count(&*self.proposal_parent.read()) * 2/3; + if n > threshold { + Ok(()) + } else { + Err(EngineError::BadSealFieldSize(OutOfBounds { + min: Some(threshold), + max: None, + found: n + })) + } } /// Find the designated for the given view. @@ -272,7 +262,7 @@ impl Tendermint { } /// Check if address is a proposer for given view. - fn is_view_proposer(&self, bh: &H256, height: Height, view: View, address: &Address) -> Result<(), EngineError> { + fn check_view_proposer(&self, bh: &H256, height: Height, view: View, address: &Address) -> Result<(), EngineError> { let proposer = self.view_proposer(bh, height, view); if proposer == *address { Ok(()) @@ -308,13 +298,13 @@ impl Tendermint { fn has_enough_any_votes(&self) -> bool { let step_votes = self.votes.count_round_votes(&VoteStep::new(self.height.load(AtomicOrdering::SeqCst), self.view.load(AtomicOrdering::SeqCst), *self.step.read())); - self.is_above_threshold(step_votes) + self.check_above_threshold(step_votes).is_ok() } fn has_enough_future_step_votes(&self, vote_step: &VoteStep) -> bool { if vote_step.view > self.view.load(AtomicOrdering::SeqCst) { let step_votes = self.votes.count_round_votes(vote_step); - self.is_above_threshold(step_votes) + self.check_above_threshold(step_votes).is_ok() } else { false } @@ -322,7 +312,7 @@ impl Tendermint { fn has_enough_aligned_votes(&self, message: &ConsensusMessage) -> bool { let aligned_count = self.votes.count_aligned_votes(&message); - self.is_above_threshold(aligned_count) + self.check_above_threshold(aligned_count).is_ok() } fn handle_valid_message(&self, message: &ConsensusMessage) { @@ -337,18 +327,32 @@ impl Tendermint { && self.has_enough_aligned_votes(message); if lock_change { trace!(target: "engine", "handle_valid_message: Lock change."); - *self.lock_change.write() = Some(message.clone()); + *self.lock_change.write() = Some(message.clone()); } // Check if it can affect the step transition. if self.is_height(message) { let next_step = match *self.step.read() { + Step::Precommit if message.block_hash.is_none() && self.has_enough_aligned_votes(message) => { + self.increment_view(1); + Some(Step::Propose) + }, Step::Precommit if self.has_enough_aligned_votes(message) => { - if message.block_hash.is_none() { - self.increment_view(1); - Some(Step::Propose) - } else { - Some(Step::Commit) + let bh = message.block_hash.expect("previous guard ensures is_some; qed"); + if *self.last_proposed.read() == bh { + // Commit the block using a complete signature set. + // Generate seal and remove old votes. + let precommits = self.votes.round_signatures(vote_step, &bh); + trace!(target: "engine", "Collected seal: {:?}", precommits); + let seal = vec![ + ::rlp::encode(&vote_step.view).to_vec(), + ::rlp::NULL_RLP.to_vec(), + ::rlp::encode_list(&precommits).to_vec() + ]; + self.submit_seal(bh, seal); + self.votes.throw_out_old(&vote_step); } + self.to_next_height(self.height.load(AtomicOrdering::SeqCst)); + Some(Step::Commit) }, Step::Precommit if self.has_enough_future_step_votes(&vote_step) => { self.increment_view(vote_step.view - self.view.load(AtomicOrdering::SeqCst)); @@ -442,6 +446,8 @@ impl Engine for Tendermint { // Insert Propose vote. debug!(target: "engine", "Submitting proposal {} at height {} view {}.", header.bare_hash(), height, view); self.votes.vote(ConsensusMessage::new(signature, height, view, Step::Propose, bh), author); + // Remember the owned block. + *self.last_proposed.write() = header.bare_hash(); // Remember proposal for later seal submission. *self.proposal.write() = bh; *self.proposal_parent.write() = header.parent_hash().clone(); @@ -462,12 +468,12 @@ impl Engine for Tendermint { if !self.votes.is_old_or_known(&message) { let sender = public_to_address(&recover(&message.signature.into(), &rlp.at(1)?.as_raw().sha3())?); if !self.is_authority(&sender) { - Err(EngineError::NotAuthorized(sender))?; + return Err(EngineError::NotAuthorized(sender).into()); } self.broadcast_message(rlp.as_raw().to_vec()); if self.votes.vote(message.clone(), &sender).is_some() { self.validators.report_malicious(&sender); - Err(EngineError::DoubleVote(sender))? + return Err(EngineError::DoubleVote(sender).into()); } trace!(target: "engine", "Handling a valid {:?} from {}.", message, sender); self.handle_valid_message(&message); @@ -491,22 +497,19 @@ impl Engine for Tendermint { fn verify_block_basic(&self, header: &Header, _block: Option<&[u8]>) -> Result<(), Error> { let seal_length = header.seal().len(); if seal_length == self.seal_fields() { - let signatures_len = header.seal()[2].len(); - if signatures_len >= 1 { + // Either proposal or commit. + if (header.seal()[1] == ::rlp::NULL_RLP.to_vec()) + != (header.seal()[2] == ::rlp::EMPTY_LIST_RLP.to_vec()) { Ok(()) } else { - Err(From::from(EngineError::BadSealFieldSize(OutOfBounds { - min: Some(1), - max: None, - found: signatures_len - }))) + warn!(target: "engine", "verify_block_basic: Block is neither a Commit nor Proposal."); + Err(BlockError::InvalidSeal.into()) } } else { - Err(From::from(BlockError::InvalidSealArity( + Err(BlockError::InvalidSealArity( Mismatch { expected: self.seal_fields(), found: seal_length } - ))) + ).into()) } - } fn verify_block_unordered(&self, _header: &Header, _block: Option<&[u8]>) -> Result<(), Error> { @@ -515,50 +518,42 @@ impl Engine for Tendermint { /// Verify validators and gas limit. fn verify_block_family(&self, header: &Header, parent: &Header, _block: Option<&[u8]>) -> Result<(), Error> { - let proposal = ConsensusMessage::new_proposal(header)?; - let proposer = proposal.verify()?; - if !self.is_authority(&proposer) { - Err(EngineError::NotAuthorized(proposer))? - } - - let precommit_hash = proposal.precommit_hash(); - let ref signatures_field = header.seal()[2]; - let mut signature_count = 0; - let mut origins = HashSet::new(); - for rlp in UntrustedRlp::new(signatures_field).iter() { - let precommit: ConsensusMessage = ConsensusMessage::new_commit(&proposal, rlp.as_val()?); - let address = match self.votes.get(&precommit) { - Some(a) => a, - None => public_to_address(&recover(&precommit.signature.into(), &precommit_hash)?), - }; - if !self.validators.contains(header.parent_hash(), &address) { - Err(EngineError::NotAuthorized(address.to_owned()))? - } - - if origins.insert(address) { - signature_count += 1; - } else { - warn!(target: "engine", "verify_block_unordered: Duplicate signature from {} on the seal.", address); - Err(BlockError::InvalidSeal)?; - } - } - - // Check if its a proposal if there is not enough precommits. - if !self.is_above_threshold(signature_count) { - let signatures_len = signatures_field.len(); - // Proposal has to have an empty signature list. - if signatures_len != 1 { - Err(EngineError::BadSealFieldSize(OutOfBounds { - min: Some(1), - max: Some(1), - found: signatures_len - }))?; - } - self.is_view_proposer(header.parent_hash(), proposal.vote_step.height, proposal.vote_step.view, &proposer)?; - } - if header.number() == 0 { - Err(BlockError::RidiculousNumber(OutOfBounds { min: Some(1), max: None, found: header.number() }))?; + return Err(BlockError::RidiculousNumber(OutOfBounds { min: Some(1), max: None, found: header.number() }).into()); + } + + if let Ok(proposal) = ConsensusMessage::new_proposal(header) { + let proposer = proposal.verify()?; + if !self.is_authority(&proposer) { + return Err(EngineError::NotAuthorized(proposer).into()); + } + self.check_view_proposer(header.parent_hash(), proposal.vote_step.height, proposal.vote_step.view, &proposer)?; + } else { + let vote_step = VoteStep::new(header.number() as usize, consensus_view(header)?, Step::Precommit); + let precommit_hash = message_hash(vote_step.clone(), header.bare_hash()); + let ref signatures_field = header.seal().get(2).expect("block went through verify_block_basic; block has .seal_fields() fields; qed"); + let mut origins = HashSet::new(); + for rlp in UntrustedRlp::new(signatures_field).iter() { + let precommit = ConsensusMessage { + signature: rlp.as_val()?, + block_hash: Some(header.bare_hash()), + vote_step: vote_step.clone(), + }; + let address = match self.votes.get(&precommit) { + Some(a) => a, + None => public_to_address(&recover(&precommit.signature.into(), &precommit_hash)?), + }; + if !self.validators.contains(header.parent_hash(), &address) { + return Err(EngineError::NotAuthorized(address.to_owned()).into()); + } + + if !origins.insert(address) { + warn!(target: "engine", "verify_block_unordered: Duplicate signature from {} on the seal.", address); + return Err(BlockError::InvalidSeal.into()); + } + } + + self.check_above_threshold(origins.len())? } let gas_limit_divisor = self.gas_limit_bound_divisor; @@ -566,7 +561,7 @@ impl Engine for Tendermint { let max_gas = parent.gas_limit().clone() + parent.gas_limit().clone() / gas_limit_divisor; if header.gas_limit() <= &min_gas || header.gas_limit() >= &max_gas { self.validators.report_malicious(header.author()); - Err(BlockError::InvalidGasLimit(OutOfBounds { min: Some(min_gas), max: Some(max_gas), found: header.gas_limit().clone() }))?; + return Err(BlockError::InvalidGasLimit(OutOfBounds { min: Some(min_gas), max: Some(max_gas), found: header.gas_limit().clone() }).into()); } Ok(()) @@ -590,13 +585,14 @@ impl Engine for Tendermint { fn is_proposal(&self, header: &Header) -> bool { let signatures_len = header.seal()[2].len(); // Signatures have to be an empty list rlp. - let proposal = ConsensusMessage::new_proposal(header).expect("block went through full verification; this Engine verifies new_proposal creation; qed"); if signatures_len != 1 { // New Commit received, skip to next height. - trace!(target: "engine", "Received a commit: {:?}.", proposal.vote_step); - self.to_next_height(proposal.vote_step.height); + trace!(target: "engine", "Received a commit: {:?}.", header.number()); + self.to_next_height(header.number() as usize); + self.to_step(Step::Commit); return false; } + let proposal = ConsensusMessage::new_proposal(header).expect("block went through full verification; this Engine verifies new_proposal creation; qed"); let proposer = proposal.verify().expect("block went through full verification; this Engine tries verify; qed"); debug!(target: "engine", "Received a new proposal {:?} from {}.", proposal.vote_step, proposer); if self.is_view(&proposal) { @@ -647,6 +643,10 @@ impl Engine for Tendermint { } fn register_client(&self, client: Weak) { + use client::BlockChainClient; + if let Some(c) = client.upgrade() { + self.height.store(c.chain_info().best_block_number as usize + 1, AtomicOrdering::SeqCst); + } *self.client.write() = Some(client.clone()); self.validators.register_contract(client); } @@ -825,6 +825,7 @@ mod tests { let vote_info = message_info_rlp(&VoteStep::new(2, 0, Step::Precommit), Some(header.bare_hash())); let signature1 = tap.sign(proposer, None, vote_info.sha3()).unwrap(); + seal[1] = ::rlp::NULL_RLP.to_vec(); seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone())]).to_vec(); header.set_seal(seal.clone()); diff --git a/ethcore/src/engines/vote_collector.rs b/ethcore/src/engines/vote_collector.rs index a2969db3a..482dd1d4b 100644 --- a/ethcore/src/engines/vote_collector.rs +++ b/ethcore/src/engines/vote_collector.rs @@ -136,30 +136,14 @@ impl VoteCollector { *guard = new_collector; } - /// Collects the signatures used to seal a block. - pub fn seal_signatures(&self, proposal_round: M::Round, commit_round: M::Round, block_hash: &H256) -> Option { - let ref bh = Some(*block_hash); - let maybe_seal = { - let guard = self.votes.read(); - guard - .get(&proposal_round) - .and_then(|c| c.block_votes.get(bh)) - .and_then(|proposals| proposals.keys().next()) - .map(|proposal| SealSignatures { - proposal: proposal.clone(), - votes: guard - .get(&commit_round) - .and_then(|c| c.block_votes.get(bh)) - .map(|precommits| precommits.keys().cloned().collect()) - .unwrap_or_else(Vec::new), - }) - .and_then(|seal| if seal.votes.is_empty() { None } else { Some(seal) }) - }; - if maybe_seal.is_some() { - // Remove messages that are no longer relevant. - self.throw_out_old(&commit_round); - } - maybe_seal + /// Collects the signatures for a given round and hash. + pub fn round_signatures(&self, round: &M::Round, block_hash: &H256) -> Vec { + let guard = self.votes.read(); + guard + .get(round) + .and_then(|c| c.block_votes.get(&Some(*block_hash))) + .map(|votes| votes.keys().cloned().collect()) + .unwrap_or_else(Vec::new) } /// Count votes which agree with the given message. @@ -275,11 +259,9 @@ mod tests { random_vote(&collector, signatures[1].clone(), commit_round.clone(), bh.clone()); // Wrong round, same signature. random_vote(&collector, signatures[1].clone(), 7, bh.clone()); - let seal = SealSignatures { - proposal: signatures[0], - votes: signatures[1..3].to_vec() - }; - assert_eq!(seal, collector.seal_signatures(propose_round, commit_round, &bh.unwrap()).unwrap()); + + assert_eq!(signatures[0..1].to_vec(), collector.round_signatures(&propose_round, &bh.unwrap())); + assert_eq!(signatures[1..3].iter().collect::>(), collector.round_signatures(&commit_round, &bh.unwrap()).iter().collect::>()); } #[test] diff --git a/ethcore/src/json_tests/chain.rs b/ethcore/src/json_tests/chain.rs index 987280bc1..45a4f1d52 100644 --- a/ethcore/src/json_tests/chain.rs +++ b/ethcore/src/json_tests/chain.rs @@ -48,7 +48,7 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { ChainEra::Frontier => ethereum::new_frontier_test(), ChainEra::Homestead => ethereum::new_homestead_test(), ChainEra::Eip150 => ethereum::new_eip150_test(), - ChainEra::Eip161 => ethereum::new_eip161_test(), + ChainEra::_Eip161 => ethereum::new_eip161_test(), ChainEra::TransitionTest => ethereum::new_transition_test(), }; spec.set_genesis_state(state); diff --git a/ethcore/src/json_tests/eip150_state.rs b/ethcore/src/json_tests/eip150_state.rs deleted file mode 100644 index fffb3f57a..000000000 --- a/ethcore/src/json_tests/eip150_state.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (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 super::test_common::*; -use tests::helpers::*; -use super::state::json_chain_test; - -fn do_json_test(json_data: &[u8]) -> Vec { - json_chain_test(json_data, ChainEra::Eip150) -} - -declare_test!{StateTests_EIP150_stEIPSpecificTest, "StateTests/EIP150/stEIPSpecificTest"} -declare_test!{StateTests_EIP150_stEIPsingleCodeGasPrices, "StateTests/EIP150/stEIPsingleCodeGasPrices"} -declare_test!{StateTests_EIP150_stMemExpandingEIPCalls, "StateTests/EIP150/stMemExpandingEIPCalls"} - -declare_test!{StateTests_EIP150_stCallCodes, "StateTests/EIP150/Homestead/stCallCodes"} -declare_test!{StateTests_EIP150_stCallCreateCallCodeTest, "StateTests/EIP150/Homestead/stCallCreateCallCodeTest"} -declare_test!{StateTests_EIP150_stDelegatecallTest, "StateTests/EIP150/Homestead/stDelegatecallTest"} -declare_test!{StateTests_EIP150_stInitCodeTest, "StateTests/EIP150/Homestead/stInitCodeTest"} -declare_test!{StateTests_EIP150_stLogTests, "StateTests/EIP150/Homestead/stLogTests"} -declare_test!{heavy => StateTests_EIP150_stMemoryStressTest, "StateTests/EIP150/Homestead/stMemoryStressTest"} -declare_test!{heavy => StateTests_EIP150_stMemoryTest, "StateTests/EIP150/Homestead/stMemoryTest"} -declare_test!{StateTests_EIP150_stPreCompiledContracts, "StateTests/EIP150/Homestead/stPreCompiledContracts"} -declare_test!{heavy => StateTests_EIP150_stQuadraticComplexityTest, "StateTests/EIP150/Homestead/stQuadraticComplexityTest"} -declare_test!{StateTests_EIP150_stRecursiveCreate, "StateTests/EIP150/Homestead/stRecursiveCreate"} -declare_test!{StateTests_EIP150_stRefundTest, "StateTests/EIP150/Homestead/stRefundTest"} -declare_test!{StateTests_EIP150_stSpecialTest, "StateTests/EIP150/Homestead/stSpecialTest"} -declare_test!{StateTests_EIP150_stSystemOperationsTest, "StateTests/EIP150/Homestead/stSystemOperationsTest"} -declare_test!{StateTests_EIP150_stTransactionTest, "StateTests/EIP150/Homestead/stTransactionTest"} -declare_test!{StateTests_EIP150_stWalletTest, "StateTests/EIP150/Homestead/stWalletTest"} diff --git a/ethcore/src/json_tests/eip161_state.rs b/ethcore/src/json_tests/eip161_state.rs deleted file mode 100644 index 44ad6a30a..000000000 --- a/ethcore/src/json_tests/eip161_state.rs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (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 super::test_common::*; -use tests::helpers::*; -use super::state::json_chain_test; - -fn do_json_test(json_data: &[u8]) -> Vec { - json_chain_test(json_data, ChainEra::Eip161) -} - -declare_test!{StateTests_EIP158_stEIP158SpecificTest, "StateTests/EIP158/stEIP158SpecificTest"} -declare_test!{StateTests_EIP158_stNonZeroCallsTest, "StateTests/EIP158/stNonZeroCallsTest"} -declare_test!{StateTests_EIP158_stZeroCallsTest, "StateTests/EIP158/stZeroCallsTest"} - -declare_test!{StateTests_EIP158_EIP150_stMemExpandingEIPCalls, "StateTests/EIP158/EIP150/stMemExpandingEIPCalls"} -declare_test!{StateTests_EIP158_EIP150_stEIPSpecificTest, "StateTests/EIP158/EIP150/stEIPSpecificTest"} -declare_test!{StateTests_EIP158_EIP150_stEIPsingleCodeGasPrices, "StateTests/EIP158/EIP150/stEIPsingleCodeGasPrices"} -declare_test!{StateTests_EIP158_EIP150_stChangedTests, "StateTests/EIP158/EIP150/stChangedTests"} - -declare_test!{StateTests_EIP158_Homestead_stBoundsTest, "StateTests/EIP158/Homestead/stBoundsTest"} -declare_test!{StateTests_EIP158_Homestead_stCallCodes, "StateTests/EIP158/Homestead/stCallCodes"} -declare_test!{StateTests_EIP158_Homestead_stCallCreateCallCodeTest, "StateTests/EIP158/Homestead/stCallCreateCallCodeTest"} -declare_test!{StateTests_EIP158_Homestead_stCallDelegateCodes, "StateTests/EIP158/Homestead/stCallDelegateCodes"} -declare_test!{StateTests_EIP158_Homestead_stCallDelegateCodesCallCode, "StateTests/EIP158/Homestead/stCallDelegateCodesCallCode"} -declare_test!{StateTests_EIP158_Homestead_stDelegatecallTest, "StateTests/EIP158/Homestead/stDelegatecallTest"} -declare_test!{StateTests_EIP158_Homestead_stHomeSteadSpecific, "StateTests/EIP158/Homestead/stHomeSteadSpecific"} -declare_test!{StateTests_EIP158_Homestead_stInitCodeTest, "StateTests/EIP158/Homestead/stInitCodeTest"} -declare_test!{StateTests_EIP158_Homestead_stLogTests, "StateTests/EIP158/Homestead/stLogTests"} -declare_test!{heavy => StateTests_EIP158_Homestead_stMemoryTest, "StateTests/EIP158/Homestead/stMemoryTest"} -declare_test!{StateTests_EIP158_Homestead_stPreCompiledContracts, "StateTests/EIP158/Homestead/stPreCompiledContracts"} -declare_test!{heavy => StateTests_EIP158_Homestead_stQuadraticComplexityTest, "StateTests/EIP158/Homestead/stQuadraticComplexityTest"} -declare_test!{StateTests_EIP158_Homestead_stRecursiveCreate, "StateTests/EIP158/Homestead/stRecursiveCreate"} -declare_test!{StateTests_EIP158_Homestead_stRefundTest, "StateTests/EIP158/Homestead/stRefundTest"} -declare_test!{StateTests_EIP158_Homestead_stSpecialTest, "StateTests/EIP158/Homestead/stSpecialTest"} -declare_test!{StateTests_EIP158_Homestead_stSystemOperationsTest, "StateTests/EIP158/Homestead/stSystemOperationsTest"} -declare_test!{StateTests_EIP158_Homestead_stTransactionTest, "StateTests/EIP158/Homestead/stTransactionTest"} -declare_test!{StateTests_EIP158_Homestead_stWalletTest, "StateTests/EIP158/Homestead/stWalletTest"} \ No newline at end of file diff --git a/ethcore/src/json_tests/homestead_chain.rs b/ethcore/src/json_tests/homestead_chain.rs index aab07674b..5f0fe5769 100644 --- a/ethcore/src/json_tests/homestead_chain.rs +++ b/ethcore/src/json_tests/homestead_chain.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use super::test_common::*; use super::chain::json_chain_test; use tests::helpers::*; diff --git a/ethcore/src/json_tests/homestead_state.rs b/ethcore/src/json_tests/homestead_state.rs deleted file mode 100644 index c8585ff15..000000000 --- a/ethcore/src/json_tests/homestead_state.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (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 super::test_common::*; -use tests::helpers::*; -use super::state::json_chain_test; - -fn do_json_test(json_data: &[u8]) -> Vec { - json_chain_test(json_data, ChainEra::Homestead) -} - -declare_test!{StateTests_Homestead_stCallCodes, "StateTests/Homestead/stCallCodes"} -declare_test!{StateTests_Homestead_stCallCreateCallCodeTest, "StateTests/Homestead/stCallCreateCallCodeTest"} -declare_test!{StateTests_Homestead_stDelegatecallTest, "StateTests/Homestead/stDelegatecallTest"} -declare_test!{StateTests_Homestead_stInitCodeTest, "StateTests/Homestead/stInitCodeTest"} -declare_test!{StateTests_Homestead_stLogTests, "StateTests/Homestead/stLogTests"} -declare_test!{heavy => StateTests_Homestead_stMemoryStressTest, "StateTests/Homestead/stMemoryStressTest"} -declare_test!{heavy => StateTests_Homestead_stMemoryTest, "StateTests/Homestead/stMemoryTest"} -declare_test!{StateTests_Homestead_stPreCompiledContracts, "StateTests/Homestead/stPreCompiledContracts"} -declare_test!{heavy => StateTests_Homestead_stQuadraticComplexityTest, "StateTests/Homestead/stQuadraticComplexityTest"} -declare_test!{StateTests_Homestead_stRecursiveCreate, "StateTests/Homestead/stRecursiveCreate"} -declare_test!{StateTests_Homestead_stRefundTest, "StateTests/Homestead/stRefundTest"} -declare_test!{StateTests_Homestead_stSpecialTest, "StateTests/Homestead/stSpecialTest"} -declare_test!{StateTests_Homestead_stSystemOperationsTest, "StateTests/Homestead/stSystemOperationsTest"} -declare_test!{StateTests_Homestead_stTransactionTest, "StateTests/Homestead/stTransactionTest"} -declare_test!{StateTests_Homestead_stWalletTest, "StateTests/Homestead/stWalletTest"} diff --git a/ethcore/src/json_tests/mod.rs b/ethcore/src/json_tests/mod.rs index 22f0dca03..406782072 100644 --- a/ethcore/src/json_tests/mod.rs +++ b/ethcore/src/json_tests/mod.rs @@ -21,8 +21,5 @@ mod transaction; mod executive; mod state; mod chain; -mod homestead_state; mod homestead_chain; -mod eip150_state; -mod eip161_state; mod trie; diff --git a/ethcore/src/json_tests/state.rs b/ethcore/src/json_tests/state.rs index 6388daf94..e4b9390db 100644 --- a/ethcore/src/json_tests/state.rs +++ b/ethcore/src/json_tests/state.rs @@ -16,749 +16,109 @@ use super::test_common::*; use tests::helpers::*; -use pod_state::{self, PodState}; -use log_entry::LogEntry; +use pod_state::PodState; use ethereum; +use spec::Spec; use ethjson; +use ethjson::state::test::ForkSpec; -pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { +lazy_static! { + pub static ref FRONTIER: Spec = ethereum::new_frontier_test(); + pub static ref HOMESTEAD: Spec = ethereum::new_homestead_test(); + pub static ref EIP150: Spec = ethereum::new_eip150_test(); + pub static ref EIP161: Spec = ethereum::new_eip161_test(); +} + +pub fn json_chain_test(json_data: &[u8]) -> Vec { ::ethcore_logger::init_log(); - let tests = ethjson::state::Test::load(json_data).unwrap(); + let tests = ethjson::state::test::Test::load(json_data).unwrap(); let mut failed = Vec::new(); - let engine = match era { - ChainEra::Frontier => ethereum::new_mainnet_like().engine, - ChainEra::Homestead => ethereum::new_homestead_test().engine, - ChainEra::Eip150 => ethereum::new_eip150_test().engine, - ChainEra::Eip161 => ethereum::new_eip161_test().engine, - ChainEra::TransitionTest => ethereum::new_transition_test().engine, - }; for (name, test) in tests.into_iter() { - let mut fail = false; { - let mut fail_unless = |cond: bool| if !cond && !fail { - failed.push(name.clone()); - flushln!("FAIL"); - fail = true; - true - } else {false}; - - flush!(" - {}...", name); - - let transaction = test.transaction.into(); - let post_state_root = test.post_state_root.into(); + let multitransaction = test.transaction; let env = test.env.into(); let pre: PodState = test.pre_state.into(); - let post: PodState = test.post_state.into(); - let logs: Vec = test.logs.into_iter().map(Into::into).collect(); - let calc_post = sec_trie_root(post.get().iter().map(|(k, v)| (k.to_vec(), v.rlp())).collect()); + for (spec, states) in test.post_states { + let total = states.len(); + let engine = match spec { + ForkSpec::Frontier => &FRONTIER.engine, + ForkSpec::Homestead => &HOMESTEAD.engine, + ForkSpec::EIP150 => &EIP150.engine, + ForkSpec::EIP158 => &EIP161.engine, + ForkSpec::Metropolis => continue, + }; - if fail_unless(post_state_root == calc_post) { - println!("!!! {}: Trie root mismatch (got: {}, expect: {}):", name, calc_post, post_state_root); - println!("!!! Post:\n{}", post); - } else { - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); - state.populate_from(pre); - state.commit() - .expect(&format!("State test {} failed due to internal error.", name)); - let res = state.apply(&env, &*engine, &transaction, false); + for (i, state) in states.into_iter().enumerate() { + let info = format!(" - {} | {:?} ({}/{}) ...", name, spec, i + 1, total); - if fail_unless(state.root() == &post_state_root) { - println!("!!! {}: State mismatch (got: {}, expect: {}):", name, state.root(), post_state_root); - let our_post = state.to_pod(); - println!("Got:\n{}", our_post); - println!("Expect:\n{}", post); - println!("Diff ---expect -> +++got:\n{}", pod_state::diff_pod(&post, &our_post)); - } + let post_root: H256 = state.hash.into(); + let transaction = multitransaction.select(&state.indexes).into(); - if let Ok(r) = res { - if fail_unless(logs == r.receipt.logs) { - println!("!!! {}: Logs mismatch:", name); - println!("Got:\n{:?}", r.receipt.logs); - println!("Expect:\n{:?}", logs); + let mut state = get_temp_mem_state(); + state.populate_from(pre.clone()); + state.commit().expect(&format!("State test {} failed due to internal error.", name)); + let _res = state.apply(&env, &**engine, &transaction, false); + if state.root() != &post_root { + println!("{} !!! State mismatch (got: {}, expect: {}", info, state.root(), post_root); + flushln!("{} fail", info); + failed.push(name.clone()); + } else { + flushln!("{} ok", info); } } } } - if !fail { - flushln!("ok"); - } } println!("!!! {:?} tests from failed.", failed.len()); failed } -mod frontier_tests { +mod state_tests { use super::json_chain_test; - use tests::helpers::ChainEra; fn do_json_test(json_data: &[u8]) -> Vec { - json_chain_test(json_data, ChainEra::Frontier) + json_chain_test(json_data) } - declare_test!{StateTests_stBlockHashTest, "StateTests/stBlockHashTest"} - declare_test!{StateTests_stCallCodes, "StateTests/stCallCodes"} - declare_test!{StateTests_stCallCreateCallCodeTest, "StateTests/stCallCreateCallCodeTest"} - declare_test!{StateTests_stExample, "StateTests/stExample"} - declare_test!{StateTests_stInitCodeTest, "StateTests/stInitCodeTest"} - declare_test!{StateTests_stLogTests, "StateTests/stLogTests"} - declare_test!{heavy => StateTests_stMemoryStressTest, "StateTests/stMemoryStressTest"} - declare_test!{heavy => StateTests_stMemoryTest, "StateTests/stMemoryTest"} - declare_test!{StateTests_stPreCompiledContracts, "StateTests/stPreCompiledContracts"} - declare_test!{heavy => StateTests_stQuadraticComplexityTest, "StateTests/stQuadraticComplexityTest"} - declare_test!{StateTests_stRecursiveCreate, "StateTests/stRecursiveCreate"} - declare_test!{StateTests_stRefundTest, "StateTests/stRefundTest"} - declare_test!{StateTests_stSolidityTest, "StateTests/stSolidityTest"} - declare_test!{StateTests_stSpecialTest, "StateTests/stSpecialTest"} - declare_test!{StateTests_stSystemOperationsTest, "StateTests/stSystemOperationsTest"} - declare_test!{StateTests_stTransactionTest, "StateTests/stTransactionTest"} - declare_test!{StateTests_stTransitionTest, "StateTests/stTransitionTest"} - declare_test!{StateTests_stWalletTest, "StateTests/stWalletTest"} - - declare_test!{StateTests_RandomTests_st201503121803PYTHON, "StateTests/RandomTests/st201503121803PYTHON"} - declare_test!{StateTests_RandomTests_st201503121806PYTHON, "StateTests/RandomTests/st201503121806PYTHON"} - declare_test!{StateTests_RandomTests_st201503121848GO, "StateTests/RandomTests/st201503121848GO"} - declare_test!{StateTests_RandomTests_st201503121849GO, "StateTests/RandomTests/st201503121849GO"} - declare_test!{StateTests_RandomTests_st201503121850GO, "StateTests/RandomTests/st201503121850GO"} - declare_test!{StateTests_RandomTests_st201503121851GO, "StateTests/RandomTests/st201503121851GO"} - declare_test!{StateTests_RandomTests_st201503121953GO, "StateTests/RandomTests/st201503121953GO"} - declare_test!{StateTests_RandomTests_st201503122023GO, "StateTests/RandomTests/st201503122023GO"} - declare_test!{StateTests_RandomTests_st201503122023PYTHON, "StateTests/RandomTests/st201503122023PYTHON"} - declare_test!{StateTests_RandomTests_st201503122027GO, "StateTests/RandomTests/st201503122027GO"} - declare_test!{StateTests_RandomTests_st201503122054GO, "StateTests/RandomTests/st201503122054GO"} - declare_test!{StateTests_RandomTests_st201503122055GO, "StateTests/RandomTests/st201503122055GO"} - declare_test!{StateTests_RandomTests_st201503122115CPPJIT, "StateTests/RandomTests/st201503122115CPPJIT"} - declare_test!{StateTests_RandomTests_st201503122115GO, "StateTests/RandomTests/st201503122115GO"} - declare_test!{StateTests_RandomTests_st201503122123GO, "StateTests/RandomTests/st201503122123GO"} - declare_test!{StateTests_RandomTests_st201503122124GO, "StateTests/RandomTests/st201503122124GO"} - declare_test!{StateTests_RandomTests_st201503122128PYTHON, "StateTests/RandomTests/st201503122128PYTHON"} - declare_test!{StateTests_RandomTests_st201503122140GO, "StateTests/RandomTests/st201503122140GO"} - declare_test!{StateTests_RandomTests_st201503122159GO, "StateTests/RandomTests/st201503122159GO"} - declare_test!{StateTests_RandomTests_st201503122204GO, "StateTests/RandomTests/st201503122204GO"} - declare_test!{StateTests_RandomTests_st201503122212GO, "StateTests/RandomTests/st201503122212GO"} - declare_test!{StateTests_RandomTests_st201503122231GO, "StateTests/RandomTests/st201503122231GO"} - declare_test!{StateTests_RandomTests_st201503122238GO, "StateTests/RandomTests/st201503122238GO"} - declare_test!{StateTests_RandomTests_st201503122252GO, "StateTests/RandomTests/st201503122252GO"} - declare_test!{StateTests_RandomTests_st201503122316GO, "StateTests/RandomTests/st201503122316GO"} - declare_test!{StateTests_RandomTests_st201503122324GO, "StateTests/RandomTests/st201503122324GO"} - declare_test!{StateTests_RandomTests_st201503122358GO, "StateTests/RandomTests/st201503122358GO"} - declare_test!{StateTests_RandomTests_st201503130002GO, "StateTests/RandomTests/st201503130002GO"} - declare_test!{StateTests_RandomTests_st201503130005GO, "StateTests/RandomTests/st201503130005GO"} - declare_test!{StateTests_RandomTests_st201503130007GO, "StateTests/RandomTests/st201503130007GO"} - declare_test!{StateTests_RandomTests_st201503130010GO, "StateTests/RandomTests/st201503130010GO"} - declare_test!{StateTests_RandomTests_st201503130023PYTHON, "StateTests/RandomTests/st201503130023PYTHON"} - declare_test!{StateTests_RandomTests_st201503130059GO, "StateTests/RandomTests/st201503130059GO"} - declare_test!{StateTests_RandomTests_st201503130101GO, "StateTests/RandomTests/st201503130101GO"} - declare_test!{StateTests_RandomTests_st201503130109GO, "StateTests/RandomTests/st201503130109GO"} - declare_test!{StateTests_RandomTests_st201503130117GO, "StateTests/RandomTests/st201503130117GO"} - declare_test!{StateTests_RandomTests_st201503130122GO, "StateTests/RandomTests/st201503130122GO"} - declare_test!{StateTests_RandomTests_st201503130156GO, "StateTests/RandomTests/st201503130156GO"} - declare_test!{StateTests_RandomTests_st201503130156PYTHON, "StateTests/RandomTests/st201503130156PYTHON"} - declare_test!{StateTests_RandomTests_st201503130207GO, "StateTests/RandomTests/st201503130207GO"} - declare_test!{StateTests_RandomTests_st201503130219CPPJIT, "StateTests/RandomTests/st201503130219CPPJIT"} - declare_test!{StateTests_RandomTests_st201503130219GO, "StateTests/RandomTests/st201503130219GO"} - declare_test!{StateTests_RandomTests_st201503130243GO, "StateTests/RandomTests/st201503130243GO"} - declare_test!{StateTests_RandomTests_st201503130246GO, "StateTests/RandomTests/st201503130246GO"} - declare_test!{StateTests_RandomTests_st201503130321GO, "StateTests/RandomTests/st201503130321GO"} - declare_test!{StateTests_RandomTests_st201503130322GO, "StateTests/RandomTests/st201503130322GO"} - declare_test!{StateTests_RandomTests_st201503130332GO, "StateTests/RandomTests/st201503130332GO"} - declare_test!{StateTests_RandomTests_st201503130359GO, "StateTests/RandomTests/st201503130359GO"} - declare_test!{StateTests_RandomTests_st201503130405GO, "StateTests/RandomTests/st201503130405GO"} - declare_test!{StateTests_RandomTests_st201503130408GO, "StateTests/RandomTests/st201503130408GO"} - declare_test!{StateTests_RandomTests_st201503130411GO, "StateTests/RandomTests/st201503130411GO"} - declare_test!{StateTests_RandomTests_st201503130431GO, "StateTests/RandomTests/st201503130431GO"} - declare_test!{StateTests_RandomTests_st201503130437GO, "StateTests/RandomTests/st201503130437GO"} - declare_test!{StateTests_RandomTests_st201503130450GO, "StateTests/RandomTests/st201503130450GO"} - declare_test!{StateTests_RandomTests_st201503130512CPPJIT, "StateTests/RandomTests/st201503130512CPPJIT"} - declare_test!{StateTests_RandomTests_st201503130512GO, "StateTests/RandomTests/st201503130512GO"} - declare_test!{StateTests_RandomTests_st201503130615GO, "StateTests/RandomTests/st201503130615GO"} - declare_test!{StateTests_RandomTests_st201503130705GO, "StateTests/RandomTests/st201503130705GO"} - declare_test!{StateTests_RandomTests_st201503130733CPPJIT, "StateTests/RandomTests/st201503130733CPPJIT"} - declare_test!{StateTests_RandomTests_st201503130733GO, "StateTests/RandomTests/st201503130733GO"} - declare_test!{StateTests_RandomTests_st201503130747GO, "StateTests/RandomTests/st201503130747GO"} - declare_test!{StateTests_RandomTests_st201503130751GO, "StateTests/RandomTests/st201503130751GO"} - declare_test!{StateTests_RandomTests_st201503130752PYTHON, "StateTests/RandomTests/st201503130752PYTHON"} - declare_test!{StateTests_RandomTests_st201503130757PYTHON, "StateTests/RandomTests/st201503130757PYTHON"} - declare_test!{StateTests_RandomTests_st201503131658GO, "StateTests/RandomTests/st201503131658GO"} - declare_test!{StateTests_RandomTests_st201503131739GO, "StateTests/RandomTests/st201503131739GO"} - declare_test!{StateTests_RandomTests_st201503131755CPPJIT, "StateTests/RandomTests/st201503131755CPPJIT"} - declare_test!{StateTests_RandomTests_st201503131755GO, "StateTests/RandomTests/st201503131755GO"} - declare_test!{StateTests_RandomTests_st201503132001CPPJIT, "StateTests/RandomTests/st201503132001CPPJIT"} - declare_test!{StateTests_RandomTests_st201503132127PYTHON, "StateTests/RandomTests/st201503132127PYTHON"} - declare_test!{StateTests_RandomTests_st201503132201CPPJIT, "StateTests/RandomTests/st201503132201CPPJIT"} - declare_test!{StateTests_RandomTests_st201503132201GO, "StateTests/RandomTests/st201503132201GO"} - declare_test!{StateTests_RandomTests_st201503132202PYTHON, "StateTests/RandomTests/st201503132202PYTHON"} - declare_test!{StateTests_RandomTests_st201503140002PYTHON, "StateTests/RandomTests/st201503140002PYTHON"} - declare_test!{StateTests_RandomTests_st201503140240PYTHON, "StateTests/RandomTests/st201503140240PYTHON"} - declare_test!{StateTests_RandomTests_st201503140522PYTHON, "StateTests/RandomTests/st201503140522PYTHON"} - declare_test!{StateTests_RandomTests_st201503140756PYTHON, "StateTests/RandomTests/st201503140756PYTHON"} - declare_test!{StateTests_RandomTests_st201503141144PYTHON, "StateTests/RandomTests/st201503141144PYTHON"} - declare_test!{StateTests_RandomTests_st201503141510PYTHON, "StateTests/RandomTests/st201503141510PYTHON"} - declare_test!{StateTests_RandomTests_st201503150427PYTHON, "StateTests/RandomTests/st201503150427PYTHON"} - declare_test!{StateTests_RandomTests_st201503150716PYTHON, "StateTests/RandomTests/st201503150716PYTHON"} - declare_test!{StateTests_RandomTests_st201503151450PYTHON, "StateTests/RandomTests/st201503151450PYTHON"} - declare_test!{StateTests_RandomTests_st201503151516PYTHON, "StateTests/RandomTests/st201503151516PYTHON"} - declare_test!{StateTests_RandomTests_st201503151753PYTHON, "StateTests/RandomTests/st201503151753PYTHON"} - declare_test!{StateTests_RandomTests_st201503152057PYTHON, "StateTests/RandomTests/st201503152057PYTHON"} - declare_test!{StateTests_RandomTests_st201503152241PYTHON, "StateTests/RandomTests/st201503152241PYTHON"} - declare_test!{StateTests_RandomTests_st201503160014PYTHON, "StateTests/RandomTests/st201503160014PYTHON"} - declare_test!{StateTests_RandomTests_st201503160733PYTHON, "StateTests/RandomTests/st201503160733PYTHON"} - declare_test!{StateTests_RandomTests_st201503170051PYTHON, "StateTests/RandomTests/st201503170051PYTHON"} - declare_test!{StateTests_RandomTests_st201503170433PYTHON, "StateTests/RandomTests/st201503170433PYTHON"} - declare_test!{StateTests_RandomTests_st201503170523PYTHON, "StateTests/RandomTests/st201503170523PYTHON"} - declare_test!{StateTests_RandomTests_st201503171108PYTHON, "StateTests/RandomTests/st201503171108PYTHON"} - declare_test!{StateTests_RandomTests_st201503181223GO, "StateTests/RandomTests/st201503181223GO"} - declare_test!{StateTests_RandomTests_st201503181225GO, "StateTests/RandomTests/st201503181225GO"} - declare_test!{StateTests_RandomTests_st201503181226CPPJIT, "StateTests/RandomTests/st201503181226CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181227CPPJIT, "StateTests/RandomTests/st201503181227CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181227GO, "StateTests/RandomTests/st201503181227GO"} - declare_test!{StateTests_RandomTests_st201503181229GO, "StateTests/RandomTests/st201503181229GO"} - declare_test!{StateTests_RandomTests_st201503181230CPPJIT, "StateTests/RandomTests/st201503181230CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181230GO, "StateTests/RandomTests/st201503181230GO"} - declare_test!{StateTests_RandomTests_st201503181231GO, "StateTests/RandomTests/st201503181231GO"} - declare_test!{StateTests_RandomTests_st201503181232CPPJIT, "StateTests/RandomTests/st201503181232CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181232GO, "StateTests/RandomTests/st201503181232GO"} - declare_test!{StateTests_RandomTests_st201503181233GO, "StateTests/RandomTests/st201503181233GO"} - declare_test!{StateTests_RandomTests_st201503181234CPPJIT, "StateTests/RandomTests/st201503181234CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181234GO, "StateTests/RandomTests/st201503181234GO"} - declare_test!{StateTests_RandomTests_st201503181235CPPJIT, "StateTests/RandomTests/st201503181235CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181235GO, "StateTests/RandomTests/st201503181235GO"} - declare_test!{StateTests_RandomTests_st201503181236GO, "StateTests/RandomTests/st201503181236GO"} - declare_test!{StateTests_RandomTests_st201503181237GO, "StateTests/RandomTests/st201503181237GO"} - declare_test!{StateTests_RandomTests_st201503181239GO, "StateTests/RandomTests/st201503181239GO"} - declare_test!{StateTests_RandomTests_st201503181241CPPJIT, "StateTests/RandomTests/st201503181241CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181241GO, "StateTests/RandomTests/st201503181241GO"} - declare_test!{StateTests_RandomTests_st201503181243GO, "StateTests/RandomTests/st201503181243GO"} - declare_test!{StateTests_RandomTests_st201503181244GO, "StateTests/RandomTests/st201503181244GO"} - declare_test!{StateTests_RandomTests_st201503181245CPPJIT, "StateTests/RandomTests/st201503181245CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181245GO, "StateTests/RandomTests/st201503181245GO"} - declare_test!{StateTests_RandomTests_st201503181246CPPJIT, "StateTests/RandomTests/st201503181246CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181246GO, "StateTests/RandomTests/st201503181246GO"} - declare_test!{StateTests_RandomTests_st201503181247GO, "StateTests/RandomTests/st201503181247GO"} - declare_test!{StateTests_RandomTests_st201503181248GO, "StateTests/RandomTests/st201503181248GO"} - declare_test!{StateTests_RandomTests_st201503181249GO, "StateTests/RandomTests/st201503181249GO"} - declare_test!{StateTests_RandomTests_st201503181250CPPJIT, "StateTests/RandomTests/st201503181250CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181250GO, "StateTests/RandomTests/st201503181250GO"} - declare_test!{StateTests_RandomTests_st201503181251GO, "StateTests/RandomTests/st201503181251GO"} - declare_test!{StateTests_RandomTests_st201503181252CPPJIT, "StateTests/RandomTests/st201503181252CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181253GO, "StateTests/RandomTests/st201503181253GO"} - declare_test!{StateTests_RandomTests_st201503181255CPPJIT, "StateTests/RandomTests/st201503181255CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181255GO, "StateTests/RandomTests/st201503181255GO"} - declare_test!{StateTests_RandomTests_st201503181257GO, "StateTests/RandomTests/st201503181257GO"} - declare_test!{StateTests_RandomTests_st201503181258CPPJIT, "StateTests/RandomTests/st201503181258CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181258GO, "StateTests/RandomTests/st201503181258GO"} - declare_test!{StateTests_RandomTests_st201503181301CPPJIT, "StateTests/RandomTests/st201503181301CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181301GO, "StateTests/RandomTests/st201503181301GO"} - declare_test!{StateTests_RandomTests_st201503181303GO, "StateTests/RandomTests/st201503181303GO"} - declare_test!{StateTests_RandomTests_st201503181304GO, "StateTests/RandomTests/st201503181304GO"} - declare_test!{StateTests_RandomTests_st201503181305GO, "StateTests/RandomTests/st201503181305GO"} - declare_test!{StateTests_RandomTests_st201503181306GO, "StateTests/RandomTests/st201503181306GO"} - declare_test!{StateTests_RandomTests_st201503181307CPPJIT, "StateTests/RandomTests/st201503181307CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181307GO, "StateTests/RandomTests/st201503181307GO"} - declare_test!{StateTests_RandomTests_st201503181308GO, "StateTests/RandomTests/st201503181308GO"} - declare_test!{StateTests_RandomTests_st201503181309GO, "StateTests/RandomTests/st201503181309GO"} - declare_test!{StateTests_RandomTests_st201503181310GO, "StateTests/RandomTests/st201503181310GO"} - declare_test!{StateTests_RandomTests_st201503181311GO, "StateTests/RandomTests/st201503181311GO"} - declare_test!{StateTests_RandomTests_st201503181313GO, "StateTests/RandomTests/st201503181313GO"} - declare_test!{StateTests_RandomTests_st201503181314GO, "StateTests/RandomTests/st201503181314GO"} - declare_test!{StateTests_RandomTests_st201503181315CPPJIT, "StateTests/RandomTests/st201503181315CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181315GO, "StateTests/RandomTests/st201503181315GO"} - declare_test!{StateTests_RandomTests_st201503181316CPPJIT, "StateTests/RandomTests/st201503181316CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181316PYTHON, "StateTests/RandomTests/st201503181316PYTHON"} - declare_test!{StateTests_RandomTests_st201503181317GO, "StateTests/RandomTests/st201503181317GO"} - declare_test!{StateTests_RandomTests_st201503181318CPPJIT, "StateTests/RandomTests/st201503181318CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181318GO, "StateTests/RandomTests/st201503181318GO"} - declare_test!{StateTests_RandomTests_st201503181319GO, "StateTests/RandomTests/st201503181319GO"} - declare_test!{StateTests_RandomTests_st201503181319PYTHON, "StateTests/RandomTests/st201503181319PYTHON"} - declare_test!{StateTests_RandomTests_st201503181322GO, "StateTests/RandomTests/st201503181322GO"} - declare_test!{StateTests_RandomTests_st201503181323CPPJIT, "StateTests/RandomTests/st201503181323CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181323GO, "StateTests/RandomTests/st201503181323GO"} - declare_test!{StateTests_RandomTests_st201503181324GO, "StateTests/RandomTests/st201503181324GO"} - declare_test!{StateTests_RandomTests_st201503181325GO, "StateTests/RandomTests/st201503181325GO"} - declare_test!{StateTests_RandomTests_st201503181326CPPJIT, "StateTests/RandomTests/st201503181326CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181326GO, "StateTests/RandomTests/st201503181326GO"} - declare_test!{StateTests_RandomTests_st201503181327GO, "StateTests/RandomTests/st201503181327GO"} - declare_test!{StateTests_RandomTests_st201503181329CPPJIT, "StateTests/RandomTests/st201503181329CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181329GO, "StateTests/RandomTests/st201503181329GO"} - declare_test!{StateTests_RandomTests_st201503181330GO, "StateTests/RandomTests/st201503181330GO"} - declare_test!{StateTests_RandomTests_st201503181332GO, "StateTests/RandomTests/st201503181332GO"} - declare_test!{StateTests_RandomTests_st201503181333GO, "StateTests/RandomTests/st201503181333GO"} - declare_test!{StateTests_RandomTests_st201503181334GO, "StateTests/RandomTests/st201503181334GO"} - declare_test!{StateTests_RandomTests_st201503181336CPPJIT, "StateTests/RandomTests/st201503181336CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181337GO, "StateTests/RandomTests/st201503181337GO"} - declare_test!{StateTests_RandomTests_st201503181338GO, "StateTests/RandomTests/st201503181338GO"} - declare_test!{StateTests_RandomTests_st201503181339CPPJIT, "StateTests/RandomTests/st201503181339CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181339GO, "StateTests/RandomTests/st201503181339GO"} - declare_test!{StateTests_RandomTests_st201503181340GO, "StateTests/RandomTests/st201503181340GO"} - declare_test!{StateTests_RandomTests_st201503181341CPPJIT, "StateTests/RandomTests/st201503181341CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181342CPPJIT, "StateTests/RandomTests/st201503181342CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181342GO, "StateTests/RandomTests/st201503181342GO"} - declare_test!{StateTests_RandomTests_st201503181345GO, "StateTests/RandomTests/st201503181345GO"} - declare_test!{StateTests_RandomTests_st201503181346GO, "StateTests/RandomTests/st201503181346GO"} - declare_test!{StateTests_RandomTests_st201503181347CPPJIT, "StateTests/RandomTests/st201503181347CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181347GO, "StateTests/RandomTests/st201503181347GO"} - declare_test!{StateTests_RandomTests_st201503181347PYTHON, "StateTests/RandomTests/st201503181347PYTHON"} - declare_test!{StateTests_RandomTests_st201503181350CPPJIT, "StateTests/RandomTests/st201503181350CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181352GO, "StateTests/RandomTests/st201503181352GO"} - declare_test!{StateTests_RandomTests_st201503181353GO, "StateTests/RandomTests/st201503181353GO"} - declare_test!{StateTests_RandomTests_st201503181354CPPJIT, "StateTests/RandomTests/st201503181354CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181354GO, "StateTests/RandomTests/st201503181354GO"} - declare_test!{StateTests_RandomTests_st201503181355GO, "StateTests/RandomTests/st201503181355GO"} - declare_test!{StateTests_RandomTests_st201503181356CPPJIT, "StateTests/RandomTests/st201503181356CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181357CPPJIT, "StateTests/RandomTests/st201503181357CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181358CPPJIT, "StateTests/RandomTests/st201503181358CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181358GO, "StateTests/RandomTests/st201503181358GO"} - declare_test!{StateTests_RandomTests_st201503181359GO, "StateTests/RandomTests/st201503181359GO"} - declare_test!{StateTests_RandomTests_st201503181402CPPJIT, "StateTests/RandomTests/st201503181402CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181403GO, "StateTests/RandomTests/st201503181403GO"} - declare_test!{StateTests_RandomTests_st201503181406CPPJIT, "StateTests/RandomTests/st201503181406CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181406GO, "StateTests/RandomTests/st201503181406GO"} - declare_test!{StateTests_RandomTests_st201503181410GO, "StateTests/RandomTests/st201503181410GO"} - declare_test!{StateTests_RandomTests_st201503181412CPPJIT, "StateTests/RandomTests/st201503181412CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181413GO, "StateTests/RandomTests/st201503181413GO"} - declare_test!{StateTests_RandomTests_st201503181415GO, "StateTests/RandomTests/st201503181415GO"} - declare_test!{StateTests_RandomTests_st201503181416GO, "StateTests/RandomTests/st201503181416GO"} - declare_test!{StateTests_RandomTests_st201503181417CPPJIT, "StateTests/RandomTests/st201503181417CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181417GO, "StateTests/RandomTests/st201503181417GO"} - declare_test!{StateTests_RandomTests_st201503181418CPPJIT, "StateTests/RandomTests/st201503181418CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181422GO, "StateTests/RandomTests/st201503181422GO"} - declare_test!{StateTests_RandomTests_st201503181423CPPJIT, "StateTests/RandomTests/st201503181423CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181424GO, "StateTests/RandomTests/st201503181424GO"} - declare_test!{StateTests_RandomTests_st201503181426CPPJIT, "StateTests/RandomTests/st201503181426CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181426GO, "StateTests/RandomTests/st201503181426GO"} - declare_test!{StateTests_RandomTests_st201503181428GO, "StateTests/RandomTests/st201503181428GO"} - declare_test!{StateTests_RandomTests_st201503181430CPPJIT, "StateTests/RandomTests/st201503181430CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181435GO, "StateTests/RandomTests/st201503181435GO"} - declare_test!{StateTests_RandomTests_st201503181436GO, "StateTests/RandomTests/st201503181436GO"} - declare_test!{StateTests_RandomTests_st201503181437CPPJIT, "StateTests/RandomTests/st201503181437CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181437GO, "StateTests/RandomTests/st201503181437GO"} - declare_test!{StateTests_RandomTests_st201503181438CPPJIT, "StateTests/RandomTests/st201503181438CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181438GO, "StateTests/RandomTests/st201503181438GO"} - declare_test!{StateTests_RandomTests_st201503181439CPPJIT, "StateTests/RandomTests/st201503181439CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181439GO, "StateTests/RandomTests/st201503181439GO"} - declare_test!{StateTests_RandomTests_st201503181439PYTHON, "StateTests/RandomTests/st201503181439PYTHON"} - declare_test!{StateTests_RandomTests_st201503181440GO, "StateTests/RandomTests/st201503181440GO"} - declare_test!{StateTests_RandomTests_st201503181441GO, "StateTests/RandomTests/st201503181441GO"} - declare_test!{StateTests_RandomTests_st201503181442GO, "StateTests/RandomTests/st201503181442GO"} - declare_test!{StateTests_RandomTests_st201503181445CPPJIT, "StateTests/RandomTests/st201503181445CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181446GO, "StateTests/RandomTests/st201503181446GO"} - declare_test!{StateTests_RandomTests_st201503181447GO, "StateTests/RandomTests/st201503181447GO"} - declare_test!{StateTests_RandomTests_st201503181450GO, "StateTests/RandomTests/st201503181450GO"} - declare_test!{StateTests_RandomTests_st201503181451CPPJIT, "StateTests/RandomTests/st201503181451CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181453GO, "StateTests/RandomTests/st201503181453GO"} - declare_test!{StateTests_RandomTests_st201503181455GO, "StateTests/RandomTests/st201503181455GO"} - declare_test!{StateTests_RandomTests_st201503181456CPPJIT, "StateTests/RandomTests/st201503181456CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181457GO, "StateTests/RandomTests/st201503181457GO"} - declare_test!{StateTests_RandomTests_st201503181458GO, "StateTests/RandomTests/st201503181458GO"} - declare_test!{StateTests_RandomTests_st201503181459GO, "StateTests/RandomTests/st201503181459GO"} - declare_test!{StateTests_RandomTests_st201503181500GO, "StateTests/RandomTests/st201503181500GO"} - declare_test!{StateTests_RandomTests_st201503181501GO, "StateTests/RandomTests/st201503181501GO"} - declare_test!{StateTests_RandomTests_st201503181503GO, "StateTests/RandomTests/st201503181503GO"} - declare_test!{StateTests_RandomTests_st201503181504GO, "StateTests/RandomTests/st201503181504GO"} - declare_test!{StateTests_RandomTests_st201503181505GO, "StateTests/RandomTests/st201503181505GO"} - declare_test!{StateTests_RandomTests_st201503181506CPPJIT, "StateTests/RandomTests/st201503181506CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181507GO, "StateTests/RandomTests/st201503181507GO"} - declare_test!{StateTests_RandomTests_st201503181509CPPJIT, "StateTests/RandomTests/st201503181509CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181509GO, "StateTests/RandomTests/st201503181509GO"} - declare_test!{StateTests_RandomTests_st201503181510GO, "StateTests/RandomTests/st201503181510GO"} - declare_test!{StateTests_RandomTests_st201503181511GO, "StateTests/RandomTests/st201503181511GO"} - declare_test!{StateTests_RandomTests_st201503181512GO, "StateTests/RandomTests/st201503181512GO"} - declare_test!{StateTests_RandomTests_st201503181513CPPJIT, "StateTests/RandomTests/st201503181513CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181513GO, "StateTests/RandomTests/st201503181513GO"} - declare_test!{StateTests_RandomTests_st201503181514CPPJIT, "StateTests/RandomTests/st201503181514CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181514GO, "StateTests/RandomTests/st201503181514GO"} - declare_test!{StateTests_RandomTests_st201503181517CPPJIT, "StateTests/RandomTests/st201503181517CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181517GO, "StateTests/RandomTests/st201503181517GO"} - declare_test!{StateTests_RandomTests_st201503181519CPPJIT, "StateTests/RandomTests/st201503181519CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181519GO, "StateTests/RandomTests/st201503181519GO"} - declare_test!{StateTests_RandomTests_st201503181520CPPJIT, "StateTests/RandomTests/st201503181520CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181520GO, "StateTests/RandomTests/st201503181520GO"} - declare_test!{StateTests_RandomTests_st201503181521GO, "StateTests/RandomTests/st201503181521GO"} - declare_test!{StateTests_RandomTests_st201503181522GO, "StateTests/RandomTests/st201503181522GO"} - declare_test!{StateTests_RandomTests_st201503181524CPPJIT, "StateTests/RandomTests/st201503181524CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181524GO, "StateTests/RandomTests/st201503181524GO"} - declare_test!{StateTests_RandomTests_st201503181526GO, "StateTests/RandomTests/st201503181526GO"} - declare_test!{StateTests_RandomTests_st201503181527GO, "StateTests/RandomTests/st201503181527GO"} - declare_test!{StateTests_RandomTests_st201503181528CPPJIT, "StateTests/RandomTests/st201503181528CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181528GO, "StateTests/RandomTests/st201503181528GO"} - declare_test!{StateTests_RandomTests_st201503181528PYTHON, "StateTests/RandomTests/st201503181528PYTHON"} - declare_test!{StateTests_RandomTests_st201503181529GO, "StateTests/RandomTests/st201503181529GO"} - declare_test!{StateTests_RandomTests_st201503181531CPPJIT, "StateTests/RandomTests/st201503181531CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181533GO, "StateTests/RandomTests/st201503181533GO"} - declare_test!{StateTests_RandomTests_st201503181534CPPJIT, "StateTests/RandomTests/st201503181534CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181534GO, "StateTests/RandomTests/st201503181534GO"} - declare_test!{StateTests_RandomTests_st201503181536CPPJIT, "StateTests/RandomTests/st201503181536CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181536GO, "StateTests/RandomTests/st201503181536GO"} - declare_test!{StateTests_RandomTests_st201503181537GO, "StateTests/RandomTests/st201503181537GO"} - declare_test!{StateTests_RandomTests_st201503181538GO, "StateTests/RandomTests/st201503181538GO"} - declare_test!{StateTests_RandomTests_st201503181539GO, "StateTests/RandomTests/st201503181539GO"} - declare_test!{StateTests_RandomTests_st201503181540CPPJIT, "StateTests/RandomTests/st201503181540CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181540PYTHON, "StateTests/RandomTests/st201503181540PYTHON"} - declare_test!{StateTests_RandomTests_st201503181543GO, "StateTests/RandomTests/st201503181543GO"} - declare_test!{StateTests_RandomTests_st201503181544CPPJIT, "StateTests/RandomTests/st201503181544CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181544GO, "StateTests/RandomTests/st201503181544GO"} - declare_test!{StateTests_RandomTests_st201503181547GO, "StateTests/RandomTests/st201503181547GO"} - declare_test!{StateTests_RandomTests_st201503181548CPPJIT, "StateTests/RandomTests/st201503181548CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181548GO, "StateTests/RandomTests/st201503181548GO"} - declare_test!{StateTests_RandomTests_st201503181551GO, "StateTests/RandomTests/st201503181551GO"} - declare_test!{StateTests_RandomTests_st201503181552CPPJIT, "StateTests/RandomTests/st201503181552CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181553GO, "StateTests/RandomTests/st201503181553GO"} - declare_test!{StateTests_RandomTests_st201503181555CPPJIT, "StateTests/RandomTests/st201503181555CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181555GO, "StateTests/RandomTests/st201503181555GO"} - declare_test!{StateTests_RandomTests_st201503181557GO, "StateTests/RandomTests/st201503181557GO"} - declare_test!{StateTests_RandomTests_st201503181559GO, "StateTests/RandomTests/st201503181559GO"} - declare_test!{StateTests_RandomTests_st201503181601CPPJIT, "StateTests/RandomTests/st201503181601CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181601GO, "StateTests/RandomTests/st201503181601GO"} - declare_test!{StateTests_RandomTests_st201503181602GO, "StateTests/RandomTests/st201503181602GO"} - declare_test!{StateTests_RandomTests_st201503181603GO, "StateTests/RandomTests/st201503181603GO"} - declare_test!{StateTests_RandomTests_st201503181604GO, "StateTests/RandomTests/st201503181604GO"} - declare_test!{StateTests_RandomTests_st201503181605GO, "StateTests/RandomTests/st201503181605GO"} - declare_test!{StateTests_RandomTests_st201503181606GO, "StateTests/RandomTests/st201503181606GO"} - declare_test!{StateTests_RandomTests_st201503181607GO, "StateTests/RandomTests/st201503181607GO"} - declare_test!{StateTests_RandomTests_st201503181608CPPJIT, "StateTests/RandomTests/st201503181608CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181608GO, "StateTests/RandomTests/st201503181608GO"} - declare_test!{StateTests_RandomTests_st201503181609GO, "StateTests/RandomTests/st201503181609GO"} - declare_test!{StateTests_RandomTests_st201503181610CPPJIT, "StateTests/RandomTests/st201503181610CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181610GO, "StateTests/RandomTests/st201503181610GO"} - declare_test!{StateTests_RandomTests_st201503181611CPPJIT, "StateTests/RandomTests/st201503181611CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181611GO, "StateTests/RandomTests/st201503181611GO"} - declare_test!{StateTests_RandomTests_st201503181612GO, "StateTests/RandomTests/st201503181612GO"} - declare_test!{StateTests_RandomTests_st201503181614CPPJIT, "StateTests/RandomTests/st201503181614CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181614GO, "StateTests/RandomTests/st201503181614GO"} - declare_test!{StateTests_RandomTests_st201503181616CPPJIT, "StateTests/RandomTests/st201503181616CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181616GO, "StateTests/RandomTests/st201503181616GO"} - declare_test!{StateTests_RandomTests_st201503181617GO, "StateTests/RandomTests/st201503181617GO"} - declare_test!{StateTests_RandomTests_st201503181618GO, "StateTests/RandomTests/st201503181618GO"} - declare_test!{StateTests_RandomTests_st201503181619GO, "StateTests/RandomTests/st201503181619GO"} - declare_test!{StateTests_RandomTests_st201503181620CPPJIT, "StateTests/RandomTests/st201503181620CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181620GO, "StateTests/RandomTests/st201503181620GO"} - declare_test!{StateTests_RandomTests_st201503181621GO, "StateTests/RandomTests/st201503181621GO"} - declare_test!{StateTests_RandomTests_st201503181625GO, "StateTests/RandomTests/st201503181625GO"} - declare_test!{StateTests_RandomTests_st201503181626CPPJIT, "StateTests/RandomTests/st201503181626CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181626GO, "StateTests/RandomTests/st201503181626GO"} - declare_test!{StateTests_RandomTests_st201503181627GO, "StateTests/RandomTests/st201503181627GO"} - declare_test!{StateTests_RandomTests_st201503181628GO, "StateTests/RandomTests/st201503181628GO"} - declare_test!{StateTests_RandomTests_st201503181629GO, "StateTests/RandomTests/st201503181629GO"} - declare_test!{StateTests_RandomTests_st201503181630CPPJIT, "StateTests/RandomTests/st201503181630CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181630GO, "StateTests/RandomTests/st201503181630GO"} - declare_test!{StateTests_RandomTests_st201503181630PYTHON, "StateTests/RandomTests/st201503181630PYTHON"} - declare_test!{StateTests_RandomTests_st201503181632GO, "StateTests/RandomTests/st201503181632GO"} - declare_test!{StateTests_RandomTests_st201503181634CPPJIT, "StateTests/RandomTests/st201503181634CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181635GO, "StateTests/RandomTests/st201503181635GO"} - declare_test!{StateTests_RandomTests_st201503181636GO, "StateTests/RandomTests/st201503181636GO"} - declare_test!{StateTests_RandomTests_st201503181638GO, "StateTests/RandomTests/st201503181638GO"} - declare_test!{StateTests_RandomTests_st201503181639CPPJIT, "StateTests/RandomTests/st201503181639CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181641GO, "StateTests/RandomTests/st201503181641GO"} - declare_test!{StateTests_RandomTests_st201503181645GO, "StateTests/RandomTests/st201503181645GO"} - declare_test!{StateTests_RandomTests_st201503181646GO, "StateTests/RandomTests/st201503181646GO"} - declare_test!{StateTests_RandomTests_st201503181647CPPJIT, "StateTests/RandomTests/st201503181647CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181649CPPJIT, "StateTests/RandomTests/st201503181649CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181650GO, "StateTests/RandomTests/st201503181650GO"} - declare_test!{StateTests_RandomTests_st201503181652CPPJIT, "StateTests/RandomTests/st201503181652CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181653GO, "StateTests/RandomTests/st201503181653GO"} - declare_test!{StateTests_RandomTests_st201503181654GO, "StateTests/RandomTests/st201503181654GO"} - declare_test!{StateTests_RandomTests_st201503181655CPPJIT, "StateTests/RandomTests/st201503181655CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181655GO, "StateTests/RandomTests/st201503181655GO"} - declare_test!{StateTests_RandomTests_st201503181656CPPJIT, "StateTests/RandomTests/st201503181656CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181656GO, "StateTests/RandomTests/st201503181656GO"} - declare_test!{StateTests_RandomTests_st201503181657GO, "StateTests/RandomTests/st201503181657GO"} - declare_test!{StateTests_RandomTests_st201503181658GO, "StateTests/RandomTests/st201503181658GO"} - declare_test!{StateTests_RandomTests_st201503181700GO, "StateTests/RandomTests/st201503181700GO"} - declare_test!{StateTests_RandomTests_st201503181702GO, "StateTests/RandomTests/st201503181702GO"} - declare_test!{StateTests_RandomTests_st201503181703CPPJIT, "StateTests/RandomTests/st201503181703CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181703GO, "StateTests/RandomTests/st201503181703GO"} - declare_test!{StateTests_RandomTests_st201503181704GO, "StateTests/RandomTests/st201503181704GO"} - declare_test!{StateTests_RandomTests_st201503181706GO, "StateTests/RandomTests/st201503181706GO"} - declare_test!{StateTests_RandomTests_st201503181709GO, "StateTests/RandomTests/st201503181709GO"} - declare_test!{StateTests_RandomTests_st201503181711CPPJIT, "StateTests/RandomTests/st201503181711CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181711GO, "StateTests/RandomTests/st201503181711GO"} - declare_test!{StateTests_RandomTests_st201503181713CPPJIT, "StateTests/RandomTests/st201503181713CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181713GO, "StateTests/RandomTests/st201503181713GO"} - declare_test!{StateTests_RandomTests_st201503181714GO, "StateTests/RandomTests/st201503181714GO"} - declare_test!{StateTests_RandomTests_st201503181715CPPJIT, "StateTests/RandomTests/st201503181715CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181715GO, "StateTests/RandomTests/st201503181715GO"} - declare_test!{StateTests_RandomTests_st201503181716GO, "StateTests/RandomTests/st201503181716GO"} - declare_test!{StateTests_RandomTests_st201503181717GO, "StateTests/RandomTests/st201503181717GO"} - declare_test!{StateTests_RandomTests_st201503181720CPPJIT, "StateTests/RandomTests/st201503181720CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181722GO, "StateTests/RandomTests/st201503181722GO"} - declare_test!{StateTests_RandomTests_st201503181723CPPJIT, "StateTests/RandomTests/st201503181723CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181723GO, "StateTests/RandomTests/st201503181723GO"} - declare_test!{StateTests_RandomTests_st201503181724CPPJIT, "StateTests/RandomTests/st201503181724CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181724GO, "StateTests/RandomTests/st201503181724GO"} - declare_test!{StateTests_RandomTests_st201503181725GO, "StateTests/RandomTests/st201503181725GO"} - declare_test!{StateTests_RandomTests_st201503181728GO, "StateTests/RandomTests/st201503181728GO"} - declare_test!{StateTests_RandomTests_st201503181729GO, "StateTests/RandomTests/st201503181729GO"} - declare_test!{StateTests_RandomTests_st201503181730GO, "StateTests/RandomTests/st201503181730GO"} - declare_test!{StateTests_RandomTests_st201503181731CPPJIT, "StateTests/RandomTests/st201503181731CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181732GO, "StateTests/RandomTests/st201503181732GO"} - declare_test!{StateTests_RandomTests_st201503181734CPPJIT, "StateTests/RandomTests/st201503181734CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181734GO, "StateTests/RandomTests/st201503181734GO"} - declare_test!{StateTests_RandomTests_st201503181735GO, "StateTests/RandomTests/st201503181735GO"} - declare_test!{StateTests_RandomTests_st201503181737CPPJIT, "StateTests/RandomTests/st201503181737CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181737GO, "StateTests/RandomTests/st201503181737GO"} - declare_test!{StateTests_RandomTests_st201503181738CPPJIT, "StateTests/RandomTests/st201503181738CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181738GO, "StateTests/RandomTests/st201503181738GO"} - declare_test!{StateTests_RandomTests_st201503181739GO, "StateTests/RandomTests/st201503181739GO"} - declare_test!{StateTests_RandomTests_st201503181740CPPJIT, "StateTests/RandomTests/st201503181740CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181740GO, "StateTests/RandomTests/st201503181740GO"} - declare_test!{StateTests_RandomTests_st201503181742CPPJIT, "StateTests/RandomTests/st201503181742CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181743GO, "StateTests/RandomTests/st201503181743GO"} - declare_test!{StateTests_RandomTests_st201503181744GO, "StateTests/RandomTests/st201503181744GO"} - declare_test!{StateTests_RandomTests_st201503181745CPPJIT, "StateTests/RandomTests/st201503181745CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181746GO, "StateTests/RandomTests/st201503181746GO"} - declare_test!{StateTests_RandomTests_st201503181747GO, "StateTests/RandomTests/st201503181747GO"} - declare_test!{StateTests_RandomTests_st201503181748GO, "StateTests/RandomTests/st201503181748GO"} - declare_test!{StateTests_RandomTests_st201503181749GO, "StateTests/RandomTests/st201503181749GO"} - declare_test!{StateTests_RandomTests_st201503181750CPPJIT, "StateTests/RandomTests/st201503181750CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181750GO, "StateTests/RandomTests/st201503181750GO"} - declare_test!{StateTests_RandomTests_st201503181752GO, "StateTests/RandomTests/st201503181752GO"} - declare_test!{StateTests_RandomTests_st201503181753CPPJIT, "StateTests/RandomTests/st201503181753CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181754CPPJIT, "StateTests/RandomTests/st201503181754CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181754GO, "StateTests/RandomTests/st201503181754GO"} - declare_test!{StateTests_RandomTests_st201503181755CPPJIT, "StateTests/RandomTests/st201503181755CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181755GO, "StateTests/RandomTests/st201503181755GO"} - declare_test!{StateTests_RandomTests_st201503181756GO, "StateTests/RandomTests/st201503181756GO"} - declare_test!{StateTests_RandomTests_st201503181757CPPJIT, "StateTests/RandomTests/st201503181757CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181757GO, "StateTests/RandomTests/st201503181757GO"} - declare_test!{StateTests_RandomTests_st201503181759GO, "StateTests/RandomTests/st201503181759GO"} - declare_test!{StateTests_RandomTests_st201503181800GO, "StateTests/RandomTests/st201503181800GO"} - declare_test!{StateTests_RandomTests_st201503181801GO, "StateTests/RandomTests/st201503181801GO"} - declare_test!{StateTests_RandomTests_st201503181802GO, "StateTests/RandomTests/st201503181802GO"} - declare_test!{StateTests_RandomTests_st201503181803CPPJIT, "StateTests/RandomTests/st201503181803CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181803GO, "StateTests/RandomTests/st201503181803GO"} - declare_test!{StateTests_RandomTests_st201503181804GO, "StateTests/RandomTests/st201503181804GO"} - declare_test!{StateTests_RandomTests_st201503181806GO, "StateTests/RandomTests/st201503181806GO"} - declare_test!{StateTests_RandomTests_st201503181808GO, "StateTests/RandomTests/st201503181808GO"} - declare_test!{StateTests_RandomTests_st201503181809CPPJIT, "StateTests/RandomTests/st201503181809CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181812CPPJIT, "StateTests/RandomTests/st201503181812CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181812GO, "StateTests/RandomTests/st201503181812GO"} - declare_test!{StateTests_RandomTests_st201503181814CPPJIT, "StateTests/RandomTests/st201503181814CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181815GO, "StateTests/RandomTests/st201503181815GO"} - declare_test!{StateTests_RandomTests_st201503181816CPPJIT, "StateTests/RandomTests/st201503181816CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181817CPPJIT, "StateTests/RandomTests/st201503181817CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181819GO, "StateTests/RandomTests/st201503181819GO"} - declare_test!{StateTests_RandomTests_st201503181821GO, "StateTests/RandomTests/st201503181821GO"} - declare_test!{StateTests_RandomTests_st201503181822GO, "StateTests/RandomTests/st201503181822GO"} - declare_test!{StateTests_RandomTests_st201503181823GO, "StateTests/RandomTests/st201503181823GO"} - declare_test!{StateTests_RandomTests_st201503181824GO, "StateTests/RandomTests/st201503181824GO"} - declare_test!{StateTests_RandomTests_st201503181825GO, "StateTests/RandomTests/st201503181825GO"} - declare_test!{StateTests_RandomTests_st201503181829GO, "StateTests/RandomTests/st201503181829GO"} - declare_test!{StateTests_RandomTests_st201503181830CPPJIT, "StateTests/RandomTests/st201503181830CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181833GO, "StateTests/RandomTests/st201503181833GO"} - declare_test!{StateTests_RandomTests_st201503181834CPPJIT, "StateTests/RandomTests/st201503181834CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181834GO, "StateTests/RandomTests/st201503181834GO"} - declare_test!{StateTests_RandomTests_st201503181837GO, "StateTests/RandomTests/st201503181837GO"} - declare_test!{StateTests_RandomTests_st201503181840GO, "StateTests/RandomTests/st201503181840GO"} - declare_test!{StateTests_RandomTests_st201503181842GO, "StateTests/RandomTests/st201503181842GO"} - declare_test!{StateTests_RandomTests_st201503181843GO, "StateTests/RandomTests/st201503181843GO"} - declare_test!{StateTests_RandomTests_st201503181844GO, "StateTests/RandomTests/st201503181844GO"} - declare_test!{StateTests_RandomTests_st201503181845GO, "StateTests/RandomTests/st201503181845GO"} - declare_test!{StateTests_RandomTests_st201503181846GO, "StateTests/RandomTests/st201503181846GO"} - declare_test!{StateTests_RandomTests_st201503181847GO, "StateTests/RandomTests/st201503181847GO"} - declare_test!{StateTests_RandomTests_st201503181848GO, "StateTests/RandomTests/st201503181848GO"} - declare_test!{StateTests_RandomTests_st201503181849GO, "StateTests/RandomTests/st201503181849GO"} - declare_test!{StateTests_RandomTests_st201503181850GO, "StateTests/RandomTests/st201503181850GO"} - declare_test!{StateTests_RandomTests_st201503181851CPPJIT, "StateTests/RandomTests/st201503181851CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181851GO, "StateTests/RandomTests/st201503181851GO"} - declare_test!{StateTests_RandomTests_st201503181852CPPJIT, "StateTests/RandomTests/st201503181852CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181854GO, "StateTests/RandomTests/st201503181854GO"} - declare_test!{StateTests_RandomTests_st201503181855CPPJIT, "StateTests/RandomTests/st201503181855CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181857PYTHON, "StateTests/RandomTests/st201503181857PYTHON"} - declare_test!{StateTests_RandomTests_st201503181859GO, "StateTests/RandomTests/st201503181859GO"} - declare_test!{StateTests_RandomTests_st201503181900GO, "StateTests/RandomTests/st201503181900GO"} - declare_test!{StateTests_RandomTests_st201503181903GO, "StateTests/RandomTests/st201503181903GO"} - declare_test!{StateTests_RandomTests_st201503181904GO, "StateTests/RandomTests/st201503181904GO"} - declare_test!{StateTests_RandomTests_st201503181906GO, "StateTests/RandomTests/st201503181906GO"} - declare_test!{StateTests_RandomTests_st201503181907GO, "StateTests/RandomTests/st201503181907GO"} - declare_test!{StateTests_RandomTests_st201503181910GO, "StateTests/RandomTests/st201503181910GO"} - declare_test!{StateTests_RandomTests_st201503181915GO, "StateTests/RandomTests/st201503181915GO"} - declare_test!{StateTests_RandomTests_st201503181919CPPJIT, "StateTests/RandomTests/st201503181919CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181919PYTHON, "StateTests/RandomTests/st201503181919PYTHON"} - declare_test!{StateTests_RandomTests_st201503181920GO, "StateTests/RandomTests/st201503181920GO"} - declare_test!{StateTests_RandomTests_st201503181922GO, "StateTests/RandomTests/st201503181922GO"} - declare_test!{StateTests_RandomTests_st201503181926GO, "StateTests/RandomTests/st201503181926GO"} - declare_test!{StateTests_RandomTests_st201503181929GO, "StateTests/RandomTests/st201503181929GO"} - declare_test!{StateTests_RandomTests_st201503181931CPPJIT, "StateTests/RandomTests/st201503181931CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181931GO, "StateTests/RandomTests/st201503181931GO"} - declare_test!{StateTests_RandomTests_st201503181931PYTHON, "StateTests/RandomTests/st201503181931PYTHON"} - declare_test!{StateTests_RandomTests_st201503191646GO, "StateTests/RandomTests/st201503191646GO"} - declare_test!{StateTests_RandomTests_st201503200837JS, "StateTests/RandomTests/st201503200837JS"} - declare_test!{StateTests_RandomTests_st201503200838JS, "StateTests/RandomTests/st201503200838JS"} - declare_test!{StateTests_RandomTests_st201503200841JS, "StateTests/RandomTests/st201503200841JS"} - declare_test!{StateTests_RandomTests_st201503200848JS, "StateTests/RandomTests/st201503200848JS"} - declare_test!{StateTests_RandomTests_st201503240609JS, "StateTests/RandomTests/st201503240609JS"} - declare_test!{StateTests_RandomTests_st201503302200JS, "StateTests/RandomTests/st201503302200JS"} - declare_test!{StateTests_RandomTests_st201503302202JS, "StateTests/RandomTests/st201503302202JS"} - declare_test!{StateTests_RandomTests_st201503302206JS, "StateTests/RandomTests/st201503302206JS"} - declare_test!{StateTests_RandomTests_st201503302208JS, "StateTests/RandomTests/st201503302208JS"} - declare_test!{StateTests_RandomTests_st201503302210JS, "StateTests/RandomTests/st201503302210JS"} - declare_test!{StateTests_RandomTests_st201503302211JS, "StateTests/RandomTests/st201503302211JS"} - declare_test!{StateTests_RandomTests_st201504011535GO, "StateTests/RandomTests/st201504011535GO"} - declare_test!{StateTests_RandomTests_st201504011536GO, "StateTests/RandomTests/st201504011536GO"} - declare_test!{StateTests_RandomTests_st201504011547GO, "StateTests/RandomTests/st201504011547GO"} - declare_test!{StateTests_RandomTests_st201504011916JS, "StateTests/RandomTests/st201504011916JS"} - declare_test!{StateTests_RandomTests_st201504012130JS, "StateTests/RandomTests/st201504012130JS"} - declare_test!{StateTests_RandomTests_st201504012259JS, "StateTests/RandomTests/st201504012259JS"} - declare_test!{StateTests_RandomTests_st201504012359JS, "StateTests/RandomTests/st201504012359JS"} - declare_test!{StateTests_RandomTests_st201504020305JS, "StateTests/RandomTests/st201504020305JS"} - declare_test!{StateTests_RandomTests_st201504020400JS, "StateTests/RandomTests/st201504020400JS"} - declare_test!{StateTests_RandomTests_st201504020428JS, "StateTests/RandomTests/st201504020428JS"} - declare_test!{StateTests_RandomTests_st201504020431JS, "StateTests/RandomTests/st201504020431JS"} - declare_test!{StateTests_RandomTests_st201504020444JS, "StateTests/RandomTests/st201504020444JS"} - declare_test!{StateTests_RandomTests_st201504020538JS, "StateTests/RandomTests/st201504020538JS"} - declare_test!{StateTests_RandomTests_st201504020639JS, "StateTests/RandomTests/st201504020639JS"} - declare_test!{StateTests_RandomTests_st201504020836JS, "StateTests/RandomTests/st201504020836JS"} - declare_test!{StateTests_RandomTests_st201504020910JS, "StateTests/RandomTests/st201504020910JS"} - declare_test!{StateTests_RandomTests_st201504021057JS, "StateTests/RandomTests/st201504021057JS"} - declare_test!{StateTests_RandomTests_st201504021104JS, "StateTests/RandomTests/st201504021104JS"} - declare_test!{StateTests_RandomTests_st201504021237CPPJIT, "StateTests/RandomTests/st201504021237CPPJIT"} - declare_test!{StateTests_RandomTests_st201504021237GO, "StateTests/RandomTests/st201504021237GO"} - declare_test!{StateTests_RandomTests_st201504021237JS, "StateTests/RandomTests/st201504021237JS"} - declare_test!{StateTests_RandomTests_st201504021237PYTHON, "StateTests/RandomTests/st201504021237PYTHON"} - declare_test!{StateTests_RandomTests_st201504021949JS, "StateTests/RandomTests/st201504021949JS"} - declare_test!{StateTests_RandomTests_st201504022003CPPJIT, "StateTests/RandomTests/st201504022003CPPJIT"} - declare_test!{StateTests_RandomTests_st201504022124JS, "StateTests/RandomTests/st201504022124JS"} - declare_test!{StateTests_RandomTests_st201504030138JS, "StateTests/RandomTests/st201504030138JS"} - declare_test!{StateTests_RandomTests_st201504030646JS, "StateTests/RandomTests/st201504030646JS"} - declare_test!{StateTests_RandomTests_st201504030709JS, "StateTests/RandomTests/st201504030709JS"} - declare_test!{StateTests_RandomTests_st201504031133JS, "StateTests/RandomTests/st201504031133JS"} - declare_test!{StateTests_RandomTests_st201504031446JS, "StateTests/RandomTests/st201504031446JS"} - declare_test!{StateTests_RandomTests_st201504031841JS, "StateTests/RandomTests/st201504031841JS"} - declare_test!{StateTests_RandomTests_st201504041605JS, "StateTests/RandomTests/st201504041605JS"} - declare_test!{StateTests_RandomTests_st201504042052JS, "StateTests/RandomTests/st201504042052JS"} - declare_test!{StateTests_RandomTests_st201504042226CPPJIT, "StateTests/RandomTests/st201504042226CPPJIT"} - declare_test!{StateTests_RandomTests_st201504042355CPPJIT, "StateTests/RandomTests/st201504042355CPPJIT"} - declare_test!{StateTests_RandomTests_st201504050059JS, "StateTests/RandomTests/st201504050059JS"} - declare_test!{StateTests_RandomTests_st201504050733JS, "StateTests/RandomTests/st201504050733JS"} - declare_test!{StateTests_RandomTests_st201504051540JS, "StateTests/RandomTests/st201504051540JS"} - declare_test!{StateTests_RandomTests_st201504051944CPPJIT, "StateTests/RandomTests/st201504051944CPPJIT"} - declare_test!{StateTests_RandomTests_st201504052008CPPJIT, "StateTests/RandomTests/st201504052008CPPJIT"} - declare_test!{StateTests_RandomTests_st201504052014GO, "StateTests/RandomTests/st201504052014GO"} - declare_test!{StateTests_RandomTests_st201504052031CPPJIT, "StateTests/RandomTests/st201504052031CPPJIT"} - declare_test!{StateTests_RandomTests_st201504060057CPPJIT, "StateTests/RandomTests/st201504060057CPPJIT"} - declare_test!{StateTests_RandomTests_st201504060418CPPJIT, "StateTests/RandomTests/st201504060418CPPJIT"} - declare_test!{StateTests_RandomTests_st201504061106CPPJIT, "StateTests/RandomTests/st201504061106CPPJIT"} - declare_test!{StateTests_RandomTests_st201504061134CPPJIT, "StateTests/RandomTests/st201504061134CPPJIT"} - declare_test!{StateTests_RandomTests_st201504062033CPPJIT, "StateTests/RandomTests/st201504062033CPPJIT"} - declare_test!{StateTests_RandomTests_st201504062046CPPJIT, "StateTests/RandomTests/st201504062046CPPJIT"} - declare_test!{StateTests_RandomTests_st201504062314CPPJIT, "StateTests/RandomTests/st201504062314CPPJIT"} - declare_test!{StateTests_RandomTests_st201504070746JS, "StateTests/RandomTests/st201504070746JS"} - declare_test!{StateTests_RandomTests_st201504070816CPPJIT, "StateTests/RandomTests/st201504070816CPPJIT"} - declare_test!{StateTests_RandomTests_st201504070836CPPJIT, "StateTests/RandomTests/st201504070836CPPJIT"} - declare_test!{StateTests_RandomTests_st201504070839CPPJIT, "StateTests/RandomTests/st201504070839CPPJIT"} - declare_test!{StateTests_RandomTests_st201504071041CPPJIT, "StateTests/RandomTests/st201504071041CPPJIT"} - declare_test!{StateTests_RandomTests_st201504071056CPPJIT, "StateTests/RandomTests/st201504071056CPPJIT"} - declare_test!{StateTests_RandomTests_st201504071621CPPJIT, "StateTests/RandomTests/st201504071621CPPJIT"} - declare_test!{StateTests_RandomTests_st201504071653CPPJIT, "StateTests/RandomTests/st201504071653CPPJIT"} - declare_test!{StateTests_RandomTests_st201504071750CPPJIT, "StateTests/RandomTests/st201504071750CPPJIT"} - declare_test!{StateTests_RandomTests_st201504071905CPPJIT, "StateTests/RandomTests/st201504071905CPPJIT"} - declare_test!{StateTests_RandomTests_st201504080454CPPJIT, "StateTests/RandomTests/st201504080454CPPJIT"} - declare_test!{StateTests_RandomTests_st201504080457CPPJIT, "StateTests/RandomTests/st201504080457CPPJIT"} - declare_test!{StateTests_RandomTests_st201504080650CPPJIT, "StateTests/RandomTests/st201504080650CPPJIT"} - declare_test!{StateTests_RandomTests_st201504080840CPPJIT, "StateTests/RandomTests/st201504080840CPPJIT"} - declare_test!{StateTests_RandomTests_st201504080948CPPJIT, "StateTests/RandomTests/st201504080948CPPJIT"} - declare_test!{StateTests_RandomTests_st201504081100CPPJIT, "StateTests/RandomTests/st201504081100CPPJIT"} - declare_test!{StateTests_RandomTests_st201504081134CPPJIT, "StateTests/RandomTests/st201504081134CPPJIT"} - declare_test!{StateTests_RandomTests_st201504081138CPPJIT, "StateTests/RandomTests/st201504081138CPPJIT"} - declare_test!{StateTests_RandomTests_st201504081611CPPJIT, "StateTests/RandomTests/st201504081611CPPJIT"} - declare_test!{StateTests_RandomTests_st201504081841JAVA, "StateTests/RandomTests/st201504081841JAVA"} - declare_test!{StateTests_RandomTests_st201504081842JAVA, "StateTests/RandomTests/st201504081842JAVA"} - declare_test!{StateTests_RandomTests_st201504081843JAVA, "StateTests/RandomTests/st201504081843JAVA"} - declare_test!{StateTests_RandomTests_st201504081928CPPJIT, "StateTests/RandomTests/st201504081928CPPJIT"} - declare_test!{StateTests_RandomTests_st201504081953JAVA, "StateTests/RandomTests/st201504081953JAVA"} - declare_test!{StateTests_RandomTests_st201504081954JAVA, "StateTests/RandomTests/st201504081954JAVA"} - declare_test!{StateTests_RandomTests_st201504081955JAVA, "StateTests/RandomTests/st201504081955JAVA"} - declare_test!{StateTests_RandomTests_st201504081956JAVA, "StateTests/RandomTests/st201504081956JAVA"} - declare_test!{StateTests_RandomTests_st201504081957JAVA, "StateTests/RandomTests/st201504081957JAVA"} - declare_test!{StateTests_RandomTests_st201504082000JAVA, "StateTests/RandomTests/st201504082000JAVA"} - declare_test!{StateTests_RandomTests_st201504082001JAVA, "StateTests/RandomTests/st201504082001JAVA"} - declare_test!{StateTests_RandomTests_st201504082002JAVA, "StateTests/RandomTests/st201504082002JAVA"} - declare_test!{StateTests_RandomTests_st201504090553CPPJIT, "StateTests/RandomTests/st201504090553CPPJIT"} - declare_test!{StateTests_RandomTests_st201504090657CPPJIT, "StateTests/RandomTests/st201504090657CPPJIT"} - declare_test!{StateTests_RandomTests_st201504091403CPPJIT, "StateTests/RandomTests/st201504091403CPPJIT"} - declare_test!{StateTests_RandomTests_st201504091641CPPJIT, "StateTests/RandomTests/st201504091641CPPJIT"} - declare_test!{StateTests_RandomTests_st201504092303CPPJIT, "StateTests/RandomTests/st201504092303CPPJIT"} - declare_test!{StateTests_RandomTests_st201504100125CPPJIT, "StateTests/RandomTests/st201504100125CPPJIT"} - declare_test!{StateTests_RandomTests_st201504100215CPPJIT, "StateTests/RandomTests/st201504100215CPPJIT"} - declare_test!{StateTests_RandomTests_st201504100226PYTHON, "StateTests/RandomTests/st201504100226PYTHON"} - declare_test!{StateTests_RandomTests_st201504100308CPPJIT, "StateTests/RandomTests/st201504100308CPPJIT"} - declare_test!{StateTests_RandomTests_st201504100337CPPJIT, "StateTests/RandomTests/st201504100337CPPJIT"} - declare_test!{StateTests_RandomTests_st201504100341CPPJIT, "StateTests/RandomTests/st201504100341CPPJIT"} - declare_test!{StateTests_RandomTests_st201504101009CPPJIT, "StateTests/RandomTests/st201504101009CPPJIT"} - declare_test!{StateTests_RandomTests_st201504101150CPPJIT, "StateTests/RandomTests/st201504101150CPPJIT"} - declare_test!{StateTests_RandomTests_st201504101223CPPJIT, "StateTests/RandomTests/st201504101223CPPJIT"} - declare_test!{StateTests_RandomTests_st201504101338CPPJIT, "StateTests/RandomTests/st201504101338CPPJIT"} - declare_test!{StateTests_RandomTests_st201504101754PYTHON, "StateTests/RandomTests/st201504101754PYTHON"} - declare_test!{StateTests_RandomTests_st201504111554CPPJIT, "StateTests/RandomTests/st201504111554CPPJIT"} - declare_test!{StateTests_RandomTests_st201504130653JS, "StateTests/RandomTests/st201504130653JS"} - declare_test!{StateTests_RandomTests_st201504131821CPPJIT, "StateTests/RandomTests/st201504131821CPPJIT"} - declare_test!{StateTests_RandomTests_st201504140229CPPJIT, "StateTests/RandomTests/st201504140229CPPJIT"} - declare_test!{StateTests_RandomTests_st201504140236CPPJIT, "StateTests/RandomTests/st201504140236CPPJIT"} - declare_test!{StateTests_RandomTests_st201504140359CPPJIT, "StateTests/RandomTests/st201504140359CPPJIT"} - declare_test!{StateTests_RandomTests_st201504140750CPPJIT, "StateTests/RandomTests/st201504140750CPPJIT"} - declare_test!{StateTests_RandomTests_st201504140818CPPJIT, "StateTests/RandomTests/st201504140818CPPJIT"} - declare_test!{StateTests_RandomTests_st201504140900CPPJIT, "StateTests/RandomTests/st201504140900CPPJIT"} - declare_test!{StateTests_RandomTests_st201504150854CPPJIT, "StateTests/RandomTests/st201504150854CPPJIT"} - declare_test!{StateTests_RandomTests_st201504151057CPPJIT, "StateTests/RandomTests/st201504151057CPPJIT"} - declare_test!{StateTests_RandomTests_st201504202124CPPJIT, "StateTests/RandomTests/st201504202124CPPJIT"} - declare_test!{StateTests_RandomTests_st201504210245CPPJIT, "StateTests/RandomTests/st201504210245CPPJIT"} - declare_test!{StateTests_RandomTests_st201504210957CPPJIT, "StateTests/RandomTests/st201504210957CPPJIT"} - declare_test!{StateTests_RandomTests_st201504211739CPPJIT, "StateTests/RandomTests/st201504211739CPPJIT"} - declare_test!{StateTests_RandomTests_st201504212038CPPJIT, "StateTests/RandomTests/st201504212038CPPJIT"} - declare_test!{StateTests_RandomTests_st201504230729CPPJIT, "StateTests/RandomTests/st201504230729CPPJIT"} - declare_test!{StateTests_RandomTests_st201504231639CPPJIT, "StateTests/RandomTests/st201504231639CPPJIT"} - declare_test!{StateTests_RandomTests_st201504231710CPPJIT, "StateTests/RandomTests/st201504231710CPPJIT"} - declare_test!{StateTests_RandomTests_st201504231742CPPJIT, "StateTests/RandomTests/st201504231742CPPJIT"} - declare_test!{StateTests_RandomTests_st201504232350CPPJIT, "StateTests/RandomTests/st201504232350CPPJIT"} - declare_test!{StateTests_RandomTests_st201504240140CPPJIT, "StateTests/RandomTests/st201504240140CPPJIT"} - declare_test!{StateTests_RandomTests_st201504240220CPPJIT, "StateTests/RandomTests/st201504240220CPPJIT"} - declare_test!{StateTests_RandomTests_st201504240351CPPJIT, "StateTests/RandomTests/st201504240351CPPJIT"} - declare_test!{StateTests_RandomTests_st201504240817CPPJIT, "StateTests/RandomTests/st201504240817CPPJIT"} - declare_test!{StateTests_RandomTests_st201504241118CPPJIT, "StateTests/RandomTests/st201504241118CPPJIT"} - declare_test!{StateTests_RandomTests_st201505021810CPPJIT, "StateTests/RandomTests/st201505021810CPPJIT"} - declare_test!{StateTests_RandomTests_st201505050557JS, "StateTests/RandomTests/st201505050557JS"} - declare_test!{StateTests_RandomTests_st201505050929GO, "StateTests/RandomTests/st201505050929GO"} - declare_test!{StateTests_RandomTests_st201505050942PYTHON, "StateTests/RandomTests/st201505050942PYTHON"} - declare_test!{StateTests_RandomTests_st201505051004PYTHON, "StateTests/RandomTests/st201505051004PYTHON"} - declare_test!{StateTests_RandomTests_st201505051016PYTHON, "StateTests/RandomTests/st201505051016PYTHON"} - declare_test!{StateTests_RandomTests_st201505051114GO, "StateTests/RandomTests/st201505051114GO"} - declare_test!{StateTests_RandomTests_st201505051238GO, "StateTests/RandomTests/st201505051238GO"} - declare_test!{StateTests_RandomTests_st201505051249GO, "StateTests/RandomTests/st201505051249GO"} - declare_test!{StateTests_RandomTests_st201505051558PYTHON, "StateTests/RandomTests/st201505051558PYTHON"} - declare_test!{StateTests_RandomTests_st201505051611PYTHON, "StateTests/RandomTests/st201505051611PYTHON"} - declare_test!{StateTests_RandomTests_st201505051648JS, "StateTests/RandomTests/st201505051648JS"} - declare_test!{StateTests_RandomTests_st201505051710GO, "StateTests/RandomTests/st201505051710GO"} - declare_test!{StateTests_RandomTests_st201505052013GO, "StateTests/RandomTests/st201505052013GO"} - declare_test!{StateTests_RandomTests_st201505052102JS, "StateTests/RandomTests/st201505052102JS"} - declare_test!{StateTests_RandomTests_st201505052235GO, "StateTests/RandomTests/st201505052235GO"} - declare_test!{StateTests_RandomTests_st201505052238JS, "StateTests/RandomTests/st201505052238JS"} - declare_test!{StateTests_RandomTests_st201505052242PYTHON, "StateTests/RandomTests/st201505052242PYTHON"} - declare_test!{StateTests_RandomTests_st201505052343PYTHON, "StateTests/RandomTests/st201505052343PYTHON"} - declare_test!{StateTests_RandomTests_st201505060120GO, "StateTests/RandomTests/st201505060120GO"} - declare_test!{StateTests_RandomTests_st201505060121GO, "StateTests/RandomTests/st201505060121GO"} - declare_test!{StateTests_RandomTests_st201505060136PYTHON, "StateTests/RandomTests/st201505060136PYTHON"} - declare_test!{StateTests_RandomTests_st201505060646JS, "StateTests/RandomTests/st201505060646JS"} - declare_test!{StateTests_RandomTests_st201505252314CPPJIT, "StateTests/RandomTests/st201505252314CPPJIT"} - declare_test!{StateTests_RandomTests_st201505272131CPPJIT, "StateTests/RandomTests/st201505272131CPPJIT"} - declare_test!{StateTests_RandomTests_st201506040034GO, "StateTests/RandomTests/st201506040034GO"} - declare_test!{StateTests_RandomTests_st201506040157GO, "StateTests/RandomTests/st201506040157GO"} - declare_test!{StateTests_RandomTests_st201506052130GO, "StateTests/RandomTests/st201506052130GO"} - declare_test!{StateTests_RandomTests_st201506060929GO, "StateTests/RandomTests/st201506060929GO"} - declare_test!{StateTests_RandomTests_st201506061255GO, "StateTests/RandomTests/st201506061255GO"} - declare_test!{StateTests_RandomTests_st201506062331GO, "StateTests/RandomTests/st201506062331GO"} - declare_test!{StateTests_RandomTests_st201506070548GO, "StateTests/RandomTests/st201506070548GO"} - declare_test!{StateTests_RandomTests_st201506071050GO, "StateTests/RandomTests/st201506071050GO"} - declare_test!{StateTests_RandomTests_st201506071624GO, "StateTests/RandomTests/st201506071624GO"} - declare_test!{StateTests_RandomTests_st201506071819GO, "StateTests/RandomTests/st201506071819GO"} - declare_test!{StateTests_RandomTests_st201506072007GO, "StateTests/RandomTests/st201506072007GO"} - declare_test!{StateTests_RandomTests_st201506080556GO, "StateTests/RandomTests/st201506080556GO"} - declare_test!{StateTests_RandomTests_st201506080721GO, "StateTests/RandomTests/st201506080721GO"} - declare_test!{StateTests_RandomTests_st201506091836GO, "StateTests/RandomTests/st201506091836GO"} - declare_test!{StateTests_RandomTests_st201506092032GO, "StateTests/RandomTests/st201506092032GO"} - declare_test!{StateTests_RandomTests_st201506101359JS, "StateTests/RandomTests/st201506101359JS"} - declare_test!{StateTests_RandomTests_st201507030359GO, "StateTests/RandomTests/st201507030359GO"} + declare_test!{GeneralStateTest_stAttackTest, "GeneralStateTests/stAttackTest/"} + declare_test!{GeneralStateTest_stBlockHashTest, "GeneralStateTests/stBlockHashTest/"} + declare_test!{GeneralStateTest_stBoundsTest, "GeneralStateTests/stBoundsTest/"} + declare_test!{GeneralStateTest_stCallCodes, "GeneralStateTests/stCallCodes/"} + declare_test!{skip => [ "createJS_ExampleContract" ], GeneralStateTest_stCallCreateCallCodeTest, "GeneralStateTests/stCallCreateCallCodeTest/"} + declare_test!{GeneralStateTest_stCallDelegateCodesCallCodeHomestead, "GeneralStateTests/stCallDelegateCodesCallCodeHomestead/"} + declare_test!{GeneralStateTest_stCallDelegateCodesHomestead, "GeneralStateTests/stCallDelegateCodesHomestead/"} + declare_test!{GeneralStateTest_stChangedEIP150, "GeneralStateTests/stChangedEIP150/"} + declare_test!{GeneralStateTest_stCodeSizeLimit, "GeneralStateTests/stCodeSizeLimit/"} + declare_test!{GeneralStateTest_stCreateTest, "GeneralStateTests/stCreateTest/"} + declare_test!{GeneralStateTest_stDelegatecallTestHomestead, "GeneralStateTests/stDelegatecallTestHomestead/"} + declare_test!{GeneralStateTest_stEIP150singleCodeGasPrices, "GeneralStateTests/stEIP150singleCodeGasPrices/"} + declare_test!{GeneralStateTest_stEIP150Specific, "GeneralStateTests/stEIP150Specific/"} + declare_test!{GeneralStateTest_stExample, "GeneralStateTests/stExample/"} + declare_test!{GeneralStateTest_stHomesteadSpecific, "GeneralStateTests/stHomesteadSpecific/"} + declare_test!{GeneralStateTest_stInitCodeTest, "GeneralStateTests/stInitCodeTest/"} + declare_test!{GeneralStateTest_stLogTests, "GeneralStateTests/stLogTests/"} + declare_test!{GeneralStateTest_stMemExpandingEIP150Calls, "GeneralStateTests/stMemExpandingEIP150Calls/"} + declare_test!{heavy => GeneralStateTest_stMemoryStressTest, "GeneralStateTests/stMemoryStressTest/"} + declare_test!{GeneralStateTest_stMemoryTest, "GeneralStateTests/stMemoryTest/"} + declare_test!{GeneralStateTest_stNonZeroCallsTest, "GeneralStateTests/stNonZeroCallsTest/"} + declare_test!{GeneralStateTest_stPreCompiledContracts, "GeneralStateTests/stPreCompiledContracts/"} + declare_test!{heavy => GeneralStateTest_stQuadraticComplexityTest, "GeneralStateTests/stQuadraticComplexityTest/"} + declare_test!{GeneralStateTest_stRandom, "GeneralStateTests/stRandom/"} + declare_test!{GeneralStateTest_stRecursiveCreate, "GeneralStateTests/stRecursiveCreate/"} + declare_test!{GeneralStateTest_stRefundTest, "GeneralStateTests/stRefundTest/"} + declare_test!{skip => [ "RevertDepthCreateAddressCollision" ], GeneralStateTest_stRevertTest, "GeneralStateTests/stRevertTest/"} + declare_test!{GeneralStateTest_stSolidityTest, "GeneralStateTests/stSolidityTest/"} + declare_test!{GeneralStateTest_stSpecialTest, "GeneralStateTests/stSpecialTest/"} + declare_test!{GeneralStateTest_stStackTests, "GeneralStateTests/stStackTests/"} + declare_test!{GeneralStateTest_stSystemOperationsTest, "GeneralStateTests/stSystemOperationsTest/"} + declare_test!{GeneralStateTest_stTransactionTest, "GeneralStateTests/stTransactionTest/"} + declare_test!{GeneralStateTest_stTransitionTest, "GeneralStateTests/stTransitionTest/"} + declare_test!{GeneralStateTest_stWalletTest, "GeneralStateTests/stWalletTest/"} + declare_test!{GeneralStateTest_stZeroCallsRevert, "GeneralStateTests/stZeroCallsRevert/"} + declare_test!{GeneralStateTest_stZeroCallsTest, "GeneralStateTests/stZeroCallsTest/"} } + diff --git a/ethcore/src/json_tests/test_common.rs b/ethcore/src/json_tests/test_common.rs index fd612b994..f9716d221 100644 --- a/ethcore/src/json_tests/test_common.rs +++ b/ethcore/src/json_tests/test_common.rs @@ -15,21 +15,63 @@ // along with Parity. If not, see . pub use util::*; +use std::fs::{File, read_dir}; +use std::path::Path; +use std::ffi::OsString; + +pub fn run_test_path(p: &Path, skip: &[&'static str], runner: fn (json_data: &[u8]) -> Vec) { + let path = Path::new(p); + let s: HashSet = skip.iter().map(|s| { + let mut os: OsString = s.into(); + os.push(".json"); + os + }).collect(); + if path.is_dir() { + for p in read_dir(path).unwrap().filter_map(|e| { + let e = e.unwrap(); + if s.contains(&e.file_name()) { + None + } else { + Some(e.path()) + }}) { + run_test_path(&p, skip, runner) + } + } else { + let mut path = p.to_path_buf(); + path.set_extension("json"); + run_test_file(&path, runner) + } +} + +pub fn run_test_file(path: &Path, runner: fn (json_data: &[u8]) -> Vec) { + let mut data = Vec::new(); + let mut file = File::open(&path).expect("Error opening test file"); + file.read_to_end(&mut data).expect("Error reading test file"); + let results = runner(&data); + assert!(results.is_empty()); +} macro_rules! test { - ($name: expr) => { - assert!(do_json_test(include_bytes!(concat!("../../res/ethereum/tests/", $name, ".json"))).is_empty()); + ($name: expr, $skip: expr) => { + ::json_tests::test_common::run_test_path(::std::path::Path::new(concat!("res/ethereum/tests/", $name)), &$skip, do_json_test); } } #[macro_export] macro_rules! declare_test { + (skip => $arr: expr, $id: ident, $name: expr) => { + #[test] + #[allow(non_snake_case)] + fn $id() { + test!($name, $arr); + } + }; (ignore => $id: ident, $name: expr) => { #[ignore] #[test] #[allow(non_snake_case)] fn $id() { - test!($name); + test!($name, []); } }; (heavy => $id: ident, $name: expr) => { @@ -37,14 +79,14 @@ macro_rules! declare_test { #[test] #[allow(non_snake_case)] fn $id() { - test!($name); + test!($name, []); } }; ($id: ident, $name: expr) => { #[test] #[allow(non_snake_case)] fn $id() { - test!($name); + test!($name, []); } } } diff --git a/ethcore/src/tests/helpers.rs b/ethcore/src/tests/helpers.rs index 2f55fd581..70269b6e4 100644 --- a/ethcore/src/tests/helpers.rs +++ b/ethcore/src/tests/helpers.rs @@ -42,7 +42,7 @@ pub enum ChainEra { Frontier, Homestead, Eip150, - Eip161, + _Eip161, TransitionTest, } @@ -359,12 +359,23 @@ pub fn get_temp_state() -> GuardedTempResult> { } } +pub fn get_temp_mem_state() -> State<::state_db::StateDB> { + let journal_db = get_temp_mem_state_db(); + State::new(journal_db, U256::from(0), Default::default()) +} + pub fn get_temp_state_db_in(path: &Path) -> StateDB { let db = new_db(path.to_str().expect("Only valid utf8 paths for tests.")); let journal_db = journaldb::new(db.clone(), journaldb::Algorithm::EarlyMerge, ::db::COL_STATE); StateDB::new(journal_db, 5 * 1024 * 1024) } +pub fn get_temp_mem_state_db() -> StateDB { + let db = Arc::new(::util::kvdb::in_memory(::db::NUM_COLUMNS.unwrap_or(0))); + let journal_db = journaldb::new(db, journaldb::Algorithm::EarlyMerge, ::db::COL_STATE); + StateDB::new(journal_db, 5 * 1024 * 1024) +} + pub fn get_temp_state_in(path: &Path) -> State<::state_db::StateDB> { let journal_db = get_temp_state_db_in(path); State::new(journal_db, U256::from(0), Default::default()) diff --git a/ethcrypto/src/lib.rs b/ethcrypto/src/lib.rs index 9c1352087..ea0ea9754 100644 --- a/ethcrypto/src/lib.rs +++ b/ethcrypto/src/lib.rs @@ -94,11 +94,11 @@ pub trait Keccak256 { fn keccak256(&self) -> T where T: Sized; } -impl Keccak256<[u8; 32]> for [u8] { +impl Keccak256<[u8; 32]> for T where T: AsRef<[u8]> { fn keccak256(&self) -> [u8; 32] { let mut keccak = Keccak::new_keccak256(); let mut result = [0u8; 32]; - keccak.update(self); + keccak.update(self.as_ref()); keccak.finalize(&mut result); result } diff --git a/ethstore/Cargo.toml b/ethstore/Cargo.toml index a6a0d1752..cd2a11db1 100755 --- a/ethstore/Cargo.toml +++ b/ethstore/Cargo.toml @@ -19,10 +19,10 @@ time = "0.1.34" itertools = "0.5" parking_lot = "0.4" ethcrypto = { path = "../ethcrypto" } -ethcore-util = { path = "../util" } +ethcore-bigint = { path = "../util/bigint" } smallvec = "0.3.1" -ethcore-devtools = { path = "../devtools" } parity-wordlist = "1.0" +tempdir = "0.3" [features] cli = ["docopt"] diff --git a/ethstore/src/account/crypto.rs b/ethstore/src/account/crypto.rs index adcae997d..343e44cb4 100755 --- a/ethstore/src/account/crypto.rs +++ b/ethstore/src/account/crypto.rs @@ -15,6 +15,7 @@ // along with Parity. If not, see . use std::iter::repeat; +use std::str; use ethkey::Secret; use {json, Error, crypto}; use crypto::Keccak256; @@ -46,22 +47,38 @@ impl From for Crypto { } } -impl Into for Crypto { - fn into(self) -> json::Crypto { +impl From for json::Crypto { + fn from(c: Crypto) -> Self { json::Crypto { - cipher: self.cipher.into(), - ciphertext: self.ciphertext.into(), - kdf: self.kdf.into(), - mac: self.mac.into(), + cipher: c.cipher.into(), + ciphertext: c.ciphertext.into(), + kdf: c.kdf.into(), + mac: c.mac.into(), } } } +impl str::FromStr for Crypto { + type Err = ::Err; + + fn from_str(s: &str) -> Result { + s.parse::().map(Into::into) + } +} + +impl From for String { + fn from(c: Crypto) -> Self { + json::Crypto::from(c).into() + } +} + impl Crypto { + /// Encrypt account secret pub fn with_secret(secret: &Secret, password: &str, iterations: u32) -> Self { Crypto::with_plain(&*secret, password, iterations) } + /// Encrypt custom plain data pub fn with_plain(plain: &[u8], password: &str, iterations: u32) -> Self { let salt: [u8; 32] = Random::random(); let iv: [u8; 16] = Random::random(); @@ -98,6 +115,7 @@ impl Crypto { } } + /// Try to decrypt and convert result to account secret pub fn secret(&self, password: &str) -> Result { if self.ciphertext.len() > 32 { return Err(Error::InvalidSecret); @@ -107,6 +125,7 @@ impl Crypto { Ok(Secret::from_slice(&secret)?) } + /// Try to decrypt and return result as is pub fn decrypt(&self, password: &str) -> Result, Error> { let expected_len = self.ciphertext.len(); self.do_decrypt(password, expected_len) diff --git a/ethstore/src/dir/disk.rs b/ethstore/src/dir/disk.rs index afca0955d..3f56ebe40 100755 --- a/ethstore/src/dir/disk.rs +++ b/ethstore/src/dir/disk.rs @@ -225,8 +225,8 @@ impl KeyDirectory for DiskDirectory where T: KeyFileManager { Some(self) } - fn unique_repr(&self) -> Result { - self.files_hash() + fn unique_repr(&self) -> Result { + self.files_hash() } } @@ -280,12 +280,14 @@ impl KeyFileManager for DiskKeyFileManager { #[cfg(test)] mod test { + extern crate tempdir; + use std::{env, fs}; use super::RootDiskDirectory; use dir::{KeyDirectory, VaultKey}; use account::SafeAccount; use ethkey::{Random, Generator}; - use devtools::RandomTempPath; + use self::tempdir::TempDir; #[test] fn should_create_new_account() { @@ -344,7 +346,7 @@ mod test { #[test] fn should_list_vaults() { // given - let temp_path = RandomTempPath::new(); + let temp_path = TempDir::new("").unwrap(); let directory = RootDiskDirectory::create(&temp_path).unwrap(); let vault_provider = directory.as_vault_provider().unwrap(); vault_provider.create("vault1", VaultKey::new("password1", 1)).unwrap(); @@ -359,11 +361,11 @@ mod test { #[test] fn hash_of_files() { - let temp_path = RandomTempPath::new(); + let temp_path = TempDir::new("").unwrap(); let directory = RootDiskDirectory::create(&temp_path).unwrap(); - let hash = directory.files_hash().expect("Files hash should be calculated ok"); - assert_eq!( + let hash = directory.files_hash().expect("Files hash should be calculated ok"); + assert_eq!( hash, 15130871412783076140 ); @@ -373,7 +375,7 @@ mod test { let account = SafeAccount::create(&keypair, [0u8; 16], password, 1024, "Test".to_owned(), "{}".to_owned()); directory.insert(account).expect("Account should be inserted ok"); - let new_hash = directory.files_hash().expect("New files hash should be calculated ok"); + let new_hash = directory.files_hash().expect("New files hash should be calculated ok"); assert!(new_hash != hash, "hash of the file list should change once directory content changed"); } diff --git a/ethstore/src/dir/vault.rs b/ethstore/src/dir/vault.rs index f321e3fbb..31c99fcc4 100755 --- a/ethstore/src/dir/vault.rs +++ b/ethstore/src/dir/vault.rs @@ -18,7 +18,7 @@ use std::{fs, io}; use std::path::{PathBuf, Path}; use parking_lot::Mutex; use {json, SafeAccount, Error}; -use util::sha3::Hashable; +use crypto::Keccak256; use super::super::account::Crypto; use super::{KeyDirectory, VaultKeyDirectory, VaultKey, SetKeyError}; use super::disk::{DiskDirectory, KeyFileManager}; @@ -234,7 +234,7 @@ fn check_vault_name(name: &str) -> bool { /// Vault can be empty, but still must be pluggable => we store vault password in separate file fn create_vault_file

(vault_dir_path: P, key: &VaultKey, meta: &str) -> Result<(), Error> where P: AsRef { - let password_hash = key.password.sha3(); + let password_hash = key.password.keccak256(); let crypto = Crypto::with_plain(&password_hash, &key.password, key.iterations); let mut vault_file_path: PathBuf = vault_dir_path.as_ref().into(); @@ -268,8 +268,8 @@ fn read_vault_file

(vault_dir_path: P, key: Option<&VaultKey>) -> Result(vault_dir_path: P, key: Option<&VaultKey>) -> Result KeyPair { Random.generate().unwrap() @@ -642,13 +643,13 @@ mod tests { struct RootDiskDirectoryGuard { pub key_dir: Option>, - _path: RandomTempPath, + _path: TempDir, } impl RootDiskDirectoryGuard { pub fn new() -> Self { - let temp_path = RandomTempPath::new(); - let disk_dir = Box::new(RootDiskDirectory::create(temp_path.as_path()).unwrap()); + let temp_path = TempDir::new("").unwrap(); + let disk_dir = Box::new(RootDiskDirectory::create(temp_path.path()).unwrap()); RootDiskDirectoryGuard { key_dir: Some(disk_dir), diff --git a/ethstore/src/json/crypto.rs b/ethstore/src/json/crypto.rs index 63d73845f..ee1f08502 100644 --- a/ethstore/src/json/crypto.rs +++ b/ethstore/src/json/crypto.rs @@ -14,10 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use std::fmt; +use std::{fmt, str}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::ser::SerializeStruct; use serde::de::{Visitor, MapVisitor, Error}; +use serde_json; use super::{Cipher, CipherSer, CipherSerParams, Kdf, KdfSer, KdfSerParams, H256, Bytes}; pub type CipherText = Bytes; @@ -30,6 +31,20 @@ pub struct Crypto { pub mac: H256, } +impl str::FromStr for Crypto { + type Err = serde_json::error::Error; + + fn from_str(s: &str) -> Result { + serde_json::from_str(s) + } +} + +impl From for String { + fn from(c: Crypto) -> Self { + serde_json::to_string(&c).expect("serialization cannot fail, cause all crypto keys are strings") + } +} + enum CryptoField { Cipher, CipherParams, diff --git a/ethstore/src/lib.rs b/ethstore/src/lib.rs index 3661cf8f2..145a58023 100755 --- a/ethstore/src/lib.rs +++ b/ethstore/src/lib.rs @@ -29,9 +29,9 @@ extern crate serde_json; extern crate smallvec; extern crate time; extern crate tiny_keccak; +extern crate tempdir; -extern crate ethcore_devtools as devtools; -extern crate ethcore_util as util; +extern crate ethcore_bigint as bigint; extern crate ethcrypto as crypto; extern crate ethkey as _ethkey; extern crate parity_wordlist; @@ -54,7 +54,7 @@ mod presale; mod random; mod secret_store; -pub use self::account::SafeAccount; +pub use self::account::{SafeAccount, Crypto}; pub use self::error::Error; pub use self::ethstore::{EthStore, EthMultiStore}; pub use self::import::{import_accounts, read_geth_accounts}; diff --git a/ethstore/src/secret_store.rs b/ethstore/src/secret_store.rs index fd7eea50d..b292f0ef4 100755 --- a/ethstore/src/secret_store.rs +++ b/ethstore/src/secret_store.rs @@ -19,7 +19,7 @@ use std::path::PathBuf; use ethkey::{Address, Message, Signature, Secret, Public}; use Error; use json::{Uuid, OpaqueKeyFile}; -use util::H256; +use bigint::hash::H256; /// Key directory reference #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] diff --git a/hash-fetch/src/client.rs b/hash-fetch/src/client.rs index cffc10e63..40682a89c 100644 --- a/hash-fetch/src/client.rs +++ b/hash-fetch/src/client.rs @@ -92,6 +92,7 @@ pub struct Client { contract: URLHintContract, fetch: F, remote: Remote, + random_path: Arc PathBuf + Sync + Send>, } impl Client { @@ -109,6 +110,7 @@ impl Client { contract: URLHintContract::new(contract), fetch: fetch, remote: remote, + random_path: Arc::new(random_temp_path), } } } @@ -131,6 +133,7 @@ impl HashFetch for Client { match url { Err(err) => on_done(Err(err)), Ok(url) => { + let random_path = self.random_path.clone(); let future = self.fetch.fetch(&url).then(move |result| { fn validate_hash(path: PathBuf, hash: H256, result: Result) -> Result { let response = result?; @@ -155,12 +158,12 @@ impl HashFetch for Client { } debug!(target: "fetch", "Content fetched, validating hash ({:?})", hash); - let path = random_temp_path(); + let path = random_path(); let res = validate_hash(path.clone(), hash, result); if let Err(ref err) = res { trace!(target: "fetch", "Error: {:?}", err); // Remove temporary file in case of error - let _ = fs::remove_dir_all(&path); + let _ = fs::remove_file(&path); } on_done(res); @@ -192,7 +195,7 @@ mod tests { use fetch::{self, Fetch}; use parity_reactor::Remote; use urlhint::tests::{FakeRegistrar, URLHINT}; - use super::{Error, Client, HashFetch}; + use super::{Error, Client, HashFetch, random_temp_path}; #[derive(Clone)] @@ -262,12 +265,16 @@ mod tests { let result = rx.recv().unwrap(); assert_eq!(result.unwrap_err(), Error::InvalidStatus); } + #[test] fn should_return_hash_mismatch() { // given let registrar = Arc::new(registrar()); let fetch = FakeFetch { return_success: true }; - let client = Client::with_fetch(registrar.clone(), fetch, Remote::new_sync()); + let mut client = Client::with_fetch(registrar.clone(), fetch, Remote::new_sync()); + let path = random_temp_path(); + let path2 = path.clone(); + client.random_path = Arc::new(move || path2.clone()); // when let (tx, rx) = mpsc::channel(); @@ -279,6 +286,7 @@ mod tests { let result = rx.recv().unwrap(); let hash = "0x06b0a4f426f6713234b2d4b2468640bc4e0bb72657a920ad24c5087153c593c8".into(); assert_eq!(result.unwrap_err(), Error::HashMismatch { expected: 2.into(), got: hash }); + assert!(!path.exists(), "Temporary file should be removed."); } #[test] diff --git a/js/package.json b/js/package.json index 56806ef41..4f4b33ab7 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "1.7.49", + "version": "1.7.53", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", diff --git a/js/src/api/api.js b/js/src/api/api.js index 5be20371e..2c102086f 100644 --- a/js/src/api/api.js +++ b/js/src/api/api.js @@ -55,7 +55,7 @@ export default class Api extends EventEmitter { .nodeKind() .then((nodeKind) => { if (nodeKind.availability === 'public') { - return new LocalAccountsMiddleware(transport); + return LocalAccountsMiddleware; } return null; diff --git a/js/src/api/local/ethkey/dummy.js b/js/src/api/local/ethkey/dummy.js deleted file mode 100644 index 38f7c84de..000000000 --- a/js/src/api/local/ethkey/dummy.js +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (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 . - -export default function () { - // empty file included while building parity.js (don't include local keygen) -} diff --git a/js/src/api/local/ethkey/index.spec.js b/js/src/api/local/ethkey/index.spec.js index c727e1d51..781c49b5c 100644 --- a/js/src/api/local/ethkey/index.spec.js +++ b/js/src/api/local/ethkey/index.spec.js @@ -18,8 +18,8 @@ import { randomPhrase } from '@parity/wordlist'; import { phraseToAddress, phraseToWallet } from './'; describe('api/local/ethkey', () => { - describe.skip('phraseToAddress', function () { - this.timeout(10000); + describe('phraseToAddress', function () { + this.timeout(30000); it('generates a valid address', () => { const phrase = randomPhrase(12); @@ -37,8 +37,8 @@ describe('api/local/ethkey', () => { }); }); - describe.skip('phraseToWallet', function () { - this.timeout(10000); + describe('phraseToWallet', function () { + this.timeout(30000); it('generates a valid wallet object', () => { const phrase = randomPhrase(12); diff --git a/js/src/api/local/ethkey/worker.js b/js/src/api/local/ethkey/worker.js index 00f4a0bed..ffb99d0e8 100644 --- a/js/src/api/local/ethkey/worker.js +++ b/js/src/api/local/ethkey/worker.js @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import secp256k1 from 'secp256k1/js'; +import secp256k1 from 'secp256k1'; import { keccak_256 as keccak256 } from 'js-sha3'; import { bytesToHex } from '~/api/util/format'; @@ -28,11 +28,9 @@ if (!isWorker) { } // keythereum should never be used outside of the browser -let keythereum = null; +let keythereum = require('keythereum'); if (isWorker) { - require('keythereum/dist/keythereum'); - keythereum = self.keythereum; } @@ -109,9 +107,13 @@ const actions = { }; self.onmessage = function ({ data }) { - const result = route(data); + try { + const result = route(data); - postMessage(result); + postMessage([null, result]); + } catch (err) { + postMessage([err, null]); + } }; // Emulate a web worker in Node.js @@ -119,9 +121,13 @@ class KeyWorker { postMessage (data) { // Force async setTimeout(() => { - const result = route(data); + try { + const result = route(data); - this.onmessage({ data: result }); + this.onmessage({ data: [null, result] }); + } catch (err) { + this.onmessage({ data: [err, null] }); + } }, 0); } diff --git a/js/src/api/local/ethkey/workerPool.js b/js/src/api/local/ethkey/workerPool.js index ff5315898..e4e4a5134 100644 --- a/js/src/api/local/ethkey/workerPool.js +++ b/js/src/api/local/ethkey/workerPool.js @@ -33,8 +33,15 @@ class WorkerContainer { return new Promise((resolve, reject) => { this._worker.postMessage({ action, payload }); this._worker.onmessage = ({ data }) => { + const [err, result] = data; + this.busy = false; - resolve(data); + + if (err) { + reject(err); + } else { + resolve(result); + } }; }); } diff --git a/js/src/api/local/index.js b/js/src/api/local/index.js index c1d4b60ca..1000fa330 100644 --- a/js/src/api/local/index.js +++ b/js/src/api/local/index.js @@ -14,4 +14,4 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -export LocalAccountsMiddleware from './middleware'; +export LocalAccountsMiddleware from './localAccountsMiddleware'; diff --git a/js/src/api/local/middleware.js b/js/src/api/local/localAccountsMiddleware.js similarity index 94% rename from js/src/api/local/middleware.js rename to js/src/api/local/localAccountsMiddleware.js index 36a8cd2cf..753de8a4c 100644 --- a/js/src/api/local/middleware.js +++ b/js/src/api/local/localAccountsMiddleware.js @@ -23,15 +23,6 @@ import { phraseToWallet, phraseToAddress, verifySecret } from './ethkey'; import { randomPhrase } from '@parity/wordlist'; export default class LocalAccountsMiddleware extends Middleware { - // Maps transaction requests to transaction hashes. - // This allows the locally-signed transactions to emulate the signer. - transactionHashes = {}; - transactions = {}; - - // Current transaction id. This doesn't need to be stored, as it's - // only relevant for the current the session. - transactionId = 1; - constructor (transport) { super(transport); @@ -170,13 +161,27 @@ export default class LocalAccountsMiddleware extends Middleware { data } = Object.assign(transactions.get(id), modify); + transactions.lock(id); + const account = accounts.get(from); return Promise.all([ this.rpcRequest('parity_nextNonce', [from]), account.decryptPrivateKey(password) ]) + .catch((err) => { + transactions.unlock(id); + + // transaction got unlocked, can propagate rejection further + throw err; + }) .then(([nonce, privateKey]) => { + if (!privateKey) { + transactions.unlock(id); + + throw new Error('Invalid password'); + } + const tx = new EthereumTx({ nonce, to, diff --git a/js/src/api/local/localAccountsMiddleware.spec.js b/js/src/api/local/localAccountsMiddleware.spec.js new file mode 100644 index 000000000..7408b4b1e --- /dev/null +++ b/js/src/api/local/localAccountsMiddleware.spec.js @@ -0,0 +1,154 @@ +// Copyright 2015-2017 Parity Technologies (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 . + +import LocalAccountsMiddleware from './localAccountsMiddleware'; +import JsonRpcBase from '../transport/jsonRpcBase'; + +const RPC_RESPONSE = Symbol('RPC response'); +const ADDRESS = '0x00a329c0648769a73afac7f9381e08fb43dbea72'; +const SECRET = '0x4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7'; +const PASSWORD = 'password'; + +const FOO_PHRASE = 'foobar'; +const FOO_PASSWORD = 'foopass'; +const FOO_ADDRESS = '0x007ef7ac1058e5955e366ab9d6b6c4ebcc937e7e'; + +class MockedTransport extends JsonRpcBase { + _execute (method, params) { + return RPC_RESPONSE; + } +} + +describe('api/local/LocalAccountsMiddleware', function () { + this.timeout(30000); + + let transport; + + beforeEach(() => { + transport = new MockedTransport(); + transport.addMiddleware(LocalAccountsMiddleware); + + // Same as `parity_newAccountFromPhrase` with empty phrase + return transport + .execute('parity_newAccountFromSecret', SECRET, PASSWORD) + .catch((_err) => { + // Ignore the error - all instances of LocalAccountsMiddleware + // share account storage + }); + }); + + it('registers all necessary methods', () => { + return Promise + .all([ + 'eth_accounts', + 'eth_coinbase', + 'parity_accountsInfo', + 'parity_allAccountsInfo', + 'parity_changePassword', + 'parity_checkRequest', + 'parity_defaultAccount', + 'parity_generateSecretPhrase', + 'parity_getNewDappsAddresses', + 'parity_hardwareAccountsInfo', + 'parity_newAccountFromPhrase', + 'parity_newAccountFromSecret', + 'parity_setAccountMeta', + 'parity_setAccountName', + 'parity_postTransaction', + 'parity_phraseToAddress', + 'parity_useLocalAccounts', + 'parity_listGethAccounts', + 'parity_listRecentDapps', + 'parity_killAccount', + 'parity_testPassword', + 'signer_confirmRequest', + 'signer_rejectRequest', + 'signer_requestsToConfirm' + ].map((method) => { + return transport + .execute(method) + .then((result) => { + expect(result).not.to.be.equal(RPC_RESPONSE); + }) + // Some errors are expected here since we are calling methods + // without parameters. + .catch((_) => {}); + })); + }); + + it('allows non-registered methods through', () => { + return transport + .execute('eth_getBalance', '0x407d73d8a49eeb85d32cf465507dd71d507100c1') + .then((result) => { + expect(result).to.be.equal(RPC_RESPONSE); + }); + }); + + it('can handle `eth_accounts`', () => { + return transport + .execute('eth_accounts') + .then((accounts) => { + expect(accounts.length).to.be.equal(1); + expect(accounts[0]).to.be.equal(ADDRESS); + }); + }); + + it('can handle `parity_defaultAccount`', () => { + return transport + .execute('parity_defaultAccount') + .then((address) => { + expect(address).to.be.equal(ADDRESS); + }); + }); + + it('can handle `parity_phraseToAddress`', () => { + return transport + .execute('parity_phraseToAddress', '') + .then((address) => { + expect(address).to.be.equal(ADDRESS); + + return transport.execute('parity_phraseToAddress', FOO_PHRASE); + }) + .then((address) => { + expect(address).to.be.equal(FOO_ADDRESS); + }); + }); + + it('can create and kill an account', () => { + return transport + .execute('parity_newAccountFromPhrase', FOO_PHRASE, FOO_PASSWORD) + .then((address) => { + expect(address).to.be.equal(FOO_ADDRESS); + + return transport.execute('eth_accounts'); + }) + .then((accounts) => { + expect(accounts.length).to.be.equal(2); + expect(accounts.includes(FOO_ADDRESS)).to.be.true; + + return transport.execute('parity_killAccount', FOO_ADDRESS, FOO_PASSWORD); + }) + .then((result) => { + expect(result).to.be.true; + + return transport.execute('eth_accounts'); + }) + .then((accounts) => { + expect(accounts.length).to.be.equal(1); + expect(accounts.includes(FOO_ADDRESS)).to.be.false; + }); + }); +}); diff --git a/js/src/api/local/transactions.js b/js/src/api/local/transactions.js index 57d1eee62..421e73012 100644 --- a/js/src/api/local/transactions.js +++ b/js/src/api/local/transactions.js @@ -18,6 +18,7 @@ import { toHex } from '../util/format'; import { TransportError } from '../transport'; const AWAITING = Symbol('awaiting'); +const LOCKED = Symbol('locked'); const CONFIRMED = Symbol('confirmed'); const REJECTED = Symbol('rejected'); @@ -57,6 +58,26 @@ class Transactions { return state.transaction; } + lock (id) { + const state = this._states[id]; + + if (!state || state.status !== AWAITING) { + throw new Error('Trying to lock an invalid transaction'); + } + + state.status = LOCKED; + } + + unlock (id) { + const state = this._states[id]; + + if (!state || state.status !== LOCKED) { + throw new Error('Trying to unlock an invalid transaction'); + } + + state.status = AWAITING; + } + hash (id) { const state = this._states[id]; @@ -76,9 +97,12 @@ class Transactions { confirm (id, hash) { const state = this._states[id]; + const status = state ? state.status : null; - if (!state || state.status !== AWAITING) { - throw new Error('Trying to confirm an invalid transaction'); + switch (status) { + case AWAITING: break; + case LOCKED: break; + default: throw new Error('Trying to confirm an invalid transaction'); } state.hash = hash; diff --git a/js/src/api/local/transactions.spec.js b/js/src/api/local/transactions.spec.js index 84482ff57..65f2d8ddc 100644 --- a/js/src/api/local/transactions.spec.js +++ b/js/src/api/local/transactions.spec.js @@ -65,4 +65,21 @@ describe('api/local/transactions', () => { expect(requests.length).to.be.equal(0); expect(() => transactions.hash(id)).to.throw(TransportError); }); + + it('can lock and confirm transactions', () => { + const id = transactions.add(DUMMY_TX); + const hash = '0x1111111111111111111111111111111111111111'; + + transactions.lock(id); + + const requests = transactions.requestsToConfirm(); + + expect(requests.length).to.be.equal(0); + expect(transactions.get(id)).to.be.null; + expect(transactions.hash(id)).to.be.null; + + transactions.confirm(id, hash); + + expect(transactions.hash(id)).to.be.equal(hash); + }); }); diff --git a/js/src/api/rpc/parity/parity.js b/js/src/api/rpc/parity/parity.js index f38e29e7b..16b14eaef 100644 --- a/js/src/api/rpc/parity/parity.js +++ b/js/src/api/rpc/parity/parity.js @@ -522,6 +522,11 @@ export default class Parity { .then(outNumber); } + signMessage (address, password, messageHash) { + return this._transport + .execute('parity_signMessage', inAddress(address), password, inHex(messageHash)); + } + testPassword (account, password) { return this._transport .execute('parity_testPassword', inAddress(account), password); diff --git a/js/src/api/transport/jsonRpcBase.js b/js/src/api/transport/jsonRpcBase.js index 573204c3e..819e1f496 100644 --- a/js/src/api/transport/jsonRpcBase.js +++ b/js/src/api/transport/jsonRpcBase.js @@ -38,20 +38,20 @@ export default class JsonRpcBase extends EventEmitter { return json; } - addMiddleware (middleware) { + addMiddleware (Middleware) { this._middlewareList = Promise .all([ - middleware, + Middleware, this._middlewareList ]) - .then(([middleware, middlewareList]) => { + .then(([Middleware, middlewareList]) => { // Do nothing if `handlerPromise` resolves to a null-y value. - if (middleware == null) { + if (Middleware == null) { return middlewareList; } // don't mutate the original array - return middlewareList.concat([middleware]); + return middlewareList.concat([new Middleware(this)]); }); } @@ -80,8 +80,8 @@ export default class JsonRpcBase extends EventEmitter { const res = middleware.handle(method, params); if (res != null) { - // If `res` isn't a promise, we need to wrap it - return Promise.resolve(res) + return Promise + .resolve(res) .then((res) => { const result = this._wrapSuccessResult(res); const json = this.encode(method, params); diff --git a/js/src/api/transport/middleware.js b/js/src/api/transport/middleware.js index 5a4945e7e..7d7199f95 100644 --- a/js/src/api/transport/middleware.js +++ b/js/src/api/transport/middleware.js @@ -28,9 +28,7 @@ export default class Middleware { const handler = this._handlers[method]; if (handler != null) { - const response = handler(params); - - return response; + return handler(params); } return null; diff --git a/js/src/api/transport/middleware.spec.js b/js/src/api/transport/middleware.spec.js index 27b81c49f..4ae894135 100644 --- a/js/src/api/transport/middleware.spec.js +++ b/js/src/api/transport/middleware.spec.js @@ -25,17 +25,21 @@ class MockTransport extends JsonRpcBase { } } +class MockMiddleware extends Middleware { + constructor (transport) { + super(transport); + + this.register('mock_rpc', ([num]) => num); + this.register('mock_null', () => null); + } +} + describe('api/transport/Middleware', () => { - let middleware; let transport; beforeEach(() => { transport = new MockTransport(); - middleware = new Middleware(transport); - - middleware.register('mock_rpc', ([num]) => num); - middleware.register('mock_null', () => null); - transport.addMiddleware(middleware); + transport.addMiddleware(MockMiddleware); }); it('Routes requests to middleware', () => { diff --git a/js/src/i18n/zh/writeContract.js b/js/src/i18n/zh/writeContract.js index fc1100b77..62f83dd4d 100644 --- a/js/src/i18n/zh/writeContract.js +++ b/js/src/i18n/zh/writeContract.js @@ -37,7 +37,7 @@ export default { params: `An error occurred with the following description` }, input: { - abi: `ABI Interface`, + abi: `ABI Definition`, code: `Bytecode`, metadata: `Metadata`, swarm: `Swarm Metadata Hash` diff --git a/js/src/jsonrpc/interfaces/parity.js b/js/src/jsonrpc/interfaces/parity.js index 3e6fa8475..e7a5f46c9 100644 --- a/js/src/jsonrpc/interfaces/parity.js +++ b/js/src/jsonrpc/interfaces/parity.js @@ -1881,5 +1881,31 @@ export default { desc: 'Decrypted message.', example: withComment('0x68656c6c6f20776f726c64', 'hello world') } + }, + + signMessage: { + desc: 'Sign the hashed message bytes with the given account.', + params: [ + { + type: Address, + desc: 'Account which signs the message.', + example: '0xc171033d5cbff7175f29dfd3a63dda3d6f8f385e' + }, + { + type: String, + desc: 'Passphrase to unlock the account.', + example: 'password1' + }, + { + type: Data, + desc: 'Hashed message.', + example: '0xbc36789e7a1e281436464229828f817d6612f7b477d66591ff96a9e064bcc98a' + } + ], + returns: { + type: Data, + desc: 'Message signature.', + example: '0x1d9e33a8cf8bfc089a172bca01da462f9e359c6cb1b0f29398bc884e4d18df4f78588aee4fb5cc067ca62d2abab995e0bba29527be6ac98105b0320020a2efaf00' + } } }; diff --git a/js/src/modals/CreateAccount/store.js b/js/src/modals/CreateAccount/store.js index 9bc60d9af..9f78360fa 100644 --- a/js/src/modals/CreateAccount/store.js +++ b/js/src/modals/CreateAccount/store.js @@ -96,6 +96,7 @@ export default class Store { } @computed get qrAddressValid () { + console.log('qrValid', this.qrAddress, this._api.util.isAddressValid(this.qrAddress)); return this._api.util.isAddressValid(this.qrAddress); } @@ -155,7 +156,10 @@ export default class Store { qrAddress = `0x${qrAddress}`; } - this.qrAddress = qrAddress; + // FIXME: Current native signer encoding is not 100% for EIP-55, lowercase for now + this.qrAddress = this._api.util + ? this._api.util.toChecksumAddress(qrAddress.toLowerCase()) + : qrAddress; } @action setVaultName = (vaultName) => { diff --git a/js/src/ui/QrCode/qrSize.js b/js/src/ui/QrCode/qrSize.js index 2671bb532..8440458ac 100644 --- a/js/src/ui/QrCode/qrSize.js +++ b/js/src/ui/QrCode/qrSize.js @@ -69,7 +69,9 @@ const QR_SIZES = [ export function calculateType (lengthBytes, errorLevel = 'M') { let type = 5; - while (type < 40 && lengthBytes > QR_SIZES[errorLevel][type - 1]) { + // subtract 3 from the capacities, since we need 2 bits for the mode and a + // bunch more for the length. + while (type < 40 && lengthBytes > QR_SIZES[errorLevel][type - 1] - 3) { type++; } diff --git a/js/src/views/WriteContract/writeContract.js b/js/src/views/WriteContract/writeContract.js index 86262820d..170c0d7c1 100644 --- a/js/src/views/WriteContract/writeContract.js +++ b/js/src/views/WriteContract/writeContract.js @@ -608,7 +608,7 @@ class WriteContract extends Component { label={ } readOnly diff --git a/js/webpack/app.js b/js/webpack/app.js index d121b6518..ded5c4468 100644 --- a/js/webpack/app.js +++ b/js/webpack/app.js @@ -138,7 +138,9 @@ module.exports = { resolve: { alias: { - '~': path.resolve(__dirname, '../src') + '~': path.resolve(__dirname, '../src'), + 'secp256k1': path.resolve(__dirname, '../node_modules/secp256k1/js'), + 'keythereum': path.resolve(__dirname, '../node_modules/keythereum/dist/keythereum') }, modules: [ path.join(__dirname, '../node_modules') diff --git a/js/webpack/libraries.js b/js/webpack/libraries.js index 3ddd45f2c..1fcb39eba 100644 --- a/js/webpack/libraries.js +++ b/js/webpack/libraries.js @@ -41,7 +41,9 @@ module.exports = { resolve: { alias: { - '~': path.resolve(__dirname, '../src') + '~': path.resolve(__dirname, '../src'), + 'secp256k1': path.resolve(__dirname, '../node_modules/secp256k1/js'), + 'keythereum': path.resolve(__dirname, '../node_modules/keythereum/dist/keythereum') } }, diff --git a/js/webpack/npm.js b/js/webpack/npm.js index b526b2f0f..2230bf90f 100644 --- a/js/webpack/npm.js +++ b/js/webpack/npm.js @@ -76,7 +76,6 @@ module.exports = { resolve: { alias: { - 'secp256k1/js': path.resolve(__dirname, '../src/api/local/ethkey/dummy.js'), '~': path.resolve(__dirname, '../src') }, modules: [ diff --git a/json/src/maybe.rs b/json/src/maybe.rs index d80020cf2..16a01dc44 100644 --- a/json/src/maybe.rs +++ b/json/src/maybe.rs @@ -8,7 +8,7 @@ use serde::de::{Error, Visitor}; use serde::de::value::ValueDeserializer; /// Deserializer of empty string values into optionals. -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum MaybeEmpty { /// Some. Some(T), diff --git a/json/src/state/test.rs b/json/src/state/test.rs index 0ee0bcf17..5cc2b5f4f 100644 --- a/json/src/state/test.rs +++ b/json/src/state/test.rs @@ -14,13 +14,16 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -//! State test deserializer. +//! General test deserialization. -use std::collections::BTreeMap; use std::io::Read; -use serde_json; -use serde_json::Error; -use state::State; +use std::collections::BTreeMap; +use uint::Uint; +use bytes::Bytes; +use hash::{Address, H256}; +use state::{Env, AccountState, Transaction}; +use maybe::MaybeEmpty; +use serde_json::{self, Error}; /// State test deserializer. #[derive(Debug, PartialEq, Deserialize)] @@ -41,3 +44,182 @@ impl Test { serde_json::from_reader(reader) } } + +/// State test deserialization. +#[derive(Debug, PartialEq, Deserialize)] +pub struct State { + /// Environment. + pub env: Env, + /// Pre state. + #[serde(rename="pre")] + pub pre_state: AccountState, + /// Post state. + #[serde(rename="post")] + pub post_states: BTreeMap>, + /// Transaction. + pub transaction: MultiTransaction, +} + +/// State test transaction deserialization. +#[derive(Debug, PartialEq, Deserialize)] +pub struct MultiTransaction { + /// Transaction data set. + pub data: Vec, + /// Gas limit set. + #[serde(rename="gasLimit")] + pub gas_limit: Vec, + /// Gas price. + #[serde(rename="gasPrice")] + pub gas_price: Uint, + /// Nonce. + pub nonce: Uint, + /// Secret key. + #[serde(rename="secretKey")] + pub secret: H256, + /// To. + pub to: MaybeEmpty

, + /// Value set. + pub value: Vec, +} + +impl MultiTransaction { + /// Build transaction with given indexes. + pub fn select(&self, indexes: &PostStateIndexes) -> Transaction { + Transaction { + data: self.data[indexes.data as usize].clone(), + gas_limit: self.gas_limit[indexes.gas as usize].clone(), + gas_price: self.gas_price.clone(), + nonce: self.nonce.clone(), + secret: self.secret.clone(), + to: self.to.clone(), + value: self.value[indexes.value as usize].clone(), + } + } +} + +/// State test transaction deserialization. +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Deserialize)] +pub enum ForkSpec { + EIP150, + EIP158, + Frontier, + Homestead, + Metropolis, +} + +/// State test indexes deserialization. +#[derive(Debug, PartialEq, Deserialize)] +pub struct PostStateIndexes { + /// Index into transaction data set. + pub data: u64, + /// Index into transaction gas limit set. + pub gas: u64, + /// Index into transaction value set. + pub value: u64, +} + +/// State test indexed state result deserialization. +#[derive(Debug, PartialEq, Deserialize)] +pub struct PostStateResult { + /// Post state hash + pub hash: H256, + /// Indexes + pub indexes: PostStateIndexes, +} + +#[cfg(test)] +mod tests { + use serde_json; + use super::{MultiTransaction, State}; + + #[test] + fn multi_transaction_deserialization() { + let s = r#"{ + "data" : [ "" ], + "gasLimit" : [ "0x2dc6c0", "0x222222" ], + "gasPrice" : "0x01", + "nonce" : "0x00", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "1000000000000000000000000000000000000000", + "value" : [ "0x00", "0x01", "0x02" ] + }"#; + let _deserialized: MultiTransaction = serde_json::from_str(s).unwrap(); + } + + #[test] + fn state_deserialization() { + let s = r#"{ + "env" : { + "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentDifficulty" : "0x0100", + "currentGasLimit" : "0x01c9c380", + "currentNumber" : "0x00", + "currentTimestamp" : "0x01", + "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" + }, + "post" : { + "EIP150" : [ + { + "hash" : "3e6dacc1575c6a8c76422255eca03529bbf4c0dda75dfc110b22d6dc4152396f", + "indexes" : { "data" : 0, "gas" : 0, "value" : 0 } + }, + { + "hash" : "99a450d8ce5b987a71346d8a0a1203711f770745c7ef326912e46761f14cd764", + "indexes" : { "data" : 0, "gas" : 0, "value" : 1 } + } + ], + "EIP158" : [ + { + "hash" : "3e6dacc1575c6a8c76422255eca03529bbf4c0dda75dfc110b22d6dc4152396f", + "indexes" : { "data" : 0, "gas" : 0, "value" : 0 } + }, + { + "hash" : "99a450d8ce5b987a71346d8a0a1203711f770745c7ef326912e46761f14cd764", + "indexes" : { "data" : 0, "gas" : 0, "value" : 1 } + } + ] + }, + "pre" : { + "1000000000000000000000000000000000000000" : { + "balance" : "0x0de0b6b3a7640000", + "code" : "0x6040600060406000600173100000000000000000000000000000000000000162055730f1600055", + "nonce" : "0x00", + "storage" : { + } + }, + "1000000000000000000000000000000000000001" : { + "balance" : "0x0de0b6b3a7640000", + "code" : "0x604060006040600060027310000000000000000000000000000000000000026203d090f1600155", + "nonce" : "0x00", + "storage" : { + } + }, + "1000000000000000000000000000000000000002" : { + "balance" : "0x00", + "code" : "0x600160025533600455346007553060e6553260e8553660ec553860ee553a60f055", + "nonce" : "0x00", + "storage" : { + } + }, + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "0x0de0b6b3a7640000", + "code" : "0x", + "nonce" : "0x00", + "storage" : { + } + } + }, + "transaction" : { + "data" : [ "" ], + "gasLimit" : [ "285000", "100000", "6000" ], + "gasPrice" : "0x01", + "nonce" : "0x00", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : [ "10", "0" ] + } + }"#; + let _deserialized: State = serde_json::from_str(s).unwrap(); + // TODO: validate all fields + } +} diff --git a/parity/run.rs b/parity/run.rs index b674c93ca..c6086d6b8 100644 --- a/parity/run.rs +++ b/parity/run.rs @@ -192,6 +192,10 @@ fn execute_light(cmd: RunCmd, can_restart: bool, logger: Arc) -> info!("Starting {}", Colour::White.bold().paint(version())); info!("Running in experimental {} mode.", Colour::Blue.bold().paint("Light Client")); + // TODO: configurable cache size. + let cache = LightDataCache::new(Default::default(), ::time::Duration::minutes(GAS_CORPUS_EXPIRATION_MINUTES)); + let cache = Arc::new(::util::Mutex::new(cache)); + // start client and create transaction queue. let mut config = light_client::Config { queue: Default::default(), @@ -204,7 +208,7 @@ fn execute_light(cmd: RunCmd, can_restart: bool, logger: Arc) -> config.queue.max_mem_use = cmd.cache_config.queue() as usize * 1024 * 1024; config.queue.verifier_settings = cmd.verifier_settings; - let service = light_client::Service::start(config, &spec, &db_dirs.client_path(algorithm)) + let service = light_client::Service::start(config, &spec, &db_dirs.client_path(algorithm), cache.clone()) .map_err(|e| format!("Error starting light client: {}", e))?; let txq = Arc::new(RwLock::new(::light::transaction_queue::TransactionQueue::default())); let provider = ::light::provider::LightProvider::new(service.client().clone(), txq.clone()); @@ -216,10 +220,6 @@ fn execute_light(cmd: RunCmd, can_restart: bool, logger: Arc) -> net_conf.boot_nodes = spec.nodes.clone(); } - // TODO: configurable cache size. - let cache = LightDataCache::new(Default::default(), ::time::Duration::minutes(GAS_CORPUS_EXPIRATION_MINUTES)); - let cache = Arc::new(::util::Mutex::new(cache)); - // start on_demand service. let on_demand = Arc::new(::light::on_demand::OnDemand::new(cache.clone())); diff --git a/rpc/src/v1/helpers/dispatch.rs b/rpc/src/v1/helpers/dispatch.rs index 32c8520e3..bf81674ac 100644 --- a/rpc/src/v1/helpers/dispatch.rs +++ b/rpc/src/v1/helpers/dispatch.rs @@ -475,7 +475,7 @@ pub fn execute( .map(ConfirmationResponse::SignTransaction) ).boxed() }, - ConfirmationPayload::Signature(address, mut data) => { + ConfirmationPayload::EthSignMessage(address, mut data) => { let mut message_data = format!("\x19Ethereum Signed Message:\n{}", data.len()) .into_bytes(); @@ -575,8 +575,8 @@ pub fn from_rpc(payload: RpcConfirmationPayload, default_account: Address, di RpcConfirmationPayload::Decrypt(RpcDecryptRequest { address, msg }) => { future::ok(ConfirmationPayload::Decrypt(address.into(), msg.into())).boxed() }, - RpcConfirmationPayload::Signature(RpcSignRequest { address, data }) => { - future::ok(ConfirmationPayload::Signature(address.into(), data.into())).boxed() + RpcConfirmationPayload::EthSignMessage(RpcSignRequest { address, data }) => { + future::ok(ConfirmationPayload::EthSignMessage(address.into(), data.into())).boxed() }, } } diff --git a/rpc/src/v1/helpers/light_fetch.rs b/rpc/src/v1/helpers/light_fetch.rs index b1373c43f..7132106cb 100644 --- a/rpc/src/v1/helpers/light_fetch.rs +++ b/rpc/src/v1/helpers/light_fetch.rs @@ -36,7 +36,7 @@ use light::on_demand::{OnDemand, request}; use ethsync::LightSync; use util::{Address, Mutex, Uint, U256}; -use v1::helpers::{CallRequest as CRequest, errors, dispatch}; +use v1::helpers::{CallRequest as CallRequestHelper, errors, dispatch}; use v1::types::{BlockNumber, CallRequest}; /// Helper for fetching blockchain data either from the light client or the network @@ -129,7 +129,7 @@ impl LightFetch { const DEFAULT_GAS_PRICE: U256 = U256([0, 0, 0, 21_000_000]); let (sync, on_demand, client) = (self.sync.clone(), self.on_demand.clone(), self.client.clone()); - let req: CRequest = req.into(); + let req: CallRequestHelper = req.into(); let id = num.0.into(); let from = req.from.unwrap_or(Address::zero()); diff --git a/rpc/src/v1/helpers/requests.rs b/rpc/src/v1/helpers/requests.rs index 4a3a3704d..aa3a4c3d4 100644 --- a/rpc/src/v1/helpers/requests.rs +++ b/rpc/src/v1/helpers/requests.rs @@ -113,8 +113,8 @@ pub enum ConfirmationPayload { SendTransaction(FilledTransactionRequest), /// Sign Transaction SignTransaction(FilledTransactionRequest), - /// Sign request - Signature(Address, Bytes), + /// Sign a message with an Ethereum specific security prefix. + EthSignMessage(Address, Bytes), /// Decrypt request Decrypt(Address, Bytes), } @@ -124,7 +124,7 @@ impl ConfirmationPayload { match *self { ConfirmationPayload::SendTransaction(ref request) => request.from, ConfirmationPayload::SignTransaction(ref request) => request.from, - ConfirmationPayload::Signature(ref address, _) => *address, + ConfirmationPayload::EthSignMessage(ref address, _) => *address, ConfirmationPayload::Decrypt(ref address, _) => *address, } } diff --git a/rpc/src/v1/impls/light/eth.rs b/rpc/src/v1/impls/light/eth.rs index 7e53f66d0..d50448554 100644 --- a/rpc/src/v1/impls/light/eth.rs +++ b/rpc/src/v1/impls/light/eth.rs @@ -475,15 +475,18 @@ impl Filterable for EthClient { use util::H2048; // early exit for "to" block before "from" block. - match filter.from_block { - BlockId::Latest | BlockId::Pending => { - let best = self.client.best_block_header(); - let chain_info = self.client.chain_info(); - if best.number() != chain_info.best_block_number || best.hash() != chain_info.best_block_hash { - return future::ok(Vec::new()).boxed() - } - } - _ => {} + let best_number = self.client.chain_info().best_block_number; + let block_number = |id| match id { + BlockId::Earliest => Some(0), + BlockId::Latest | BlockId::Pending => Some(best_number), + BlockId::Hash(h) => self.client.block_header(BlockId::Hash(h)).map(|hdr| hdr.number()), + BlockId::Number(x) => Some(x), + }; + + match (block_number(filter.to_block), block_number(filter.from_block)) { + (Some(to), Some(from)) if to < from => return future::ok(Vec::new()).boxed(), + (Some(_), Some(_)) => {}, + _ => return future::err(errors::unknown_block()).boxed(), } let maybe_future = self.sync.with_context(move |ctx| { diff --git a/rpc/src/v1/impls/parity_accounts.rs b/rpc/src/v1/impls/parity_accounts.rs index c22285cc9..cc206696f 100644 --- a/rpc/src/v1/impls/parity_accounts.rs +++ b/rpc/src/v1/impls/parity_accounts.rs @@ -17,7 +17,7 @@ //! Account management (personal) rpc implementation use std::sync::{Arc, Weak}; use std::collections::BTreeMap; -use util::{Address}; +use util::Address; use ethkey::{Brain, Generator, Secret}; use ethstore::KeyFile; @@ -27,7 +27,7 @@ use jsonrpc_core::Error; use v1::helpers::errors; use v1::helpers::accounts::unwrap_provider; use v1::traits::ParityAccounts; -use v1::types::{H160 as RpcH160, H256 as RpcH256, DappId, Derive, DeriveHierarchical, DeriveHash}; +use v1::types::{H160 as RpcH160, H256 as RpcH256, H520 as RpcH520, DappId, Derive, DeriveHierarchical, DeriveHash}; /// Account management (personal) rpc implementation. pub struct ParityAccountsClient { @@ -334,6 +334,17 @@ impl ParityAccounts for ParityAccountsClient { .map(Into::into) .map_err(|e| errors::account("Could not export account.", e)) } + + fn sign_message(&self, addr: RpcH160, password: String, message: RpcH256) -> Result { + self.account_provider()? + .sign( + addr.into(), + Some(password), + message.into() + ) + .map(Into::into) + .map_err(|e| errors::account("Could not sign message.", e)) + } } fn into_vec(a: Vec) -> Vec where diff --git a/rpc/src/v1/impls/signing.rs b/rpc/src/v1/impls/signing.rs index dfb0c4f80..376418ead 100644 --- a/rpc/src/v1/impls/signing.rs +++ b/rpc/src/v1/impls/signing.rs @@ -140,7 +140,7 @@ impl ParitySigning for SigningQueueClient { fn post_sign(&self, meta: Metadata, address: RpcH160, data: RpcBytes) -> BoxFuture, Error> { let pending = self.pending.clone(); self.dispatch( - RpcConfirmationPayload::Signature((address.clone(), data).into()), + RpcConfirmationPayload::EthSignMessage((address.clone(), data).into()), DefaultAccount::Provided(address.into()), meta.origin ).map(move |result| match result { @@ -216,7 +216,7 @@ impl EthSigning for SigningQueueClient { fn sign(&self, meta: Metadata, address: RpcH160, data: RpcBytes) -> BoxFuture { let res = self.dispatch( - RpcConfirmationPayload::Signature((address.clone(), data).into()), + RpcConfirmationPayload::EthSignMessage((address.clone(), data).into()), address.into(), meta.origin, ); diff --git a/rpc/src/v1/impls/signing_unsafe.rs b/rpc/src/v1/impls/signing_unsafe.rs index 8fbb6595a..6fb483c5e 100644 --- a/rpc/src/v1/impls/signing_unsafe.rs +++ b/rpc/src/v1/impls/signing_unsafe.rs @@ -78,7 +78,7 @@ impl EthSigning for SigningUnsafeClient type Metadata = Metadata; fn sign(&self, _: Metadata, address: RpcH160, data: RpcBytes) -> BoxFuture { - self.handle(RpcConfirmationPayload::Signature((address.clone(), data).into()), address.into()) + self.handle(RpcConfirmationPayload::EthSignMessage((address.clone(), data).into()), address.into()) .then(|res| match res { Ok(RpcConfirmationResponse::Signature(signature)) => Ok(signature), Err(e) => Err(e), diff --git a/rpc/src/v1/tests/mocked/parity_accounts.rs b/rpc/src/v1/tests/mocked/parity_accounts.rs index 949498c61..b3ea644fa 100644 --- a/rpc/src/v1/tests/mocked/parity_accounts.rs +++ b/rpc/src/v1/tests/mocked/parity_accounts.rs @@ -500,3 +500,20 @@ fn should_export_account() { println!("Response: {:?}", response); assert_eq!(result, Some(response.into())); } + +#[test] +fn should_sign_message() { + let tester = setup(); + let hash = tester.accounts + .insert_account( + "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a".parse().unwrap(), + "password1") + .expect("account should be inserted ok"); + + assert_eq!(hash, "c171033d5cbff7175f29dfd3a63dda3d6f8f385e".parse().unwrap()); + + let request = r#"{"jsonrpc": "2.0", "method": "parity_signMessage", "params": ["0xc171033d5cbff7175f29dfd3a63dda3d6f8f385e", "password1", "0xbc36789e7a1e281436464229828f817d6612f7b477d66591ff96a9e064bcc98a"], "id": 3}"#; + let response = r#"{"jsonrpc":"2.0","result":"0x1d9e33a8cf8bfc089a172bca01da462f9e359c6cb1b0f29398bc884e4d18df4f78588aee4fb5cc067ca62d2abab995e0bba29527be6ac98105b0320020a2efaf00","id":3}"#; + let res = tester.io.handle_request_sync(&request); + assert_eq!(res, Some(response.into())); +} diff --git a/rpc/src/v1/tests/mocked/signer.rs b/rpc/src/v1/tests/mocked/signer.rs index a20e94bcc..973e33528 100644 --- a/rpc/src/v1/tests/mocked/signer.rs +++ b/rpc/src/v1/tests/mocked/signer.rs @@ -90,7 +90,7 @@ fn should_return_list_of_items_to_confirm() { nonce: None, condition: None, }), Origin::Dapps("http://parity.io".into())).unwrap(); - tester.signer.add_request(ConfirmationPayload::Signature(1.into(), vec![5].into()), Origin::Unknown).unwrap(); + tester.signer.add_request(ConfirmationPayload::EthSignMessage(1.into(), vec![5].into()), Origin::Unknown).unwrap(); // when let request = r#"{"jsonrpc":"2.0","method":"signer_requestsToConfirm","params":[],"id":1}"#; @@ -163,7 +163,7 @@ fn should_not_remove_transaction_if_password_is_invalid() { fn should_not_remove_sign_if_password_is_invalid() { // given let tester = signer_tester(); - tester.signer.add_request(ConfirmationPayload::Signature(0.into(), vec![5].into()), Origin::Unknown).unwrap(); + tester.signer.add_request(ConfirmationPayload::EthSignMessage(0.into(), vec![5].into()), Origin::Unknown).unwrap(); assert_eq!(tester.signer.requests().len(), 1); // when diff --git a/rpc/src/v1/traits/parity_accounts.rs b/rpc/src/v1/traits/parity_accounts.rs index 46372560c..7d49148b1 100644 --- a/rpc/src/v1/traits/parity_accounts.rs +++ b/rpc/src/v1/traits/parity_accounts.rs @@ -19,7 +19,7 @@ use std::collections::BTreeMap; use jsonrpc_core::Error; use ethstore::KeyFile; -use v1::types::{H160, H256, DappId, DeriveHash, DeriveHierarchical}; +use v1::types::{H160, H256, H520, DappId, DeriveHash, DeriveHierarchical}; build_rpc_trait! { /// Personal Parity rpc interface. @@ -180,5 +180,9 @@ build_rpc_trait! { /// Exports an account with given address if provided password matches. #[rpc(name = "parity_exportAccount")] fn export_account(&self, H160, String) -> Result; + + /// Sign raw hash with the key corresponding to address and password. + #[rpc(name = "parity_signMessage")] + fn sign_message(&self, H160, String, H256) -> Result; } } diff --git a/rpc/src/v1/types/confirmations.rs b/rpc/src/v1/types/confirmations.rs index f749df449..ac1fba4fe 100644 --- a/rpc/src/v1/types/confirmations.rs +++ b/rpc/src/v1/types/confirmations.rs @@ -57,7 +57,7 @@ impl fmt::Display for ConfirmationPayload { match *self { ConfirmationPayload::SendTransaction(ref transaction) => write!(f, "{}", transaction), ConfirmationPayload::SignTransaction(ref transaction) => write!(f, "(Sign only) {}", transaction), - ConfirmationPayload::Signature(ref sign) => write!(f, "{}", sign), + ConfirmationPayload::EthSignMessage(ref sign) => write!(f, "{}", sign), ConfirmationPayload::Decrypt(ref decrypt) => write!(f, "{}", decrypt), } } @@ -169,7 +169,7 @@ pub enum ConfirmationPayload { SignTransaction(TransactionRequest), /// Signature #[serde(rename="sign")] - Signature(SignRequest), + EthSignMessage(SignRequest), /// Decryption #[serde(rename="decrypt")] Decrypt(DecryptRequest), @@ -180,7 +180,7 @@ impl From for ConfirmationPayload { match c { helpers::ConfirmationPayload::SendTransaction(t) => ConfirmationPayload::SendTransaction(t.into()), helpers::ConfirmationPayload::SignTransaction(t) => ConfirmationPayload::SignTransaction(t.into()), - helpers::ConfirmationPayload::Signature(address, data) => ConfirmationPayload::Signature(SignRequest { + helpers::ConfirmationPayload::EthSignMessage(address, data) => ConfirmationPayload::EthSignMessage(SignRequest { address: address.into(), data: data.into(), }), @@ -255,7 +255,7 @@ mod tests { // given let request = helpers::ConfirmationRequest { id: 15.into(), - payload: helpers::ConfirmationPayload::Signature(1.into(), vec![5].into()), + payload: helpers::ConfirmationPayload::EthSignMessage(1.into(), vec![5].into()), origin: Origin::Rpc("test service".into()), }; diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 3c1717620..be2aeada7 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -2132,7 +2132,7 @@ impl ChainSync { let queue_info = io.chain().queue_info(); let is_syncing = self.status().is_syncing(queue_info); - if !is_syncing || !sealed.is_empty() { + if !is_syncing || !sealed.is_empty() || !proposed.is_empty() { trace!(target: "sync", "Propagating blocks, state={:?}", self.state); self.propagate_latest_blocks(io, sealed); self.propagate_proposed_blocks(io, proposed); diff --git a/sync/src/light_sync/tests/test_net.rs b/sync/src/light_sync/tests/test_net.rs index 2319e8d35..1da4d1659 100644 --- a/sync/src/light_sync/tests/test_net.rs +++ b/sync/src/light_sync/tests/test_net.rs @@ -32,6 +32,9 @@ use light::provider::LightProvider; use network::{NodeId, PeerId}; use util::RwLock; +use time::Duration; +use light::cache::Cache; + const NETWORK_ID: u64 = 0xcafebabe; struct TestIoContext<'a> { @@ -207,7 +210,8 @@ impl TestNet { pub fn light(n_light: usize, n_full: usize) -> Self { let mut peers = Vec::with_capacity(n_light + n_full); for _ in 0..n_light { - let client = LightClient::in_memory(Default::default(), &Spec::new_test(), IoChannel::disconnected()); + let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::hours(6)))); + let client = LightClient::in_memory(Default::default(), &Spec::new_test(), IoChannel::disconnected(), cache); peers.push(Arc::new(Peer::new_light(Arc::new(client)))) } diff --git a/sync/src/tests/consensus.rs b/sync/src/tests/consensus.rs index 2c45bbd28..00a7452c4 100644 --- a/sync/src/tests/consensus.rs +++ b/sync/src/tests/consensus.rs @@ -196,8 +196,8 @@ fn tendermint() { // Propose net.peer(0).chain.engine().step(); net.peer(1).chain.engine().step(); -net.peer(0).chain.miner().import_own_transaction(&*net.peer(0).chain, new_tx(s0.secret(), 2.into())).unwrap(); - net.peer(1).chain.miner().import_own_transaction(&*net.peer(1).chain, new_tx(s1.secret(), 2.into())).unwrap(); + net.peer(0).chain.miner().import_own_transaction(&*net.peer(0).chain, new_tx(s0.secret(), 2.into())).unwrap(); + net.peer(1).chain.miner().import_own_transaction(&*net.peer(1).chain, new_tx(s1.secret(), 2.into())).unwrap(); // Send different prevotes net.sync(); // Prevote timeout diff --git a/sync/src/tests/helpers.rs b/sync/src/tests/helpers.rs index 328c0a24f..9d32d1951 100644 --- a/sync/src/tests/helpers.rs +++ b/sync/src/tests/helpers.rs @@ -277,31 +277,32 @@ impl TestNet> { started: false, disconnect_events: Vec::new(), }; - for _ in 0..n { - let spec = spec_factory(); - let client = EthcoreClient::new( - ClientConfig::default(), - &spec, - Arc::new(::util::kvdb::in_memory(::ethcore::db::NUM_COLUMNS.unwrap_or(0))), - Arc::new(Miner::with_spec_and_accounts(&spec, accounts.clone())), - IoChannel::disconnected(), - ).unwrap(); - - let ss = Arc::new(TestSnapshotService::new()); - let sync = ChainSync::new(config.clone(), &*client); - let peer = Arc::new(EthPeer { - sync: RwLock::new(sync), - snapshot_service: ss, - chain: client, - queue: RwLock::new(VecDeque::new()), - }); - peer.chain.add_notify(peer.clone()); - net.peers.push(peer); + net.add_peer(config.clone(), spec_factory(), accounts.clone()); } - net } + + pub fn add_peer(&mut self, config: SyncConfig, spec: Spec, accounts: Option>) { + let client = EthcoreClient::new( + ClientConfig::default(), + &spec, + Arc::new(::util::kvdb::in_memory(::ethcore::db::NUM_COLUMNS.unwrap_or(0))), + Arc::new(Miner::with_spec_and_accounts(&spec, accounts)), + IoChannel::disconnected(), + ).unwrap(); + + let ss = Arc::new(TestSnapshotService::new()); + let sync = ChainSync::new(config, &*client); + let peer = Arc::new(EthPeer { + sync: RwLock::new(sync), + snapshot_service: ss, + chain: client, + queue: RwLock::new(VecDeque::new()), + }); + peer.chain.add_notify(peer.clone()); + self.peers.push(peer); + } } impl

TestNet

where P: Peer {