diff --git a/bin/Cargo.toml b/bin/Cargo.toml index 7174ada14..8fc233796 100644 --- a/bin/Cargo.toml +++ b/bin/Cargo.toml @@ -15,6 +15,7 @@ ctrlc = "1.0" ethcore-util = { path = "../util" } ethcore-rpc = { path = "../rpc", optional = true } ethcore = { path = ".." } +ethsync = { path = "../sync" } clippy = "0.0.37" [features] diff --git a/bin/src/main.rs b/bin/src/main.rs index 3d4199fcf..92f0cbf20 100644 --- a/bin/src/main.rs +++ b/bin/src/main.rs @@ -8,6 +8,7 @@ extern crate docopt; extern crate rustc_serialize; extern crate ethcore_util as util; extern crate ethcore; +extern crate ethsync; extern crate log; extern crate env_logger; extern crate ctrlc; @@ -24,7 +25,7 @@ use ethcore::client::*; use ethcore::service::{ClientService, NetSyncMessage}; use ethcore::ethereum; use ethcore::blockchain::CacheSize; -use ethcore::sync::EthSync; +use ethsync::EthSync; docopt!(Args derive Debug, " Parity. Ethereum Client. @@ -81,8 +82,10 @@ fn main() { let mut net_settings = NetworkConfiguration::new(); net_settings.boot_nodes = init_nodes; let mut service = ClientService::start(spec, net_settings).unwrap(); - setup_rpc_server(service.client(), service.sync()); - let io_handler = Arc::new(ClientIoHandler { client: service.client(), info: Default::default(), sync: service.sync() }); + let client = service.client().clone(); + let sync = EthSync::register(service.network(), client); + setup_rpc_server(service.client(), sync.clone()); + let io_handler = Arc::new(ClientIoHandler { client: service.client(), info: Default::default(), sync: sync }); service.io().register_handler(io_handler).expect("Error registering IO handler"); let exit = Arc::new(Condvar::new()); diff --git a/src/block.rs b/src/block.rs index 83780ab43..963124be0 100644 --- a/src/block.rs +++ b/src/block.rs @@ -45,14 +45,14 @@ impl Decodable for Block { if decoder.as_raw().len() != try!(decoder.as_rlp().payload_info()).total() { return Err(DecoderError::RlpIsTooBig); } - let d = try!(decoder.as_list()); - if d.len() != 3 { + let d = decoder.as_rlp(); + if d.item_count() != 3 { return Err(DecoderError::RlpIncorrectListLen); } Ok(Block { - header: try!(Decodable::decode(&d[0])), - transactions: try!(Decodable::decode(&d[1])), - uncles: try!(Decodable::decode(&d[2])), + header: try!(d.val_at(0)), + transactions: try!(d.val_at(1)), + uncles: try!(d.val_at(2)), }) } } @@ -245,11 +245,11 @@ impl<'x, 'y> OpenBlock<'x, 'y> { pub fn close(self) -> ClosedBlock<'x, 'y> { let mut s = self; s.engine.on_close_block(&mut s.block); - s.block.base.header.transactions_root = ordered_trie_root(s.block.base.transactions.iter().map(|ref e| e.rlp_bytes()).collect()); + s.block.base.header.transactions_root = ordered_trie_root(s.block.base.transactions.iter().map(|ref e| e.rlp_bytes().to_vec()).collect()); let uncle_bytes = s.block.base.uncles.iter().fold(RlpStream::new_list(s.block.base.uncles.len()), |mut s, u| {s.append(&u.rlp(Seal::With)); s} ).out(); s.block.base.header.uncles_hash = uncle_bytes.sha3(); s.block.base.header.state_root = s.block.state.root().clone(); - s.block.base.header.receipts_root = ordered_trie_root(s.block.receipts.iter().map(|ref r| r.rlp_bytes()).collect()); + s.block.base.header.receipts_root = ordered_trie_root(s.block.receipts.iter().map(|ref r| r.rlp_bytes().to_vec()).collect()); s.block.base.header.log_bloom = s.block.receipts.iter().fold(LogBloom::zero(), |mut b, r| {b |= &r.log_bloom; b}); s.block.base.header.gas_used = s.block.receipts.last().map_or(U256::zero(), |r| r.gas_used); s.block.base.header.note_dirty(); @@ -301,8 +301,7 @@ impl SealedBlock { pub fn rlp_bytes(&self) -> Bytes { let mut block_rlp = RlpStream::new_list(3); self.block.base.header.stream_rlp(&mut block_rlp, Seal::With); - block_rlp.append_list(self.block.receipts.len()); - for t in &self.block.base.transactions { t.rlp_append(&mut block_rlp); } + block_rlp.append(&self.block.base.transactions); block_rlp.append_raw(&self.uncle_bytes, 1); block_rlp.out() } diff --git a/src/blockchain.rs b/src/blockchain.rs index 2610407ac..757e51c59 100644 --- a/src/blockchain.rs +++ b/src/blockchain.rs @@ -785,8 +785,9 @@ mod tests { } assert!(bc.cache_size().blocks > 1024 * 1024); - bc.collect_garbage(true); - + for _ in 0..2 { + bc.collect_garbage(true); + } assert!(bc.cache_size().blocks < 1024 * 1024); } diff --git a/src/ethereum/ethash.rs b/src/ethereum/ethash.rs index 4736beb92..f28ea31c6 100644 --- a/src/ethereum/ethash.rs +++ b/src/ethereum/ethash.rs @@ -48,7 +48,7 @@ impl Engine for Ethash { // Two fields - mix fn seal_fields(&self) -> usize { 2 } // Two empty data items in RLP. - fn seal_rlp(&self) -> Bytes { encode(&H64::new()) } + fn seal_rlp(&self) -> Bytes { encode(&H64::new()).to_vec() } /// Additional engine-specific information for the user/developer concerning `header`. fn extra_info(&self, _header: &Header) -> HashMap { HashMap::new() } diff --git a/src/ethereum/mod.rs b/src/ethereum/mod.rs index 66bb7f356..caab556de 100644 --- a/src/ethereum/mod.rs +++ b/src/ethereum/mod.rs @@ -26,7 +26,7 @@ pub fn new_frontier_test() -> Spec { Spec::from_json_utf8(include_bytes!("../../ pub fn new_homestead_test() -> Spec { Spec::from_json_utf8(include_bytes!("../../res/ethereum/homestead_test.json")) } /// Create a new Frontier main net chain spec without genesis accounts. -pub fn new_frontier_like_test() -> Spec { Spec::from_json_utf8(include_bytes!("../../res/ethereum/frontier_like_test.json")) } +pub fn new_mainnet_like() -> Spec { Spec::from_json_utf8(include_bytes!("../../res/ethereum/frontier_like_test.json")) } /// Create a new Morden chain spec. pub fn new_morden() -> Spec { Spec::from_json_utf8(include_bytes!("../../res/ethereum/morden.json")) } diff --git a/src/executive.rs b/src/executive.rs index b113363fd..039a6007e 100644 --- a/src/executive.rs +++ b/src/executive.rs @@ -251,12 +251,13 @@ impl<'a> Executive<'a> { // part of substate that may be reverted let mut unconfirmed_substate = Substate::new(); - // at first create new contract - self.state.new_contract(¶ms.address); - - // then transfer value to it + // create contract and transfer value to it if necessary + let prev_bal = self.state.balance(¶ms.address); if let ActionValue::Transfer(val) = params.value { - self.state.transfer_balance(¶ms.sender, ¶ms.address, &val); + self.state.sub_balance(¶ms.sender, &val); + self.state.new_contract(¶ms.address, val + prev_bal); + } else { + self.state.new_contract(¶ms.address, prev_bal); } let res = { diff --git a/src/extras.rs b/src/extras.rs index fb4748447..4459826cc 100644 --- a/src/extras.rs +++ b/src/extras.rs @@ -133,25 +133,24 @@ impl HeapSizeOf for BlockDetails { impl Decodable for BlockDetails { fn decode(decoder: &D) -> Result where D: Decoder { - let d = try!(decoder.as_list()); + let d = decoder.as_rlp(); let details = BlockDetails { - number: try!(Decodable::decode(&d[0])), - total_difficulty: try!(Decodable::decode(&d[1])), - parent: try!(Decodable::decode(&d[2])), - children: try!(Decodable::decode(&d[3])) + number: try!(d.val_at(0)), + total_difficulty: try!(d.val_at(1)), + parent: try!(d.val_at(2)), + children: try!(d.val_at(3)), }; Ok(details) } } impl Encodable for BlockDetails { - fn encode(&self, encoder: &mut E) where E: Encoder { - encoder.emit_list(| e | { - self.number.encode(e); - self.total_difficulty.encode(e); - self.parent.encode(e); - self.children.encode(e); - }) + fn rlp_append(&self, s: &mut RlpStream) { + s.begin_list(4); + s.append(&self.number); + s.append(&self.total_difficulty); + s.append(&self.parent); + s.append(&self.children); } } @@ -185,8 +184,8 @@ impl Decodable for BlockLogBlooms { } impl Encodable for BlockLogBlooms { - fn encode(&self, encoder: &mut E) where E: Encoder { - self.blooms.encode(encoder); + fn rlp_append(&self, s: &mut RlpStream) { + s.append(&self.blooms); } } @@ -231,9 +230,9 @@ impl Decodable for BlocksBlooms { } impl Encodable for BlocksBlooms { - fn encode(&self, encoder: &mut E) where E: Encoder { + fn rlp_append(&self, s: &mut RlpStream) { let blooms_ref: &[H2048] = &self.blooms; - blooms_ref.encode(encoder); + s.append(&blooms_ref); } } @@ -258,10 +257,10 @@ impl HeapSizeOf for TransactionAddress { impl Decodable for TransactionAddress { fn decode(decoder: &D) -> Result where D: Decoder { - let d = try!(decoder.as_list()); + let d = decoder.as_rlp(); let tx_address = TransactionAddress { - block_hash: try!(Decodable::decode(&d[0])), - index: try!(Decodable::decode(&d[1])) + block_hash: try!(d.val_at(0)), + index: try!(d.val_at(1)), }; Ok(tx_address) @@ -269,10 +268,9 @@ impl Decodable for TransactionAddress { } impl Encodable for TransactionAddress { - fn encode(&self, encoder: &mut E) where E: Encoder { - encoder.emit_list(| e | { - self.block_hash.encode(e); - self.index.encode(e); - }) + fn rlp_append(&self, s: &mut RlpStream) { + s.begin_list(2); + s.append(&self.block_hash); + s.append(&self.index); } } diff --git a/src/header.rs b/src/header.rs index a57d4166d..c6c18bf4b 100644 --- a/src/header.rs +++ b/src/header.rs @@ -157,7 +157,7 @@ impl Header { // TODO: make these functions traity /// TODO [Gav Wood] Please document me pub fn stream_rlp(&self, s: &mut RlpStream, with_seal: Seal) { - s.append_list(13 + match with_seal { Seal::With => self.seal.len(), _ => 0 }); + s.begin_list(13 + match with_seal { Seal::With => self.seal.len(), _ => 0 }); s.append(&self.parent_hash); s.append(&self.uncles_hash); s.append(&self.author); @@ -221,26 +221,8 @@ impl Decodable for Header { } impl Encodable for Header { - fn encode(&self, encoder: &mut E) where E: Encoder { - encoder.emit_list(| e | { - self.parent_hash.encode(e); - self.uncles_hash.encode(e); - self.author.encode(e); - self.state_root.encode(e); - self.transactions_root.encode(e); - self.receipts_root.encode(e); - self.log_bloom.encode(e); - self.difficulty.encode(e); - self.number.encode(e); - self.gas_limit.encode(e); - self.gas_used.encode(e); - self.timestamp.encode(e); - self.extra_data.encode(e); - - for b in &self.seal { - e.emit_raw(&b); - } - }) + fn rlp_append(&self, s: &mut RlpStream) { + self.stream_rlp(s, Seal::With); } } diff --git a/src/lib.rs b/src/lib.rs index e084635dd..0652d964e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -151,8 +151,6 @@ mod tests; /// TODO [arkpar] Please document me pub mod client; /// TODO [arkpar] Please document me -pub mod sync; -/// TODO [arkpar] Please document me pub mod block; /// TODO [arkpar] Please document me pub mod verification; diff --git a/src/log_entry.rs b/src/log_entry.rs index be39a72f2..8141549a3 100644 --- a/src/log_entry.rs +++ b/src/log_entry.rs @@ -12,9 +12,9 @@ pub struct LogEntry { pub data: Bytes, } -impl RlpStandard for LogEntry { +impl Encodable for LogEntry { fn rlp_append(&self, s: &mut RlpStream) { - s.append_list(3); + s.begin_list(3); s.append(&self.address); s.append(&self.topics); s.append(&self.data); diff --git a/src/pod_account.rs b/src/pod_account.rs index 979658202..97cfcb6fd 100644 --- a/src/pod_account.rs +++ b/src/pod_account.rs @@ -36,7 +36,7 @@ impl PodAccount { let mut stream = RlpStream::new_list(4); stream.append(&self.nonce); stream.append(&self.balance); - stream.append(&sec_trie_root(self.storage.iter().map(|(k, v)| (k.to_vec(), encode(&U256::from(v.as_slice())))).collect())); + stream.append(&sec_trie_root(self.storage.iter().map(|(k, v)| (k.to_vec(), encode(&U256::from(v.as_slice())).to_vec())).collect())); stream.append(&self.code.sha3()); stream.out() } diff --git a/src/receipt.rs b/src/receipt.rs index 4389de962..d320373d6 100644 --- a/src/receipt.rs +++ b/src/receipt.rs @@ -27,17 +27,12 @@ impl Receipt { } } -impl RlpStandard for Receipt { +impl Encodable for Receipt { fn rlp_append(&self, s: &mut RlpStream) { - s.append_list(4); + s.begin_list(4); s.append(&self.state_root); s.append(&self.gas_used); s.append(&self.log_bloom); - // TODO: make work: - //s.append(&self.logs); - s.append_list(self.logs.len()); - for l in &self.logs { - l.rlp_append(s); - } + s.append(&self.logs); } } diff --git a/src/service.rs b/src/service.rs index 8c900d20a..a56ed7f44 100644 --- a/src/service.rs +++ b/src/service.rs @@ -1,5 +1,4 @@ use util::*; -use sync::*; use spec::Spec; use error::*; use std::env; @@ -21,7 +20,6 @@ pub type NetSyncMessage = NetworkIoMessage; pub struct ClientService { net_service: NetworkService, client: Arc, - sync: Arc, } impl ClientService { @@ -34,7 +32,6 @@ impl ClientService { dir.push(".parity"); dir.push(H64::from(spec.genesis_header().hash()).hex()); let client = try!(Client::new(spec, &dir, net_service.io().channel())); - let sync = EthSync::register(&mut net_service, client.clone()); let client_io = Arc::new(ClientIoHandler { client: client.clone() }); @@ -43,29 +40,28 @@ impl ClientService { Ok(ClientService { net_service: net_service, client: client, - sync: sync, }) } - /// Get the network service. + /// Add a node to network pub fn add_node(&mut self, _enode: &str) { unimplemented!(); } - /// TODO [arkpar] Please document me + /// Get general IO interface pub fn io(&mut self) -> &mut IoService { self.net_service.io() } - /// TODO [arkpar] Please document me + /// Get client interface pub fn client(&self) -> Arc { self.client.clone() } - - /// Get shared sync handler - pub fn sync(&self) -> Arc { - self.sync.clone() + + /// Get network service component + pub fn network(&mut self) -> &mut NetworkService { + &mut self.net_service } } diff --git a/src/spec.rs b/src/spec.rs index 4d342f713..d51246b23 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -20,14 +20,14 @@ pub fn gzip64res_to_json(source: &[u8]) -> Json { // TODO: handle container types. fn json_to_rlp(json: &Json) -> Bytes { match *json { - Json::Boolean(o) => encode(&(if o {1u64} else {0})), - Json::I64(o) => encode(&(o as u64)), - Json::U64(o) => encode(&o), + Json::Boolean(o) => encode(&(if o {1u64} else {0})).to_vec(), + Json::I64(o) => encode(&(o as u64)).to_vec(), + Json::U64(o) => encode(&o).to_vec(), Json::String(ref s) if s.len() >= 2 && &s[0..2] == "0x" && U256::from_str(&s[2..]).is_ok() => { - encode(&U256::from_str(&s[2..]).unwrap()) + encode(&U256::from_str(&s[2..]).unwrap()).to_vec() }, Json::String(ref s) => { - encode(s) + encode(s).to_vec() }, _ => panic!() } diff --git a/src/state.rs b/src/state.rs index 7310f63a7..9b44d7194 100644 --- a/src/state.rs +++ b/src/state.rs @@ -72,8 +72,8 @@ impl State { /// Create a new contract at address `contract`. If there is already an account at the address /// it will have its code reset, ready for `init_code()`. - pub fn new_contract(&mut self, contract: &Address) { - self.require_or_from(contract, false, || Account::new_contract(U256::from(0u8)), |r| r.reset_code()); + pub fn new_contract(&mut self, contract: &Address, balance: U256) { + self.cache.borrow_mut().insert(contract.clone(), Some(Account::new_contract(balance))); } /// Remove an existing account. diff --git a/src/tests/chain.rs b/src/tests/chain.rs index d56d99491..4d1835033 100644 --- a/src/tests/chain.rs +++ b/src/tests/chain.rs @@ -1,6 +1,3 @@ -use std::env; -use log::{LogLevelFilter}; -use env_logger::LogBuilder; use super::test_common::*; use client::{BlockChainClient,Client}; use pod_state::*; @@ -8,29 +5,8 @@ use block::Block; use ethereum; use super::helpers::*; -pub enum ChainEra { - Frontier, - Homestead, -} - -lazy_static! { - static ref LOG_DUMMY: bool = { - let mut builder = LogBuilder::new(); - builder.filter(None, LogLevelFilter::Info); - - if let Ok(log) = env::var("RUST_LOG") { - builder.parse(&log); - } - - if let Ok(_) = builder.init() { - println!("logger initialized"); - } - true - }; -} - pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { - let _ = LOG_DUMMY.deref(); + init_log(); let json = Json::from_str(::std::str::from_utf8(json_data).unwrap()).expect("Json is invalid"); let mut failed = Vec::new(); diff --git a/src/tests/executive.rs b/src/tests/executive.rs index 1df1b7eec..ab5cdaf98 100644 --- a/src/tests/executive.rs +++ b/src/tests/executive.rs @@ -182,8 +182,7 @@ fn do_json_test_for(vm: &VMType, json_data: &[u8]) -> Vec { let code = xjson!(&s["code"]); let _nonce: U256 = xjson!(&s["nonce"]); - state.new_contract(&address); - state.add_balance(&address, &balance); + state.new_contract(&address, balance); state.init_code(&address, code); BTreeMap::from_json(&s["storage"]).into_iter().foreach(|(k, v)| state.set_storage(&address, k, v)); }); diff --git a/src/tests/helpers.rs b/src/tests/helpers.rs index f87138795..7f24b6c6f 100644 --- a/src/tests/helpers.rs +++ b/src/tests/helpers.rs @@ -6,6 +6,10 @@ use spec::*; use std::fs::{remove_dir_all}; use blockchain::{BlockChain}; +pub enum ChainEra { + Frontier, + Homestead, +} pub struct RandomTempPath { path: PathBuf @@ -86,6 +90,17 @@ fn create_unverifiable_block(order: u32, parent_hash: H256) -> Bytes { create_test_block(&create_unverifiable_block_header(order, parent_hash)) } +pub fn create_test_block_with_data(header: &Header, transactions: &[&Transaction], uncles: &[Header]) -> Bytes { + let mut rlp = RlpStream::new_list(3); + rlp.append(header); + rlp.begin_list(transactions.len()); + for t in transactions { + rlp.append_raw(&t.rlp_bytes_opt(Seal::With), 1); + } + rlp.append(&uncles); + rlp.out() +} + pub fn generate_dummy_client(block_number: u32) -> GuardedTempResult> { let dir = RandomTempPath::new(); diff --git a/src/tests/homestead_chain.rs b/src/tests/homestead_chain.rs index a9f544d8f..5691f3a19 100644 --- a/src/tests/homestead_chain.rs +++ b/src/tests/homestead_chain.rs @@ -1,5 +1,6 @@ use super::test_common::*; -use super::chain::{ChainEra, json_chain_test}; +use super::helpers::*; +use super::chain::json_chain_test; fn do_json_test(json_data: &[u8]) -> Vec { json_chain_test(json_data, ChainEra::Homestead) diff --git a/src/tests/homestead_state.rs b/src/tests/homestead_state.rs new file mode 100644 index 000000000..f0f7cd21e --- /dev/null +++ b/src/tests/homestead_state.rs @@ -0,0 +1,23 @@ +use super::test_common::*; +use super::helpers::*; +use super::state::json_chain_test; + +fn do_json_test(json_data: &[u8]) -> Vec { + json_chain_test(json_data, ChainEra::Homestead) +} + +declare_test!{StateTests_Homestead_stCallCodes, "StateTests/Homestead/stCallCodes"} +declare_test!{StateTests_Homestead_stCallCreateCallCodeTest, "StateTests/Homestead/stCallCreateCallCodeTest"} +declare_test!{StateTests_Homestead_stDelegatecallTest, "StateTests/Homestead/stDelegatecallTest"} +declare_test!{StateTests_Homestead_stInitCodeTest, "StateTests/Homestead/stInitCodeTest"} +declare_test!{StateTests_Homestead_stLogTests, "StateTests/Homestead/stLogTests"} +declare_test!{heavy => StateTests_Homestead_stMemoryStressTest, "StateTests/Homestead/stMemoryStressTest"} +declare_test!{heavy => StateTests_Homestead_stMemoryTest, "StateTests/Homestead/stMemoryTest"} +declare_test!{StateTests_Homestead_stPreCompiledContracts, "StateTests/Homestead/stPreCompiledContracts"} +declare_test!{heavy => StateTests_Homestead_stQuadraticComplexityTest, "StateTests/Homestead/stQuadraticComplexityTest"} +declare_test!{StateTests_Homestead_stRecursiveCreate, "StateTests/Homestead/stRecursiveCreate"} +declare_test!{StateTests_Homestead_stRefundTest, "StateTests/Homestead/stRefundTest"} +declare_test!{StateTests_Homestead_stSpecialTest, "StateTests/Homestead/stSpecialTest"} +declare_test!{StateTests_Homestead_stSystemOperationsTest, "StateTests/Homestead/stSystemOperationsTest"} +declare_test!{StateTests_Homestead_stTransactionTest, "StateTests/Homestead/stTransactionTest"} +declare_test!{StateTests_Homestead_stWalletTest, "StateTests/Homestead/stWalletTest"} diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 8ee6ef7e1..bda581eac 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -7,4 +7,5 @@ mod state; mod client; mod chain; pub mod helpers; +mod homestead_state; mod homestead_chain; \ No newline at end of file diff --git a/src/tests/state.rs b/src/tests/state.rs index ebb4fabda..cf5efbca1 100644 --- a/src/tests/state.rs +++ b/src/tests/state.rs @@ -1,14 +1,25 @@ use super::test_common::*; +use super::helpers::*; use state::*; use pod_state::*; use state_diff::*; use ethereum; fn do_json_test(json_data: &[u8]) -> Vec { + json_chain_test(json_data, ChainEra::Frontier) +} + +pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { + init_log(); + let json = Json::from_str(::std::str::from_utf8(json_data).unwrap()).expect("Json is invalid"); let mut failed = Vec::new(); - let engine = ethereum::new_frontier_like_test().to_engine().unwrap(); + let engine = match era { + ChainEra::Frontier => ethereum::new_mainnet_like(), + ChainEra::Homestead => ethereum::new_homestead_test(), + }.to_engine().unwrap(); + flush(format!("\n")); for (name, test) in json.as_object().unwrap() { @@ -90,3 +101,647 @@ declare_test!{StateTests_stSystemOperationsTest, "StateTests/stSystemOperationsT 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"} diff --git a/src/transaction.rs b/src/transaction.rs index cacdf2a25..24b617f67 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -111,7 +111,7 @@ impl Transaction { /// Append object into RLP stream, optionally with or without the signature. pub fn rlp_append_opt(&self, s: &mut RlpStream, with_seal: Seal) { - s.append_list(6 + match with_seal { Seal::With => 3, _ => 0 }); + s.begin_list(6 + match with_seal { Seal::With => 3, _ => 0 }); s.append(&self.nonce); s.append(&self.gas_price); s.append(&self.gas); @@ -162,7 +162,7 @@ impl FromJson for Transaction { } } -impl RlpStandard for Transaction { +impl Encodable for Transaction { fn rlp_append(&self, s: &mut RlpStream) { self.rlp_append_opt(s, Seal::With) } } @@ -267,20 +267,20 @@ impl Decodable for Action { impl Decodable for Transaction { fn decode(decoder: &D) -> Result where D: Decoder { - let d = try!(decoder.as_list()); - if d.len() != 9 { + let d = decoder.as_rlp(); + if d.item_count() != 9 { return Err(DecoderError::RlpIncorrectListLen); } Ok(Transaction { - nonce: try!(Decodable::decode(&d[0])), - gas_price: try!(Decodable::decode(&d[1])), - gas: try!(Decodable::decode(&d[2])), - action: try!(Decodable::decode(&d[3])), - value: try!(Decodable::decode(&d[4])), - data: try!(Decodable::decode(&d[5])), - v: try!(u16::decode(&d[6])) as u8, - r: try!(Decodable::decode(&d[7])), - s: try!(Decodable::decode(&d[8])), + nonce: try!(d.val_at(0)), + gas_price: try!(d.val_at(1)), + gas: try!(d.val_at(2)), + action: try!(d.val_at(3)), + value: try!(d.val_at(4)), + data: try!(d.val_at(5)), + v: try!(d.val_at(6)), + r: try!(d.val_at(7)), + s: try!(d.val_at(8)), hash: RefCell::new(None), sender: RefCell::new(None), }) diff --git a/src/verification.rs b/src/verification.rs index 158f28f95..368ff84e9 100644 --- a/src/verification.rs +++ b/src/verification.rs @@ -221,28 +221,7 @@ mod tests { use spec::*; use transaction::*; use basic_types::*; - - fn create_test_block(header: &Header) -> Bytes { - let mut rlp = RlpStream::new_list(3); - rlp.append(header); - rlp.append_raw(&rlp::EMPTY_LIST_RLP, 1); - rlp.append_raw(&rlp::EMPTY_LIST_RLP, 1); - rlp.out() - } - - fn create_test_block_with_data(header: &Header, transactions: &[&Transaction], uncles: &[Header]) -> Bytes { - let mut rlp = RlpStream::new_list(3); - rlp.append(header); - rlp.append_list(transactions.len()); - for t in transactions { - rlp.append_raw(&t.rlp_bytes_opt(Seal::With), 1); - } - rlp.append_list(uncles.len()); - for h in uncles { - rlp.append(h); - } - rlp.out() - } + use tests::helpers::*; fn check_ok(result: Result<(), Error>) { result.unwrap_or_else(|e| panic!("Block verification failed: {:?}", e)); diff --git a/sync/Cargo.toml b/sync/Cargo.toml new file mode 100644 index 000000000..c3ae470fd --- /dev/null +++ b/sync/Cargo.toml @@ -0,0 +1,16 @@ +[package] +description = "Ethcore blockchain sync" +name = "ethsync" +version = "0.1.0" +license = "GPL-3.0" +authors = ["Ethcore usize { @@ -669,6 +670,12 @@ impl ChainSync { block_rlp.append_raw(body.at(0).as_raw(), 1); block_rlp.append_raw(body.at(1).as_raw(), 1); let h = &headers.1[i].hash; + // Perform basic block verification + if !Block::is_good(block_rlp.as_raw()) { + debug!(target: "sync", "Bad block rlp {:?} : {:?}", h, block_rlp.as_raw()); + restart = true; + break; + } match io.chain().import_block(block_rlp.out()) { Err(ImportError::AlreadyInChain) => { trace!(target: "sync", "Block already in chain {:?}", h); diff --git a/src/sync/io.rs b/sync/src/io.rs similarity index 96% rename from src/sync/io.rs rename to sync/src/io.rs index 501d36ad2..4425a2555 100644 --- a/src/sync/io.rs +++ b/sync/src/io.rs @@ -1,7 +1,7 @@ -use client::BlockChainClient; +use ethcore::client::BlockChainClient; use util::{NetworkContext, PeerId, PacketId,}; use util::error::UtilError; -use service::SyncMessage; +use ethcore::service::SyncMessage; /// IO interface for the syning handler. /// Provides peer connection management and an interface to the blockchain client. diff --git a/src/sync/mod.rs b/sync/src/lib.rs similarity index 65% rename from src/sync/mod.rs rename to sync/src/lib.rs index 34a1e429d..09f3eb521 100644 --- a/src/sync/mod.rs +++ b/sync/src/lib.rs @@ -1,34 +1,46 @@ -/// Blockchain sync module -/// Implements ethereum protocol version 63 as specified here: -/// https://github.com/ethereum/wiki/wiki/Ethereum-Wire-Protocol -/// -/// Usage example: -/// -/// ```rust -/// extern crate ethcore_util as util; -/// extern crate ethcore; -/// use std::env; -/// use std::sync::Arc; -/// use util::network::{NetworkService, NetworkConfiguration}; -/// use ethcore::client::Client; -/// use ethcore::sync::EthSync; -/// use ethcore::ethereum; -/// -/// fn main() { -/// let mut service = NetworkService::start(NetworkConfiguration::new()).unwrap(); -/// let dir = env::temp_dir(); -/// let client = Client::new(ethereum::new_frontier(), &dir, service.io().channel()).unwrap(); -/// EthSync::register(&mut service, client); -/// } -/// ``` +#![warn(missing_docs)] +#![feature(plugin)] +#![plugin(clippy)] +#![feature(augmented_assignments)] +//! Blockchain sync module +//! Implements ethereum protocol version 63 as specified here: +//! https://github.com/ethereum/wiki/wiki/Ethereum-Wire-Protocol +//! +//! Usage example: +//! +//! ```rust +//! extern crate ethcore_util as util; +//! extern crate ethcore; +//! extern crate ethsync; +//! use std::env; +//! use std::sync::Arc; +//! use util::network::{NetworkService, NetworkConfiguration}; +//! use ethcore::client::Client; +//! use ethsync::EthSync; +//! use ethcore::ethereum; +//! +//! fn main() { +//! let mut service = NetworkService::start(NetworkConfiguration::new()).unwrap(); +//! let dir = env::temp_dir(); +//! let client = Client::new(ethereum::new_frontier(), &dir, service.io().channel()).unwrap(); +//! EthSync::register(&mut service, client); +//! } +//! ``` + +#[macro_use] +extern crate log; +#[macro_use] +extern crate ethcore_util as util; +extern crate ethcore; +extern crate env_logger; use std::ops::*; use std::sync::*; -use client::Client; +use ethcore::client::Client; use util::network::{NetworkProtocolHandler, NetworkService, NetworkContext, PeerId}; -use sync::chain::ChainSync; -use service::SyncMessage; -use sync::io::NetSyncIo; +use chain::ChainSync; +use ethcore::service::SyncMessage; +use io::NetSyncIo; mod chain; mod io; diff --git a/src/sync/range_collection.rs b/sync/src/range_collection.rs similarity index 100% rename from src/sync/range_collection.rs rename to sync/src/range_collection.rs diff --git a/sync/src/service.rs b/sync/src/service.rs new file mode 100644 index 000000000..8c900d20a --- /dev/null +++ b/sync/src/service.rs @@ -0,0 +1,104 @@ +use util::*; +use sync::*; +use spec::Spec; +use error::*; +use std::env; +use client::Client; + +/// Message type for external and internal events +#[derive(Clone)] +pub enum SyncMessage { + /// New block has been imported into the blockchain + NewChainBlock(Bytes), //TODO: use Cow + /// A block is ready + BlockVerified, +} + +/// TODO [arkpar] Please document me +pub type NetSyncMessage = NetworkIoMessage; + +/// Client service setup. Creates and registers client and network services with the IO subsystem. +pub struct ClientService { + net_service: NetworkService, + client: Arc, + sync: Arc, +} + +impl ClientService { + /// Start the service in a separate thread. + pub fn start(spec: Spec, net_config: NetworkConfiguration) -> Result { + let mut net_service = try!(NetworkService::start(net_config)); + info!("Starting {}", net_service.host_info()); + info!("Configured for {} using {} engine", spec.name, spec.engine_name); + let mut dir = env::home_dir().unwrap(); + dir.push(".parity"); + dir.push(H64::from(spec.genesis_header().hash()).hex()); + let client = try!(Client::new(spec, &dir, net_service.io().channel())); + let sync = EthSync::register(&mut net_service, client.clone()); + let client_io = Arc::new(ClientIoHandler { + client: client.clone() + }); + try!(net_service.io().register_handler(client_io)); + + Ok(ClientService { + net_service: net_service, + client: client, + sync: sync, + }) + } + + /// Get the network service. + pub fn add_node(&mut self, _enode: &str) { + unimplemented!(); + } + + /// TODO [arkpar] Please document me + pub fn io(&mut self) -> &mut IoService { + self.net_service.io() + } + + /// TODO [arkpar] Please document me + pub fn client(&self) -> Arc { + self.client.clone() + + } + + /// Get shared sync handler + pub fn sync(&self) -> Arc { + self.sync.clone() + } +} + +/// IO interface for the Client handler +struct ClientIoHandler { + client: Arc +} + +const CLIENT_TICK_TIMER: TimerToken = 0; +const CLIENT_TICK_MS: u64 = 5000; + +impl IoHandler for ClientIoHandler { + fn initialize(&self, io: &IoContext) { + io.register_timer(CLIENT_TICK_TIMER, CLIENT_TICK_MS).expect("Error registering client timer"); + } + + fn timeout(&self, _io: &IoContext, timer: TimerToken) { + if timer == CLIENT_TICK_TIMER { + self.client.tick(); + } + } + + #[allow(match_ref_pats)] + #[allow(single_match)] + fn message(&self, io: &IoContext, net_message: &NetSyncMessage) { + if let &UserMessage(ref message) = net_message { + match message { + &SyncMessage::BlockVerified => { + self.client.import_verified_blocks(&io.channel()); + }, + _ => {}, // ignore other messages + } + } + } +} + diff --git a/src/sync/tests.rs b/sync/src/tests.rs similarity index 95% rename from src/sync/tests.rs rename to sync/src/tests.rs index eca8a07a6..41516ef60 100644 --- a/src/sync/tests.rs +++ b/sync/src/tests.rs @@ -1,10 +1,10 @@ use util::*; -use client::{BlockChainClient, BlockStatus, TreeRoute, BlockChainInfo}; -use block_queue::BlockQueueInfo; -use header::{Header as BlockHeader, BlockNumber}; -use error::*; -use sync::io::SyncIo; -use sync::chain::ChainSync; +use ethcore::client::{BlockChainClient, BlockStatus, TreeRoute, BlockChainInfo}; +use ethcore::block_queue::BlockQueueInfo; +use ethcore::header::{Header as BlockHeader, BlockNumber}; +use ethcore::error::*; +use io::SyncIo; +use chain::ChainSync; struct TestBlockChainClient { blocks: RwLock>, @@ -38,7 +38,11 @@ impl TestBlockChainClient { header.number = n as BlockNumber; let mut uncles = RlpStream::new_list(if empty {0} else {1}); if !empty { - uncles.append(&H256::from(&U256::from(n))); + let mut uncle_header = BlockHeader::new(); + uncle_header.difficulty = From::from(n); + uncle_header.parent_hash = self.last_hash.read().unwrap().clone(); + uncle_header.number = n as BlockNumber; + uncles.append(&uncle_header); header.uncles_hash = uncles.as_raw().sha3(); } let mut rlp = RlpStream::new_list(3); diff --git a/util/src/bytes.rs b/util/src/bytes.rs index 3144dd482..050c07a66 100644 --- a/util/src/bytes.rs +++ b/util/src/bytes.rs @@ -11,39 +11,55 @@ //! let slice: &[u8] = arr.bytes(); //! } //! -//! fn to_bytes() { -//! use util::bytes::ToBytes; -//! -//! let a: Vec = "hello_world".to_bytes(); -//! let b: Vec = 400u32.to_bytes(); -//! let c: Vec = 0xffffffffffffffffu64.to_bytes(); -//! } -//! -//! fn from_bytes() { -//! use util::bytes::FromBytes; -//! -//! let a = String::from_bytes(&[b'd', b'o', b'g']); -//! let b = u16::from_bytes(&[0xfa]); -//! let c = u64::from_bytes(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]); -//! } -//! //! fn main() { //! bytes_convertable(); -//! to_bytes(); -//! from_bytes(); //! } //! ``` -use std::mem; use std::fmt; use std::slice; -use std::cmp::Ordering; -use std::error::Error as StdError; use std::ops::{Deref, DerefMut}; -use uint::{Uint, U128, U256}; use hash::FixedHash; +use elastic_array::*; -/// TODO [Gav Wood] Please document me +/// Vector like object +pub trait VecLike { + /// Add an element to the collection + fn vec_push(&mut self, value: T); + + /// Add a slice to the collection + fn vec_extend(&mut self, slice: &[T]); +} + +impl VecLike for Vec where T: Copy { + fn vec_push(&mut self, value: T) { + Vec::::push(self, value) + } + + fn vec_extend(&mut self, slice: &[T]) { + Vec::::extend_from_slice(self, slice) + } +} + +macro_rules! impl_veclike_for_elastic_array { + ($from: ident) => { + impl VecLike for $from where T: Copy { + fn vec_push(&mut self, value: T) { + $from::::push(self, value) + } + fn vec_extend(&mut self, slice: &[T]) { + $from::::append_slice(self, slice) + + } + } + } +} + +impl_veclike_for_elastic_array!(ElasticArray16); +impl_veclike_for_elastic_array!(ElasticArray32); +impl_veclike_for_elastic_array!(ElasticArray1024); + +/// Slie pretty print helper pub struct PrettySlice<'a> (&'a [u8]); impl<'a> fmt::Debug for PrettySlice<'a> { @@ -166,223 +182,6 @@ fn bytes_convertable() { assert_eq!([0u8; 0].bytes(), &[]); } -/// Converts given type to its shortest representation in bytes -/// -/// TODO: optimise some conversations -pub trait ToBytes { - /// TODO [Gav Wood] Please document me - fn to_bytes(&self) -> Vec; - /// TODO [Gav Wood] Please document me - fn to_bytes_len(&self) -> usize { self.to_bytes().len() } - /// TODO [debris] Please document me - fn first_byte(&self) -> Option { self.to_bytes().first().map(|&x| { x })} -} - -impl <'a> ToBytes for &'a str { - fn to_bytes(&self) -> Vec { - From::from(*self) - } - - fn to_bytes_len(&self) -> usize { self.len() } -} - -impl ToBytes for String { - fn to_bytes(&self) -> Vec { - let s: &str = self.as_ref(); - From::from(s) - } - - fn to_bytes_len(&self) -> usize { self.len() } -} - -impl ToBytes for u64 { - fn to_bytes(&self) -> Vec { - let mut res= vec![]; - let count = self.to_bytes_len(); - res.reserve(count); - for i in 0..count { - let j = count - 1 - i; - res.push((*self >> (j * 8)) as u8); - } - res - } - - fn to_bytes_len(&self) -> usize { 8 - self.leading_zeros() as usize / 8 } -} - -impl ToBytes for bool { - fn to_bytes(&self) -> Vec { - vec![ if *self { 1u8 } else { 0u8 } ] - } - - fn to_bytes_len(&self) -> usize { 1 } -} - -macro_rules! impl_map_to_bytes { - ($from: ident, $to: ty) => { - impl ToBytes for $from { - fn to_bytes(&self) -> Vec { (*self as $to).to_bytes() } - fn to_bytes_len(&self) -> usize { (*self as $to).to_bytes_len() } - } - } -} - -impl_map_to_bytes!(usize, u64); -impl_map_to_bytes!(u16, u64); -impl_map_to_bytes!(u32, u64); - -macro_rules! impl_uint_to_bytes { - ($name: ident) => { - impl ToBytes for $name { - fn to_bytes(&self) -> Vec { - let mut res= vec![]; - let count = self.to_bytes_len(); - res.reserve(count); - for i in 0..count { - let j = count - 1 - i; - res.push(self.byte(j)); - } - res - } - fn to_bytes_len(&self) -> usize { (self.bits() + 7) / 8 } - } - } -} - -impl_uint_to_bytes!(U256); -impl_uint_to_bytes!(U128); - -impl ToBytes for T where T: FixedHash { - fn to_bytes(&self) -> Vec { - let mut res: Vec = vec![]; - res.reserve(T::size()); - - unsafe { - use std::ptr; - ptr::copy(self.bytes().as_ptr(), res.as_mut_ptr(), T::size()); - res.set_len(T::size()); - } - - res - } -} - -/// Error returned when FromBytes conversation goes wrong -#[derive(Debug, PartialEq, Eq)] -pub enum FromBytesError { - /// TODO [debris] Please document me - DataIsTooShort, - /// TODO [debris] Please document me - DataIsTooLong, - /// Integer-representation is non-canonically prefixed with zero byte(s). - ZeroPrefixedInt, -} - -impl StdError for FromBytesError { - fn description(&self) -> &str { "from_bytes error" } -} - -impl fmt::Display for FromBytesError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&self, f) - } -} - -/// Alias for the result of FromBytes trait -pub type FromBytesResult = Result; - -/// Converts to given type from its bytes representation -/// -/// TODO: check size of bytes before conversation and return appropriate error -pub trait FromBytes: Sized { - /// TODO [debris] Please document me - fn from_bytes(bytes: &[u8]) -> FromBytesResult; -} - -impl FromBytes for String { - fn from_bytes(bytes: &[u8]) -> FromBytesResult { - Ok(::std::str::from_utf8(bytes).unwrap().to_owned()) - } -} - -macro_rules! impl_uint_from_bytes { - ($to: ident) => { - impl FromBytes for $to { - fn from_bytes(bytes: &[u8]) -> FromBytesResult<$to> { - match bytes.len() { - 0 => Ok(0), - l if l <= mem::size_of::<$to>() => { - if bytes[0] == 0 { - return Err(FromBytesError::ZeroPrefixedInt) - } - let mut res = 0 as $to; - for i in 0..l { - let shift = (l - 1 - i) * 8; - res = res + ((bytes[i] as $to) << shift); - } - Ok(res) - } - _ => Err(FromBytesError::DataIsTooLong) - } - } - } - } -} - -impl FromBytes for bool { - fn from_bytes(bytes: &[u8]) -> FromBytesResult { - match bytes.len() { - 0 => Ok(false), - 1 => Ok(bytes[0] != 0), - _ => Err(FromBytesError::DataIsTooLong), - } - } -} - -//impl_uint_from_bytes!(u8); -impl_uint_from_bytes!(u16); -impl_uint_from_bytes!(u32); -impl_uint_from_bytes!(u64); -impl_uint_from_bytes!(usize); - -macro_rules! impl_uint_from_bytes { - ($name: ident) => { - impl FromBytes for $name { - fn from_bytes(bytes: &[u8]) -> FromBytesResult<$name> { - if !bytes.is_empty() && bytes[0] == 0 { - Err(FromBytesError::ZeroPrefixedInt) - } else if bytes.len() <= $name::SIZE { - Ok($name::from(bytes)) - } else { - Err(FromBytesError::DataIsTooLong) - } - } - } - } -} - -impl_uint_from_bytes!(U256); -impl_uint_from_bytes!(U128); - -impl FromBytes for T where T: FixedHash { - fn from_bytes(bytes: &[u8]) -> FromBytesResult { - match bytes.len().cmp(&T::size()) { - Ordering::Less => return Err(FromBytesError::DataIsTooShort), - Ordering::Greater => return Err(FromBytesError::DataIsTooLong), - Ordering::Equal => () - }; - - unsafe { - use std::{mem, ptr}; - - let mut res: T = mem::uninitialized(); - ptr::copy(bytes.as_ptr(), res.as_slice_mut().as_mut_ptr(), T::size()); - - Ok(res) - } - } -} - /// Simple trait to allow for raw population of a Sized object from a byte slice. pub trait Populatable { /// Copies a bunch of bytes `d` to `self`, overwriting as necessary. diff --git a/util/src/lib.rs b/util/src/lib.rs index b1b93968c..622fc950b 100644 --- a/util/src/lib.rs +++ b/util/src/lib.rs @@ -43,8 +43,6 @@ extern crate tiny_keccak; #[macro_use] extern crate heapsize; #[macro_use] -extern crate log; -#[macro_use] extern crate lazy_static; #[macro_use] extern crate itertools; @@ -56,6 +54,8 @@ extern crate arrayvec; extern crate elastic_array; extern crate crossbeam; extern crate serde; +#[macro_use] +extern crate log as rlog; /// TODO [Gav Wood] Please document me pub mod standard; @@ -98,6 +98,7 @@ pub mod semantic_version; pub mod io; /// TODO [Gav Wood] Please document me pub mod network; +pub mod log; pub use common::*; pub use misc::*; @@ -118,3 +119,4 @@ pub use squeeze::*; pub use semantic_version::*; pub use network::*; pub use io::*; +pub use log::*; diff --git a/util/src/log.rs b/util/src/log.rs new file mode 100644 index 000000000..619d4af3a --- /dev/null +++ b/util/src/log.rs @@ -0,0 +1,26 @@ +//! Common log helper functions + +use std::env; +use rlog::{LogLevelFilter}; +use env_logger::LogBuilder; + +lazy_static! { + static ref LOG_DUMMY: bool = { + let mut builder = LogBuilder::new(); + builder.filter(None, LogLevelFilter::Info); + + if let Ok(log) = env::var("RUST_LOG") { + builder.parse(&log); + } + + if let Ok(_) = builder.init() { + println!("logger initialized"); + } + true + }; +} + +/// Intialize log with default settings +pub fn init_log() { + let _ = *LOG_DUMMY; +} diff --git a/util/src/network/host.rs b/util/src/network/host.rs index 6f306ecb0..95b1e3668 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -124,11 +124,10 @@ pub struct CapabilityInfo { } impl Encodable for CapabilityInfo { - fn encode(&self, encoder: &mut E) -> () where E: Encoder { - encoder.emit_list(|e| { - self.protocol.encode(e); - (self.version as u32).encode(e); - }); + fn rlp_append(&self, s: &mut RlpStream) { + s.begin_list(2); + s.append(&self.protocol); + s.append(&self.version); } } diff --git a/util/src/network/session.rs b/util/src/network/session.rs index 2817f008d..fb385b487 100644 --- a/util/src/network/session.rs +++ b/util/src/network/session.rs @@ -57,11 +57,10 @@ pub struct PeerCapabilityInfo { impl Decodable for PeerCapabilityInfo { fn decode(decoder: &D) -> Result where D: Decoder { - let c = try!(decoder.as_list()); - let v: u32 = try!(Decodable::decode(&c[1])); + let c = decoder.as_rlp(); Ok(PeerCapabilityInfo { - protocol: try!(Decodable::decode(&c[0])), - version: v as u8, + protocol: try!(c.val_at(0)), + version: try!(c.val_at(1)) }) } } @@ -199,7 +198,7 @@ impl Session { fn write_hello(&mut self, host: &HostInfo) -> Result<(), UtilError> { let mut rlp = RlpStream::new(); rlp.append_raw(&[PACKET_HELLO as u8], 0); - rlp.append_list(5) + rlp.begin_list(5) .append(&host.protocol_version) .append(&host.client_version) .append(&host.capabilities) @@ -267,7 +266,7 @@ impl Session { fn disconnect(&mut self, reason: DisconnectReason) -> NetworkError { let mut rlp = RlpStream::new(); rlp.append(&(PACKET_DISCONNECT as u32)); - rlp.append_list(1); + rlp.begin_list(1); rlp.append(&(reason.clone() as u32)); self.connection.send_packet(&rlp.out()).ok(); NetworkError::Disconnect(reason) @@ -276,7 +275,7 @@ impl Session { fn prepare(packet_id: u8) -> Result { let mut rlp = RlpStream::new(); rlp.append(&(packet_id as u32)); - rlp.append_list(0); + rlp.begin_list(0); Ok(rlp) } diff --git a/util/src/overlaydb.rs b/util/src/overlaydb.rs index d2f56a520..7ef0c3309 100644 --- a/util/src/overlaydb.rs +++ b/util/src/overlaydb.rs @@ -143,7 +143,6 @@ impl OverlayDB { self.backing.delete(&key.bytes()).expect("Low-level database error. Some issue with your hard disk?"); true } - } } diff --git a/util/src/rlp/bytes.rs b/util/src/rlp/bytes.rs new file mode 100644 index 000000000..69562764c --- /dev/null +++ b/util/src/rlp/bytes.rs @@ -0,0 +1,255 @@ +//! Unified interfaces for RLP bytes operations on basic types +//! + +use std::mem; +use std::fmt; +use std::cmp::Ordering; +use std::error::Error as StdError; +use uint::{Uint, U128, U256}; +use hash::FixedHash; +use elastic_array::*; + +/// Vector like object +pub trait VecLike { + /// Add an element to the collection + fn vec_push(&mut self, value: T); + + /// Add a slice to the collection + fn vec_extend(&mut self, slice: &[T]); +} + +impl VecLike for Vec where T: Copy { + fn vec_push(&mut self, value: T) { + Vec::::push(self, value) + } + + fn vec_extend(&mut self, slice: &[T]) { + Vec::::extend_from_slice(self, slice) + } +} + +macro_rules! impl_veclike_for_elastic_array { + ($from: ident) => { + impl VecLike for $from where T: Copy { + fn vec_push(&mut self, value: T) { + $from::::push(self, value) + } + fn vec_extend(&mut self, slice: &[T]) { + $from::::append_slice(self, slice) + + } + } + } +} + +impl_veclike_for_elastic_array!(ElasticArray16); +impl_veclike_for_elastic_array!(ElasticArray32); +impl_veclike_for_elastic_array!(ElasticArray1024); + +/// Converts given type to its shortest representation in bytes +/// +/// TODO: optimise some conversations +pub trait ToBytes { + /// Serialize self to byte array + fn to_bytes>(&self, out: &mut V); + /// Get length of serialized data in bytes + fn to_bytes_len(&self) -> usize; +} + +impl <'a> ToBytes for &'a str { + fn to_bytes>(&self, out: &mut V) { + out.vec_extend(self.as_bytes()); + } + + fn to_bytes_len(&self) -> usize { + self.as_bytes().len() + } +} + +impl ToBytes for String { + fn to_bytes>(&self, out: &mut V) { + out.vec_extend(self.as_bytes()); + } + + fn to_bytes_len(&self) -> usize { + self.len() + } +} + +impl ToBytes for u64 { + fn to_bytes>(&self, out: &mut V) { + let count = self.to_bytes_len(); + for i in 0..count { + let j = count - 1 - i; + out.vec_push((*self >> (j * 8)) as u8); + } + } + + fn to_bytes_len(&self) -> usize { 8 - self.leading_zeros() as usize / 8 } +} + +impl ToBytes for bool { + fn to_bytes>(&self, out: &mut V) { + out.vec_push(if *self { 1u8 } else { 0u8 }) + } + + fn to_bytes_len(&self) -> usize { 1 } +} + +macro_rules! impl_map_to_bytes { + ($from: ident, $to: ty) => { + impl ToBytes for $from { + fn to_bytes>(&self, out: &mut V) { + (*self as $to).to_bytes(out) + } + + fn to_bytes_len(&self) -> usize { (*self as $to).to_bytes_len() } + } + } +} + +impl_map_to_bytes!(usize, u64); +impl_map_to_bytes!(u16, u64); +impl_map_to_bytes!(u32, u64); + +macro_rules! impl_uint_to_bytes { + ($name: ident) => { + impl ToBytes for $name { + fn to_bytes>(&self, out: &mut V) { + let count = self.to_bytes_len(); + for i in 0..count { + let j = count - 1 - i; + out.vec_push(self.byte(j)); + } + } + fn to_bytes_len(&self) -> usize { (self.bits() + 7) / 8 } + } + } +} + +impl_uint_to_bytes!(U256); +impl_uint_to_bytes!(U128); + +impl ToBytes for T where T: FixedHash { + fn to_bytes>(&self, out: &mut V) { + out.vec_extend(self.bytes()); + } + fn to_bytes_len(&self) -> usize { self.bytes().len() } +} + +/// Error returned when FromBytes conversation goes wrong +#[derive(Debug, PartialEq, Eq)] +pub enum FromBytesError { + /// TODO [debris] Please document me + DataIsTooShort, + /// TODO [debris] Please document me + DataIsTooLong, + /// Integer-representation is non-canonically prefixed with zero byte(s). + ZeroPrefixedInt, +} + +impl StdError for FromBytesError { + fn description(&self) -> &str { "from_bytes error" } +} + +impl fmt::Display for FromBytesError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self, f) + } +} + +/// Alias for the result of FromBytes trait +pub type FromBytesResult = Result; + +/// Converts to given type from its bytes representation +/// +/// TODO: check size of bytes before conversation and return appropriate error +pub trait FromBytes: Sized { + /// TODO [debris] Please document me + fn from_bytes(bytes: &[u8]) -> FromBytesResult; +} + +impl FromBytes for String { + fn from_bytes(bytes: &[u8]) -> FromBytesResult { + Ok(::std::str::from_utf8(bytes).unwrap().to_owned()) + } +} + +macro_rules! impl_uint_from_bytes { + ($to: ident) => { + impl FromBytes for $to { + fn from_bytes(bytes: &[u8]) -> FromBytesResult<$to> { + match bytes.len() { + 0 => Ok(0), + l if l <= mem::size_of::<$to>() => { + if bytes[0] == 0 { + return Err(FromBytesError::ZeroPrefixedInt) + } + let mut res = 0 as $to; + for i in 0..l { + let shift = (l - 1 - i) * 8; + res = res + ((bytes[i] as $to) << shift); + } + Ok(res) + } + _ => Err(FromBytesError::DataIsTooLong) + } + } + } + } +} + +impl FromBytes for bool { + fn from_bytes(bytes: &[u8]) -> FromBytesResult { + match bytes.len() { + 0 => Ok(false), + 1 => Ok(bytes[0] != 0), + _ => Err(FromBytesError::DataIsTooLong), + } + } +} + +//impl_uint_from_bytes!(u8); +impl_uint_from_bytes!(u16); +impl_uint_from_bytes!(u32); +impl_uint_from_bytes!(u64); +impl_uint_from_bytes!(usize); + +macro_rules! impl_uint_from_bytes { + ($name: ident) => { + impl FromBytes for $name { + fn from_bytes(bytes: &[u8]) -> FromBytesResult<$name> { + if !bytes.is_empty() && bytes[0] == 0 { + Err(FromBytesError::ZeroPrefixedInt) + } else if bytes.len() <= $name::SIZE { + Ok($name::from(bytes)) + } else { + Err(FromBytesError::DataIsTooLong) + } + } + } + } +} + +impl_uint_from_bytes!(U256); +impl_uint_from_bytes!(U128); + +impl FromBytes for T where T: FixedHash { + fn from_bytes(bytes: &[u8]) -> FromBytesResult { + match bytes.len().cmp(&T::size()) { + Ordering::Less => return Err(FromBytesError::DataIsTooShort), + Ordering::Greater => return Err(FromBytesError::DataIsTooLong), + Ordering::Equal => () + }; + + unsafe { + use std::{mem, ptr}; + + let mut res: T = mem::uninitialized(); + ptr::copy(bytes.as_ptr(), res.as_slice_mut().as_mut_ptr(), T::size()); + + Ok(res) + } + } +} + diff --git a/util/src/rlp/mod.rs b/util/src/rlp/mod.rs index f6acdf180..f6101abc6 100644 --- a/util/src/rlp/mod.rs +++ b/util/src/rlp/mod.rs @@ -30,25 +30,22 @@ //! * You want to get view onto rlp-slice. //! * You don't want to decode whole rlp at once. -/// TODO [Gav Wood] Please document me pub mod rlptraits; -/// TODO [Gav Wood] Please document me -pub mod rlperrors; -/// TODO [debris] Please document me -pub mod rlpin; -/// TODO [debris] Please document me -pub mod untrusted_rlp; -/// TODO [debris] Please document me -pub mod rlpstream; +mod rlperrors; +mod rlpin; +mod untrusted_rlp; +mod rlpstream; +mod bytes; #[cfg(test)] mod tests; pub use self::rlperrors::DecoderError; -pub use self::rlptraits::{Decoder, Decodable, View, Stream, Encodable, Encoder}; +pub use self::rlptraits::{Decoder, Decodable, View, Stream, Encodable, Encoder, RlpEncodable, RlpDecodable}; pub use self::untrusted_rlp::{UntrustedRlp, UntrustedRlpIterator, PayloadInfo, Prototype}; pub use self::rlpin::{Rlp, RlpIterator}; -pub use self::rlpstream::{RlpStream,RlpStandard}; +pub use self::rlpstream::{RlpStream}; +pub use elastic_array::ElasticArray1024; use super::hash::H256; /// TODO [arkpar] Please document me @@ -72,7 +69,7 @@ pub const SHA3_EMPTY_LIST_RLP: H256 = H256( [0x1d, 0xcc, 0x4d, 0xe8, 0xde, 0xc7, /// assert_eq!(animals, vec!["cat".to_string(), "dog".to_string()]); /// } /// ``` -pub fn decode(bytes: &[u8]) -> T where T: Decodable { +pub fn decode(bytes: &[u8]) -> T where T: RlpDecodable { let rlp = Rlp::new(bytes); rlp.as_val() } @@ -84,13 +81,13 @@ pub fn decode(bytes: &[u8]) -> T where T: Decodable { /// use util::rlp::*; /// /// fn main () { -/// let animals = vec!["cat", "dog"]; -/// let out = encode(&animals); -/// assert_eq!(out, vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']); +/// let animal = "cat"; +/// let out = encode(&animal).to_vec(); +/// assert_eq!(out, vec![0x83, b'c', b'a', b't']); /// } /// ``` -pub fn encode(object: &E) -> Vec where E: Encodable { +pub fn encode(object: &E) -> ElasticArray1024 where E: RlpEncodable { let mut stream = RlpStream::new(); stream.append(object); - stream.out() + stream.drain() } diff --git a/util/src/rlp/rlperrors.rs b/util/src/rlp/rlperrors.rs index 6ac162236..f5d4629ad 100644 --- a/util/src/rlp/rlperrors.rs +++ b/util/src/rlp/rlperrors.rs @@ -1,6 +1,6 @@ use std::fmt; use std::error::Error as StdError; -use bytes::FromBytesError; +use rlp::bytes::FromBytesError; #[derive(Debug, PartialEq, Eq)] /// TODO [debris] Please document me diff --git a/util/src/rlp/rlpin.rs b/util/src/rlp/rlpin.rs index 5cecce44f..cfcaee014 100644 --- a/util/src/rlp/rlpin.rs +++ b/util/src/rlp/rlpin.rs @@ -1,5 +1,5 @@ use std::fmt; -use rlp::{View, Decodable, DecoderError, UntrustedRlp, PayloadInfo, Prototype}; +use rlp::{View, DecoderError, UntrustedRlp, PayloadInfo, Prototype, RlpDecodable}; impl<'a> From> for Rlp<'a> { fn from(rlp: UntrustedRlp<'a>) -> Rlp<'a> { @@ -88,28 +88,28 @@ impl<'a, 'view> View<'a, 'view> for Rlp<'a> where 'a: 'view { self.into_iter() } - fn as_val(&self) -> Result where T: Decodable { + fn as_val(&self) -> Result where T: RlpDecodable { self.rlp.as_val() } - fn val_at(&self, index: usize) -> Result where T: Decodable { + fn val_at(&self, index: usize) -> Result where T: RlpDecodable { self.at(index).rlp.as_val() } } impl <'a, 'view> Rlp<'a> where 'a: 'view { - fn view_as_val(r: &R) -> T where R: View<'a, 'view>, T: Decodable { + fn view_as_val(r: &R) -> T where R: View<'a, 'view>, T: RlpDecodable { let res: Result = r.as_val(); res.unwrap_or_else(|_| panic!()) } /// TODO [debris] Please document me - pub fn as_val(&self) -> T where T: Decodable { + pub fn as_val(&self) -> T where T: RlpDecodable { Self::view_as_val(self) } /// TODO [debris] Please document me - pub fn val_at(&self, index: usize) -> T where T: Decodable { + pub fn val_at(&self, index: usize) -> T where T: RlpDecodable { Self::view_as_val(&self.at(index)) } } diff --git a/util/src/rlp/rlpstream.rs b/util/src/rlp/rlpstream.rs index ac22736fc..b6b500a74 100644 --- a/util/src/rlp/rlpstream.rs +++ b/util/src/rlp/rlpstream.rs @@ -1,8 +1,8 @@ +use std::ops::Deref; use elastic_array::*; -use bytes::{Bytes, ToBytes}; +use rlp::bytes::{ToBytes, VecLike}; use rlp::{Stream, Encoder, Encodable}; -use hash::H256; -use sha3::*; +use rlp::rlptraits::{ByteEncodable, RlpEncodable}; #[derive(Debug, Copy, Clone)] struct ListInfo { @@ -25,6 +25,7 @@ impl ListInfo { pub struct RlpStream { unfinished_lists: ElasticArray16, encoder: BasicEncoder, + finished_list: bool, } impl Stream for RlpStream { @@ -32,27 +33,27 @@ impl Stream for RlpStream { RlpStream { unfinished_lists: ElasticArray16::new(), encoder: BasicEncoder::new(), + finished_list: false, } } fn new_list(len: usize) -> Self { let mut stream = RlpStream::new(); - stream.append_list(len); + stream.begin_list(len); stream } - fn append(&mut self, object: &E) -> &mut RlpStream where E: Encodable { - // encode given value and add it at the end of the stream - object.encode(&mut self.encoder); - - // if list is finished, prepend the length - self.note_appended(1); - - // return chainable self + fn append<'a, E>(&'a mut self, value: &E) -> &'a mut Self where E: RlpEncodable { + self.finished_list = false; + value.rlp_append(self); + if !self.finished_list { + self.note_appended(1); + } self } - fn append_list(&mut self, len: usize) -> &mut RlpStream { + fn begin_list(&mut self, len: usize) -> &mut RlpStream { + self.finished_list = false; match len { 0 => { // we may finish, if the appended list len is equal 0 @@ -117,6 +118,21 @@ impl Stream for RlpStream { impl RlpStream { + /// Appends primitive value to the end of stream + fn append_value(&mut self, object: &E) where E: ByteEncodable { + // encode given value and add it at the end of the stream + self.encoder.emit_value(object); + } + + fn append_internal<'a, E>(&'a mut self, value: &E) -> &'a mut Self where E: Encodable { + self.finished_list = false; + value.rlp_append(self); + if !self.finished_list { + self.note_appended(1); + } + self + } + /// Try to finish lists fn note_appended(&mut self, inserted_items: usize) -> () { if self.unfinished_lists.len() == 0 { @@ -141,6 +157,7 @@ impl RlpStream { self.encoder.insert_list_len_at_pos(len, x.position); self.note_appended(1); } + self.finished_list = should_finish; } /// Drain the object and return the underlying ElasticArray. @@ -164,12 +181,12 @@ impl BasicEncoder { /// inserts list prefix at given position /// TODO: optimise it further? fn insert_list_len_at_pos(&mut self, len: usize, pos: usize) -> () { - let mut res = vec![]; + let mut res = ElasticArray16::new(); match len { 0...55 => res.push(0xc0u8 + len as u8), _ => { res.push(0xf7u8 + len.to_bytes_len() as u8); - res.extend(len.to_bytes()); + ToBytes::to_bytes(&len, &mut res); } }; @@ -183,22 +200,30 @@ impl BasicEncoder { } impl Encoder for BasicEncoder { - fn emit_value(&mut self, bytes: &[u8]) -> () { - match bytes.len() { + fn emit_value(&mut self, value: &E) { + match value.bytes_len() { // just 0 0 => self.bytes.push(0x80u8), - // byte is its own encoding - 1 if bytes[0] < 0x80 => self.bytes.append_slice(bytes), + // byte is its own encoding if < 0x80 + 1 => { + value.to_bytes(&mut self.bytes); + let len = self.bytes.len(); + let last_byte = self.bytes[len - 1]; + if last_byte >= 0x80 { + self.bytes.push(last_byte); + self.bytes[len - 1] = 0x81; + } + } // (prefix + length), followed by the string - len @ 1 ... 55 => { + len @ 2 ... 55 => { self.bytes.push(0x80u8 + len as u8); - self.bytes.append_slice(bytes); + value.to_bytes(&mut self.bytes); } // (prefix + length of length), followed by the length, followd by the string len => { self.bytes.push(0xb7 + len.to_bytes_len() as u8); - self.bytes.append_slice(&len.to_bytes()); - self.bytes.append_slice(bytes); + ToBytes::to_bytes(&len, &mut self.bytes); + value.to_bytes(&mut self.bytes); } } } @@ -206,86 +231,82 @@ impl Encoder for BasicEncoder { fn emit_raw(&mut self, bytes: &[u8]) -> () { self.bytes.append_slice(bytes); } +} - fn emit_list(&mut self, f: F) -> () where F: FnOnce(&mut Self) -> () { - // get len before inserting a list - let before_len = self.bytes.len(); +impl ByteEncodable for T where T: ToBytes { + fn to_bytes>(&self, out: &mut V) { + ToBytes::to_bytes(self, out) + } - // insert all list elements - f(self); - - // get len after inserting a list - let after_len = self.bytes.len(); - - // diff is list len - let list_len = after_len - before_len; - self.insert_list_len_at_pos(list_len, before_len); + fn bytes_len(&self) -> usize { + ToBytes::to_bytes_len(self) } } -/// TODO [Gav Wood] Please document me -pub trait RlpStandard { - /// TODO [Gav Wood] Please document me - fn rlp_append(&self, s: &mut RlpStream); +struct U8Slice<'a>(&'a [u8]); - /// TODO [Gav Wood] Please document me - fn rlp_bytes(&self) -> Bytes { - let mut s = RlpStream::new(); - self.rlp_append(&mut s); - s.out() +impl<'a> ByteEncodable for U8Slice<'a> { + fn to_bytes>(&self, out: &mut V) { + out.vec_extend(self.0) } - /// TODO [Gav Wood] Please document me - fn rlp_sha3(&self) -> H256 { self.rlp_bytes().sha3() } -} - -// @debris TODO: implement Encoder for RlpStandard. - -impl Encodable for T where T: ToBytes { - fn encode(&self, encoder: &mut E) where E: Encoder { - encoder.emit_value(&self.to_bytes()) + fn bytes_len(&self) -> usize { + self.0.len() } } -impl<'a, T> Encodable for &'a [T] where T: Encodable + 'a { - fn encode(&self, encoder: &mut E) where E: Encoder { - encoder.emit_list(|e| { - // insert all list elements - for el in self.iter() { - el.encode(e); - } - }) +impl<'a> Encodable for &'a[u8] { + fn rlp_append(&self, s: &mut RlpStream) { + s.append_value(&U8Slice(self)) } } -impl Encodable for Vec where T: Encodable { - fn encode(&self, encoder: &mut E) where E: Encoder { - let r: &[T] = self.as_ref(); - r.encode(encoder) - } -} - -/// lets treat bytes differently than other lists -/// they are a single value -impl<'a> Encodable for &'a [u8] { - fn encode(&self, encoder: &mut E) where E: Encoder { - encoder.emit_value(self) - } -} - -/// lets treat bytes differently than other lists -/// they are a single value impl Encodable for Vec { - fn encode(&self, encoder: &mut E) where E: Encoder { - encoder.emit_value(self) + fn rlp_append(&self, s: &mut RlpStream) { + s.append_value(&U8Slice(self.deref())) } } -impl Encodable for Option where T: Encodable { - fn encode(&self, encoder: &mut E) where E: Encoder { - match *self { - Some(ref x) => x.encode(encoder), - None => encoder.emit_value(&[]) +impl Encodable for T where T: ByteEncodable { + fn rlp_append(&self, s: &mut RlpStream) { + s.append_value(self) + } +} + +struct EncodableU8 (u8); + +impl ByteEncodable for EncodableU8 { + fn to_bytes>(&self, out: &mut V) { + out.vec_push(self.0) + } + + fn bytes_len(&self) -> usize { 1 } +} + +impl RlpEncodable for u8 { + fn rlp_append(&self, s: &mut RlpStream) { + s.append_value(&EncodableU8(*self)) + } +} + +impl<'a, T> Encodable for &'a[T] where T: Encodable { + fn rlp_append(&self, s: &mut RlpStream) { + s.begin_list(self.len()); + for el in self.iter() { + s.append_internal(el); } } } + +impl Encodable for Vec where T: Encodable { + fn rlp_append(&self, s: &mut RlpStream) { + Encodable::rlp_append(&self.deref(), s); + } +} + +impl RlpEncodable for T where T: Encodable { + fn rlp_append(&self, s: &mut RlpStream) { + Encodable::rlp_append(self, s) + } +} + diff --git a/util/src/rlp/rlptraits.rs b/util/src/rlp/rlptraits.rs index d6ef16932..17acbb40b 100644 --- a/util/src/rlp/rlptraits.rs +++ b/util/src/rlp/rlptraits.rs @@ -1,4 +1,11 @@ +//! Common RLP traits +use std::ops::Deref; +use rlp::bytes::VecLike; use rlp::{DecoderError, UntrustedRlp}; +use rlp::rlpstream::RlpStream; +use elastic_array::ElasticArray1024; +use hash::H256; +use sha3::*; /// TODO [debris] Please document me pub trait Decoder: Sized { @@ -6,17 +13,21 @@ pub trait Decoder: Sized { fn read_value(&self, f: F) -> Result where F: FnOnce(&[u8]) -> Result; - /// TODO [arkpar] Please document me - fn as_list(&self) -> Result, DecoderError>; /// TODO [Gav Wood] Please document me fn as_rlp(&self) -> &UntrustedRlp; /// TODO [debris] Please document me fn as_raw(&self) -> &[u8]; } -/// TODO [debris] Please document me +/// RLP decodable trait pub trait Decodable: Sized { - /// TODO [debris] Please document me + /// Decode a value from RLP bytes + fn decode(decoder: &D) -> Result where D: Decoder; +} + +/// Internal helper trait. Implement `Decodable` for custom types. +pub trait RlpDecodable: Sized { + /// Decode a value from RLP bytes fn decode(decoder: &D) -> Result where D: Decoder; } @@ -195,26 +206,48 @@ pub trait View<'a, 'view>: Sized { fn iter(&'view self) -> Self::Iter; /// TODO [debris] Please document me - fn as_val(&self) -> Result where T: Decodable; + fn as_val(&self) -> Result where T: RlpDecodable; /// TODO [debris] Please document me - fn val_at(&self, index: usize) -> Result where T: Decodable; + fn val_at(&self, index: usize) -> Result where T: RlpDecodable; } /// TODO [debris] Please document me pub trait Encoder { /// TODO [debris] Please document me - fn emit_value(&mut self, bytes: &[u8]) -> (); - /// TODO [Gav Wood] Please document me - fn emit_list(&mut self, f: F) -> () where F: FnOnce(&mut Self) -> (); + fn emit_value(&mut self, value: &E); /// TODO [debris] Please document me fn emit_raw(&mut self, bytes: &[u8]) -> (); } -/// TODO [debris] Please document me +/// Primitive data type encodable to RLP +pub trait ByteEncodable { + /// Serialize this object to given byte container + fn to_bytes>(&self, out: &mut V); + /// Get size of serialised data in bytes + fn bytes_len(&self) -> usize; +} + +/// Structure encodable to RLP. Implement this trait for pub trait Encodable { - /// TODO [debris] Please document me - fn encode(&self, encoder: &mut E) -> () where E: Encoder; + /// Append a value to the stream + fn rlp_append(&self, s: &mut RlpStream); + + /// Get rlp-encoded bytes for this instance + fn rlp_bytes(&self) -> ElasticArray1024 { + let mut s = RlpStream::new(); + self.rlp_append(&mut s); + s.drain() + } + + /// Get the hash or RLP encoded representation + fn rlp_sha3(&self) -> H256 { self.rlp_bytes().deref().sha3() } +} + +/// Encodable wrapper trait required to handle special case of encoding a &[u8] as string and not as list +pub trait RlpEncodable { + /// Append a value to the stream + fn rlp_append(&self, s: &mut RlpStream); } /// TODO [debris] Please document me @@ -239,7 +272,7 @@ pub trait Stream: Sized { /// assert_eq!(out, vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']); /// } /// ``` - fn append<'a, E>(&'a mut self, object: &E) -> &'a mut Self where E: Encodable; + fn append<'a, E>(&'a mut self, value: &E) -> &'a mut Self where E: RlpEncodable; /// Declare appending the list of given size, chainable. /// @@ -249,13 +282,13 @@ pub trait Stream: Sized { /// /// fn main () { /// let mut stream = RlpStream::new_list(2); - /// stream.append_list(2).append(&"cat").append(&"dog"); + /// stream.begin_list(2).append(&"cat").append(&"dog"); /// stream.append(&""); /// let out = stream.out(); /// assert_eq!(out, vec![0xca, 0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g', 0x80]); /// } /// ``` - fn append_list(&mut self, len: usize) -> &mut Self; + fn begin_list(&mut self, len: usize) -> &mut Self; /// Apends null to the end of stream, chainable. /// diff --git a/util/src/rlp/tests.rs b/util/src/rlp/tests.rs index 84c00e633..3b00676f8 100644 --- a/util/src/rlp/tests.rs +++ b/util/src/rlp/tests.rs @@ -13,7 +13,7 @@ fn rlp_at() { { let rlp = UntrustedRlp::new(&data); assert!(rlp.is_list()); - //let animals = as rlp::Decodable>::decode_untrusted(&rlp).unwrap(); + //let animals = as rlp::RlpDecodable>::decode_untrusted(&rlp).unwrap(); let animals: Vec = rlp.as_val().unwrap(); assert_eq!(animals, vec!["cat".to_owned(), "dog".to_owned()]); @@ -83,7 +83,7 @@ fn run_encode_tests(tests: Vec>) { for t in &tests { let res = rlp::encode(&t.0); - assert_eq!(res, &t.1[..]); + assert_eq!(&res[..], &t.1[..]); } } @@ -193,15 +193,9 @@ fn encode_vector_str() { run_encode_tests(tests); } -#[test] -fn encode_vector_of_vectors_str() { - let tests = vec![ETestPair(vec![vec!["cat"]], vec![0xc5, 0xc4, 0x83, b'c', b'a', b't'])]; - run_encode_tests(tests); -} +struct DTestPair(T, Vec) where T: rlp::RlpDecodable + fmt::Debug + cmp::Eq; -struct DTestPair(T, Vec) where T: rlp::Decodable + fmt::Debug + cmp::Eq; - -fn run_decode_tests(tests: Vec>) where T: rlp::Decodable + fmt::Debug + cmp::Eq { +fn run_decode_tests(tests: Vec>) where T: rlp::RlpDecodable + fmt::Debug + cmp::Eq { for t in &tests { let res: T = rlp::decode(&t.1); assert_eq!(res, t.0); @@ -220,12 +214,21 @@ fn decode_vector_u8() { run_decode_tests(tests); } +#[test] +fn decode_untrusted_u8() { + let tests = vec![ + DTestPair(0x0u8, vec![0x80]), + DTestPair(0x77u8, vec![0x77]), + DTestPair(0xccu8, vec![0x81, 0xcc]), + ]; + run_decode_tests(tests); +} + #[test] fn decode_untrusted_u16() { let tests = vec![ - DTestPair(0u16, vec![0u8]), - DTestPair(0x100, vec![0x82, 0x01, 0x00]), - DTestPair(0xffff, vec![0x82, 0xff, 0xff]), + DTestPair(0x100u16, vec![0x82, 0x01, 0x00]), + DTestPair(0xffffu16, vec![0x82, 0xff, 0xff]), ]; run_decode_tests(tests); } @@ -233,9 +236,8 @@ fn decode_untrusted_u16() { #[test] fn decode_untrusted_u32() { let tests = vec![ - DTestPair(0u32, vec![0u8]), - DTestPair(0x10000, vec![0x83, 0x01, 0x00, 0x00]), - DTestPair(0xffffff, vec![0x83, 0xff, 0xff, 0xff]), + DTestPair(0x10000u32, vec![0x83, 0x01, 0x00, 0x00]), + DTestPair(0xffffffu32, vec![0x83, 0xff, 0xff, 0xff]), ]; run_decode_tests(tests); } @@ -243,9 +245,8 @@ fn decode_untrusted_u32() { #[test] fn decode_untrusted_u64() { let tests = vec![ - DTestPair(0u64, vec![0u8]), - DTestPair(0x1000000, vec![0x84, 0x01, 0x00, 0x00, 0x00]), - DTestPair(0xFFFFFFFF, vec![0x84, 0xff, 0xff, 0xff, 0xff]), + DTestPair(0x1000000u64, vec![0x84, 0x01, 0x00, 0x00, 0x00]), + DTestPair(0xFFFFFFFFu64, vec![0x84, 0xff, 0xff, 0xff, 0xff]), ]; run_decode_tests(tests); } @@ -333,7 +334,7 @@ fn test_rlp_json() { for operation in input.into_iter() { match operation { rlptest::Operation::Append(ref v) => stream.append(v), - rlptest::Operation::AppendList(len) => stream.append_list(len), + rlptest::Operation::AppendList(len) => stream.begin_list(len), rlptest::Operation::AppendRaw(ref raw, len) => stream.append_raw(raw, len), rlptest::Operation::AppendEmpty => stream.append_empty_data() }; diff --git a/util/src/rlp/untrusted_rlp.rs b/util/src/rlp/untrusted_rlp.rs index 07a9a4cde..604273b20 100644 --- a/util/src/rlp/untrusted_rlp.rs +++ b/util/src/rlp/untrusted_rlp.rs @@ -1,8 +1,8 @@ use std::cell::Cell; use std::fmt; use rustc_serialize::hex::ToHex; -use bytes::{FromBytes}; -use rlp::{View, Decoder, Decodable, DecoderError}; +use rlp::bytes::{FromBytes, FromBytesResult, FromBytesError}; +use rlp::{View, Decoder, Decodable, DecoderError, RlpDecodable}; /// rlp offset #[derive(Copy, Clone, Debug)] @@ -211,12 +211,12 @@ impl<'a, 'view> View<'a, 'view> for UntrustedRlp<'a> where 'a: 'view { self.into_iter() } - fn as_val(&self) -> Result where T: Decodable { + fn as_val(&self) -> Result where T: RlpDecodable { // optimize, so it doesn't use clone (although This clone is cheap) T::decode(&BasicDecoder::new(self.clone())) } - fn val_at(&self, index: usize) -> Result where T: Decodable { + fn val_at(&self, index: usize) -> Result where T: RlpDecodable { try!(self.at(index)).as_val() } } @@ -369,13 +369,6 @@ impl<'a> Decoder for BasicDecoder<'a> { self.rlp.as_raw() } - fn as_list(&self) -> Result, DecoderError> { - let v: Vec> = self.rlp.iter() - .map(BasicDecoder::new) - .collect(); - Ok(v) - } - fn as_rlp(&self) -> &UntrustedRlp { &self.rlp } @@ -391,8 +384,7 @@ impl Decodable for T where T: FromBytes { impl Decodable for Vec where T: Decodable { fn decode(decoder: &D) -> Result where D: Decoder { - let decoders = try!(decoder.as_list()); - decoders.iter().map(|d| T::decode(d)).collect() + decoder.as_rlp().iter().map(|d| T::decode(&BasicDecoder::new(d))).collect() } } @@ -423,15 +415,15 @@ macro_rules! impl_array_decodable { impl Decodable for [T; $len] where T: Decodable { #[allow(len_zero)] fn decode(decoder: &D) -> Result where D: Decoder { - let decoders = try!(decoder.as_list()); + let decoders = decoder.as_rlp(); let mut result: [T; $len] = unsafe { ::std::mem::uninitialized() }; - if decoders.len() != $len { + if decoders.item_count() != $len { return Err(DecoderError::RlpIncorrectListLen); } - for i in 0..decoders.len() { - result[i] = try!(T::decode(&decoders[i])); + for i in 0..decoders.item_count() { + result[i] = try!(T::decode(&BasicDecoder::new(try!(decoders.at(i))))); } Ok(result) @@ -454,6 +446,36 @@ impl_array_decodable_recursive!( 32, 40, 48, 56, 64, 72, 96, 128, 160, 192, 224, ); +impl RlpDecodable for T where T: Decodable { + fn decode(decoder: &D) -> Result where D: Decoder { + Decodable::decode(decoder) + } +} + +struct DecodableU8 (u8); + +impl FromBytes for DecodableU8 { + fn from_bytes(bytes: &[u8]) -> FromBytesResult { + match bytes.len() { + 0 => Ok(DecodableU8(0u8)), + 1 => { + if bytes[0] == 0 { + return Err(FromBytesError::ZeroPrefixedInt) + } + Ok(DecodableU8(bytes[0])) + } + _ => Err(FromBytesError::DataIsTooLong) + } + } +} + +impl RlpDecodable for u8 { + fn decode(decoder: &D) -> Result where D: Decoder { + let u: DecodableU8 = try!(Decodable::decode(decoder)); + Ok(u.0) + } +} + #[test] fn test_rlp_display() { use rustc_serialize::hex::FromHex; diff --git a/util/src/trie/node.rs b/util/src/trie/node.rs index dad5830b2..c47a0d25f 100644 --- a/util/src/trie/node.rs +++ b/util/src/trie/node.rs @@ -89,17 +89,17 @@ impl<'a> Node<'a> { let mut stream = RlpStream::new(); match *self { Node::Leaf(ref slice, ref value) => { - stream.append_list(2); + stream.begin_list(2); stream.append(&slice.encoded(true)); stream.append(value); }, Node::Extension(ref slice, ref raw_rlp) => { - stream.append_list(2); + stream.begin_list(2); stream.append(&slice.encoded(false)); stream.append_raw(raw_rlp, 1); }, Node::Branch(ref nodes, ref value) => { - stream.append_list(17); + stream.begin_list(17); for i in 0..16 { stream.append_raw(nodes[i], 1); } diff --git a/util/src/trie/triedbmut.rs b/util/src/trie/triedbmut.rs index 17d3f5866..4c3d36646 100644 --- a/util/src/trie/triedbmut.rs +++ b/util/src/trie/triedbmut.rs @@ -671,7 +671,6 @@ mod tests { use super::*; use nibbleslice::*; use rlp::*; - use env_logger; use rand::random; use std::collections::HashSet; use bytes::{ToPretty,Bytes,Populatable}; @@ -689,11 +688,11 @@ mod tests { fn random_value_indexed(j: usize) -> Bytes { match random::() % 2 { - 0 => encode(&j), + 0 => encode(&j).to_vec(), _ => { let mut h = H256::new(); h.as_slice_mut()[31] = j as u8; - encode(&h) + encode(&h).to_vec() }, } } @@ -727,7 +726,6 @@ mod tests { #[test] fn playpen() { - env_logger::init().ok(); /*let maps = map!{ "six-low" => StandardMap{alphabet: Alphabet::Low, min_key: 6, journal_key: 0, count: 1000}, @@ -1040,7 +1038,7 @@ mod tests { let alphabet = b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_"; for j in 0..4u32 { let key = random_key(alphabet, 5, 1); - x.push((key, encode(&j))); + x.push((key, encode(&j).to_vec())); } let real = trie_root(x.clone()); let mut memdb = MemoryDB::new(); diff --git a/util/src/triehash.rs b/util/src/triehash.rs index 66f9072b8..6ff6b790d 100644 --- a/util/src/triehash.rs +++ b/util/src/triehash.rs @@ -30,7 +30,7 @@ pub fn ordered_trie_root(input: Vec>) -> H256 { // optimize it later .into_iter() .enumerate() - .fold(BTreeMap::new(), | mut acc, (i, vec) | { acc.insert(rlp::encode(&i), vec); acc }) + .fold(BTreeMap::new(), | mut acc, (i, vec) | { acc.insert(rlp::encode(&i).to_vec(), vec); acc }) // then move them to a vector .into_iter() .map(|(k, v)| (as_nibbles(&k), v) ) @@ -189,7 +189,7 @@ fn hash256rlp(input: &[(Vec, Vec)], pre_len: usize, stream: &mut RlpStre // if the slice contains just one item, append the suffix of the key // and then append value if inlen == 1 { - stream.append_list(2); + stream.begin_list(2); stream.append(&hex_prefix_encode(&key[pre_len..], true)); stream.append(&value); return; @@ -208,7 +208,7 @@ fn hash256rlp(input: &[(Vec, Vec)], pre_len: usize, stream: &mut RlpStre // new part of the key to the stream // then recursively append suffixes of all items who had this key if shared_prefix > pre_len { - stream.append_list(2); + stream.begin_list(2); stream.append(&hex_prefix_encode(&key[pre_len..shared_prefix], false)); hash256aux(input, shared_prefix, stream); return; @@ -216,7 +216,7 @@ fn hash256rlp(input: &[(Vec, Vec)], pre_len: usize, stream: &mut RlpStre // an item for every possible nibble/suffix // + 1 for data - stream.append_list(17); + stream.begin_list(17); // if first key len is equal to prefix_len, move to next element let mut begin = match pre_len == key.len() {