Merge branch 'master' into on-demand-priority
This commit is contained in:
commit
a98052fe74
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -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)",
|
||||
]
|
||||
|
@ -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<H256, encoded::Header>,
|
||||
canon_hashes: MemoryLruCache<BlockNumber, H256>,
|
||||
|
@ -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.
|
||||
|
@ -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<BlockDescriptor>,
|
||||
db: Arc<KeyValueDB>,
|
||||
col: Option<u32>,
|
||||
cache: Arc<Mutex<Cache>>,
|
||||
}
|
||||
|
||||
impl HeaderChain {
|
||||
/// Create a new header chain given this genesis block and database to read from.
|
||||
pub fn new(db: Arc<KeyValueDB>, col: Option<u32>, genesis: &[u8]) -> Result<Self, String> {
|
||||
pub fn new(db: Arc<KeyValueDB>, col: Option<u32>, genesis: &[u8], cache: Arc<Mutex<Cache>>) -> Result<Self, String> {
|
||||
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<encoded::Header> {
|
||||
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())
|
||||
}
|
||||
|
@ -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<KeyValueDB>, chain_col: Option<u32>, spec: &Spec, io_channel: IoChannel<ClientIoMessage>) -> Result<Self, String> {
|
||||
pub fn new(config: Config, db: Arc<KeyValueDB>, chain_col: Option<u32>, spec: &Spec, io_channel: IoChannel<ClientIoMessage>, cache: Arc<Mutex<Cache>>) -> Result<Self, String> {
|
||||
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<ClientIoMessage>) -> Self {
|
||||
pub fn in_memory(config: Config, spec: &Spec, io_channel: IoChannel<ClientIoMessage>, cache: Arc<Mutex<Cache>>) -> 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.
|
||||
|
@ -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<Self, Error> {
|
||||
pub fn start(config: ClientConfig, spec: &Spec, path: &Path, cache: Arc<Mutex<Cache>>) -> Result<Self, Error> {
|
||||
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! PIP Protocol Version 1 implementation.
|
||||
//! PLP Protocol Version 1 implementation.
|
||||
//!
|
||||
//! This uses a "Provider" to answer requests.
|
||||
|
||||
|
@ -14,7 +14,8 @@
|
||||
"eip155Transition": "0x7fffffffffffffff",
|
||||
"eip160Transition": "0x7fffffffffffffff",
|
||||
"eip161abcTransition": "0x7fffffffffffffff",
|
||||
"eip161dTransition": "0x7fffffffffffffff"
|
||||
"eip161dTransition": "0x7fffffffffffffff",
|
||||
"maxCodeSize": 24576
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -14,7 +14,8 @@
|
||||
"eip155Transition": "0x7fffffffffffffff",
|
||||
"eip160Transition": "0x0",
|
||||
"eip161abcTransition": "0x0",
|
||||
"eip161dTransition": "0x0"
|
||||
"eip161dTransition": "0x0",
|
||||
"maxCodeSize": 24576
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -61,6 +61,11 @@ pub fn consensus_view(header: &Header) -> Result<View, ::rlp::DecoderError> {
|
||||
UntrustedRlp::new(view_rlp.as_slice()).as_val()
|
||||
}
|
||||
|
||||
/// Proposal signature.
|
||||
pub fn proposal_signature(header: &Header) -> Result<H520, ::rlp::DecoderError> {
|
||||
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<Self, ::rlp::DecoderError> {
|
||||
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<Address, Error> {
|
||||
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));
|
||||
|
@ -97,6 +97,8 @@ pub struct Tendermint {
|
||||
proposal: RwLock<Option<H256>>,
|
||||
/// Hash of the proposal parent block.
|
||||
proposal_parent: RwLock<H256>,
|
||||
/// Last block proposed by this validator.
|
||||
last_proposed: RwLock<H256>,
|
||||
/// Set used to determine the current validators.
|
||||
validators: Box<ValidatorSet>,
|
||||
}
|
||||
@ -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<Engine>, 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<Client>) {
|
||||
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());
|
||||
|
||||
|
@ -136,30 +136,14 @@ impl <M: Message + Default + Encodable + Debug> VoteCollector<M> {
|
||||
*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<SealSignatures> {
|
||||
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<H520> {
|
||||
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::<HashSet<_>>(), collector.round_signatures(&commit_round, &bh.unwrap()).iter().collect::<HashSet<_>>());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -48,7 +48,7 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> {
|
||||
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);
|
||||
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
use super::test_common::*;
|
||||
use tests::helpers::*;
|
||||
use super::state::json_chain_test;
|
||||
|
||||
fn do_json_test(json_data: &[u8]) -> Vec<String> {
|
||||
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"}
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
use super::test_common::*;
|
||||
use tests::helpers::*;
|
||||
use super::state::json_chain_test;
|
||||
|
||||
fn do_json_test(json_data: &[u8]) -> Vec<String> {
|
||||
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"}
|
@ -14,7 +14,6 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use super::test_common::*;
|
||||
use super::chain::json_chain_test;
|
||||
use tests::helpers::*;
|
||||
|
||||
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
use super::test_common::*;
|
||||
use tests::helpers::*;
|
||||
use super::state::json_chain_test;
|
||||
|
||||
fn do_json_test(json_data: &[u8]) -> Vec<String> {
|
||||
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"}
|
@ -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;
|
||||
|
@ -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<String> {
|
||||
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<String> {
|
||||
::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<LogEntry> = 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<String> {
|
||||
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/"}
|
||||
}
|
||||
|
||||
|
@ -15,21 +15,63 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
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<String>) {
|
||||
let path = Path::new(p);
|
||||
let s: HashSet<OsString> = 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<String>) {
|
||||
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, []);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ pub enum ChainEra {
|
||||
Frontier,
|
||||
Homestead,
|
||||
Eip150,
|
||||
Eip161,
|
||||
_Eip161,
|
||||
TransitionTest,
|
||||
}
|
||||
|
||||
@ -359,12 +359,23 @@ pub fn get_temp_state() -> GuardedTempResult<State<::state_db::StateDB>> {
|
||||
}
|
||||
}
|
||||
|
||||
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())
|
||||
|
@ -94,11 +94,11 @@ pub trait Keccak256<T> {
|
||||
fn keccak256(&self) -> T where T: Sized;
|
||||
}
|
||||
|
||||
impl Keccak256<[u8; 32]> for [u8] {
|
||||
impl<T> 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
|
||||
}
|
||||
|
@ -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"]
|
||||
|
@ -15,6 +15,7 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::iter::repeat;
|
||||
use std::str;
|
||||
use ethkey::Secret;
|
||||
use {json, Error, crypto};
|
||||
use crypto::Keccak256;
|
||||
@ -46,22 +47,38 @@ impl From<json::Crypto> for Crypto {
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<json::Crypto> for Crypto {
|
||||
fn into(self) -> json::Crypto {
|
||||
impl From<Crypto> 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 = <json::Crypto as str::FromStr>::Err;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
s.parse::<json::Crypto>().map(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Crypto> 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<Secret, Error> {
|
||||
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<Vec<u8>, Error> {
|
||||
let expected_len = self.ciphertext.len();
|
||||
self.do_decrypt(password, expected_len)
|
||||
|
@ -225,8 +225,8 @@ impl<T> KeyDirectory for DiskDirectory<T> where T: KeyFileManager {
|
||||
Some(self)
|
||||
}
|
||||
|
||||
fn unique_repr(&self) -> Result<u64, Error> {
|
||||
self.files_hash()
|
||||
fn unique_repr(&self) -> Result<u64, Error> {
|
||||
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");
|
||||
}
|
||||
|
@ -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<P>(vault_dir_path: P, key: &VaultKey, meta: &str) -> Result<(), Error> where P: AsRef<Path> {
|
||||
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<P>(vault_dir_path: P, key: Option<&VaultKey>) -> Result<Strin
|
||||
|
||||
if let Some(key) = key {
|
||||
let password_bytes = vault_file_crypto.decrypt(&key.password)?;
|
||||
let password_hash = key.password.sha3();
|
||||
if &*password_hash != password_bytes.as_slice() {
|
||||
let password_hash = key.password.keccak256();
|
||||
if password_hash != password_bytes.as_slice() {
|
||||
return Err(Error::InvalidPassword);
|
||||
}
|
||||
}
|
||||
@ -279,12 +279,14 @@ fn read_vault_file<P>(vault_dir_path: P, key: Option<&VaultKey>) -> Result<Strin
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
extern crate tempdir;
|
||||
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
use dir::VaultKey;
|
||||
use super::{VAULT_FILE_NAME, check_vault_name, make_vault_dir_path, create_vault_file, read_vault_file, VaultDiskDirectory};
|
||||
use devtools::RandomTempPath;
|
||||
use self::tempdir::TempDir;
|
||||
|
||||
#[test]
|
||||
fn check_vault_name_succeeds() {
|
||||
@ -320,9 +322,9 @@ mod test {
|
||||
#[test]
|
||||
fn create_vault_file_succeeds() {
|
||||
// given
|
||||
let temp_path = RandomTempPath::new();
|
||||
let temp_path = TempDir::new("").unwrap();
|
||||
let key = VaultKey::new("password", 1024);
|
||||
let mut vault_dir: PathBuf = temp_path.as_path().into();
|
||||
let mut vault_dir: PathBuf = temp_path.path().into();
|
||||
vault_dir.push("vault");
|
||||
fs::create_dir_all(&vault_dir).unwrap();
|
||||
|
||||
@ -339,10 +341,10 @@ mod test {
|
||||
#[test]
|
||||
fn read_vault_file_succeeds() {
|
||||
// given
|
||||
let temp_path = RandomTempPath::create_dir();
|
||||
let temp_path = TempDir::new("").unwrap();
|
||||
let key = VaultKey::new("password", 1024);
|
||||
let vault_file_contents = r#"{"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"758696c8dc6378ab9b25bb42790da2f5"},"ciphertext":"54eb50683717d41caaeb12ea969f2c159daada5907383f26f327606a37dc7168","kdf":"pbkdf2","kdfparams":{"c":1024,"dklen":32,"prf":"hmac-sha256","salt":"3c320fa566a1a7963ac8df68a19548d27c8f40bf92ef87c84594dcd5bbc402b6"},"mac":"9e5c2314c2a0781962db85611417c614bd6756666b6b1e93840f5b6ed895f003"}}"#;
|
||||
let dir: PathBuf = temp_path.as_path().into();
|
||||
let dir: PathBuf = temp_path.path().into();
|
||||
let mut vault_file_path: PathBuf = dir.clone();
|
||||
vault_file_path.push(VAULT_FILE_NAME);
|
||||
{
|
||||
@ -360,9 +362,9 @@ mod test {
|
||||
#[test]
|
||||
fn read_vault_file_fails() {
|
||||
// given
|
||||
let temp_path = RandomTempPath::create_dir();
|
||||
let temp_path = TempDir::new("").unwrap();
|
||||
let key = VaultKey::new("password1", 1024);
|
||||
let dir: PathBuf = temp_path.as_path().into();
|
||||
let dir: PathBuf = temp_path.path().into();
|
||||
let mut vault_file_path: PathBuf = dir.clone();
|
||||
vault_file_path.push(VAULT_FILE_NAME);
|
||||
|
||||
@ -389,9 +391,9 @@ mod test {
|
||||
#[test]
|
||||
fn vault_directory_can_be_created() {
|
||||
// given
|
||||
let temp_path = RandomTempPath::new();
|
||||
let temp_path = TempDir::new("").unwrap();
|
||||
let key = VaultKey::new("password", 1024);
|
||||
let dir: PathBuf = temp_path.as_path().into();
|
||||
let dir: PathBuf = temp_path.path().into();
|
||||
|
||||
// when
|
||||
let vault = VaultDiskDirectory::create(&dir, "vault", key.clone());
|
||||
@ -409,9 +411,9 @@ mod test {
|
||||
#[test]
|
||||
fn vault_directory_cannot_be_created_if_already_exists() {
|
||||
// given
|
||||
let temp_path = RandomTempPath::new();
|
||||
let temp_path = TempDir::new("").unwrap();
|
||||
let key = VaultKey::new("password", 1024);
|
||||
let dir: PathBuf = temp_path.as_path().into();
|
||||
let dir: PathBuf = temp_path.path().into();
|
||||
let mut vault_dir = dir.clone();
|
||||
vault_dir.push("vault");
|
||||
fs::create_dir_all(&vault_dir).unwrap();
|
||||
@ -426,9 +428,9 @@ mod test {
|
||||
#[test]
|
||||
fn vault_directory_cannot_be_opened_if_not_exists() {
|
||||
// given
|
||||
let temp_path = RandomTempPath::create_dir();
|
||||
let temp_path = TempDir::new("").unwrap();
|
||||
let key = VaultKey::new("password", 1024);
|
||||
let dir: PathBuf = temp_path.as_path().into();
|
||||
let dir: PathBuf = temp_path.path().into();
|
||||
|
||||
// when
|
||||
let vault = VaultDiskDirectory::at(&dir, "vault", key);
|
||||
|
@ -620,13 +620,14 @@ impl SimpleSecretStore for EthMultiStore {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
extern crate tempdir;
|
||||
|
||||
use dir::{KeyDirectory, MemoryDirectory, RootDiskDirectory};
|
||||
use ethkey::{Random, Generator, KeyPair};
|
||||
use secret_store::{SimpleSecretStore, SecretStore, SecretVaultRef, StoreAccountRef, Derivation};
|
||||
use super::{EthStore, EthMultiStore};
|
||||
use devtools::RandomTempPath;
|
||||
use util::H256;
|
||||
use self::tempdir::TempDir;
|
||||
use bigint::hash::H256;
|
||||
|
||||
fn keypair() -> KeyPair {
|
||||
Random.generate().unwrap()
|
||||
@ -642,13 +643,13 @@ mod tests {
|
||||
|
||||
struct RootDiskDirectoryGuard {
|
||||
pub key_dir: Option<Box<KeyDirectory>>,
|
||||
_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),
|
||||
|
@ -14,10 +14,11 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
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<Self, Self::Err> {
|
||||
serde_json::from_str(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Crypto> 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,
|
||||
|
@ -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};
|
||||
|
@ -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)]
|
||||
|
@ -92,6 +92,7 @@ pub struct Client<F: Fetch + 'static = FetchClient> {
|
||||
contract: URLHintContract,
|
||||
fetch: F,
|
||||
remote: Remote,
|
||||
random_path: Arc<Fn() -> PathBuf + Sync + Send>,
|
||||
}
|
||||
|
||||
impl Client {
|
||||
@ -109,6 +110,7 @@ impl<F: Fetch + 'static> Client<F> {
|
||||
contract: URLHintContract::new(contract),
|
||||
fetch: fetch,
|
||||
remote: remote,
|
||||
random_path: Arc::new(random_temp_path),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -131,6 +133,7 @@ impl<F: Fetch + 'static> HashFetch for Client<F> {
|
||||
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<Response, FetchError>) -> Result<PathBuf, Error> {
|
||||
let response = result?;
|
||||
@ -155,12 +158,12 @@ impl<F: Fetch + 'static> HashFetch for Client<F> {
|
||||
}
|
||||
|
||||
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]
|
||||
|
@ -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 <admin@parity.io>",
|
||||
|
@ -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;
|
||||
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
export default function () {
|
||||
// empty file included while building parity.js (don't include local keygen)
|
||||
}
|
@ -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);
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
@ -14,4 +14,4 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
export LocalAccountsMiddleware from './middleware';
|
||||
export LocalAccountsMiddleware from './localAccountsMiddleware';
|
||||
|
@ -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,
|
154
js/src/api/local/localAccountsMiddleware.spec.js
Normal file
154
js/src/api/local/localAccountsMiddleware.spec.js
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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;
|
||||
});
|
||||
});
|
||||
});
|
@ -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;
|
||||
|
@ -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);
|
||||
});
|
||||
});
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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', () => {
|
||||
|
@ -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`
|
||||
|
@ -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'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -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) => {
|
||||
|
@ -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++;
|
||||
}
|
||||
|
||||
|
@ -608,7 +608,7 @@ class WriteContract extends Component {
|
||||
label={
|
||||
<FormattedMessage
|
||||
id='writeContract.input.abi'
|
||||
defaultMessage='ABI Interface'
|
||||
defaultMessage='ABI Definition'
|
||||
/>
|
||||
}
|
||||
readOnly
|
||||
|
@ -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')
|
||||
|
@ -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')
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -76,7 +76,6 @@ module.exports = {
|
||||
|
||||
resolve: {
|
||||
alias: {
|
||||
'secp256k1/js': path.resolve(__dirname, '../src/api/local/ethkey/dummy.js'),
|
||||
'~': path.resolve(__dirname, '../src')
|
||||
},
|
||||
modules: [
|
||||
|
@ -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<T> {
|
||||
/// Some.
|
||||
Some(T),
|
||||
|
@ -14,13 +14,16 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! 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<ForkSpec, Vec<PostStateResult>>,
|
||||
/// Transaction.
|
||||
pub transaction: MultiTransaction,
|
||||
}
|
||||
|
||||
/// State test transaction deserialization.
|
||||
#[derive(Debug, PartialEq, Deserialize)]
|
||||
pub struct MultiTransaction {
|
||||
/// Transaction data set.
|
||||
pub data: Vec<Bytes>,
|
||||
/// Gas limit set.
|
||||
#[serde(rename="gasLimit")]
|
||||
pub gas_limit: Vec<Uint>,
|
||||
/// 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<Address>,
|
||||
/// Value set.
|
||||
pub value: Vec<Uint>,
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -192,6 +192,10 @@ fn execute_light(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) ->
|
||||
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<RotatingLogger>) ->
|
||||
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<RotatingLogger>) ->
|
||||
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()));
|
||||
|
||||
|
@ -475,7 +475,7 @@ pub fn execute<D: Dispatcher + 'static>(
|
||||
.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<D>(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()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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| {
|
||||
|
@ -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<RpcH520, Error> {
|
||||
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, B>(a: Vec<A>) -> Vec<B> where
|
||||
|
@ -140,7 +140,7 @@ impl<D: Dispatcher + 'static> ParitySigning for SigningQueueClient<D> {
|
||||
fn post_sign(&self, meta: Metadata, address: RpcH160, data: RpcBytes) -> BoxFuture<RpcEither<RpcU256, RpcConfirmationResponse>, 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<D: Dispatcher + 'static> EthSigning for SigningQueueClient<D> {
|
||||
|
||||
fn sign(&self, meta: Metadata, address: RpcH160, data: RpcBytes) -> BoxFuture<RpcH520, Error> {
|
||||
let res = self.dispatch(
|
||||
RpcConfirmationPayload::Signature((address.clone(), data).into()),
|
||||
RpcConfirmationPayload::EthSignMessage((address.clone(), data).into()),
|
||||
address.into(),
|
||||
meta.origin,
|
||||
);
|
||||
|
@ -78,7 +78,7 @@ impl<D: Dispatcher + 'static> EthSigning for SigningUnsafeClient<D>
|
||||
type Metadata = Metadata;
|
||||
|
||||
fn sign(&self, _: Metadata, address: RpcH160, data: RpcBytes) -> BoxFuture<RpcH520, Error> {
|
||||
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),
|
||||
|
@ -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()));
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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<KeyFile, Error>;
|
||||
|
||||
/// Sign raw hash with the key corresponding to address and password.
|
||||
#[rpc(name = "parity_signMessage")]
|
||||
fn sign_message(&self, H160, String, H256) -> Result<H520, Error>;
|
||||
}
|
||||
}
|
||||
|
@ -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<helpers::ConfirmationPayload> 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()),
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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<Peer> {
|
||||
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))))
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -277,31 +277,32 @@ impl TestNet<EthPeer<EthcoreClient>> {
|
||||
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<Arc<AccountProvider>>) {
|
||||
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<P> TestNet<P> where P: Peer {
|
||||
|
Loading…
Reference in New Issue
Block a user