diff --git a/Cargo.lock b/Cargo.lock
index d20026a774f..c63bff47183 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1170,7 +1170,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "parity-dapps"
version = "1.4.0"
-source = "git+https://github.com/ethcore/parity-ui.git#926b09b66c4940b09dc82c52adb4afd9e31155bc"
+source = "git+https://github.com/ethcore/parity-ui.git#8b1c31319228ad4cf9bd4ae740a0b933aa9e19c7"
dependencies = [
"aster 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1197,7 +1197,7 @@ dependencies = [
[[package]]
name = "parity-dapps-home"
version = "1.4.0"
-source = "git+https://github.com/ethcore/parity-ui.git#926b09b66c4940b09dc82c52adb4afd9e31155bc"
+source = "git+https://github.com/ethcore/parity-ui.git#8b1c31319228ad4cf9bd4ae740a0b933aa9e19c7"
dependencies = [
"parity-dapps 1.4.0 (git+https://github.com/ethcore/parity-ui.git)",
]
@@ -1205,7 +1205,7 @@ dependencies = [
[[package]]
name = "parity-dapps-status"
version = "1.4.0"
-source = "git+https://github.com/ethcore/parity-ui.git#926b09b66c4940b09dc82c52adb4afd9e31155bc"
+source = "git+https://github.com/ethcore/parity-ui.git#8b1c31319228ad4cf9bd4ae740a0b933aa9e19c7"
dependencies = [
"parity-dapps 1.4.0 (git+https://github.com/ethcore/parity-ui.git)",
]
@@ -1213,7 +1213,7 @@ dependencies = [
[[package]]
name = "parity-dapps-wallet"
version = "1.4.0"
-source = "git+https://github.com/ethcore/parity-ui.git#926b09b66c4940b09dc82c52adb4afd9e31155bc"
+source = "git+https://github.com/ethcore/parity-ui.git#8b1c31319228ad4cf9bd4ae740a0b933aa9e19c7"
dependencies = [
"parity-dapps 1.4.0 (git+https://github.com/ethcore/parity-ui.git)",
]
@@ -1421,7 +1421,7 @@ dependencies = [
[[package]]
name = "rocksdb"
version = "0.4.5"
-source = "git+https://github.com/ethcore/rust-rocksdb#ffc7c82380fe8569f85ae6743f7f620af2d4a679"
+source = "git+https://github.com/ethcore/rust-rocksdb#64c63ccbe1f62c2e2b39262486f9ba813793af58"
dependencies = [
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
"rocksdb-sys 0.3.0 (git+https://github.com/ethcore/rust-rocksdb)",
@@ -1430,7 +1430,7 @@ dependencies = [
[[package]]
name = "rocksdb-sys"
version = "0.3.0"
-source = "git+https://github.com/ethcore/rust-rocksdb#ffc7c82380fe8569f85ae6743f7f620af2d4a679"
+source = "git+https://github.com/ethcore/rust-rocksdb#64c63ccbe1f62c2e2b39262486f9ba813793af58"
dependencies = [
"gcc 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/dapps/js-glue/src/lib.rs.in b/dapps/js-glue/src/lib.rs.in
index 3974413a539..fa6c17de5b4 100644
--- a/dapps/js-glue/src/lib.rs.in
+++ b/dapps/js-glue/src/lib.rs.in
@@ -43,10 +43,3 @@ pub trait WebApp : Default + Send + Sync {
fn file(&self, path: &str) -> Option<&File>;
fn info(&self) -> Info;
}
-
-#[cfg(test)]
-mod tests {
- #[test]
- fn it_works() {
- }
-}
diff --git a/ethcore/res/ethereum/classic.json b/ethcore/res/ethereum/classic.json
index 8feee79e61c..5d951752f9a 100644
--- a/ethcore/res/ethereum/classic.json
+++ b/ethcore/res/ethereum/classic.json
@@ -10,7 +10,8 @@
"durationLimit": "0x0d",
"blockReward": "0x4563918244F40000",
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
- "frontierCompatibilityModeLimit": "0x118c30"
+ "homesteadTransition": "0x118c30",
+ "eip150Transition": "0x2625a0"
}
}
},
diff --git a/ethcore/res/ethereum/eip150_test.json b/ethcore/res/ethereum/eip150_test.json
new file mode 100644
index 00000000000..39d4b3fe8fd
--- /dev/null
+++ b/ethcore/res/ethereum/eip150_test.json
@@ -0,0 +1,43 @@
+{
+ "name": "Homestead (Test)",
+ "engine": {
+ "Ethash": {
+ "params": {
+ "gasLimitBoundDivisor": "0x0400",
+ "minimumDifficulty": "0x020000",
+ "difficultyBoundDivisor": "0x0800",
+ "durationLimit": "0x0d",
+ "blockReward": "0x4563918244F40000",
+ "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
+ "homesteadTransition": "0x0",
+ "eip150Transition": "0x0"
+ }
+ }
+ },
+ "params": {
+ "accountStartNonce": "0x00",
+ "maximumExtraDataSize": "0x20",
+ "minGasLimit": "0x1388",
+ "networkID" : "0x1"
+ },
+ "genesis": {
+ "seal": {
+ "ethereum": {
+ "nonce": "0x0000000000000042",
+ "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
+ }
+ },
+ "difficulty": "0x400000000",
+ "author": "0x0000000000000000000000000000000000000000",
+ "timestamp": "0x00",
+ "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
+ "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
+ "gasLimit": "0x1388"
+ },
+ "accounts": {
+ "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
+ "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
+ "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
+ "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }
+ }
+}
diff --git a/ethcore/res/ethereum/expanse.json b/ethcore/res/ethereum/expanse.json
index 9b005096b45..d2d036487e3 100644
--- a/ethcore/res/ethereum/expanse.json
+++ b/ethcore/res/ethereum/expanse.json
@@ -11,10 +11,11 @@
"durationLimit": "0x3C",
"blockReward": "0x6f05b59d3b200000",
"registrar" : "0x6c221ca53705f3497ec90ca7b84c59ae7382fc21",
- "frontierCompatibilityModeLimit": "0x30d40",
+ "homesteadTransition": "0x30d40",
"difficultyHardforkTransition": "0x59d9",
"difficultyHardforkBoundDivisor": "0x0200",
- "bombDefuseTransition": "0x30d40"
+ "bombDefuseTransition": "0x30d40",
+ "eip150Transition": "0x7fffffffffffffff"
}
}
},
diff --git a/ethcore/res/ethereum/frontier.json b/ethcore/res/ethereum/frontier.json
index 903e87cc7ba..8e92e49b326 100644
--- a/ethcore/res/ethereum/frontier.json
+++ b/ethcore/res/ethereum/frontier.json
@@ -9,10 +9,10 @@
"durationLimit": "0x0d",
"blockReward": "0x4563918244F40000",
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
- "frontierCompatibilityModeLimit": "0x118c30",
+ "homesteadTransition": "0x118c30",
"daoHardforkTransition": "0x1d4c00",
"daoHardforkBeneficiary": "0xbf4ed7b27f1d666546e30d74d50d173d20bca754",
- "daoHardforkAccounts": [
+ "daoHardforkAccounts": [
"0xd4fe7bc31cedb7bfb8a345f31e668033056b2728",
"0xb3fb0e5aba0e20e5c49d252dfd30e102b171a425",
"0x2c19c7f9ae8b751e37aeb2d93a699722395ae18f",
@@ -129,7 +129,8 @@
"0x7602b46df5390e432ef1c307d4f2c9ff6d65cc97",
"0xbb9bc244d798123fde783fcc1c72d3bb8c189413",
"0x807640a13483f8ac783c557fcdf27be11ea4ac7a"
- ]
+ ],
+ "eip150Transition": "0x259518"
}
}
},
diff --git a/ethcore/res/ethereum/frontier_like_test.json b/ethcore/res/ethereum/frontier_like_test.json
index aab48e78eda..99a7ad7128f 100644
--- a/ethcore/res/ethereum/frontier_like_test.json
+++ b/ethcore/res/ethereum/frontier_like_test.json
@@ -9,7 +9,7 @@
"durationLimit": "0x0d",
"blockReward": "0x4563918244F40000",
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
- "frontierCompatibilityModeLimit": "0x118c30",
+ "homesteadTransition": "0x118c30",
"daoHardforkTransition": "0x1d4c00",
"daoHardforkBeneficiary": "0xbf4ed7b27f1d666546e30d74d50d173d20bca754",
"daoHardforkAccounts": [
@@ -129,7 +129,8 @@
"0x7602b46df5390e432ef1c307d4f2c9ff6d65cc97",
"0xbb9bc244d798123fde783fcc1c72d3bb8c189413",
"0x807640a13483f8ac783c557fcdf27be11ea4ac7a"
- ]
+ ],
+ "eip150Transition": "0x7fffffffffffffff"
}
}
},
diff --git a/ethcore/res/ethereum/frontier_test.json b/ethcore/res/ethereum/frontier_test.json
index 3964d33adf0..1cb3d8cfc03 100644
--- a/ethcore/res/ethereum/frontier_test.json
+++ b/ethcore/res/ethereum/frontier_test.json
@@ -9,7 +9,8 @@
"durationLimit": "0x0d",
"blockReward": "0x4563918244F40000",
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
- "frontierCompatibilityModeLimit": "0xffffffffffffffff"
+ "homesteadTransition": "0x7fffffffffffffff",
+ "eip150Transition": "0x7fffffffffffffff"
}
}
},
diff --git a/ethcore/res/ethereum/homestead_test.json b/ethcore/res/ethereum/homestead_test.json
index 8a362009ff4..ad64ce2d530 100644
--- a/ethcore/res/ethereum/homestead_test.json
+++ b/ethcore/res/ethereum/homestead_test.json
@@ -9,7 +9,8 @@
"durationLimit": "0x0d",
"blockReward": "0x4563918244F40000",
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
- "frontierCompatibilityModeLimit": "0x0"
+ "homesteadTransition": "0x0",
+ "eip150Transition": "0x7fffffffffffffff"
}
}
},
diff --git a/ethcore/res/ethereum/morden.json b/ethcore/res/ethereum/morden.json
index ef18df97d6d..fdbe1fec271 100644
--- a/ethcore/res/ethereum/morden.json
+++ b/ethcore/res/ethereum/morden.json
@@ -9,7 +9,8 @@
"durationLimit": "0x0d",
"blockReward": "0x4563918244F40000",
"registrar": "0x52dff57a8a1532e6afb3dc07e2af58bb9eb05b3d",
- "frontierCompatibilityModeLimit": "0x789b0"
+ "homesteadTransition": "0x789b0",
+ "eip150Transition": "0x1b34d8"
}
}
},
diff --git a/ethcore/res/ethereum/olympic.json b/ethcore/res/ethereum/olympic.json
index 99686b07365..ebc7abd4ea2 100644
--- a/ethcore/res/ethereum/olympic.json
+++ b/ethcore/res/ethereum/olympic.json
@@ -8,7 +8,9 @@
"difficultyBoundDivisor": "0x0800",
"durationLimit": "0x08",
"blockReward": "0x14D1120D7B160000",
- "registrar": "5e70c0bbcd5636e0f9f9316e9f8633feb64d4050"
+ "registrar": "5e70c0bbcd5636e0f9f9316e9f8633feb64d4050",
+ "homesteadTransition": "0x7fffffffffffffff",
+ "eip150Transition": "0x7fffffffffffffff"
}
}
},
diff --git a/ethcore/res/ethereum/tests b/ethcore/res/ethereum/tests
index 9df948802f4..cd2a6746bb6 160000
--- a/ethcore/res/ethereum/tests
+++ b/ethcore/res/ethereum/tests
@@ -1 +1 @@
-Subproject commit 9df948802f40d86141a7b34f1132ebb9707a1e6a
+Subproject commit cd2a6746bb653bf4b1acb6198b40df19ed8dde3b
diff --git a/ethcore/res/ethereum/daohardfork_test.json b/ethcore/res/ethereum/transition_test.json
similarity index 98%
rename from ethcore/res/ethereum/daohardfork_test.json
rename to ethcore/res/ethereum/transition_test.json
index 90875f4f604..c004bc2ba38 100644
--- a/ethcore/res/ethereum/daohardfork_test.json
+++ b/ethcore/res/ethereum/transition_test.json
@@ -1,5 +1,5 @@
{
- "name": "DAO hard-fork consensus test",
+ "name": "EIP150.1b hard-fork consensus test",
"engine": {
"Ethash": {
"params": {
@@ -9,7 +9,7 @@
"durationLimit": "0x0d",
"blockReward": "0x4563918244F40000",
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
- "frontierCompatibilityModeLimit": "0x5",
+ "homesteadTransition": "0x5",
"daoHardforkTransition": "0x8",
"daoHardforkBeneficiary": "0xbf4ed7b27f1d666546e30d74d50d173d20bca754",
"daoHardforkAccounts": [
@@ -129,7 +129,8 @@
"0x7602b46df5390e432ef1c307d4f2c9ff6d65cc97",
"0xbb9bc244d798123fde783fcc1c72d3bb8c189413",
"0x807640a13483f8ac783c557fcdf27be11ea4ac7a"
- ]
+ ],
+ "eip150Transition": "0xa"
}
}
},
diff --git a/ethcore/src/account_provider.rs b/ethcore/src/account_provider.rs
index 851d015bac1..3f4511f4bab 100644
--- a/ethcore/src/account_provider.rs
+++ b/ethcore/src/account_provider.rs
@@ -23,7 +23,7 @@ use std::time::{Instant, Duration};
use util::{Mutex, RwLock};
use ethstore::{SecretStore, Error as SSError, SafeAccount, EthStore};
use ethstore::dir::{KeyDirectory};
-use ethstore::ethkey::{Address, Message, Secret, Random, Generator};
+use ethstore::ethkey::{Address, Message, Public, Secret, Random, Generator};
use ethjson::misc::AccountMeta;
pub use ethstore::ethkey::Signature;
@@ -182,9 +182,16 @@ impl AccountProvider {
/// Creates new random account.
pub fn new_account(&self, password: &str) -> Result
{
- let secret = Random.generate().unwrap().secret().clone();
+ self.new_account_and_public(password).map(|d| d.0)
+ }
+
+ /// Creates new random account and returns address and public key
+ pub fn new_account_and_public(&self, password: &str) -> Result<(Address, Public), Error> {
+ let acc = Random.generate().unwrap();
+ let public = acc.public().clone();
+ let secret = acc.secret().clone();
let address = try!(self.sstore.insert_account(secret, password));
- Ok(address)
+ Ok((address, public))
}
/// Inserts new account into underlying store.
@@ -280,6 +287,21 @@ impl AccountProvider {
Ok(())
}
+ fn password(&self, account: &Address) -> Result {
+ let mut unlocked = self.unlocked.lock();
+ let data = try!(unlocked.get(account).ok_or(Error::NotUnlocked)).clone();
+ if let Unlock::Temp = data.unlock {
+ unlocked.remove(account).expect("data exists: so key must exist: qed");
+ }
+ if let Unlock::Timed((ref start, ref duration)) = data.unlock {
+ if start.elapsed() > Duration::from_millis(*duration as u64) {
+ unlocked.remove(account).expect("data exists: so key must exist: qed");
+ return Err(Error::NotUnlocked);
+ }
+ }
+ Ok(data.password.clone())
+ }
+
/// Unlocks account permanently.
pub fn unlock_account_permanently(&self, account: Address, password: String) -> Result<(), Error> {
self.unlock_account(account, password, Unlock::Perm)
@@ -301,51 +323,16 @@ impl AccountProvider {
unlocked.get(&account).is_some()
}
- /// Signs the message. Account must be unlocked.
- pub fn sign(&self, account: Address, message: Message) -> Result {
- let data = {
- let mut unlocked = self.unlocked.lock();
- let data = try!(unlocked.get(&account).ok_or(Error::NotUnlocked)).clone();
- if let Unlock::Temp = data.unlock {
- unlocked.remove(&account).expect("data exists: so key must exist: qed");
- }
- if let Unlock::Timed((ref start, ref duration)) = data.unlock {
- if start.elapsed() > Duration::from_millis(*duration as u64) {
- unlocked.remove(&account).expect("data exists: so key must exist: qed");
- return Err(Error::NotUnlocked);
- }
- }
- data
- };
-
- let signature = try!(self.sstore.sign(&account, &data.password, &message));
- Ok(signature)
- }
-
- /// Decrypts a message. Account must be unlocked.
- pub fn decrypt(&self, account: Address, shared_mac: &[u8], message: &[u8]) -> Result, Error> {
- let data = {
- let mut unlocked = self.unlocked.lock();
- let data = try!(unlocked.get(&account).ok_or(Error::NotUnlocked)).clone();
- if let Unlock::Temp = data.unlock {
- unlocked.remove(&account).expect("data exists: so key must exist: qed");
- }
- if let Unlock::Timed((ref start, ref duration)) = data.unlock {
- if start.elapsed() > Duration::from_millis(*duration as u64) {
- unlocked.remove(&account).expect("data exists: so key must exist: qed");
- return Err(Error::NotUnlocked);
- }
- }
- data
- };
-
- Ok(try!(self.sstore.decrypt(&account, &data.password, shared_mac, message)))
+ /// Signs the message. If password is not provided the account must be unlocked.
+ pub fn sign(&self, account: Address, password: Option, message: Message) -> Result {
+ let password = try!(password.map(Ok).unwrap_or_else(|| self.password(&account)));
+ Ok(try!(self.sstore.sign(&account, &password, &message)))
}
- /// Unlocks an account, signs the message, and locks it again.
- pub fn sign_with_password(&self, account: Address, password: String, message: Message) -> Result {
- let signature = try!(self.sstore.sign(&account, &password, &message));
- Ok(signature)
+ /// Decrypts a message. If password is not provided the account must be unlocked.
+ pub fn decrypt(&self, account: Address, password: Option, shared_mac: &[u8], message: &[u8]) -> Result, Error> {
+ let password = try!(password.map(Ok).unwrap_or_else(|| self.password(&account)));
+ Ok(try!(self.sstore.decrypt(&account, &password, shared_mac, message)))
}
/// Returns the underlying `SecretStore` reference if one exists.
@@ -386,8 +373,8 @@ mod tests {
assert!(ap.insert_account(kp.secret().clone(), "test").is_ok());
assert!(ap.unlock_account_temporarily(kp.address(), "test1".into()).is_err());
assert!(ap.unlock_account_temporarily(kp.address(), "test".into()).is_ok());
- assert!(ap.sign(kp.address(), Default::default()).is_ok());
- assert!(ap.sign(kp.address(), Default::default()).is_err());
+ assert!(ap.sign(kp.address(), None, Default::default()).is_ok());
+ assert!(ap.sign(kp.address(), None, Default::default()).is_err());
}
#[test]
@@ -397,11 +384,11 @@ mod tests {
assert!(ap.insert_account(kp.secret().clone(), "test").is_ok());
assert!(ap.unlock_account_permanently(kp.address(), "test1".into()).is_err());
assert!(ap.unlock_account_permanently(kp.address(), "test".into()).is_ok());
- assert!(ap.sign(kp.address(), Default::default()).is_ok());
- assert!(ap.sign(kp.address(), Default::default()).is_ok());
+ assert!(ap.sign(kp.address(), None, Default::default()).is_ok());
+ assert!(ap.sign(kp.address(), None, Default::default()).is_ok());
assert!(ap.unlock_account_temporarily(kp.address(), "test".into()).is_ok());
- assert!(ap.sign(kp.address(), Default::default()).is_ok());
- assert!(ap.sign(kp.address(), Default::default()).is_ok());
+ assert!(ap.sign(kp.address(), None, Default::default()).is_ok());
+ assert!(ap.sign(kp.address(), None, Default::default()).is_ok());
}
#[test]
@@ -411,8 +398,8 @@ mod tests {
assert!(ap.insert_account(kp.secret().clone(), "test").is_ok());
assert!(ap.unlock_account_timed(kp.address(), "test1".into(), 2000).is_err());
assert!(ap.unlock_account_timed(kp.address(), "test".into(), 2000).is_ok());
- assert!(ap.sign(kp.address(), Default::default()).is_ok());
+ assert!(ap.sign(kp.address(), None, Default::default()).is_ok());
::std::thread::sleep(Duration::from_millis(2000));
- assert!(ap.sign(kp.address(), Default::default()).is_err());
+ assert!(ap.sign(kp.address(), None, Default::default()).is_err());
}
}
diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs
index 80c35d1d0aa..5cd9835114f 100644
--- a/ethcore/src/block.rs
+++ b/ethcore/src/block.rs
@@ -404,6 +404,10 @@ impl<'x> OpenBlock<'x> {
uncle_bytes: uncle_bytes,
}
}
+
+ #[cfg(test)]
+ /// Return mutable block reference. To be used in tests only.
+ pub fn block_mut (&mut self) -> &mut ExecutedBlock { &mut self.block }
}
impl<'x> IsBlock for OpenBlock<'x> {
diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs
index 8daf672b917..51be6504397 100644
--- a/ethcore/src/blockchain/blockchain.rs
+++ b/ethcore/src/blockchain/blockchain.rs
@@ -332,7 +332,10 @@ impl BlockProvider for BlockChain {
.filter_map(|(number, hash)| self.block_receipts(&hash).map(|r| (number, hash, r.receipts)))
.filter_map(|(number, hash, receipts)| self.block_body(&hash).map(|ref b| (number, hash, receipts, BodyView::new(b).transaction_hashes())))
.flat_map(|(number, hash, mut receipts, mut hashes)| {
- assert_eq!(receipts.len(), hashes.len());
+ if receipts.len() != hashes.len() {
+ warn!("Block {} ({}) has different number of receipts ({}) to transactions ({}). Database corrupt?", number, hash, receipts.len(), hashes.len());
+ assert!(false);
+ }
log_index = receipts.iter().fold(0, |sum, receipt| sum + receipt.logs.len());
let receipts_len = receipts.len();
diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs
index 6ba00092649..f5d10266f24 100644
--- a/ethcore/src/client/client.rs
+++ b/ethcore/src/client/client.rs
@@ -74,6 +74,7 @@ pub use blockchain::CacheSize as BlockChainCacheSize;
const MAX_TX_QUEUE_SIZE: usize = 4096;
const MAX_QUEUE_SIZE_TO_SLEEP_ON: usize = 2;
+const MIN_HISTORY_SIZE: u64 = 8;
impl fmt::Display for BlockChainInfo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -141,12 +142,9 @@ pub struct Client {
queue_transactions: AtomicUsize,
last_hashes: RwLock>,
factories: Factories,
+ history: u64,
}
-/// The pruning constant -- how old blocks must be before we
-/// assume finality of a given candidate.
-pub const HISTORY: u64 = 1200;
-
impl Client {
/// Create a new client with given spec and DB path and custom verifier.
pub fn new(
@@ -173,10 +171,32 @@ impl Client {
let mut state_db = StateDB::new(journal_db, config.state_cache_size);
if state_db.journal_db().is_empty() && try!(spec.ensure_db_good(&mut state_db)) {
let mut batch = DBTransaction::new(&db);
- try!(state_db.commit(&mut batch, 0, &spec.genesis_header().hash(), None));
+ try!(state_db.journal_under(&mut batch, 0, &spec.genesis_header().hash()));
try!(db.write(batch).map_err(ClientError::Database));
}
+ trace!("Cleanup journal: DB Earliest = {:?}, Latest = {:?}", state_db.journal_db().earliest_era(), state_db.journal_db().latest_era());
+
+ let history = if config.history < MIN_HISTORY_SIZE {
+ info!(target: "client", "Ignoring pruning history parameter of {}\
+ , falling back to minimum of {}",
+ config.history, MIN_HISTORY_SIZE);
+ MIN_HISTORY_SIZE
+ } else {
+ config.history
+ };
+
+ if let (Some(earliest), Some(latest)) = (state_db.journal_db().earliest_era(), state_db.journal_db().latest_era()) {
+ if latest > earliest && latest - earliest > history {
+ for era in earliest..(latest - history + 1) {
+ trace!("Removing era {}", era);
+ let mut batch = DBTransaction::new(&db);
+ try!(state_db.mark_canonical(&mut batch, era, &chain.block_hash(era).expect("Old block not found in the database")));
+ try!(db.write(batch).map_err(ClientError::Database));
+ }
+ }
+ }
+
if !chain.block_header(&chain.best_block_hash()).map_or(true, |h| state_db.journal_db().contains(h.state_root())) {
warn!("State root not found for block #{} ({})", chain.best_block_number(), chain.best_block_hash().hex());
}
@@ -217,6 +237,7 @@ impl Client {
queue_transactions: AtomicUsize::new(0),
last_hashes: RwLock::new(VecDeque::new()),
factories: factories,
+ history: history,
};
Ok(Arc::new(client))
}
@@ -275,7 +296,7 @@ impl Client {
let chain = self.chain.read();
// Check the block isn't so old we won't be able to enact it.
let best_block_number = chain.best_block_number();
- if best_block_number >= HISTORY && header.number() <= best_block_number - HISTORY {
+ if best_block_number >= self.history && header.number() <= best_block_number - self.history {
warn!(target: "client", "Block import failed for #{} ({})\nBlock is ancient (current best block: #{}).", header.number(), header.hash(), best_block_number);
return Err(());
}
@@ -414,13 +435,6 @@ impl Client {
let number = block.header().number();
let parent = block.header().parent_hash().clone();
let chain = self.chain.read();
- // Are we committing an era?
- let ancient = if number >= HISTORY {
- let n = number - HISTORY;
- Some((n, chain.block_hash(n).expect("only verified blocks can be commited; verified block has hash; qed")))
- } else {
- None
- };
// Commit results
let receipts = block.receipts().to_owned();
@@ -436,7 +450,13 @@ impl Client {
// already-imported block of the same number.
// TODO: Prove it with a test.
let mut state = block.drain();
- state.commit(&mut batch, number, hash, ancient).expect("DB commit failed.");
+
+ state.journal_under(&mut batch, number, hash).expect("DB commit failed");
+
+ if number >= self.history {
+ let n = number - self.history;
+ state.mark_canonical(&mut batch, n, &chain.block_hash(n).unwrap()).expect("DB commit failed");
+ }
let route = chain.insert_block(&mut batch, block_data, receipts);
self.tracedb.read().import(&mut batch, TraceImportRequest {
@@ -446,6 +466,7 @@ impl Client {
enacted: route.enacted.clone(),
retracted: route.retracted.len()
});
+
let is_canon = route.enacted.last().map_or(false, |h| h == hash);
state.sync_cache(&route.enacted, &route.retracted, is_canon);
// Final commit to the DB
@@ -495,7 +516,7 @@ impl Client {
let db = self.state_db.lock().boxed_clone();
// early exit for pruned blocks
- if db.is_pruned() && self.chain.read().best_block_number() >= block_number + HISTORY {
+ if db.is_pruned() && self.chain.read().best_block_number() >= block_number + self.history {
return None;
}
@@ -600,7 +621,7 @@ impl Client {
let best_block_number = self.chain_info().best_block_number;
let block_number = try!(self.block_number(at).ok_or(snapshot::Error::InvalidStartingBlock(at)));
- if best_block_number > HISTORY + block_number && db.is_pruned() {
+ if best_block_number > self.history + block_number && db.is_pruned() {
return Err(snapshot::Error::OldBlockPrunedDB.into());
}
@@ -612,8 +633,10 @@ impl Client {
0
};
- self.block_hash(BlockID::Number(start_num))
- .expect("blocks within HISTORY are always stored.")
+ match self.block_hash(BlockID::Number(start_num)) {
+ Some(h) => h,
+ None => return Err(snapshot::Error::InvalidStartingBlock(at).into()),
+ }
}
_ => match self.block_hash(at) {
Some(hash) => hash,
@@ -626,6 +649,11 @@ impl Client {
Ok(())
}
+ /// Ask the client what the history parameter is.
+ pub fn pruning_history(&self) -> u64 {
+ self.history
+ }
+
fn block_hash(chain: &BlockChain, id: BlockID) -> Option {
match id {
BlockID::Hash(hash) => Some(hash),
diff --git a/ethcore/src/client/config.rs b/ethcore/src/client/config.rs
index e0ac51f0ad4..69b9d9efe4c 100644
--- a/ethcore/src/client/config.rs
+++ b/ethcore/src/client/config.rs
@@ -110,6 +110,8 @@ pub struct ClientConfig {
pub state_cache_size: usize,
/// EVM jump-tables cache size.
pub jump_table_size: usize,
+ /// State pruning history size.
+ pub history: u64,
}
#[cfg(test)]
diff --git a/ethcore/src/engines/basic_authority.rs b/ethcore/src/engines/basic_authority.rs
index 6e3c2f1dd99..bd3eb5bc693 100644
--- a/ethcore/src/engines/basic_authority.rs
+++ b/ethcore/src/engines/basic_authority.rs
@@ -112,7 +112,7 @@ impl Engine for BasicAuthority {
let header = block.header();
let message = header.bare_hash();
// account should be pernamently unlocked, otherwise sealing will fail
- if let Ok(signature) = ap.sign(*block.header().author(), message) {
+ if let Ok(signature) = ap.sign(*block.header().author(), None, message) {
return Some(vec![::rlp::encode(&(&*signature as &[u8])).to_vec()]);
} else {
trace!(target: "basicauthority", "generate_seal: FAIL: accounts secret key unavailable");
diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs
index 982698a5069..e0c18292b0a 100644
--- a/ethcore/src/ethereum/ethash.rs
+++ b/ethcore/src/ethereum/ethash.rs
@@ -41,7 +41,7 @@ pub struct EthashParams {
/// Namereg contract address.
pub registrar: Address,
/// Homestead transition block number.
- pub frontier_compatibility_mode_limit: u64,
+ pub homestead_transition: u64,
/// DAO hard-fork transition block (X).
pub dao_hardfork_transition: u64,
/// DAO hard-fork refund contract address (C).
@@ -54,6 +54,8 @@ pub struct EthashParams {
pub difficulty_hardfork_bound_divisor: U256,
/// Block on which there is no additional difficulty from the exponential bomb.
pub bomb_defuse_transition: u64,
+ /// Bad gas transition block number.
+ pub eip150_transition: u64,
}
impl From for EthashParams {
@@ -66,13 +68,14 @@ impl From for EthashParams {
duration_limit: p.duration_limit.into(),
block_reward: p.block_reward.into(),
registrar: p.registrar.map_or_else(Address::new, Into::into),
- frontier_compatibility_mode_limit: p.frontier_compatibility_mode_limit.map_or(0, Into::into),
+ homestead_transition: p.homestead_transition.map_or(0, Into::into),
dao_hardfork_transition: p.dao_hardfork_transition.map_or(0x7fffffffffffffff, Into::into),
dao_hardfork_beneficiary: p.dao_hardfork_beneficiary.map_or_else(Address::new, Into::into),
dao_hardfork_accounts: p.dao_hardfork_accounts.unwrap_or_else(Vec::new).into_iter().map(Into::into).collect(),
difficulty_hardfork_transition: p.difficulty_hardfork_transition.map_or(0x7fffffffffffffff, Into::into),
difficulty_hardfork_bound_divisor: p.difficulty_hardfork_bound_divisor.map_or(p.difficulty_bound_divisor.into(), Into::into),
bomb_defuse_transition: p.bomb_defuse_transition.map_or(0x7fffffffffffffff, Into::into),
+ eip150_transition: p.eip150_transition.map_or(0, Into::into),
}
}
}
@@ -117,12 +120,14 @@ impl Engine for Ethash {
}
fn schedule(&self, env_info: &EnvInfo) -> Schedule {
- trace!(target: "client", "Creating schedule. fCML={}", self.ethash_params.frontier_compatibility_mode_limit);
+ trace!(target: "client", "Creating schedule. fCML={}, bGCML={}", self.ethash_params.homestead_transition, self.ethash_params.eip150_transition);
- if env_info.number < self.ethash_params.frontier_compatibility_mode_limit {
+ if env_info.number < self.ethash_params.homestead_transition {
Schedule::new_frontier()
- } else {
+ } else if env_info.number < self.ethash_params.eip150_transition {
Schedule::new_homestead()
+ } else {
+ Schedule::new_homestead_gas_fix()
}
}
@@ -264,7 +269,7 @@ impl Engine for Ethash {
}
fn verify_transaction_basic(&self, t: &SignedTransaction, header: &Header) -> result::Result<(), Error> {
- if header.number() >= self.ethash_params.frontier_compatibility_mode_limit {
+ if header.number() >= self.ethash_params.homestead_transition {
try!(t.check_low_s());
}
Ok(())
@@ -290,7 +295,7 @@ impl Ethash {
false => self.ethash_params.difficulty_bound_divisor,
};
let duration_limit = self.ethash_params.duration_limit;
- let frontier_limit = self.ethash_params.frontier_compatibility_mode_limit;
+ let frontier_limit = self.ethash_params.homestead_transition;
let mut target = if header.number() < frontier_limit {
if header.timestamp() >= parent.timestamp() + duration_limit {
diff --git a/ethcore/src/ethereum/mod.rs b/ethcore/src/ethereum/mod.rs
index 6d4502d2d90..219b3bf5c19 100644
--- a/ethcore/src/ethereum/mod.rs
+++ b/ethcore/src/ethereum/mod.rs
@@ -51,8 +51,11 @@ pub fn new_frontier_test() -> Spec { load(include_bytes!("../../res/ethereum/fro
/// Create a new Homestead chain spec as though it never changed from Frontier.
pub fn new_homestead_test() -> Spec { load(include_bytes!("../../res/ethereum/homestead_test.json")) }
+/// Create a new Homestead-EIP150 chain spec as though it never changed from Homestead/Frontier.
+pub fn new_eip150_test() -> Spec { load(include_bytes!("../../res/ethereum/eip150_test.json")) }
+
/// Create a new Frontier/Homestead/DAO chain spec with transition points at #5 and #8.
-pub fn new_daohardfork_test() -> Spec { load(include_bytes!("../../res/ethereum/daohardfork_test.json")) }
+pub fn new_transition_test() -> Spec { load(include_bytes!("../../res/ethereum/transition_test.json")) }
/// Create a new Frontier main net chain spec without genesis accounts.
pub fn new_mainnet_like() -> Spec { load(include_bytes!("../../res/ethereum/frontier_like_test.json")) }
diff --git a/ethcore/src/evm/interpreter/gasometer.rs b/ethcore/src/evm/interpreter/gasometer.rs
index d7022be7ceb..d4c329be05d 100644
--- a/ethcore/src/evm/interpreter/gasometer.rs
+++ b/ethcore/src/evm/interpreter/gasometer.rs
@@ -19,6 +19,7 @@ use super::u256_to_address;
use evm::{self, CostType};
use evm::instructions::{self, Instruction, InstructionInfo};
use evm::interpreter::stack::Stack;
+use evm::schedule::Schedule;
macro_rules! overflowing {
($x: expr) => {{
@@ -31,7 +32,7 @@ macro_rules! overflowing {
#[cfg_attr(feature="dev", allow(enum_variant_names))]
enum InstructionCost {
Gas(Cost),
- GasMem(Cost, Cost),
+ GasMem(Cost, Cost, Option),
GasMemCopy(Cost, Cost, Cost)
}
@@ -56,7 +57,37 @@ impl Gasometer {
}
}
+ /// How much gas is provided to a CALL/CREATE, given that we need to deduct `needed` for this operation
+ /// and that we `requested` some.
+ pub fn gas_provided(&self, schedule: &Schedule, needed: Gas, requested: Option>) -> evm::Result {
+ match schedule.sub_gas_cap_divisor {
+ Some(cap_divisor) if self.current_gas >= needed => {
+ let gas_remaining = self.current_gas - needed;
+ let max_gas_provided = gas_remaining - gas_remaining / Gas::from(cap_divisor);
+ if let Some(Ok(r)) = requested {
+ Ok(min(r, max_gas_provided))
+ } else {
+ Ok(max_gas_provided)
+ }
+ },
+ _ => {
+ if let Some(r) = requested {
+ r
+ } else if self.current_gas >= needed {
+ Ok(self.current_gas - needed)
+ } else {
+ Ok(0.into())
+ }
+ }
+ }
+ }
+
#[cfg_attr(feature="dev", allow(cyclomatic_complexity))]
+ /// Determine how much gas is used by the given instruction, given the machine's state.
+ ///
+ /// We guarantee that the final element of the returned tuple (`provided`) will be `Some`
+ /// iff the `instruction` is one of `CREATE`, or any of the `CALL` variants. In this case,
+ /// it will be the amount of gas that the current context provides to the child context.
pub fn get_gas_cost_mem(
&mut self,
ext: &evm::Ext,
@@ -64,7 +95,7 @@ impl Gasometer {
info: &InstructionInfo,
stack: &Stack,
current_mem_size: usize,
- ) -> evm::Result<(Gas, Gas, usize)> {
+ ) -> evm::Result<(Gas, Gas, usize, Option)> {
let schedule = ext.schedule();
let tier = instructions::get_tier_idx(info.tier);
let default_gas = Gas::from(schedule.tier_step_gas[tier]);
@@ -90,26 +121,42 @@ impl Gasometer {
instructions::SLOAD => {
InstructionCost::Gas(Gas::from(schedule.sload_gas))
},
+ instructions::BALANCE => {
+ InstructionCost::Gas(Gas::from(schedule.balance_gas))
+ },
+ instructions::EXTCODESIZE => {
+ InstructionCost::Gas(Gas::from(schedule.extcodesize_gas))
+ },
+ instructions::SUICIDE => {
+ let mut gas = Gas::from(schedule.suicide_gas);
+
+ let address = u256_to_address(stack.peek(0));
+ if !ext.exists(&address) {
+ gas = overflowing!(gas.overflow_add(schedule.suicide_to_new_account_cost.into()));
+ }
+
+ InstructionCost::Gas(gas)
+ },
instructions::MSTORE | instructions::MLOAD => {
- InstructionCost::GasMem(default_gas, try!(mem_needed_const(stack.peek(0), 32)))
+ InstructionCost::GasMem(default_gas, try!(mem_needed_const(stack.peek(0), 32)), None)
},
instructions::MSTORE8 => {
- InstructionCost::GasMem(default_gas, try!(mem_needed_const(stack.peek(0), 1)))
+ InstructionCost::GasMem(default_gas, try!(mem_needed_const(stack.peek(0), 1)), None)
},
instructions::RETURN => {
- InstructionCost::GasMem(default_gas, try!(mem_needed(stack.peek(0), stack.peek(1))))
+ InstructionCost::GasMem(default_gas, try!(mem_needed(stack.peek(0), stack.peek(1))), None)
},
instructions::SHA3 => {
let w = overflowing!(add_gas_usize(try!(Gas::from_u256(*stack.peek(1))), 31));
let words = w >> 5;
let gas = Gas::from(schedule.sha3_gas) + (Gas::from(schedule.sha3_word_gas) * words);
- InstructionCost::GasMem(gas, try!(mem_needed(stack.peek(0), stack.peek(1))))
+ InstructionCost::GasMem(gas, try!(mem_needed(stack.peek(0), stack.peek(1))), None)
},
instructions::CALLDATACOPY | instructions::CODECOPY => {
InstructionCost::GasMemCopy(default_gas, try!(mem_needed(stack.peek(0), stack.peek(2))), try!(Gas::from_u256(*stack.peek(2))))
},
instructions::EXTCODECOPY => {
- InstructionCost::GasMemCopy(default_gas, try!(mem_needed(stack.peek(1), stack.peek(3))), try!(Gas::from_u256(*stack.peek(3))))
+ InstructionCost::GasMemCopy(schedule.extcodecopy_base_gas.into(), try!(mem_needed(stack.peek(1), stack.peek(3))), try!(Gas::from_u256(*stack.peek(3))))
},
instructions::LOG0...instructions::LOG4 => {
let no_of_topics = instructions::get_log_topics(instruction);
@@ -117,10 +164,10 @@ impl Gasometer {
let data_gas = overflowing!(try!(Gas::from_u256(*stack.peek(1))).overflow_mul(Gas::from(schedule.log_data_gas)));
let gas = overflowing!(data_gas.overflow_add(Gas::from(log_gas)));
- InstructionCost::GasMem(gas, try!(mem_needed(stack.peek(0), stack.peek(1))))
+ InstructionCost::GasMem(gas, try!(mem_needed(stack.peek(0), stack.peek(1))), None)
},
instructions::CALL | instructions::CALLCODE => {
- let mut gas = overflowing!(add_gas_usize(try!(Gas::from_u256(*stack.peek(0))), schedule.call_gas));
+ let mut gas = Gas::from(schedule.call_gas);
let mem = cmp::max(
try!(mem_needed(stack.peek(5), stack.peek(6))),
try!(mem_needed(stack.peek(3), stack.peek(4)))
@@ -129,27 +176,49 @@ impl Gasometer {
let address = u256_to_address(stack.peek(1));
if instruction == instructions::CALL && !ext.exists(&address) {
- gas = overflowing!(gas.overflow_add(Gas::from(schedule.call_new_account_gas)));
+ gas = overflowing!(gas.overflow_add(schedule.call_new_account_gas.into()));
};
if !stack.peek(2).is_zero() {
- gas = overflowing!(gas.overflow_add(Gas::from(schedule.call_value_transfer_gas)));
+ gas = overflowing!(gas.overflow_add(schedule.call_value_transfer_gas.into()));
};
- InstructionCost::GasMem(gas,mem)
+ // TODO: refactor to avoid duplicate calculation here and later on.
+ let (mem_gas_cost, _, _) = try!(self.mem_gas_cost(schedule, current_mem_size, &mem));
+ let cost_so_far = overflowing!(gas.overflow_add(mem_gas_cost.into()));
+ let requested = Gas::from_u256(*stack.peek(0));
+ let provided = try!(self.gas_provided(schedule, cost_so_far, Some(requested)));
+ gas = overflowing!(gas.overflow_add(provided));
+
+ InstructionCost::GasMem(gas, mem, Some(provided))
},
instructions::DELEGATECALL => {
- let gas = overflowing!(add_gas_usize(try!(Gas::from_u256(*stack.peek(0))), schedule.call_gas));
+ let mut gas = Gas::from(schedule.call_gas);
let mem = cmp::max(
try!(mem_needed(stack.peek(4), stack.peek(5))),
try!(mem_needed(stack.peek(2), stack.peek(3)))
);
- InstructionCost::GasMem(gas, mem)
+
+ // TODO: refactor to avoid duplicate calculation here and later on.
+ let (mem_gas_cost, _, _) = try!(self.mem_gas_cost(schedule, current_mem_size, &mem));
+ let cost_so_far = overflowing!(gas.overflow_add(mem_gas_cost.into()));
+ let requested = Gas::from_u256(*stack.peek(0));
+ let provided = try!(self.gas_provided(schedule, cost_so_far, Some(requested)));
+ gas = overflowing!(gas.overflow_add(provided));
+
+ InstructionCost::GasMem(gas, mem, Some(provided))
},
instructions::CREATE => {
- let gas = Gas::from(schedule.create_gas);
+ let mut gas = Gas::from(schedule.create_gas);
let mem = try!(mem_needed(stack.peek(1), stack.peek(2)));
- InstructionCost::GasMem(gas, mem)
+
+ // TODO: refactor to avoid duplicate calculation here and later on.
+ let (mem_gas_cost, _, _) = try!(self.mem_gas_cost(schedule, current_mem_size, &mem));
+ let cost_so_far = overflowing!(gas.overflow_add(mem_gas_cost.into()));
+ let provided = try!(self.gas_provided(schedule, cost_so_far, None));
+ gas = overflowing!(gas.overflow_add(provided));
+
+ InstructionCost::GasMem(gas, mem, Some(provided))
},
instructions::EXP => {
let expon = stack.peek(1);
@@ -157,17 +226,17 @@ impl Gasometer {
let gas = Gas::from(schedule.exp_gas + schedule.exp_byte_gas * bytes);
InstructionCost::Gas(gas)
},
- _ => InstructionCost::Gas(default_gas)
+ _ => InstructionCost::Gas(default_gas),
};
match cost {
InstructionCost::Gas(gas) => {
- Ok((gas, self.current_mem_gas, 0))
+ Ok((gas, self.current_mem_gas, 0, None))
},
- InstructionCost::GasMem(gas, mem_size) => {
+ InstructionCost::GasMem(gas, mem_size, provided) => {
let (mem_gas_cost, new_mem_gas, new_mem_size) = try!(self.mem_gas_cost(schedule, current_mem_size, &mem_size));
let gas = overflowing!(gas.overflow_add(mem_gas_cost));
- Ok((gas, new_mem_gas, new_mem_size))
+ Ok((gas, new_mem_gas, new_mem_size, provided))
},
InstructionCost::GasMemCopy(gas, mem_size, copy) => {
let (mem_gas_cost, new_mem_gas, new_mem_size) = try!(self.mem_gas_cost(schedule, current_mem_size, &mem_size));
@@ -175,7 +244,7 @@ impl Gasometer {
let copy_gas = Gas::from(schedule.copy_gas) * copy;
let gas = overflowing!(gas.overflow_add(copy_gas));
let gas = overflowing!(gas.overflow_add(mem_gas_cost));
- Ok((gas, new_mem_gas, new_mem_size))
+ Ok((gas, new_mem_gas, new_mem_size, None))
}
}
}
diff --git a/ethcore/src/evm/interpreter/mod.rs b/ethcore/src/evm/interpreter/mod.rs
index 887f37cefd6..51dd8bacdce 100644
--- a/ethcore/src/evm/interpreter/mod.rs
+++ b/ethcore/src/evm/interpreter/mod.rs
@@ -81,8 +81,6 @@ impl<'a> CodeReader<'a> {
enum InstructionResult {
Ok,
- UseAllGas,
- GasLeft(Gas),
UnusedGas(Gas),
JumpToPosition(U256),
// gas left, init_orf, init_size
@@ -120,7 +118,7 @@ impl evm::Evm for Interpreter {
try!(self.verify_instruction(ext, instruction, info, &stack));
// Calculate gas cost
- let (gas_cost, mem_gas, mem_size) = try!(gasometer.get_gas_cost_mem(ext, instruction, info, &stack, self.mem.size()));
+ let (gas_cost, mem_gas, mem_size, provided) = try!(gasometer.get_gas_cost_mem(ext, instruction, info, &stack, self.mem.size()));
// TODO: make compile-time removable if too much of a performance hit.
let trace_executed = ext.trace_prepare_execute(reader.position - 1, instruction, &gas_cost.as_u256());
@@ -138,27 +136,21 @@ impl evm::Evm for Interpreter {
// Execute instruction
let result = try!(self.exec_instruction(
- gasometer.current_gas, ¶ms, ext, instruction, &mut reader, &mut stack
+ gasometer.current_gas, ¶ms, ext, instruction, &mut reader, &mut stack, provided
));
evm_debug!({ informant.after_instruction(instruction) });
+ if let InstructionResult::UnusedGas(ref gas) = result {
+ gasometer.current_gas = gasometer.current_gas + *gas;
+ }
+
if trace_executed {
ext.trace_executed(gasometer.current_gas.as_u256(), stack.peek_top(info.ret), mem_written.map(|(o, s)| (o, &(self.mem[o..(o + s)]))), store_written);
}
// Advance
match result {
- InstructionResult::Ok => {},
- InstructionResult::UnusedGas(gas) => {
- gasometer.current_gas = gasometer.current_gas + gas;
- },
- InstructionResult::UseAllGas => {
- gasometer.current_gas = Cost::from(0);
- },
- InstructionResult::GasLeft(gas_left) => {
- gasometer.current_gas = gas_left;
- },
InstructionResult::JumpToPosition(position) => {
let pos = try!(self.verify_jump(position, &valid_jump_destinations));
reader.position = pos;
@@ -168,6 +160,7 @@ impl evm::Evm for Interpreter {
return Ok(GasLeft::NeedsReturn(gas.as_u256(), self.mem.read_slice(off, size)));
},
InstructionResult::StopExecution => break,
+ _ => {},
}
}
informant.done();
@@ -250,7 +243,8 @@ impl Interpreter {
ext: &mut evm::Ext,
instruction: Instruction,
code: &mut CodeReader,
- stack: &mut Stack
+ stack: &mut Stack,
+ provided: Option
) -> evm::Result> {
match instruction {
instructions::JUMP => {
@@ -275,31 +269,32 @@ impl Interpreter {
let endowment = stack.pop_back();
let init_off = stack.pop_back();
let init_size = stack.pop_back();
+ let create_gas = provided.expect("`provided` comes through Self::exec from `Gasometer::get_gas_cost_mem`; `gas_gas_mem_cost` guarantees `Some` when instruction is `CALL`/`CALLCODE`/`DELEGATECALL`/`CREATE`; this is `CREATE`; qed");
let contract_code = self.mem.read_slice(init_off, init_size);
let can_create = ext.balance(¶ms.address) >= endowment && ext.depth() < ext.schedule().max_depth;
if !can_create {
stack.push(U256::zero());
- return Ok(InstructionResult::Ok);
+ return Ok(InstructionResult::UnusedGas(create_gas));
}
- let create_result = ext.create(&gas.as_u256(), &endowment, contract_code);
+ let create_result = ext.create(&create_gas.as_u256(), &endowment, contract_code);
return match create_result {
ContractCreateResult::Created(address, gas_left) => {
stack.push(address_to_u256(address));
- Ok(InstructionResult::GasLeft(Cost::from_u256(gas_left).expect("Gas left cannot be greater.")))
+ Ok(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater.")))
},
ContractCreateResult::Failed => {
stack.push(U256::zero());
- // TODO [todr] Should we just StopExecution here?
- Ok(InstructionResult::UseAllGas)
+ Ok(InstructionResult::Ok)
}
};
},
instructions::CALL | instructions::CALLCODE | instructions::DELEGATECALL => {
assert!(ext.schedule().call_value_transfer_gas > ext.schedule().call_stipend, "overflow possible");
- let call_gas = Cost::from_u256(stack.pop_back()).expect("Gas is already validated.");
+ stack.pop_back();
+ let call_gas = provided.expect("`provided` comes through Self::exec from `Gasometer::get_gas_cost_mem`; `gas_gas_mem_cost` guarantees `Some` when instruction is `CALL`/`CALLCODE`/`DELEGATECALL`/`CREATE`; this is one of `CALL`/`CALLCODE`/`DELEGATECALL`; qed");
let code_address = stack.pop_back();
let code_address = u256_to_address(&code_address);
@@ -317,7 +312,7 @@ impl Interpreter {
// Add stipend (only CALL|CALLCODE when value > 0)
let call_gas = call_gas + value.map_or_else(|| Cost::from(0), |val| match val.is_zero() {
false => Cost::from(ext.schedule().call_stipend),
- true => Cost::from(0)
+ true => Cost::from(0),
});
// Get sender & receive addresses, check if we have balance
diff --git a/ethcore/src/evm/schedule.rs b/ethcore/src/evm/schedule.rs
index e3e4e3b7bff..b8de785b397 100644
--- a/ethcore/src/evm/schedule.rs
+++ b/ethcore/src/evm/schedule.rs
@@ -80,6 +80,19 @@ pub struct Schedule {
pub tx_data_non_zero_gas: usize,
/// Gas price for copying memory
pub copy_gas: usize,
+ /// Price of EXTCODESIZE
+ pub extcodesize_gas: usize,
+ /// Base price of EXTCODECOPY
+ pub extcodecopy_base_gas: usize,
+ /// Price of BALANCE
+ pub balance_gas: usize,
+ /// Price of SUICIDE
+ pub suicide_gas: usize,
+ /// Amount of additional gas to pay when SUICIDE credits a non-existant account
+ pub suicide_to_new_account_cost: usize,
+ /// If Some(x): let limit = GAS * (x - 1) / x; let CALL's gas = min(requested, limit). let CREATE's gas = limit.
+ /// If None: let CALL's gas = (requested > GAS ? [OOG] : GAS). let CREATE's gas = GAS
+ pub sub_gas_cap_divisor: Option,
}
impl Schedule {
@@ -93,6 +106,49 @@ impl Schedule {
Self::new(true, true, 53000)
}
+ /// Schedule for the Homestead-era of the Ethereum main net.
+ pub fn new_homestead_gas_fix() -> Schedule {
+ Schedule{
+ exceptional_failed_code_deposit: true,
+ have_delegate_call: true,
+ stack_limit: 1024,
+ max_depth: 1024,
+ tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0],
+ exp_gas: 10,
+ exp_byte_gas: 10,
+ sha3_gas: 30,
+ sha3_word_gas: 6,
+ sload_gas: 200,
+ sstore_set_gas: 20000,
+ sstore_reset_gas: 5000,
+ sstore_refund_gas: 15000,
+ jumpdest_gas: 1,
+ log_gas: 375,
+ log_data_gas: 8,
+ log_topic_gas: 375,
+ create_gas: 32000,
+ call_gas: 700,
+ call_stipend: 2300,
+ call_value_transfer_gas: 9000,
+ call_new_account_gas: 25000,
+ suicide_refund_gas: 24000,
+ memory_gas: 3,
+ quad_coeff_div: 512,
+ create_data_gas: 200,
+ tx_gas: 21000,
+ tx_create_gas: 53000,
+ tx_data_zero_gas: 4,
+ tx_data_non_zero_gas: 68,
+ copy_gas: 3,
+ extcodesize_gas: 700,
+ extcodecopy_base_gas: 700,
+ balance_gas: 400,
+ suicide_gas: 5000,
+ suicide_to_new_account_cost: 25000,
+ sub_gas_cap_divisor: Some(64),
+ }
+ }
+
fn new(efcd: bool, hdc: bool, tcg: usize) -> Schedule {
Schedule{
exceptional_failed_code_deposit: efcd,
@@ -126,6 +182,12 @@ impl Schedule {
tx_data_zero_gas: 4,
tx_data_non_zero_gas: 68,
copy_gas: 3,
+ extcodesize_gas: 20,
+ extcodecopy_base_gas: 20,
+ balance_gas: 20,
+ suicide_gas: 0,
+ suicide_to_new_account_cost: 0,
+ sub_gas_cap_divisor: None,
}
}
}
diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs
index 3c8b6171e3f..54fd902035f 100644
--- a/ethcore/src/executive.rs
+++ b/ethcore/src/executive.rs
@@ -697,7 +697,7 @@ mod tests {
VMOperation { pc: 33, instruction: 96, gas_cost: 3.into(), executed: Some(VMExecutedOperation { gas_used: 99985.into(), stack_push: vec_into![29], mem_diff: None, store_diff: None }) },
VMOperation { pc: 35, instruction: 96, gas_cost: 3.into(), executed: Some(VMExecutedOperation { gas_used: 99982.into(), stack_push: vec_into![3], mem_diff: None, store_diff: None }) },
VMOperation { pc: 37, instruction: 96, gas_cost: 3.into(), executed: Some(VMExecutedOperation { gas_used: 99979.into(), stack_push: vec_into![23], mem_diff: None, store_diff: None }) },
- VMOperation { pc: 39, instruction: 240, gas_cost: 32000.into(), executed: Some(VMExecutedOperation { gas_used: 67979.into(), stack_push: vec_into![U256::from_dec_str("1135198453258042933984631383966629874710669425204").unwrap()], mem_diff: None, store_diff: None }) },
+ VMOperation { pc: 39, instruction: 240, gas_cost: 99979.into(), executed: Some(VMExecutedOperation { gas_used: 64755.into(), stack_push: vec_into![U256::from_dec_str("1135198453258042933984631383966629874710669425204").unwrap()], mem_diff: None, store_diff: None }) },
VMOperation { pc: 40, instruction: 96, gas_cost: 3.into(), executed: Some(VMExecutedOperation { gas_used: 64752.into(), stack_push: vec_into![0], mem_diff: None, store_diff: None }) },
VMOperation { pc: 42, instruction: 85, gas_cost: 20000.into(), executed: Some(VMExecutedOperation { gas_used: 44752.into(), stack_push: vec_into![], mem_diff: None, store_diff: Some(StorageDiff { location: 0.into(), value: U256::from_dec_str("1135198453258042933984631383966629874710669425204").unwrap() }) }) }
],
diff --git a/ethcore/src/json_tests/chain.rs b/ethcore/src/json_tests/chain.rs
index 93b0cf82cd7..bf32db1337f 100644
--- a/ethcore/src/json_tests/chain.rs
+++ b/ethcore/src/json_tests/chain.rs
@@ -48,7 +48,8 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec {
let mut spec = match era {
ChainEra::Frontier => ethereum::new_frontier_test(),
ChainEra::Homestead => ethereum::new_homestead_test(),
- ChainEra::DaoHardfork => ethereum::new_daohardfork_test(),
+ ChainEra::Eip150 => ethereum::new_eip150_test(),
+ ChainEra::TransitionTest => ethereum::new_transition_test(),
};
spec.set_genesis_state(state);
spec.overwrite_genesis_params(genesis);
@@ -116,14 +117,38 @@ mod frontier_era_tests {
declare_test!{BlockchainTests_RandomTests_bl201507071825GO, "BlockchainTests/RandomTests/bl201507071825GO"}
}
-mod daohardfork_tests {
+mod transition_tests {
use tests::helpers::*;
use super::json_chain_test;
fn do_json_test(json_data: &[u8]) -> Vec {
- json_chain_test(json_data, ChainEra::DaoHardfork)
+ json_chain_test(json_data, ChainEra::TransitionTest)
}
declare_test!{BlockchainTests_TestNetwork_bcSimpleTransitionTest, "BlockchainTests/TestNetwork/bcSimpleTransitionTest"}
declare_test!{BlockchainTests_TestNetwork_bcTheDaoTest, "BlockchainTests/TestNetwork/bcTheDaoTest"}
+ declare_test!{BlockchainTests_TestNetwork_bcEIP150Test, "BlockchainTests/TestNetwork/bcEIP150Test"}
+}
+
+mod eip150_blockchain_tests {
+ use tests::helpers::*;
+ use super::json_chain_test;
+
+ fn do_json_test(json_data: &[u8]) -> Vec {
+ json_chain_test(json_data, ChainEra::Eip150)
+ }
+
+ declare_test!{BlockchainTests_EIP150_bcBlockGasLimitTest, "BlockchainTests/EIP150/bcBlockGasLimitTest"}
+ declare_test!{BlockchainTests_EIP150_bcForkStressTest, "BlockchainTests/EIP150/bcForkStressTest"}
+ declare_test!{BlockchainTests_EIP150_bcGasPricerTest, "BlockchainTests/EIP150/bcGasPricerTest"}
+ declare_test!{BlockchainTests_EIP150_bcInvalidHeaderTest, "BlockchainTests/EIP150/bcInvalidHeaderTest"}
+ declare_test!{BlockchainTests_EIP150_bcInvalidRLPTest, "BlockchainTests/EIP150/bcInvalidRLPTest"}
+ declare_test!{BlockchainTests_EIP150_bcMultiChainTest, "BlockchainTests/EIP150/bcMultiChainTest"}
+ declare_test!{BlockchainTests_EIP150_bcRPC_API_Test, "BlockchainTests/EIP150/bcRPC_API_Test"}
+ declare_test!{BlockchainTests_EIP150_bcStateTest, "BlockchainTests/EIP150/bcStateTest"}
+ declare_test!{BlockchainTests_EIP150_bcTotalDifficultyTest, "BlockchainTests/EIP150/bcTotalDifficultyTest"}
+ declare_test!{BlockchainTests_EIP150_bcUncleHeaderValiditiy, "BlockchainTests/EIP150/bcUncleHeaderValiditiy"}
+ declare_test!{BlockchainTests_EIP150_bcUncleTest, "BlockchainTests/EIP150/bcUncleTest"}
+ declare_test!{BlockchainTests_EIP150_bcValidBlockTest, "BlockchainTests/EIP150/bcValidBlockTest"}
+ declare_test!{BlockchainTests_EIP150_bcWalletTest, "BlockchainTests/EIP150/bcWalletTest"}
}
diff --git a/ethcore/src/json_tests/eip150_state.rs b/ethcore/src/json_tests/eip150_state.rs
new file mode 100644
index 00000000000..9076286eb46
--- /dev/null
+++ b/ethcore/src/json_tests/eip150_state.rs
@@ -0,0 +1,43 @@
+// Copyright 2015, 2016 Ethcore (UK) Ltd.
+// This file is part of Parity.
+
+// Parity is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity. If not, see .
+
+use super::test_common::*;
+use tests::helpers::*;
+use super::state::json_chain_test;
+
+fn do_json_test(json_data: &[u8]) -> Vec {
+ json_chain_test(json_data, ChainEra::Eip150)
+}
+
+declare_test!{StateTests_EIP150_stEIPSpecificTest, "StateTests/EIP150/stEIPSpecificTest"}
+declare_test!{StateTests_EIP150_stEIPsingleCodeGasPrices, "StateTests/EIP150/stEIPsingleCodeGasPrices"}
+declare_test!{StateTests_EIP150_stMemExpandingEIPCalls, "StateTests/EIP150/stMemExpandingEIPCalls"}
+
+declare_test!{StateTests_EIP150_stCallCodes, "StateTests/EIP150/Homestead/stCallCodes"}
+declare_test!{StateTests_EIP150_stCallCreateCallCodeTest, "StateTests/EIP150/Homestead/stCallCreateCallCodeTest"}
+declare_test!{StateTests_EIP150_stDelegatecallTest, "StateTests/EIP150/Homestead/stDelegatecallTest"}
+declare_test!{StateTests_EIP150_stInitCodeTest, "StateTests/EIP150/Homestead/stInitCodeTest"}
+declare_test!{StateTests_EIP150_stLogTests, "StateTests/EIP150/Homestead/stLogTests"}
+declare_test!{heavy => StateTests_EIP150_stMemoryStressTest, "StateTests/EIP150/Homestead/stMemoryStressTest"}
+declare_test!{heavy => StateTests_EIP150_stMemoryTest, "StateTests/EIP150/Homestead/stMemoryTest"}
+declare_test!{StateTests_EIP150_stPreCompiledContracts, "StateTests/EIP150/Homestead/stPreCompiledContracts"}
+declare_test!{heavy => StateTests_EIP150_stQuadraticComplexityTest, "StateTests/EIP150/Homestead/stQuadraticComplexityTest"}
+declare_test!{StateTests_EIP150_stRecursiveCreate, "StateTests/EIP150/Homestead/stRecursiveCreate"}
+declare_test!{StateTests_EIP150_stRefundTest, "StateTests/EIP150/Homestead/stRefundTest"}
+declare_test!{StateTests_EIP150_stSpecialTest, "StateTests/EIP150/Homestead/stSpecialTest"}
+declare_test!{StateTests_EIP150_stSystemOperationsTest, "StateTests/EIP150/Homestead/stSystemOperationsTest"}
+declare_test!{StateTests_EIP150_stTransactionTest, "StateTests/EIP150/Homestead/stTransactionTest"}
+declare_test!{StateTests_EIP150_stWalletTest, "StateTests/EIP150/Homestead/stWalletTest"}
diff --git a/ethcore/src/json_tests/homestead_chain.rs b/ethcore/src/json_tests/homestead_chain.rs
index 314c36cf177..d92b8a7f1aa 100644
--- a/ethcore/src/json_tests/homestead_chain.rs
+++ b/ethcore/src/json_tests/homestead_chain.rs
@@ -37,6 +37,6 @@ declare_test!{BlockchainTests_Homestead_bcUncleTest, "BlockchainTests/Homestead/
declare_test!{BlockchainTests_Homestead_bcValidBlockTest, "BlockchainTests/Homestead/bcValidBlockTest"}
declare_test!{BlockchainTests_Homestead_bcWalletTest, "BlockchainTests/Homestead/bcWalletTest"}
declare_test!{BlockchainTests_Homestead_bcShanghaiLove, "BlockchainTests/Homestead/bcShanghaiLove"}
-// Uncomment once the test is correct.
+// TODO [ToDr] uncomment as soon as eip150 tests are merged to develop branch of ethereum/tests
// declare_test!{BlockchainTests_Homestead_bcSuicideIssue, "BlockchainTests/Homestead/bcSuicideIssue"}
declare_test!{BlockchainTests_Homestead_bcExploitTest, "BlockchainTests/Homestead/bcExploitTest"}
diff --git a/ethcore/src/json_tests/mod.rs b/ethcore/src/json_tests/mod.rs
index 841db229ee6..7a5dd30d249 100644
--- a/ethcore/src/json_tests/mod.rs
+++ b/ethcore/src/json_tests/mod.rs
@@ -23,4 +23,5 @@ mod state;
mod chain;
mod homestead_state;
mod homestead_chain;
+mod eip150_state;
mod trie;
diff --git a/ethcore/src/json_tests/state.rs b/ethcore/src/json_tests/state.rs
index d7011cd28c2..16e532401b4 100644
--- a/ethcore/src/json_tests/state.rs
+++ b/ethcore/src/json_tests/state.rs
@@ -20,10 +20,6 @@ use pod_state::{self, PodState};
use ethereum;
use ethjson;
-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 tests = ethjson::state::Test::load(json_data).unwrap();
@@ -31,8 +27,9 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec {
let engine = match era {
ChainEra::Frontier => ethereum::new_mainnet_like().engine,
ChainEra::Homestead => ethereum::new_homestead_test().engine,
- ChainEra::DaoHardfork => ethereum::new_daohardfork_test().engine,
-};
+ ChainEra::Eip150 => ethereum::new_eip150_test().engine,
+ ChainEra::TransitionTest => ethereum::new_transition_test().engine,
+ };
for (name, test) in tests.into_iter() {
let mut fail = false;
@@ -93,665 +90,673 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec {
failed
}
-declare_test!{StateTests_stBlockHashTest, "StateTests/stBlockHashTest"}
-declare_test!{StateTests_stCallCodes, "StateTests/stCallCodes"}
-declare_test!{StateTests_stCallCreateCallCodeTest, "StateTests/stCallCreateCallCodeTest"}
-declare_test!{StateTests_stExample, "StateTests/stExample"}
-declare_test!{StateTests_stInitCodeTest, "StateTests/stInitCodeTest"}
-declare_test!{StateTests_stLogTests, "StateTests/stLogTests"}
-declare_test!{heavy => StateTests_stMemoryStressTest, "StateTests/stMemoryStressTest"}
-declare_test!{heavy => StateTests_stMemoryTest, "StateTests/stMemoryTest"}
-declare_test!{StateTests_stPreCompiledContracts, "StateTests/stPreCompiledContracts"}
-declare_test!{heavy => StateTests_stQuadraticComplexityTest, "StateTests/stQuadraticComplexityTest"}
-declare_test!{StateTests_stRecursiveCreate, "StateTests/stRecursiveCreate"}
-declare_test!{StateTests_stRefundTest, "StateTests/stRefundTest"}
-declare_test!{StateTests_stSolidityTest, "StateTests/stSolidityTest"}
-declare_test!{StateTests_stSpecialTest, "StateTests/stSpecialTest"}
-declare_test!{StateTests_stSystemOperationsTest, "StateTests/stSystemOperationsTest"}
-declare_test!{StateTests_stTransactionTest, "StateTests/stTransactionTest"}
-declare_test!{StateTests_stTransitionTest, "StateTests/stTransitionTest"}
-declare_test!{StateTests_stWalletTest, "StateTests/stWalletTest"}
+mod frontier_tests {
+ use super::json_chain_test;
+ use tests::helpers::ChainEra;
+ fn do_json_test(json_data: &[u8]) -> Vec {
+ json_chain_test(json_data, ChainEra::Frontier)
+ }
-declare_test!{StateTests_RandomTests_st201503121803PYTHON, "StateTests/RandomTests/st201503121803PYTHON"}
-declare_test!{StateTests_RandomTests_st201503121806PYTHON, "StateTests/RandomTests/st201503121806PYTHON"}
-declare_test!{StateTests_RandomTests_st201503121848GO, "StateTests/RandomTests/st201503121848GO"}
-declare_test!{StateTests_RandomTests_st201503121849GO, "StateTests/RandomTests/st201503121849GO"}
-declare_test!{StateTests_RandomTests_st201503121850GO, "StateTests/RandomTests/st201503121850GO"}
-declare_test!{StateTests_RandomTests_st201503121851GO, "StateTests/RandomTests/st201503121851GO"}
-declare_test!{StateTests_RandomTests_st201503121953GO, "StateTests/RandomTests/st201503121953GO"}
-declare_test!{StateTests_RandomTests_st201503122023GO, "StateTests/RandomTests/st201503122023GO"}
-declare_test!{StateTests_RandomTests_st201503122023PYTHON, "StateTests/RandomTests/st201503122023PYTHON"}
-declare_test!{StateTests_RandomTests_st201503122027GO, "StateTests/RandomTests/st201503122027GO"}
-declare_test!{StateTests_RandomTests_st201503122054GO, "StateTests/RandomTests/st201503122054GO"}
-declare_test!{StateTests_RandomTests_st201503122055GO, "StateTests/RandomTests/st201503122055GO"}
-declare_test!{StateTests_RandomTests_st201503122115CPPJIT, "StateTests/RandomTests/st201503122115CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503122115GO, "StateTests/RandomTests/st201503122115GO"}
-declare_test!{StateTests_RandomTests_st201503122123GO, "StateTests/RandomTests/st201503122123GO"}
-declare_test!{StateTests_RandomTests_st201503122124GO, "StateTests/RandomTests/st201503122124GO"}
-declare_test!{StateTests_RandomTests_st201503122128PYTHON, "StateTests/RandomTests/st201503122128PYTHON"}
-declare_test!{StateTests_RandomTests_st201503122140GO, "StateTests/RandomTests/st201503122140GO"}
-declare_test!{StateTests_RandomTests_st201503122159GO, "StateTests/RandomTests/st201503122159GO"}
-declare_test!{StateTests_RandomTests_st201503122204GO, "StateTests/RandomTests/st201503122204GO"}
-declare_test!{StateTests_RandomTests_st201503122212GO, "StateTests/RandomTests/st201503122212GO"}
-declare_test!{StateTests_RandomTests_st201503122231GO, "StateTests/RandomTests/st201503122231GO"}
-declare_test!{StateTests_RandomTests_st201503122238GO, "StateTests/RandomTests/st201503122238GO"}
-declare_test!{StateTests_RandomTests_st201503122252GO, "StateTests/RandomTests/st201503122252GO"}
-declare_test!{StateTests_RandomTests_st201503122316GO, "StateTests/RandomTests/st201503122316GO"}
-declare_test!{StateTests_RandomTests_st201503122324GO, "StateTests/RandomTests/st201503122324GO"}
-declare_test!{StateTests_RandomTests_st201503122358GO, "StateTests/RandomTests/st201503122358GO"}
-declare_test!{StateTests_RandomTests_st201503130002GO, "StateTests/RandomTests/st201503130002GO"}
-declare_test!{StateTests_RandomTests_st201503130005GO, "StateTests/RandomTests/st201503130005GO"}
-declare_test!{StateTests_RandomTests_st201503130007GO, "StateTests/RandomTests/st201503130007GO"}
-declare_test!{StateTests_RandomTests_st201503130010GO, "StateTests/RandomTests/st201503130010GO"}
-declare_test!{StateTests_RandomTests_st201503130023PYTHON, "StateTests/RandomTests/st201503130023PYTHON"}
-declare_test!{StateTests_RandomTests_st201503130059GO, "StateTests/RandomTests/st201503130059GO"}
-declare_test!{StateTests_RandomTests_st201503130101GO, "StateTests/RandomTests/st201503130101GO"}
-declare_test!{StateTests_RandomTests_st201503130109GO, "StateTests/RandomTests/st201503130109GO"}
-declare_test!{StateTests_RandomTests_st201503130117GO, "StateTests/RandomTests/st201503130117GO"}
-declare_test!{StateTests_RandomTests_st201503130122GO, "StateTests/RandomTests/st201503130122GO"}
-declare_test!{StateTests_RandomTests_st201503130156GO, "StateTests/RandomTests/st201503130156GO"}
-declare_test!{StateTests_RandomTests_st201503130156PYTHON, "StateTests/RandomTests/st201503130156PYTHON"}
-declare_test!{StateTests_RandomTests_st201503130207GO, "StateTests/RandomTests/st201503130207GO"}
-declare_test!{StateTests_RandomTests_st201503130219CPPJIT, "StateTests/RandomTests/st201503130219CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503130219GO, "StateTests/RandomTests/st201503130219GO"}
-declare_test!{StateTests_RandomTests_st201503130243GO, "StateTests/RandomTests/st201503130243GO"}
-declare_test!{StateTests_RandomTests_st201503130246GO, "StateTests/RandomTests/st201503130246GO"}
-declare_test!{StateTests_RandomTests_st201503130321GO, "StateTests/RandomTests/st201503130321GO"}
-declare_test!{StateTests_RandomTests_st201503130322GO, "StateTests/RandomTests/st201503130322GO"}
-declare_test!{StateTests_RandomTests_st201503130332GO, "StateTests/RandomTests/st201503130332GO"}
-declare_test!{StateTests_RandomTests_st201503130359GO, "StateTests/RandomTests/st201503130359GO"}
-declare_test!{StateTests_RandomTests_st201503130405GO, "StateTests/RandomTests/st201503130405GO"}
-declare_test!{StateTests_RandomTests_st201503130408GO, "StateTests/RandomTests/st201503130408GO"}
-declare_test!{StateTests_RandomTests_st201503130411GO, "StateTests/RandomTests/st201503130411GO"}
-declare_test!{StateTests_RandomTests_st201503130431GO, "StateTests/RandomTests/st201503130431GO"}
-declare_test!{StateTests_RandomTests_st201503130437GO, "StateTests/RandomTests/st201503130437GO"}
-declare_test!{StateTests_RandomTests_st201503130450GO, "StateTests/RandomTests/st201503130450GO"}
-declare_test!{StateTests_RandomTests_st201503130512CPPJIT, "StateTests/RandomTests/st201503130512CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503130512GO, "StateTests/RandomTests/st201503130512GO"}
-declare_test!{StateTests_RandomTests_st201503130615GO, "StateTests/RandomTests/st201503130615GO"}
-declare_test!{StateTests_RandomTests_st201503130705GO, "StateTests/RandomTests/st201503130705GO"}
-declare_test!{StateTests_RandomTests_st201503130733CPPJIT, "StateTests/RandomTests/st201503130733CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503130733GO, "StateTests/RandomTests/st201503130733GO"}
-declare_test!{StateTests_RandomTests_st201503130747GO, "StateTests/RandomTests/st201503130747GO"}
-declare_test!{StateTests_RandomTests_st201503130751GO, "StateTests/RandomTests/st201503130751GO"}
-declare_test!{StateTests_RandomTests_st201503130752PYTHON, "StateTests/RandomTests/st201503130752PYTHON"}
-declare_test!{StateTests_RandomTests_st201503130757PYTHON, "StateTests/RandomTests/st201503130757PYTHON"}
-declare_test!{StateTests_RandomTests_st201503131658GO, "StateTests/RandomTests/st201503131658GO"}
-declare_test!{StateTests_RandomTests_st201503131739GO, "StateTests/RandomTests/st201503131739GO"}
-declare_test!{StateTests_RandomTests_st201503131755CPPJIT, "StateTests/RandomTests/st201503131755CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503131755GO, "StateTests/RandomTests/st201503131755GO"}
-declare_test!{StateTests_RandomTests_st201503132001CPPJIT, "StateTests/RandomTests/st201503132001CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503132127PYTHON, "StateTests/RandomTests/st201503132127PYTHON"}
-declare_test!{StateTests_RandomTests_st201503132201CPPJIT, "StateTests/RandomTests/st201503132201CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503132201GO, "StateTests/RandomTests/st201503132201GO"}
-declare_test!{StateTests_RandomTests_st201503132202PYTHON, "StateTests/RandomTests/st201503132202PYTHON"}
-declare_test!{StateTests_RandomTests_st201503140002PYTHON, "StateTests/RandomTests/st201503140002PYTHON"}
-declare_test!{StateTests_RandomTests_st201503140240PYTHON, "StateTests/RandomTests/st201503140240PYTHON"}
-declare_test!{StateTests_RandomTests_st201503140522PYTHON, "StateTests/RandomTests/st201503140522PYTHON"}
-declare_test!{StateTests_RandomTests_st201503140756PYTHON, "StateTests/RandomTests/st201503140756PYTHON"}
-declare_test!{StateTests_RandomTests_st201503141144PYTHON, "StateTests/RandomTests/st201503141144PYTHON"}
-declare_test!{StateTests_RandomTests_st201503141510PYTHON, "StateTests/RandomTests/st201503141510PYTHON"}
-declare_test!{StateTests_RandomTests_st201503150427PYTHON, "StateTests/RandomTests/st201503150427PYTHON"}
-declare_test!{StateTests_RandomTests_st201503150716PYTHON, "StateTests/RandomTests/st201503150716PYTHON"}
-declare_test!{StateTests_RandomTests_st201503151450PYTHON, "StateTests/RandomTests/st201503151450PYTHON"}
-declare_test!{StateTests_RandomTests_st201503151516PYTHON, "StateTests/RandomTests/st201503151516PYTHON"}
-declare_test!{StateTests_RandomTests_st201503151753PYTHON, "StateTests/RandomTests/st201503151753PYTHON"}
-declare_test!{StateTests_RandomTests_st201503152057PYTHON, "StateTests/RandomTests/st201503152057PYTHON"}
-declare_test!{StateTests_RandomTests_st201503152241PYTHON, "StateTests/RandomTests/st201503152241PYTHON"}
-declare_test!{StateTests_RandomTests_st201503160014PYTHON, "StateTests/RandomTests/st201503160014PYTHON"}
-declare_test!{StateTests_RandomTests_st201503160733PYTHON, "StateTests/RandomTests/st201503160733PYTHON"}
-declare_test!{StateTests_RandomTests_st201503170051PYTHON, "StateTests/RandomTests/st201503170051PYTHON"}
-declare_test!{StateTests_RandomTests_st201503170433PYTHON, "StateTests/RandomTests/st201503170433PYTHON"}
-declare_test!{StateTests_RandomTests_st201503170523PYTHON, "StateTests/RandomTests/st201503170523PYTHON"}
-declare_test!{StateTests_RandomTests_st201503171108PYTHON, "StateTests/RandomTests/st201503171108PYTHON"}
-declare_test!{StateTests_RandomTests_st201503181223GO, "StateTests/RandomTests/st201503181223GO"}
-declare_test!{StateTests_RandomTests_st201503181225GO, "StateTests/RandomTests/st201503181225GO"}
-declare_test!{StateTests_RandomTests_st201503181226CPPJIT, "StateTests/RandomTests/st201503181226CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181227CPPJIT, "StateTests/RandomTests/st201503181227CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181227GO, "StateTests/RandomTests/st201503181227GO"}
-declare_test!{StateTests_RandomTests_st201503181229GO, "StateTests/RandomTests/st201503181229GO"}
-declare_test!{StateTests_RandomTests_st201503181230CPPJIT, "StateTests/RandomTests/st201503181230CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181230GO, "StateTests/RandomTests/st201503181230GO"}
-declare_test!{StateTests_RandomTests_st201503181231GO, "StateTests/RandomTests/st201503181231GO"}
-declare_test!{StateTests_RandomTests_st201503181232CPPJIT, "StateTests/RandomTests/st201503181232CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181232GO, "StateTests/RandomTests/st201503181232GO"}
-declare_test!{StateTests_RandomTests_st201503181233GO, "StateTests/RandomTests/st201503181233GO"}
-declare_test!{StateTests_RandomTests_st201503181234CPPJIT, "StateTests/RandomTests/st201503181234CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181234GO, "StateTests/RandomTests/st201503181234GO"}
-declare_test!{StateTests_RandomTests_st201503181235CPPJIT, "StateTests/RandomTests/st201503181235CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181235GO, "StateTests/RandomTests/st201503181235GO"}
-declare_test!{StateTests_RandomTests_st201503181236GO, "StateTests/RandomTests/st201503181236GO"}
-declare_test!{StateTests_RandomTests_st201503181237GO, "StateTests/RandomTests/st201503181237GO"}
-declare_test!{StateTests_RandomTests_st201503181239GO, "StateTests/RandomTests/st201503181239GO"}
-declare_test!{StateTests_RandomTests_st201503181241CPPJIT, "StateTests/RandomTests/st201503181241CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181241GO, "StateTests/RandomTests/st201503181241GO"}
-declare_test!{StateTests_RandomTests_st201503181243GO, "StateTests/RandomTests/st201503181243GO"}
-declare_test!{StateTests_RandomTests_st201503181244GO, "StateTests/RandomTests/st201503181244GO"}
-declare_test!{StateTests_RandomTests_st201503181245CPPJIT, "StateTests/RandomTests/st201503181245CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181245GO, "StateTests/RandomTests/st201503181245GO"}
-declare_test!{StateTests_RandomTests_st201503181246CPPJIT, "StateTests/RandomTests/st201503181246CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181246GO, "StateTests/RandomTests/st201503181246GO"}
-declare_test!{StateTests_RandomTests_st201503181247GO, "StateTests/RandomTests/st201503181247GO"}
-declare_test!{StateTests_RandomTests_st201503181248GO, "StateTests/RandomTests/st201503181248GO"}
-declare_test!{StateTests_RandomTests_st201503181249GO, "StateTests/RandomTests/st201503181249GO"}
-declare_test!{StateTests_RandomTests_st201503181250CPPJIT, "StateTests/RandomTests/st201503181250CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181250GO, "StateTests/RandomTests/st201503181250GO"}
-declare_test!{StateTests_RandomTests_st201503181251GO, "StateTests/RandomTests/st201503181251GO"}
-declare_test!{StateTests_RandomTests_st201503181252CPPJIT, "StateTests/RandomTests/st201503181252CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181253GO, "StateTests/RandomTests/st201503181253GO"}
-declare_test!{StateTests_RandomTests_st201503181255CPPJIT, "StateTests/RandomTests/st201503181255CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181255GO, "StateTests/RandomTests/st201503181255GO"}
-declare_test!{StateTests_RandomTests_st201503181257GO, "StateTests/RandomTests/st201503181257GO"}
-declare_test!{StateTests_RandomTests_st201503181258CPPJIT, "StateTests/RandomTests/st201503181258CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181258GO, "StateTests/RandomTests/st201503181258GO"}
-declare_test!{StateTests_RandomTests_st201503181301CPPJIT, "StateTests/RandomTests/st201503181301CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181301GO, "StateTests/RandomTests/st201503181301GO"}
-declare_test!{StateTests_RandomTests_st201503181303GO, "StateTests/RandomTests/st201503181303GO"}
-declare_test!{StateTests_RandomTests_st201503181304GO, "StateTests/RandomTests/st201503181304GO"}
-declare_test!{StateTests_RandomTests_st201503181305GO, "StateTests/RandomTests/st201503181305GO"}
-declare_test!{StateTests_RandomTests_st201503181306GO, "StateTests/RandomTests/st201503181306GO"}
-declare_test!{StateTests_RandomTests_st201503181307CPPJIT, "StateTests/RandomTests/st201503181307CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181307GO, "StateTests/RandomTests/st201503181307GO"}
-declare_test!{StateTests_RandomTests_st201503181308GO, "StateTests/RandomTests/st201503181308GO"}
-declare_test!{StateTests_RandomTests_st201503181309GO, "StateTests/RandomTests/st201503181309GO"}
-declare_test!{StateTests_RandomTests_st201503181310GO, "StateTests/RandomTests/st201503181310GO"}
-declare_test!{StateTests_RandomTests_st201503181311GO, "StateTests/RandomTests/st201503181311GO"}
-declare_test!{StateTests_RandomTests_st201503181313GO, "StateTests/RandomTests/st201503181313GO"}
-declare_test!{StateTests_RandomTests_st201503181314GO, "StateTests/RandomTests/st201503181314GO"}
-declare_test!{StateTests_RandomTests_st201503181315CPPJIT, "StateTests/RandomTests/st201503181315CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181315GO, "StateTests/RandomTests/st201503181315GO"}
-declare_test!{StateTests_RandomTests_st201503181316CPPJIT, "StateTests/RandomTests/st201503181316CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181316PYTHON, "StateTests/RandomTests/st201503181316PYTHON"}
-declare_test!{StateTests_RandomTests_st201503181317GO, "StateTests/RandomTests/st201503181317GO"}
-declare_test!{StateTests_RandomTests_st201503181318CPPJIT, "StateTests/RandomTests/st201503181318CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181318GO, "StateTests/RandomTests/st201503181318GO"}
-declare_test!{StateTests_RandomTests_st201503181319GO, "StateTests/RandomTests/st201503181319GO"}
-declare_test!{StateTests_RandomTests_st201503181319PYTHON, "StateTests/RandomTests/st201503181319PYTHON"}
-declare_test!{StateTests_RandomTests_st201503181322GO, "StateTests/RandomTests/st201503181322GO"}
-declare_test!{StateTests_RandomTests_st201503181323CPPJIT, "StateTests/RandomTests/st201503181323CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181323GO, "StateTests/RandomTests/st201503181323GO"}
-declare_test!{StateTests_RandomTests_st201503181324GO, "StateTests/RandomTests/st201503181324GO"}
-declare_test!{StateTests_RandomTests_st201503181325GO, "StateTests/RandomTests/st201503181325GO"}
-declare_test!{StateTests_RandomTests_st201503181326CPPJIT, "StateTests/RandomTests/st201503181326CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181326GO, "StateTests/RandomTests/st201503181326GO"}
-declare_test!{StateTests_RandomTests_st201503181327GO, "StateTests/RandomTests/st201503181327GO"}
-declare_test!{StateTests_RandomTests_st201503181329CPPJIT, "StateTests/RandomTests/st201503181329CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181329GO, "StateTests/RandomTests/st201503181329GO"}
-declare_test!{StateTests_RandomTests_st201503181330GO, "StateTests/RandomTests/st201503181330GO"}
-declare_test!{StateTests_RandomTests_st201503181332GO, "StateTests/RandomTests/st201503181332GO"}
-declare_test!{StateTests_RandomTests_st201503181333GO, "StateTests/RandomTests/st201503181333GO"}
-declare_test!{StateTests_RandomTests_st201503181334GO, "StateTests/RandomTests/st201503181334GO"}
-declare_test!{StateTests_RandomTests_st201503181336CPPJIT, "StateTests/RandomTests/st201503181336CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181337GO, "StateTests/RandomTests/st201503181337GO"}
-declare_test!{StateTests_RandomTests_st201503181338GO, "StateTests/RandomTests/st201503181338GO"}
-declare_test!{StateTests_RandomTests_st201503181339CPPJIT, "StateTests/RandomTests/st201503181339CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181339GO, "StateTests/RandomTests/st201503181339GO"}
-declare_test!{StateTests_RandomTests_st201503181340GO, "StateTests/RandomTests/st201503181340GO"}
-declare_test!{StateTests_RandomTests_st201503181341CPPJIT, "StateTests/RandomTests/st201503181341CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181342CPPJIT, "StateTests/RandomTests/st201503181342CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181342GO, "StateTests/RandomTests/st201503181342GO"}
-declare_test!{StateTests_RandomTests_st201503181345GO, "StateTests/RandomTests/st201503181345GO"}
-declare_test!{StateTests_RandomTests_st201503181346GO, "StateTests/RandomTests/st201503181346GO"}
-declare_test!{StateTests_RandomTests_st201503181347CPPJIT, "StateTests/RandomTests/st201503181347CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181347GO, "StateTests/RandomTests/st201503181347GO"}
-declare_test!{StateTests_RandomTests_st201503181347PYTHON, "StateTests/RandomTests/st201503181347PYTHON"}
-declare_test!{StateTests_RandomTests_st201503181350CPPJIT, "StateTests/RandomTests/st201503181350CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181352GO, "StateTests/RandomTests/st201503181352GO"}
-declare_test!{StateTests_RandomTests_st201503181353GO, "StateTests/RandomTests/st201503181353GO"}
-declare_test!{StateTests_RandomTests_st201503181354CPPJIT, "StateTests/RandomTests/st201503181354CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181354GO, "StateTests/RandomTests/st201503181354GO"}
-declare_test!{StateTests_RandomTests_st201503181355GO, "StateTests/RandomTests/st201503181355GO"}
-declare_test!{StateTests_RandomTests_st201503181356CPPJIT, "StateTests/RandomTests/st201503181356CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181357CPPJIT, "StateTests/RandomTests/st201503181357CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181358CPPJIT, "StateTests/RandomTests/st201503181358CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181358GO, "StateTests/RandomTests/st201503181358GO"}
-declare_test!{StateTests_RandomTests_st201503181359GO, "StateTests/RandomTests/st201503181359GO"}
-declare_test!{StateTests_RandomTests_st201503181402CPPJIT, "StateTests/RandomTests/st201503181402CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181403GO, "StateTests/RandomTests/st201503181403GO"}
-declare_test!{StateTests_RandomTests_st201503181406CPPJIT, "StateTests/RandomTests/st201503181406CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181406GO, "StateTests/RandomTests/st201503181406GO"}
-declare_test!{StateTests_RandomTests_st201503181410GO, "StateTests/RandomTests/st201503181410GO"}
-declare_test!{StateTests_RandomTests_st201503181412CPPJIT, "StateTests/RandomTests/st201503181412CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181413GO, "StateTests/RandomTests/st201503181413GO"}
-declare_test!{StateTests_RandomTests_st201503181415GO, "StateTests/RandomTests/st201503181415GO"}
-declare_test!{StateTests_RandomTests_st201503181416GO, "StateTests/RandomTests/st201503181416GO"}
-declare_test!{StateTests_RandomTests_st201503181417CPPJIT, "StateTests/RandomTests/st201503181417CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181417GO, "StateTests/RandomTests/st201503181417GO"}
-declare_test!{StateTests_RandomTests_st201503181418CPPJIT, "StateTests/RandomTests/st201503181418CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181422GO, "StateTests/RandomTests/st201503181422GO"}
-declare_test!{StateTests_RandomTests_st201503181423CPPJIT, "StateTests/RandomTests/st201503181423CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181424GO, "StateTests/RandomTests/st201503181424GO"}
-declare_test!{StateTests_RandomTests_st201503181426CPPJIT, "StateTests/RandomTests/st201503181426CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181426GO, "StateTests/RandomTests/st201503181426GO"}
-declare_test!{StateTests_RandomTests_st201503181428GO, "StateTests/RandomTests/st201503181428GO"}
-declare_test!{StateTests_RandomTests_st201503181430CPPJIT, "StateTests/RandomTests/st201503181430CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181435GO, "StateTests/RandomTests/st201503181435GO"}
-declare_test!{StateTests_RandomTests_st201503181436GO, "StateTests/RandomTests/st201503181436GO"}
-declare_test!{StateTests_RandomTests_st201503181437CPPJIT, "StateTests/RandomTests/st201503181437CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181437GO, "StateTests/RandomTests/st201503181437GO"}
-declare_test!{StateTests_RandomTests_st201503181438CPPJIT, "StateTests/RandomTests/st201503181438CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181438GO, "StateTests/RandomTests/st201503181438GO"}
-declare_test!{StateTests_RandomTests_st201503181439CPPJIT, "StateTests/RandomTests/st201503181439CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181439GO, "StateTests/RandomTests/st201503181439GO"}
-declare_test!{StateTests_RandomTests_st201503181439PYTHON, "StateTests/RandomTests/st201503181439PYTHON"}
-declare_test!{StateTests_RandomTests_st201503181440GO, "StateTests/RandomTests/st201503181440GO"}
-declare_test!{StateTests_RandomTests_st201503181441GO, "StateTests/RandomTests/st201503181441GO"}
-declare_test!{StateTests_RandomTests_st201503181442GO, "StateTests/RandomTests/st201503181442GO"}
-declare_test!{StateTests_RandomTests_st201503181445CPPJIT, "StateTests/RandomTests/st201503181445CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181446GO, "StateTests/RandomTests/st201503181446GO"}
-declare_test!{StateTests_RandomTests_st201503181447GO, "StateTests/RandomTests/st201503181447GO"}
-declare_test!{StateTests_RandomTests_st201503181450GO, "StateTests/RandomTests/st201503181450GO"}
-declare_test!{StateTests_RandomTests_st201503181451CPPJIT, "StateTests/RandomTests/st201503181451CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181453GO, "StateTests/RandomTests/st201503181453GO"}
-declare_test!{StateTests_RandomTests_st201503181455GO, "StateTests/RandomTests/st201503181455GO"}
-declare_test!{StateTests_RandomTests_st201503181456CPPJIT, "StateTests/RandomTests/st201503181456CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181457GO, "StateTests/RandomTests/st201503181457GO"}
-declare_test!{StateTests_RandomTests_st201503181458GO, "StateTests/RandomTests/st201503181458GO"}
-declare_test!{StateTests_RandomTests_st201503181459GO, "StateTests/RandomTests/st201503181459GO"}
-declare_test!{StateTests_RandomTests_st201503181500GO, "StateTests/RandomTests/st201503181500GO"}
-declare_test!{StateTests_RandomTests_st201503181501GO, "StateTests/RandomTests/st201503181501GO"}
-declare_test!{StateTests_RandomTests_st201503181503GO, "StateTests/RandomTests/st201503181503GO"}
-declare_test!{StateTests_RandomTests_st201503181504GO, "StateTests/RandomTests/st201503181504GO"}
-declare_test!{StateTests_RandomTests_st201503181505GO, "StateTests/RandomTests/st201503181505GO"}
-declare_test!{StateTests_RandomTests_st201503181506CPPJIT, "StateTests/RandomTests/st201503181506CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181507GO, "StateTests/RandomTests/st201503181507GO"}
-declare_test!{StateTests_RandomTests_st201503181509CPPJIT, "StateTests/RandomTests/st201503181509CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181509GO, "StateTests/RandomTests/st201503181509GO"}
-declare_test!{StateTests_RandomTests_st201503181510GO, "StateTests/RandomTests/st201503181510GO"}
-declare_test!{StateTests_RandomTests_st201503181511GO, "StateTests/RandomTests/st201503181511GO"}
-declare_test!{StateTests_RandomTests_st201503181512GO, "StateTests/RandomTests/st201503181512GO"}
-declare_test!{StateTests_RandomTests_st201503181513CPPJIT, "StateTests/RandomTests/st201503181513CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181513GO, "StateTests/RandomTests/st201503181513GO"}
-declare_test!{StateTests_RandomTests_st201503181514CPPJIT, "StateTests/RandomTests/st201503181514CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181514GO, "StateTests/RandomTests/st201503181514GO"}
-declare_test!{StateTests_RandomTests_st201503181517CPPJIT, "StateTests/RandomTests/st201503181517CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181517GO, "StateTests/RandomTests/st201503181517GO"}
-declare_test!{StateTests_RandomTests_st201503181519CPPJIT, "StateTests/RandomTests/st201503181519CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181519GO, "StateTests/RandomTests/st201503181519GO"}
-declare_test!{StateTests_RandomTests_st201503181520CPPJIT, "StateTests/RandomTests/st201503181520CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181520GO, "StateTests/RandomTests/st201503181520GO"}
-declare_test!{StateTests_RandomTests_st201503181521GO, "StateTests/RandomTests/st201503181521GO"}
-declare_test!{StateTests_RandomTests_st201503181522GO, "StateTests/RandomTests/st201503181522GO"}
-declare_test!{StateTests_RandomTests_st201503181524CPPJIT, "StateTests/RandomTests/st201503181524CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181524GO, "StateTests/RandomTests/st201503181524GO"}
-declare_test!{StateTests_RandomTests_st201503181526GO, "StateTests/RandomTests/st201503181526GO"}
-declare_test!{StateTests_RandomTests_st201503181527GO, "StateTests/RandomTests/st201503181527GO"}
-declare_test!{StateTests_RandomTests_st201503181528CPPJIT, "StateTests/RandomTests/st201503181528CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181528GO, "StateTests/RandomTests/st201503181528GO"}
-declare_test!{StateTests_RandomTests_st201503181528PYTHON, "StateTests/RandomTests/st201503181528PYTHON"}
-declare_test!{StateTests_RandomTests_st201503181529GO, "StateTests/RandomTests/st201503181529GO"}
-declare_test!{StateTests_RandomTests_st201503181531CPPJIT, "StateTests/RandomTests/st201503181531CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181533GO, "StateTests/RandomTests/st201503181533GO"}
-declare_test!{StateTests_RandomTests_st201503181534CPPJIT, "StateTests/RandomTests/st201503181534CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181534GO, "StateTests/RandomTests/st201503181534GO"}
-declare_test!{StateTests_RandomTests_st201503181536CPPJIT, "StateTests/RandomTests/st201503181536CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181536GO, "StateTests/RandomTests/st201503181536GO"}
-declare_test!{StateTests_RandomTests_st201503181537GO, "StateTests/RandomTests/st201503181537GO"}
-declare_test!{StateTests_RandomTests_st201503181538GO, "StateTests/RandomTests/st201503181538GO"}
-declare_test!{StateTests_RandomTests_st201503181539GO, "StateTests/RandomTests/st201503181539GO"}
-declare_test!{StateTests_RandomTests_st201503181540CPPJIT, "StateTests/RandomTests/st201503181540CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181540PYTHON, "StateTests/RandomTests/st201503181540PYTHON"}
-declare_test!{StateTests_RandomTests_st201503181543GO, "StateTests/RandomTests/st201503181543GO"}
-declare_test!{StateTests_RandomTests_st201503181544CPPJIT, "StateTests/RandomTests/st201503181544CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181544GO, "StateTests/RandomTests/st201503181544GO"}
-declare_test!{StateTests_RandomTests_st201503181547GO, "StateTests/RandomTests/st201503181547GO"}
-declare_test!{StateTests_RandomTests_st201503181548CPPJIT, "StateTests/RandomTests/st201503181548CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181548GO, "StateTests/RandomTests/st201503181548GO"}
-declare_test!{StateTests_RandomTests_st201503181551GO, "StateTests/RandomTests/st201503181551GO"}
-declare_test!{StateTests_RandomTests_st201503181552CPPJIT, "StateTests/RandomTests/st201503181552CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181553GO, "StateTests/RandomTests/st201503181553GO"}
-declare_test!{StateTests_RandomTests_st201503181555CPPJIT, "StateTests/RandomTests/st201503181555CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181555GO, "StateTests/RandomTests/st201503181555GO"}
-declare_test!{StateTests_RandomTests_st201503181557GO, "StateTests/RandomTests/st201503181557GO"}
-declare_test!{StateTests_RandomTests_st201503181559GO, "StateTests/RandomTests/st201503181559GO"}
-declare_test!{StateTests_RandomTests_st201503181601CPPJIT, "StateTests/RandomTests/st201503181601CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181601GO, "StateTests/RandomTests/st201503181601GO"}
-declare_test!{StateTests_RandomTests_st201503181602GO, "StateTests/RandomTests/st201503181602GO"}
-declare_test!{StateTests_RandomTests_st201503181603GO, "StateTests/RandomTests/st201503181603GO"}
-declare_test!{StateTests_RandomTests_st201503181604GO, "StateTests/RandomTests/st201503181604GO"}
-declare_test!{StateTests_RandomTests_st201503181605GO, "StateTests/RandomTests/st201503181605GO"}
-declare_test!{StateTests_RandomTests_st201503181606GO, "StateTests/RandomTests/st201503181606GO"}
-declare_test!{StateTests_RandomTests_st201503181607GO, "StateTests/RandomTests/st201503181607GO"}
-declare_test!{StateTests_RandomTests_st201503181608CPPJIT, "StateTests/RandomTests/st201503181608CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181608GO, "StateTests/RandomTests/st201503181608GO"}
-declare_test!{StateTests_RandomTests_st201503181609GO, "StateTests/RandomTests/st201503181609GO"}
-declare_test!{StateTests_RandomTests_st201503181610CPPJIT, "StateTests/RandomTests/st201503181610CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181610GO, "StateTests/RandomTests/st201503181610GO"}
-declare_test!{StateTests_RandomTests_st201503181611CPPJIT, "StateTests/RandomTests/st201503181611CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181611GO, "StateTests/RandomTests/st201503181611GO"}
-declare_test!{StateTests_RandomTests_st201503181612GO, "StateTests/RandomTests/st201503181612GO"}
-declare_test!{StateTests_RandomTests_st201503181614CPPJIT, "StateTests/RandomTests/st201503181614CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181614GO, "StateTests/RandomTests/st201503181614GO"}
-declare_test!{StateTests_RandomTests_st201503181616CPPJIT, "StateTests/RandomTests/st201503181616CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181616GO, "StateTests/RandomTests/st201503181616GO"}
-declare_test!{StateTests_RandomTests_st201503181617GO, "StateTests/RandomTests/st201503181617GO"}
-declare_test!{StateTests_RandomTests_st201503181618GO, "StateTests/RandomTests/st201503181618GO"}
-declare_test!{StateTests_RandomTests_st201503181619GO, "StateTests/RandomTests/st201503181619GO"}
-declare_test!{StateTests_RandomTests_st201503181620CPPJIT, "StateTests/RandomTests/st201503181620CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181620GO, "StateTests/RandomTests/st201503181620GO"}
-declare_test!{StateTests_RandomTests_st201503181621GO, "StateTests/RandomTests/st201503181621GO"}
-declare_test!{StateTests_RandomTests_st201503181625GO, "StateTests/RandomTests/st201503181625GO"}
-declare_test!{StateTests_RandomTests_st201503181626CPPJIT, "StateTests/RandomTests/st201503181626CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181626GO, "StateTests/RandomTests/st201503181626GO"}
-declare_test!{StateTests_RandomTests_st201503181627GO, "StateTests/RandomTests/st201503181627GO"}
-declare_test!{StateTests_RandomTests_st201503181628GO, "StateTests/RandomTests/st201503181628GO"}
-declare_test!{StateTests_RandomTests_st201503181629GO, "StateTests/RandomTests/st201503181629GO"}
-declare_test!{StateTests_RandomTests_st201503181630CPPJIT, "StateTests/RandomTests/st201503181630CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181630GO, "StateTests/RandomTests/st201503181630GO"}
-declare_test!{StateTests_RandomTests_st201503181630PYTHON, "StateTests/RandomTests/st201503181630PYTHON"}
-declare_test!{StateTests_RandomTests_st201503181632GO, "StateTests/RandomTests/st201503181632GO"}
-declare_test!{StateTests_RandomTests_st201503181634CPPJIT, "StateTests/RandomTests/st201503181634CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181635GO, "StateTests/RandomTests/st201503181635GO"}
-declare_test!{StateTests_RandomTests_st201503181636GO, "StateTests/RandomTests/st201503181636GO"}
-declare_test!{StateTests_RandomTests_st201503181638GO, "StateTests/RandomTests/st201503181638GO"}
-declare_test!{StateTests_RandomTests_st201503181639CPPJIT, "StateTests/RandomTests/st201503181639CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181641GO, "StateTests/RandomTests/st201503181641GO"}
-declare_test!{StateTests_RandomTests_st201503181645GO, "StateTests/RandomTests/st201503181645GO"}
-declare_test!{StateTests_RandomTests_st201503181646GO, "StateTests/RandomTests/st201503181646GO"}
-declare_test!{StateTests_RandomTests_st201503181647CPPJIT, "StateTests/RandomTests/st201503181647CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181649CPPJIT, "StateTests/RandomTests/st201503181649CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181650GO, "StateTests/RandomTests/st201503181650GO"}
-declare_test!{StateTests_RandomTests_st201503181652CPPJIT, "StateTests/RandomTests/st201503181652CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181653GO, "StateTests/RandomTests/st201503181653GO"}
-declare_test!{StateTests_RandomTests_st201503181654GO, "StateTests/RandomTests/st201503181654GO"}
-declare_test!{StateTests_RandomTests_st201503181655CPPJIT, "StateTests/RandomTests/st201503181655CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181655GO, "StateTests/RandomTests/st201503181655GO"}
-declare_test!{StateTests_RandomTests_st201503181656CPPJIT, "StateTests/RandomTests/st201503181656CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181656GO, "StateTests/RandomTests/st201503181656GO"}
-declare_test!{StateTests_RandomTests_st201503181657GO, "StateTests/RandomTests/st201503181657GO"}
-declare_test!{StateTests_RandomTests_st201503181658GO, "StateTests/RandomTests/st201503181658GO"}
-declare_test!{StateTests_RandomTests_st201503181700GO, "StateTests/RandomTests/st201503181700GO"}
-declare_test!{StateTests_RandomTests_st201503181702GO, "StateTests/RandomTests/st201503181702GO"}
-declare_test!{StateTests_RandomTests_st201503181703CPPJIT, "StateTests/RandomTests/st201503181703CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181703GO, "StateTests/RandomTests/st201503181703GO"}
-declare_test!{StateTests_RandomTests_st201503181704GO, "StateTests/RandomTests/st201503181704GO"}
-declare_test!{StateTests_RandomTests_st201503181706GO, "StateTests/RandomTests/st201503181706GO"}
-declare_test!{StateTests_RandomTests_st201503181709GO, "StateTests/RandomTests/st201503181709GO"}
-declare_test!{StateTests_RandomTests_st201503181711CPPJIT, "StateTests/RandomTests/st201503181711CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181711GO, "StateTests/RandomTests/st201503181711GO"}
-declare_test!{StateTests_RandomTests_st201503181713CPPJIT, "StateTests/RandomTests/st201503181713CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181713GO, "StateTests/RandomTests/st201503181713GO"}
-declare_test!{StateTests_RandomTests_st201503181714GO, "StateTests/RandomTests/st201503181714GO"}
-declare_test!{StateTests_RandomTests_st201503181715CPPJIT, "StateTests/RandomTests/st201503181715CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181715GO, "StateTests/RandomTests/st201503181715GO"}
-declare_test!{StateTests_RandomTests_st201503181716GO, "StateTests/RandomTests/st201503181716GO"}
-declare_test!{StateTests_RandomTests_st201503181717GO, "StateTests/RandomTests/st201503181717GO"}
-declare_test!{StateTests_RandomTests_st201503181720CPPJIT, "StateTests/RandomTests/st201503181720CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181722GO, "StateTests/RandomTests/st201503181722GO"}
-declare_test!{StateTests_RandomTests_st201503181723CPPJIT, "StateTests/RandomTests/st201503181723CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181723GO, "StateTests/RandomTests/st201503181723GO"}
-declare_test!{StateTests_RandomTests_st201503181724CPPJIT, "StateTests/RandomTests/st201503181724CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181724GO, "StateTests/RandomTests/st201503181724GO"}
-declare_test!{StateTests_RandomTests_st201503181725GO, "StateTests/RandomTests/st201503181725GO"}
-declare_test!{StateTests_RandomTests_st201503181728GO, "StateTests/RandomTests/st201503181728GO"}
-declare_test!{StateTests_RandomTests_st201503181729GO, "StateTests/RandomTests/st201503181729GO"}
-declare_test!{StateTests_RandomTests_st201503181730GO, "StateTests/RandomTests/st201503181730GO"}
-declare_test!{StateTests_RandomTests_st201503181731CPPJIT, "StateTests/RandomTests/st201503181731CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181732GO, "StateTests/RandomTests/st201503181732GO"}
-declare_test!{StateTests_RandomTests_st201503181734CPPJIT, "StateTests/RandomTests/st201503181734CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181734GO, "StateTests/RandomTests/st201503181734GO"}
-declare_test!{StateTests_RandomTests_st201503181735GO, "StateTests/RandomTests/st201503181735GO"}
-declare_test!{StateTests_RandomTests_st201503181737CPPJIT, "StateTests/RandomTests/st201503181737CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181737GO, "StateTests/RandomTests/st201503181737GO"}
-declare_test!{StateTests_RandomTests_st201503181738CPPJIT, "StateTests/RandomTests/st201503181738CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181738GO, "StateTests/RandomTests/st201503181738GO"}
-declare_test!{StateTests_RandomTests_st201503181739GO, "StateTests/RandomTests/st201503181739GO"}
-declare_test!{StateTests_RandomTests_st201503181740CPPJIT, "StateTests/RandomTests/st201503181740CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181740GO, "StateTests/RandomTests/st201503181740GO"}
-declare_test!{StateTests_RandomTests_st201503181742CPPJIT, "StateTests/RandomTests/st201503181742CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181743GO, "StateTests/RandomTests/st201503181743GO"}
-declare_test!{StateTests_RandomTests_st201503181744GO, "StateTests/RandomTests/st201503181744GO"}
-declare_test!{StateTests_RandomTests_st201503181745CPPJIT, "StateTests/RandomTests/st201503181745CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181746GO, "StateTests/RandomTests/st201503181746GO"}
-declare_test!{StateTests_RandomTests_st201503181747GO, "StateTests/RandomTests/st201503181747GO"}
-declare_test!{StateTests_RandomTests_st201503181748GO, "StateTests/RandomTests/st201503181748GO"}
-declare_test!{StateTests_RandomTests_st201503181749GO, "StateTests/RandomTests/st201503181749GO"}
-declare_test!{StateTests_RandomTests_st201503181750CPPJIT, "StateTests/RandomTests/st201503181750CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181750GO, "StateTests/RandomTests/st201503181750GO"}
-declare_test!{StateTests_RandomTests_st201503181752GO, "StateTests/RandomTests/st201503181752GO"}
-declare_test!{StateTests_RandomTests_st201503181753CPPJIT, "StateTests/RandomTests/st201503181753CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181754CPPJIT, "StateTests/RandomTests/st201503181754CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181754GO, "StateTests/RandomTests/st201503181754GO"}
-declare_test!{StateTests_RandomTests_st201503181755CPPJIT, "StateTests/RandomTests/st201503181755CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181755GO, "StateTests/RandomTests/st201503181755GO"}
-declare_test!{StateTests_RandomTests_st201503181756GO, "StateTests/RandomTests/st201503181756GO"}
-declare_test!{StateTests_RandomTests_st201503181757CPPJIT, "StateTests/RandomTests/st201503181757CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181757GO, "StateTests/RandomTests/st201503181757GO"}
-declare_test!{StateTests_RandomTests_st201503181759GO, "StateTests/RandomTests/st201503181759GO"}
-declare_test!{StateTests_RandomTests_st201503181800GO, "StateTests/RandomTests/st201503181800GO"}
-declare_test!{StateTests_RandomTests_st201503181801GO, "StateTests/RandomTests/st201503181801GO"}
-declare_test!{StateTests_RandomTests_st201503181802GO, "StateTests/RandomTests/st201503181802GO"}
-declare_test!{StateTests_RandomTests_st201503181803CPPJIT, "StateTests/RandomTests/st201503181803CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181803GO, "StateTests/RandomTests/st201503181803GO"}
-declare_test!{StateTests_RandomTests_st201503181804GO, "StateTests/RandomTests/st201503181804GO"}
-declare_test!{StateTests_RandomTests_st201503181806GO, "StateTests/RandomTests/st201503181806GO"}
-declare_test!{StateTests_RandomTests_st201503181808GO, "StateTests/RandomTests/st201503181808GO"}
-declare_test!{StateTests_RandomTests_st201503181809CPPJIT, "StateTests/RandomTests/st201503181809CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181812CPPJIT, "StateTests/RandomTests/st201503181812CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181812GO, "StateTests/RandomTests/st201503181812GO"}
-declare_test!{StateTests_RandomTests_st201503181814CPPJIT, "StateTests/RandomTests/st201503181814CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181815GO, "StateTests/RandomTests/st201503181815GO"}
-declare_test!{StateTests_RandomTests_st201503181816CPPJIT, "StateTests/RandomTests/st201503181816CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181817CPPJIT, "StateTests/RandomTests/st201503181817CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181819GO, "StateTests/RandomTests/st201503181819GO"}
-declare_test!{StateTests_RandomTests_st201503181821GO, "StateTests/RandomTests/st201503181821GO"}
-declare_test!{StateTests_RandomTests_st201503181822GO, "StateTests/RandomTests/st201503181822GO"}
-declare_test!{StateTests_RandomTests_st201503181823GO, "StateTests/RandomTests/st201503181823GO"}
-declare_test!{StateTests_RandomTests_st201503181824GO, "StateTests/RandomTests/st201503181824GO"}
-declare_test!{StateTests_RandomTests_st201503181825GO, "StateTests/RandomTests/st201503181825GO"}
-declare_test!{StateTests_RandomTests_st201503181829GO, "StateTests/RandomTests/st201503181829GO"}
-declare_test!{StateTests_RandomTests_st201503181830CPPJIT, "StateTests/RandomTests/st201503181830CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181833GO, "StateTests/RandomTests/st201503181833GO"}
-declare_test!{StateTests_RandomTests_st201503181834CPPJIT, "StateTests/RandomTests/st201503181834CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181834GO, "StateTests/RandomTests/st201503181834GO"}
-declare_test!{StateTests_RandomTests_st201503181837GO, "StateTests/RandomTests/st201503181837GO"}
-declare_test!{StateTests_RandomTests_st201503181840GO, "StateTests/RandomTests/st201503181840GO"}
-declare_test!{StateTests_RandomTests_st201503181842GO, "StateTests/RandomTests/st201503181842GO"}
-declare_test!{StateTests_RandomTests_st201503181843GO, "StateTests/RandomTests/st201503181843GO"}
-declare_test!{StateTests_RandomTests_st201503181844GO, "StateTests/RandomTests/st201503181844GO"}
-declare_test!{StateTests_RandomTests_st201503181845GO, "StateTests/RandomTests/st201503181845GO"}
-declare_test!{StateTests_RandomTests_st201503181846GO, "StateTests/RandomTests/st201503181846GO"}
-declare_test!{StateTests_RandomTests_st201503181847GO, "StateTests/RandomTests/st201503181847GO"}
-declare_test!{StateTests_RandomTests_st201503181848GO, "StateTests/RandomTests/st201503181848GO"}
-declare_test!{StateTests_RandomTests_st201503181849GO, "StateTests/RandomTests/st201503181849GO"}
-declare_test!{StateTests_RandomTests_st201503181850GO, "StateTests/RandomTests/st201503181850GO"}
-declare_test!{StateTests_RandomTests_st201503181851CPPJIT, "StateTests/RandomTests/st201503181851CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181851GO, "StateTests/RandomTests/st201503181851GO"}
-declare_test!{StateTests_RandomTests_st201503181852CPPJIT, "StateTests/RandomTests/st201503181852CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181854GO, "StateTests/RandomTests/st201503181854GO"}
-declare_test!{StateTests_RandomTests_st201503181855CPPJIT, "StateTests/RandomTests/st201503181855CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181857PYTHON, "StateTests/RandomTests/st201503181857PYTHON"}
-declare_test!{StateTests_RandomTests_st201503181859GO, "StateTests/RandomTests/st201503181859GO"}
-declare_test!{StateTests_RandomTests_st201503181900GO, "StateTests/RandomTests/st201503181900GO"}
-declare_test!{StateTests_RandomTests_st201503181903GO, "StateTests/RandomTests/st201503181903GO"}
-declare_test!{StateTests_RandomTests_st201503181904GO, "StateTests/RandomTests/st201503181904GO"}
-declare_test!{StateTests_RandomTests_st201503181906GO, "StateTests/RandomTests/st201503181906GO"}
-declare_test!{StateTests_RandomTests_st201503181907GO, "StateTests/RandomTests/st201503181907GO"}
-declare_test!{StateTests_RandomTests_st201503181910GO, "StateTests/RandomTests/st201503181910GO"}
-declare_test!{StateTests_RandomTests_st201503181915GO, "StateTests/RandomTests/st201503181915GO"}
-declare_test!{StateTests_RandomTests_st201503181919CPPJIT, "StateTests/RandomTests/st201503181919CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181919PYTHON, "StateTests/RandomTests/st201503181919PYTHON"}
-declare_test!{StateTests_RandomTests_st201503181920GO, "StateTests/RandomTests/st201503181920GO"}
-declare_test!{StateTests_RandomTests_st201503181922GO, "StateTests/RandomTests/st201503181922GO"}
-declare_test!{StateTests_RandomTests_st201503181926GO, "StateTests/RandomTests/st201503181926GO"}
-declare_test!{StateTests_RandomTests_st201503181929GO, "StateTests/RandomTests/st201503181929GO"}
-declare_test!{StateTests_RandomTests_st201503181931CPPJIT, "StateTests/RandomTests/st201503181931CPPJIT"}
-declare_test!{StateTests_RandomTests_st201503181931GO, "StateTests/RandomTests/st201503181931GO"}
-declare_test!{StateTests_RandomTests_st201503181931PYTHON, "StateTests/RandomTests/st201503181931PYTHON"}
-declare_test!{StateTests_RandomTests_st201503191646GO, "StateTests/RandomTests/st201503191646GO"}
-declare_test!{StateTests_RandomTests_st201503200837JS, "StateTests/RandomTests/st201503200837JS"}
-declare_test!{StateTests_RandomTests_st201503200838JS, "StateTests/RandomTests/st201503200838JS"}
-declare_test!{StateTests_RandomTests_st201503200841JS, "StateTests/RandomTests/st201503200841JS"}
-declare_test!{StateTests_RandomTests_st201503200848JS, "StateTests/RandomTests/st201503200848JS"}
-declare_test!{StateTests_RandomTests_st201503240609JS, "StateTests/RandomTests/st201503240609JS"}
-declare_test!{StateTests_RandomTests_st201503302200JS, "StateTests/RandomTests/st201503302200JS"}
-declare_test!{StateTests_RandomTests_st201503302202JS, "StateTests/RandomTests/st201503302202JS"}
-declare_test!{StateTests_RandomTests_st201503302206JS, "StateTests/RandomTests/st201503302206JS"}
-declare_test!{StateTests_RandomTests_st201503302208JS, "StateTests/RandomTests/st201503302208JS"}
-declare_test!{StateTests_RandomTests_st201503302210JS, "StateTests/RandomTests/st201503302210JS"}
-declare_test!{StateTests_RandomTests_st201503302211JS, "StateTests/RandomTests/st201503302211JS"}
-declare_test!{StateTests_RandomTests_st201504011535GO, "StateTests/RandomTests/st201504011535GO"}
-declare_test!{StateTests_RandomTests_st201504011536GO, "StateTests/RandomTests/st201504011536GO"}
-declare_test!{StateTests_RandomTests_st201504011547GO, "StateTests/RandomTests/st201504011547GO"}
-declare_test!{StateTests_RandomTests_st201504011916JS, "StateTests/RandomTests/st201504011916JS"}
-declare_test!{StateTests_RandomTests_st201504012130JS, "StateTests/RandomTests/st201504012130JS"}
-declare_test!{StateTests_RandomTests_st201504012259JS, "StateTests/RandomTests/st201504012259JS"}
-declare_test!{StateTests_RandomTests_st201504012359JS, "StateTests/RandomTests/st201504012359JS"}
-declare_test!{StateTests_RandomTests_st201504020305JS, "StateTests/RandomTests/st201504020305JS"}
-declare_test!{StateTests_RandomTests_st201504020400JS, "StateTests/RandomTests/st201504020400JS"}
-declare_test!{StateTests_RandomTests_st201504020428JS, "StateTests/RandomTests/st201504020428JS"}
-declare_test!{StateTests_RandomTests_st201504020431JS, "StateTests/RandomTests/st201504020431JS"}
-declare_test!{StateTests_RandomTests_st201504020444JS, "StateTests/RandomTests/st201504020444JS"}
-declare_test!{StateTests_RandomTests_st201504020538JS, "StateTests/RandomTests/st201504020538JS"}
-declare_test!{StateTests_RandomTests_st201504020639JS, "StateTests/RandomTests/st201504020639JS"}
-declare_test!{StateTests_RandomTests_st201504020836JS, "StateTests/RandomTests/st201504020836JS"}
-declare_test!{StateTests_RandomTests_st201504020910JS, "StateTests/RandomTests/st201504020910JS"}
-declare_test!{StateTests_RandomTests_st201504021057JS, "StateTests/RandomTests/st201504021057JS"}
-declare_test!{StateTests_RandomTests_st201504021104JS, "StateTests/RandomTests/st201504021104JS"}
-declare_test!{StateTests_RandomTests_st201504021237CPPJIT, "StateTests/RandomTests/st201504021237CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504021237GO, "StateTests/RandomTests/st201504021237GO"}
-declare_test!{StateTests_RandomTests_st201504021237JS, "StateTests/RandomTests/st201504021237JS"}
-declare_test!{StateTests_RandomTests_st201504021237PYTHON, "StateTests/RandomTests/st201504021237PYTHON"}
-declare_test!{StateTests_RandomTests_st201504021949JS, "StateTests/RandomTests/st201504021949JS"}
-declare_test!{StateTests_RandomTests_st201504022003CPPJIT, "StateTests/RandomTests/st201504022003CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504022124JS, "StateTests/RandomTests/st201504022124JS"}
-declare_test!{StateTests_RandomTests_st201504030138JS, "StateTests/RandomTests/st201504030138JS"}
-declare_test!{StateTests_RandomTests_st201504030646JS, "StateTests/RandomTests/st201504030646JS"}
-declare_test!{StateTests_RandomTests_st201504030709JS, "StateTests/RandomTests/st201504030709JS"}
-declare_test!{StateTests_RandomTests_st201504031133JS, "StateTests/RandomTests/st201504031133JS"}
-declare_test!{StateTests_RandomTests_st201504031446JS, "StateTests/RandomTests/st201504031446JS"}
-declare_test!{StateTests_RandomTests_st201504031841JS, "StateTests/RandomTests/st201504031841JS"}
-declare_test!{StateTests_RandomTests_st201504041605JS, "StateTests/RandomTests/st201504041605JS"}
-declare_test!{StateTests_RandomTests_st201504042052JS, "StateTests/RandomTests/st201504042052JS"}
-declare_test!{StateTests_RandomTests_st201504042226CPPJIT, "StateTests/RandomTests/st201504042226CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504042355CPPJIT, "StateTests/RandomTests/st201504042355CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504050059JS, "StateTests/RandomTests/st201504050059JS"}
-declare_test!{StateTests_RandomTests_st201504050733JS, "StateTests/RandomTests/st201504050733JS"}
-declare_test!{StateTests_RandomTests_st201504051540JS, "StateTests/RandomTests/st201504051540JS"}
-declare_test!{StateTests_RandomTests_st201504051944CPPJIT, "StateTests/RandomTests/st201504051944CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504052008CPPJIT, "StateTests/RandomTests/st201504052008CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504052014GO, "StateTests/RandomTests/st201504052014GO"}
-declare_test!{StateTests_RandomTests_st201504052031CPPJIT, "StateTests/RandomTests/st201504052031CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504060057CPPJIT, "StateTests/RandomTests/st201504060057CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504060418CPPJIT, "StateTests/RandomTests/st201504060418CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504061106CPPJIT, "StateTests/RandomTests/st201504061106CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504061134CPPJIT, "StateTests/RandomTests/st201504061134CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504062033CPPJIT, "StateTests/RandomTests/st201504062033CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504062046CPPJIT, "StateTests/RandomTests/st201504062046CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504062314CPPJIT, "StateTests/RandomTests/st201504062314CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504070746JS, "StateTests/RandomTests/st201504070746JS"}
-declare_test!{StateTests_RandomTests_st201504070816CPPJIT, "StateTests/RandomTests/st201504070816CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504070836CPPJIT, "StateTests/RandomTests/st201504070836CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504070839CPPJIT, "StateTests/RandomTests/st201504070839CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504071041CPPJIT, "StateTests/RandomTests/st201504071041CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504071056CPPJIT, "StateTests/RandomTests/st201504071056CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504071621CPPJIT, "StateTests/RandomTests/st201504071621CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504071653CPPJIT, "StateTests/RandomTests/st201504071653CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504071750CPPJIT, "StateTests/RandomTests/st201504071750CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504071905CPPJIT, "StateTests/RandomTests/st201504071905CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504080454CPPJIT, "StateTests/RandomTests/st201504080454CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504080457CPPJIT, "StateTests/RandomTests/st201504080457CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504080650CPPJIT, "StateTests/RandomTests/st201504080650CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504080840CPPJIT, "StateTests/RandomTests/st201504080840CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504080948CPPJIT, "StateTests/RandomTests/st201504080948CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504081100CPPJIT, "StateTests/RandomTests/st201504081100CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504081134CPPJIT, "StateTests/RandomTests/st201504081134CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504081138CPPJIT, "StateTests/RandomTests/st201504081138CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504081611CPPJIT, "StateTests/RandomTests/st201504081611CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504081841JAVA, "StateTests/RandomTests/st201504081841JAVA"}
-declare_test!{StateTests_RandomTests_st201504081842JAVA, "StateTests/RandomTests/st201504081842JAVA"}
-declare_test!{StateTests_RandomTests_st201504081843JAVA, "StateTests/RandomTests/st201504081843JAVA"}
-declare_test!{StateTests_RandomTests_st201504081928CPPJIT, "StateTests/RandomTests/st201504081928CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504081953JAVA, "StateTests/RandomTests/st201504081953JAVA"}
-declare_test!{StateTests_RandomTests_st201504081954JAVA, "StateTests/RandomTests/st201504081954JAVA"}
-declare_test!{StateTests_RandomTests_st201504081955JAVA, "StateTests/RandomTests/st201504081955JAVA"}
-declare_test!{StateTests_RandomTests_st201504081956JAVA, "StateTests/RandomTests/st201504081956JAVA"}
-declare_test!{StateTests_RandomTests_st201504081957JAVA, "StateTests/RandomTests/st201504081957JAVA"}
-declare_test!{StateTests_RandomTests_st201504082000JAVA, "StateTests/RandomTests/st201504082000JAVA"}
-declare_test!{StateTests_RandomTests_st201504082001JAVA, "StateTests/RandomTests/st201504082001JAVA"}
-declare_test!{StateTests_RandomTests_st201504082002JAVA, "StateTests/RandomTests/st201504082002JAVA"}
-declare_test!{StateTests_RandomTests_st201504090553CPPJIT, "StateTests/RandomTests/st201504090553CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504090657CPPJIT, "StateTests/RandomTests/st201504090657CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504091403CPPJIT, "StateTests/RandomTests/st201504091403CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504091641CPPJIT, "StateTests/RandomTests/st201504091641CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504092303CPPJIT, "StateTests/RandomTests/st201504092303CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504100125CPPJIT, "StateTests/RandomTests/st201504100125CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504100215CPPJIT, "StateTests/RandomTests/st201504100215CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504100226PYTHON, "StateTests/RandomTests/st201504100226PYTHON"}
-declare_test!{StateTests_RandomTests_st201504100308CPPJIT, "StateTests/RandomTests/st201504100308CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504100337CPPJIT, "StateTests/RandomTests/st201504100337CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504100341CPPJIT, "StateTests/RandomTests/st201504100341CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504101009CPPJIT, "StateTests/RandomTests/st201504101009CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504101150CPPJIT, "StateTests/RandomTests/st201504101150CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504101223CPPJIT, "StateTests/RandomTests/st201504101223CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504101338CPPJIT, "StateTests/RandomTests/st201504101338CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504101754PYTHON, "StateTests/RandomTests/st201504101754PYTHON"}
-declare_test!{StateTests_RandomTests_st201504111554CPPJIT, "StateTests/RandomTests/st201504111554CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504130653JS, "StateTests/RandomTests/st201504130653JS"}
-declare_test!{StateTests_RandomTests_st201504131821CPPJIT, "StateTests/RandomTests/st201504131821CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504140229CPPJIT, "StateTests/RandomTests/st201504140229CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504140236CPPJIT, "StateTests/RandomTests/st201504140236CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504140359CPPJIT, "StateTests/RandomTests/st201504140359CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504140750CPPJIT, "StateTests/RandomTests/st201504140750CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504140818CPPJIT, "StateTests/RandomTests/st201504140818CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504140900CPPJIT, "StateTests/RandomTests/st201504140900CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504150854CPPJIT, "StateTests/RandomTests/st201504150854CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504151057CPPJIT, "StateTests/RandomTests/st201504151057CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504202124CPPJIT, "StateTests/RandomTests/st201504202124CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504210245CPPJIT, "StateTests/RandomTests/st201504210245CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504210957CPPJIT, "StateTests/RandomTests/st201504210957CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504211739CPPJIT, "StateTests/RandomTests/st201504211739CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504212038CPPJIT, "StateTests/RandomTests/st201504212038CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504230729CPPJIT, "StateTests/RandomTests/st201504230729CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504231639CPPJIT, "StateTests/RandomTests/st201504231639CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504231710CPPJIT, "StateTests/RandomTests/st201504231710CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504231742CPPJIT, "StateTests/RandomTests/st201504231742CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504232350CPPJIT, "StateTests/RandomTests/st201504232350CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504240140CPPJIT, "StateTests/RandomTests/st201504240140CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504240220CPPJIT, "StateTests/RandomTests/st201504240220CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504240351CPPJIT, "StateTests/RandomTests/st201504240351CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504240817CPPJIT, "StateTests/RandomTests/st201504240817CPPJIT"}
-declare_test!{StateTests_RandomTests_st201504241118CPPJIT, "StateTests/RandomTests/st201504241118CPPJIT"}
-declare_test!{StateTests_RandomTests_st201505021810CPPJIT, "StateTests/RandomTests/st201505021810CPPJIT"}
-declare_test!{StateTests_RandomTests_st201505050557JS, "StateTests/RandomTests/st201505050557JS"}
-declare_test!{StateTests_RandomTests_st201505050929GO, "StateTests/RandomTests/st201505050929GO"}
-declare_test!{StateTests_RandomTests_st201505050942PYTHON, "StateTests/RandomTests/st201505050942PYTHON"}
-declare_test!{StateTests_RandomTests_st201505051004PYTHON, "StateTests/RandomTests/st201505051004PYTHON"}
-declare_test!{StateTests_RandomTests_st201505051016PYTHON, "StateTests/RandomTests/st201505051016PYTHON"}
-declare_test!{StateTests_RandomTests_st201505051114GO, "StateTests/RandomTests/st201505051114GO"}
-declare_test!{StateTests_RandomTests_st201505051238GO, "StateTests/RandomTests/st201505051238GO"}
-declare_test!{StateTests_RandomTests_st201505051249GO, "StateTests/RandomTests/st201505051249GO"}
-declare_test!{StateTests_RandomTests_st201505051558PYTHON, "StateTests/RandomTests/st201505051558PYTHON"}
-declare_test!{StateTests_RandomTests_st201505051611PYTHON, "StateTests/RandomTests/st201505051611PYTHON"}
-declare_test!{StateTests_RandomTests_st201505051648JS, "StateTests/RandomTests/st201505051648JS"}
-declare_test!{StateTests_RandomTests_st201505051710GO, "StateTests/RandomTests/st201505051710GO"}
-declare_test!{StateTests_RandomTests_st201505052013GO, "StateTests/RandomTests/st201505052013GO"}
-declare_test!{StateTests_RandomTests_st201505052102JS, "StateTests/RandomTests/st201505052102JS"}
-declare_test!{StateTests_RandomTests_st201505052235GO, "StateTests/RandomTests/st201505052235GO"}
-declare_test!{StateTests_RandomTests_st201505052238JS, "StateTests/RandomTests/st201505052238JS"}
-declare_test!{StateTests_RandomTests_st201505052242PYTHON, "StateTests/RandomTests/st201505052242PYTHON"}
-declare_test!{StateTests_RandomTests_st201505052343PYTHON, "StateTests/RandomTests/st201505052343PYTHON"}
-declare_test!{StateTests_RandomTests_st201505060120GO, "StateTests/RandomTests/st201505060120GO"}
-declare_test!{StateTests_RandomTests_st201505060121GO, "StateTests/RandomTests/st201505060121GO"}
-declare_test!{StateTests_RandomTests_st201505060136PYTHON, "StateTests/RandomTests/st201505060136PYTHON"}
-declare_test!{StateTests_RandomTests_st201505060646JS, "StateTests/RandomTests/st201505060646JS"}
-declare_test!{StateTests_RandomTests_st201505252314CPPJIT, "StateTests/RandomTests/st201505252314CPPJIT"}
-declare_test!{StateTests_RandomTests_st201505272131CPPJIT, "StateTests/RandomTests/st201505272131CPPJIT"}
-declare_test!{StateTests_RandomTests_st201506040034GO, "StateTests/RandomTests/st201506040034GO"}
-declare_test!{StateTests_RandomTests_st201506040157GO, "StateTests/RandomTests/st201506040157GO"}
-declare_test!{StateTests_RandomTests_st201506052130GO, "StateTests/RandomTests/st201506052130GO"}
-declare_test!{StateTests_RandomTests_st201506060929GO, "StateTests/RandomTests/st201506060929GO"}
-declare_test!{StateTests_RandomTests_st201506061255GO, "StateTests/RandomTests/st201506061255GO"}
-declare_test!{StateTests_RandomTests_st201506062331GO, "StateTests/RandomTests/st201506062331GO"}
-declare_test!{StateTests_RandomTests_st201506070548GO, "StateTests/RandomTests/st201506070548GO"}
-declare_test!{StateTests_RandomTests_st201506071050GO, "StateTests/RandomTests/st201506071050GO"}
-declare_test!{StateTests_RandomTests_st201506071624GO, "StateTests/RandomTests/st201506071624GO"}
-declare_test!{StateTests_RandomTests_st201506071819GO, "StateTests/RandomTests/st201506071819GO"}
-declare_test!{StateTests_RandomTests_st201506072007GO, "StateTests/RandomTests/st201506072007GO"}
-declare_test!{StateTests_RandomTests_st201506080556GO, "StateTests/RandomTests/st201506080556GO"}
-declare_test!{StateTests_RandomTests_st201506080721GO, "StateTests/RandomTests/st201506080721GO"}
-declare_test!{StateTests_RandomTests_st201506091836GO, "StateTests/RandomTests/st201506091836GO"}
-declare_test!{StateTests_RandomTests_st201506092032GO, "StateTests/RandomTests/st201506092032GO"}
-declare_test!{StateTests_RandomTests_st201506101359JS, "StateTests/RandomTests/st201506101359JS"}
-declare_test!{StateTests_RandomTests_st201507030359GO, "StateTests/RandomTests/st201507030359GO"}
+ declare_test!{StateTests_stBlockHashTest, "StateTests/stBlockHashTest"}
+ declare_test!{StateTests_stCallCodes, "StateTests/stCallCodes"}
+ declare_test!{StateTests_stCallCreateCallCodeTest, "StateTests/stCallCreateCallCodeTest"}
+ declare_test!{StateTests_stExample, "StateTests/stExample"}
+ declare_test!{StateTests_stInitCodeTest, "StateTests/stInitCodeTest"}
+ declare_test!{StateTests_stLogTests, "StateTests/stLogTests"}
+ declare_test!{heavy => StateTests_stMemoryStressTest, "StateTests/stMemoryStressTest"}
+ declare_test!{heavy => StateTests_stMemoryTest, "StateTests/stMemoryTest"}
+ declare_test!{StateTests_stPreCompiledContracts, "StateTests/stPreCompiledContracts"}
+ declare_test!{heavy => StateTests_stQuadraticComplexityTest, "StateTests/stQuadraticComplexityTest"}
+ declare_test!{StateTests_stRecursiveCreate, "StateTests/stRecursiveCreate"}
+ declare_test!{StateTests_stRefundTest, "StateTests/stRefundTest"}
+ declare_test!{StateTests_stSolidityTest, "StateTests/stSolidityTest"}
+ declare_test!{StateTests_stSpecialTest, "StateTests/stSpecialTest"}
+ declare_test!{StateTests_stSystemOperationsTest, "StateTests/stSystemOperationsTest"}
+ declare_test!{StateTests_stTransactionTest, "StateTests/stTransactionTest"}
+ declare_test!{StateTests_stTransitionTest, "StateTests/stTransitionTest"}
+ declare_test!{StateTests_stWalletTest, "StateTests/stWalletTest"}
+
+ declare_test!{StateTests_RandomTests_st201503121803PYTHON, "StateTests/RandomTests/st201503121803PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503121806PYTHON, "StateTests/RandomTests/st201503121806PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503121848GO, "StateTests/RandomTests/st201503121848GO"}
+ declare_test!{StateTests_RandomTests_st201503121849GO, "StateTests/RandomTests/st201503121849GO"}
+ declare_test!{StateTests_RandomTests_st201503121850GO, "StateTests/RandomTests/st201503121850GO"}
+ declare_test!{StateTests_RandomTests_st201503121851GO, "StateTests/RandomTests/st201503121851GO"}
+ declare_test!{StateTests_RandomTests_st201503121953GO, "StateTests/RandomTests/st201503121953GO"}
+ declare_test!{StateTests_RandomTests_st201503122023GO, "StateTests/RandomTests/st201503122023GO"}
+ declare_test!{StateTests_RandomTests_st201503122023PYTHON, "StateTests/RandomTests/st201503122023PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503122027GO, "StateTests/RandomTests/st201503122027GO"}
+ declare_test!{StateTests_RandomTests_st201503122054GO, "StateTests/RandomTests/st201503122054GO"}
+ declare_test!{StateTests_RandomTests_st201503122055GO, "StateTests/RandomTests/st201503122055GO"}
+ declare_test!{StateTests_RandomTests_st201503122115CPPJIT, "StateTests/RandomTests/st201503122115CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503122115GO, "StateTests/RandomTests/st201503122115GO"}
+ declare_test!{StateTests_RandomTests_st201503122123GO, "StateTests/RandomTests/st201503122123GO"}
+ declare_test!{StateTests_RandomTests_st201503122124GO, "StateTests/RandomTests/st201503122124GO"}
+ declare_test!{StateTests_RandomTests_st201503122128PYTHON, "StateTests/RandomTests/st201503122128PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503122140GO, "StateTests/RandomTests/st201503122140GO"}
+ declare_test!{StateTests_RandomTests_st201503122159GO, "StateTests/RandomTests/st201503122159GO"}
+ declare_test!{StateTests_RandomTests_st201503122204GO, "StateTests/RandomTests/st201503122204GO"}
+ declare_test!{StateTests_RandomTests_st201503122212GO, "StateTests/RandomTests/st201503122212GO"}
+ declare_test!{StateTests_RandomTests_st201503122231GO, "StateTests/RandomTests/st201503122231GO"}
+ declare_test!{StateTests_RandomTests_st201503122238GO, "StateTests/RandomTests/st201503122238GO"}
+ declare_test!{StateTests_RandomTests_st201503122252GO, "StateTests/RandomTests/st201503122252GO"}
+ declare_test!{StateTests_RandomTests_st201503122316GO, "StateTests/RandomTests/st201503122316GO"}
+ declare_test!{StateTests_RandomTests_st201503122324GO, "StateTests/RandomTests/st201503122324GO"}
+ declare_test!{StateTests_RandomTests_st201503122358GO, "StateTests/RandomTests/st201503122358GO"}
+ declare_test!{StateTests_RandomTests_st201503130002GO, "StateTests/RandomTests/st201503130002GO"}
+ declare_test!{StateTests_RandomTests_st201503130005GO, "StateTests/RandomTests/st201503130005GO"}
+ declare_test!{StateTests_RandomTests_st201503130007GO, "StateTests/RandomTests/st201503130007GO"}
+ declare_test!{StateTests_RandomTests_st201503130010GO, "StateTests/RandomTests/st201503130010GO"}
+ declare_test!{StateTests_RandomTests_st201503130023PYTHON, "StateTests/RandomTests/st201503130023PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503130059GO, "StateTests/RandomTests/st201503130059GO"}
+ declare_test!{StateTests_RandomTests_st201503130101GO, "StateTests/RandomTests/st201503130101GO"}
+ declare_test!{StateTests_RandomTests_st201503130109GO, "StateTests/RandomTests/st201503130109GO"}
+ declare_test!{StateTests_RandomTests_st201503130117GO, "StateTests/RandomTests/st201503130117GO"}
+ declare_test!{StateTests_RandomTests_st201503130122GO, "StateTests/RandomTests/st201503130122GO"}
+ declare_test!{StateTests_RandomTests_st201503130156GO, "StateTests/RandomTests/st201503130156GO"}
+ declare_test!{StateTests_RandomTests_st201503130156PYTHON, "StateTests/RandomTests/st201503130156PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503130207GO, "StateTests/RandomTests/st201503130207GO"}
+ declare_test!{StateTests_RandomTests_st201503130219CPPJIT, "StateTests/RandomTests/st201503130219CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503130219GO, "StateTests/RandomTests/st201503130219GO"}
+ declare_test!{StateTests_RandomTests_st201503130243GO, "StateTests/RandomTests/st201503130243GO"}
+ declare_test!{StateTests_RandomTests_st201503130246GO, "StateTests/RandomTests/st201503130246GO"}
+ declare_test!{StateTests_RandomTests_st201503130321GO, "StateTests/RandomTests/st201503130321GO"}
+ declare_test!{StateTests_RandomTests_st201503130322GO, "StateTests/RandomTests/st201503130322GO"}
+ declare_test!{StateTests_RandomTests_st201503130332GO, "StateTests/RandomTests/st201503130332GO"}
+ declare_test!{StateTests_RandomTests_st201503130359GO, "StateTests/RandomTests/st201503130359GO"}
+ declare_test!{StateTests_RandomTests_st201503130405GO, "StateTests/RandomTests/st201503130405GO"}
+ declare_test!{StateTests_RandomTests_st201503130408GO, "StateTests/RandomTests/st201503130408GO"}
+ declare_test!{StateTests_RandomTests_st201503130411GO, "StateTests/RandomTests/st201503130411GO"}
+ declare_test!{StateTests_RandomTests_st201503130431GO, "StateTests/RandomTests/st201503130431GO"}
+ declare_test!{StateTests_RandomTests_st201503130437GO, "StateTests/RandomTests/st201503130437GO"}
+ declare_test!{StateTests_RandomTests_st201503130450GO, "StateTests/RandomTests/st201503130450GO"}
+ declare_test!{StateTests_RandomTests_st201503130512CPPJIT, "StateTests/RandomTests/st201503130512CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503130512GO, "StateTests/RandomTests/st201503130512GO"}
+ declare_test!{StateTests_RandomTests_st201503130615GO, "StateTests/RandomTests/st201503130615GO"}
+ declare_test!{StateTests_RandomTests_st201503130705GO, "StateTests/RandomTests/st201503130705GO"}
+ declare_test!{StateTests_RandomTests_st201503130733CPPJIT, "StateTests/RandomTests/st201503130733CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503130733GO, "StateTests/RandomTests/st201503130733GO"}
+ declare_test!{StateTests_RandomTests_st201503130747GO, "StateTests/RandomTests/st201503130747GO"}
+ declare_test!{StateTests_RandomTests_st201503130751GO, "StateTests/RandomTests/st201503130751GO"}
+ declare_test!{StateTests_RandomTests_st201503130752PYTHON, "StateTests/RandomTests/st201503130752PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503130757PYTHON, "StateTests/RandomTests/st201503130757PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503131658GO, "StateTests/RandomTests/st201503131658GO"}
+ declare_test!{StateTests_RandomTests_st201503131739GO, "StateTests/RandomTests/st201503131739GO"}
+ declare_test!{StateTests_RandomTests_st201503131755CPPJIT, "StateTests/RandomTests/st201503131755CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503131755GO, "StateTests/RandomTests/st201503131755GO"}
+ declare_test!{StateTests_RandomTests_st201503132001CPPJIT, "StateTests/RandomTests/st201503132001CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503132127PYTHON, "StateTests/RandomTests/st201503132127PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503132201CPPJIT, "StateTests/RandomTests/st201503132201CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503132201GO, "StateTests/RandomTests/st201503132201GO"}
+ declare_test!{StateTests_RandomTests_st201503132202PYTHON, "StateTests/RandomTests/st201503132202PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503140002PYTHON, "StateTests/RandomTests/st201503140002PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503140240PYTHON, "StateTests/RandomTests/st201503140240PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503140522PYTHON, "StateTests/RandomTests/st201503140522PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503140756PYTHON, "StateTests/RandomTests/st201503140756PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503141144PYTHON, "StateTests/RandomTests/st201503141144PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503141510PYTHON, "StateTests/RandomTests/st201503141510PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503150427PYTHON, "StateTests/RandomTests/st201503150427PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503150716PYTHON, "StateTests/RandomTests/st201503150716PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503151450PYTHON, "StateTests/RandomTests/st201503151450PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503151516PYTHON, "StateTests/RandomTests/st201503151516PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503151753PYTHON, "StateTests/RandomTests/st201503151753PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503152057PYTHON, "StateTests/RandomTests/st201503152057PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503152241PYTHON, "StateTests/RandomTests/st201503152241PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503160014PYTHON, "StateTests/RandomTests/st201503160014PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503160733PYTHON, "StateTests/RandomTests/st201503160733PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503170051PYTHON, "StateTests/RandomTests/st201503170051PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503170433PYTHON, "StateTests/RandomTests/st201503170433PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503170523PYTHON, "StateTests/RandomTests/st201503170523PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503171108PYTHON, "StateTests/RandomTests/st201503171108PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503181223GO, "StateTests/RandomTests/st201503181223GO"}
+ declare_test!{StateTests_RandomTests_st201503181225GO, "StateTests/RandomTests/st201503181225GO"}
+ declare_test!{StateTests_RandomTests_st201503181226CPPJIT, "StateTests/RandomTests/st201503181226CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181227CPPJIT, "StateTests/RandomTests/st201503181227CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181227GO, "StateTests/RandomTests/st201503181227GO"}
+ declare_test!{StateTests_RandomTests_st201503181229GO, "StateTests/RandomTests/st201503181229GO"}
+ declare_test!{StateTests_RandomTests_st201503181230CPPJIT, "StateTests/RandomTests/st201503181230CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181230GO, "StateTests/RandomTests/st201503181230GO"}
+ declare_test!{StateTests_RandomTests_st201503181231GO, "StateTests/RandomTests/st201503181231GO"}
+ declare_test!{StateTests_RandomTests_st201503181232CPPJIT, "StateTests/RandomTests/st201503181232CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181232GO, "StateTests/RandomTests/st201503181232GO"}
+ declare_test!{StateTests_RandomTests_st201503181233GO, "StateTests/RandomTests/st201503181233GO"}
+ declare_test!{StateTests_RandomTests_st201503181234CPPJIT, "StateTests/RandomTests/st201503181234CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181234GO, "StateTests/RandomTests/st201503181234GO"}
+ declare_test!{StateTests_RandomTests_st201503181235CPPJIT, "StateTests/RandomTests/st201503181235CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181235GO, "StateTests/RandomTests/st201503181235GO"}
+ declare_test!{StateTests_RandomTests_st201503181236GO, "StateTests/RandomTests/st201503181236GO"}
+ declare_test!{StateTests_RandomTests_st201503181237GO, "StateTests/RandomTests/st201503181237GO"}
+ declare_test!{StateTests_RandomTests_st201503181239GO, "StateTests/RandomTests/st201503181239GO"}
+ declare_test!{StateTests_RandomTests_st201503181241CPPJIT, "StateTests/RandomTests/st201503181241CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181241GO, "StateTests/RandomTests/st201503181241GO"}
+ declare_test!{StateTests_RandomTests_st201503181243GO, "StateTests/RandomTests/st201503181243GO"}
+ declare_test!{StateTests_RandomTests_st201503181244GO, "StateTests/RandomTests/st201503181244GO"}
+ declare_test!{StateTests_RandomTests_st201503181245CPPJIT, "StateTests/RandomTests/st201503181245CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181245GO, "StateTests/RandomTests/st201503181245GO"}
+ declare_test!{StateTests_RandomTests_st201503181246CPPJIT, "StateTests/RandomTests/st201503181246CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181246GO, "StateTests/RandomTests/st201503181246GO"}
+ declare_test!{StateTests_RandomTests_st201503181247GO, "StateTests/RandomTests/st201503181247GO"}
+ declare_test!{StateTests_RandomTests_st201503181248GO, "StateTests/RandomTests/st201503181248GO"}
+ declare_test!{StateTests_RandomTests_st201503181249GO, "StateTests/RandomTests/st201503181249GO"}
+ declare_test!{StateTests_RandomTests_st201503181250CPPJIT, "StateTests/RandomTests/st201503181250CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181250GO, "StateTests/RandomTests/st201503181250GO"}
+ declare_test!{StateTests_RandomTests_st201503181251GO, "StateTests/RandomTests/st201503181251GO"}
+ declare_test!{StateTests_RandomTests_st201503181252CPPJIT, "StateTests/RandomTests/st201503181252CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181253GO, "StateTests/RandomTests/st201503181253GO"}
+ declare_test!{StateTests_RandomTests_st201503181255CPPJIT, "StateTests/RandomTests/st201503181255CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181255GO, "StateTests/RandomTests/st201503181255GO"}
+ declare_test!{StateTests_RandomTests_st201503181257GO, "StateTests/RandomTests/st201503181257GO"}
+ declare_test!{StateTests_RandomTests_st201503181258CPPJIT, "StateTests/RandomTests/st201503181258CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181258GO, "StateTests/RandomTests/st201503181258GO"}
+ declare_test!{StateTests_RandomTests_st201503181301CPPJIT, "StateTests/RandomTests/st201503181301CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181301GO, "StateTests/RandomTests/st201503181301GO"}
+ declare_test!{StateTests_RandomTests_st201503181303GO, "StateTests/RandomTests/st201503181303GO"}
+ declare_test!{StateTests_RandomTests_st201503181304GO, "StateTests/RandomTests/st201503181304GO"}
+ declare_test!{StateTests_RandomTests_st201503181305GO, "StateTests/RandomTests/st201503181305GO"}
+ declare_test!{StateTests_RandomTests_st201503181306GO, "StateTests/RandomTests/st201503181306GO"}
+ declare_test!{StateTests_RandomTests_st201503181307CPPJIT, "StateTests/RandomTests/st201503181307CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181307GO, "StateTests/RandomTests/st201503181307GO"}
+ declare_test!{StateTests_RandomTests_st201503181308GO, "StateTests/RandomTests/st201503181308GO"}
+ declare_test!{StateTests_RandomTests_st201503181309GO, "StateTests/RandomTests/st201503181309GO"}
+ declare_test!{StateTests_RandomTests_st201503181310GO, "StateTests/RandomTests/st201503181310GO"}
+ declare_test!{StateTests_RandomTests_st201503181311GO, "StateTests/RandomTests/st201503181311GO"}
+ declare_test!{StateTests_RandomTests_st201503181313GO, "StateTests/RandomTests/st201503181313GO"}
+ declare_test!{StateTests_RandomTests_st201503181314GO, "StateTests/RandomTests/st201503181314GO"}
+ declare_test!{StateTests_RandomTests_st201503181315CPPJIT, "StateTests/RandomTests/st201503181315CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181315GO, "StateTests/RandomTests/st201503181315GO"}
+ declare_test!{StateTests_RandomTests_st201503181316CPPJIT, "StateTests/RandomTests/st201503181316CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181316PYTHON, "StateTests/RandomTests/st201503181316PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503181317GO, "StateTests/RandomTests/st201503181317GO"}
+ declare_test!{StateTests_RandomTests_st201503181318CPPJIT, "StateTests/RandomTests/st201503181318CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181318GO, "StateTests/RandomTests/st201503181318GO"}
+ declare_test!{StateTests_RandomTests_st201503181319GO, "StateTests/RandomTests/st201503181319GO"}
+ declare_test!{StateTests_RandomTests_st201503181319PYTHON, "StateTests/RandomTests/st201503181319PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503181322GO, "StateTests/RandomTests/st201503181322GO"}
+ declare_test!{StateTests_RandomTests_st201503181323CPPJIT, "StateTests/RandomTests/st201503181323CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181323GO, "StateTests/RandomTests/st201503181323GO"}
+ declare_test!{StateTests_RandomTests_st201503181324GO, "StateTests/RandomTests/st201503181324GO"}
+ declare_test!{StateTests_RandomTests_st201503181325GO, "StateTests/RandomTests/st201503181325GO"}
+ declare_test!{StateTests_RandomTests_st201503181326CPPJIT, "StateTests/RandomTests/st201503181326CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181326GO, "StateTests/RandomTests/st201503181326GO"}
+ declare_test!{StateTests_RandomTests_st201503181327GO, "StateTests/RandomTests/st201503181327GO"}
+ declare_test!{StateTests_RandomTests_st201503181329CPPJIT, "StateTests/RandomTests/st201503181329CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181329GO, "StateTests/RandomTests/st201503181329GO"}
+ declare_test!{StateTests_RandomTests_st201503181330GO, "StateTests/RandomTests/st201503181330GO"}
+ declare_test!{StateTests_RandomTests_st201503181332GO, "StateTests/RandomTests/st201503181332GO"}
+ declare_test!{StateTests_RandomTests_st201503181333GO, "StateTests/RandomTests/st201503181333GO"}
+ declare_test!{StateTests_RandomTests_st201503181334GO, "StateTests/RandomTests/st201503181334GO"}
+ declare_test!{StateTests_RandomTests_st201503181336CPPJIT, "StateTests/RandomTests/st201503181336CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181337GO, "StateTests/RandomTests/st201503181337GO"}
+ declare_test!{StateTests_RandomTests_st201503181338GO, "StateTests/RandomTests/st201503181338GO"}
+ declare_test!{StateTests_RandomTests_st201503181339CPPJIT, "StateTests/RandomTests/st201503181339CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181339GO, "StateTests/RandomTests/st201503181339GO"}
+ declare_test!{StateTests_RandomTests_st201503181340GO, "StateTests/RandomTests/st201503181340GO"}
+ declare_test!{StateTests_RandomTests_st201503181341CPPJIT, "StateTests/RandomTests/st201503181341CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181342CPPJIT, "StateTests/RandomTests/st201503181342CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181342GO, "StateTests/RandomTests/st201503181342GO"}
+ declare_test!{StateTests_RandomTests_st201503181345GO, "StateTests/RandomTests/st201503181345GO"}
+ declare_test!{StateTests_RandomTests_st201503181346GO, "StateTests/RandomTests/st201503181346GO"}
+ declare_test!{StateTests_RandomTests_st201503181347CPPJIT, "StateTests/RandomTests/st201503181347CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181347GO, "StateTests/RandomTests/st201503181347GO"}
+ declare_test!{StateTests_RandomTests_st201503181347PYTHON, "StateTests/RandomTests/st201503181347PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503181350CPPJIT, "StateTests/RandomTests/st201503181350CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181352GO, "StateTests/RandomTests/st201503181352GO"}
+ declare_test!{StateTests_RandomTests_st201503181353GO, "StateTests/RandomTests/st201503181353GO"}
+ declare_test!{StateTests_RandomTests_st201503181354CPPJIT, "StateTests/RandomTests/st201503181354CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181354GO, "StateTests/RandomTests/st201503181354GO"}
+ declare_test!{StateTests_RandomTests_st201503181355GO, "StateTests/RandomTests/st201503181355GO"}
+ declare_test!{StateTests_RandomTests_st201503181356CPPJIT, "StateTests/RandomTests/st201503181356CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181357CPPJIT, "StateTests/RandomTests/st201503181357CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181358CPPJIT, "StateTests/RandomTests/st201503181358CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181358GO, "StateTests/RandomTests/st201503181358GO"}
+ declare_test!{StateTests_RandomTests_st201503181359GO, "StateTests/RandomTests/st201503181359GO"}
+ declare_test!{StateTests_RandomTests_st201503181402CPPJIT, "StateTests/RandomTests/st201503181402CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181403GO, "StateTests/RandomTests/st201503181403GO"}
+ declare_test!{StateTests_RandomTests_st201503181406CPPJIT, "StateTests/RandomTests/st201503181406CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181406GO, "StateTests/RandomTests/st201503181406GO"}
+ declare_test!{StateTests_RandomTests_st201503181410GO, "StateTests/RandomTests/st201503181410GO"}
+ declare_test!{StateTests_RandomTests_st201503181412CPPJIT, "StateTests/RandomTests/st201503181412CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181413GO, "StateTests/RandomTests/st201503181413GO"}
+ declare_test!{StateTests_RandomTests_st201503181415GO, "StateTests/RandomTests/st201503181415GO"}
+ declare_test!{StateTests_RandomTests_st201503181416GO, "StateTests/RandomTests/st201503181416GO"}
+ declare_test!{StateTests_RandomTests_st201503181417CPPJIT, "StateTests/RandomTests/st201503181417CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181417GO, "StateTests/RandomTests/st201503181417GO"}
+ declare_test!{StateTests_RandomTests_st201503181418CPPJIT, "StateTests/RandomTests/st201503181418CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181422GO, "StateTests/RandomTests/st201503181422GO"}
+ declare_test!{StateTests_RandomTests_st201503181423CPPJIT, "StateTests/RandomTests/st201503181423CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181424GO, "StateTests/RandomTests/st201503181424GO"}
+ declare_test!{StateTests_RandomTests_st201503181426CPPJIT, "StateTests/RandomTests/st201503181426CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181426GO, "StateTests/RandomTests/st201503181426GO"}
+ declare_test!{StateTests_RandomTests_st201503181428GO, "StateTests/RandomTests/st201503181428GO"}
+ declare_test!{StateTests_RandomTests_st201503181430CPPJIT, "StateTests/RandomTests/st201503181430CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181435GO, "StateTests/RandomTests/st201503181435GO"}
+ declare_test!{StateTests_RandomTests_st201503181436GO, "StateTests/RandomTests/st201503181436GO"}
+ declare_test!{StateTests_RandomTests_st201503181437CPPJIT, "StateTests/RandomTests/st201503181437CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181437GO, "StateTests/RandomTests/st201503181437GO"}
+ declare_test!{StateTests_RandomTests_st201503181438CPPJIT, "StateTests/RandomTests/st201503181438CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181438GO, "StateTests/RandomTests/st201503181438GO"}
+ declare_test!{StateTests_RandomTests_st201503181439CPPJIT, "StateTests/RandomTests/st201503181439CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181439GO, "StateTests/RandomTests/st201503181439GO"}
+ declare_test!{StateTests_RandomTests_st201503181439PYTHON, "StateTests/RandomTests/st201503181439PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503181440GO, "StateTests/RandomTests/st201503181440GO"}
+ declare_test!{StateTests_RandomTests_st201503181441GO, "StateTests/RandomTests/st201503181441GO"}
+ declare_test!{StateTests_RandomTests_st201503181442GO, "StateTests/RandomTests/st201503181442GO"}
+ declare_test!{StateTests_RandomTests_st201503181445CPPJIT, "StateTests/RandomTests/st201503181445CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181446GO, "StateTests/RandomTests/st201503181446GO"}
+ declare_test!{StateTests_RandomTests_st201503181447GO, "StateTests/RandomTests/st201503181447GO"}
+ declare_test!{StateTests_RandomTests_st201503181450GO, "StateTests/RandomTests/st201503181450GO"}
+ declare_test!{StateTests_RandomTests_st201503181451CPPJIT, "StateTests/RandomTests/st201503181451CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181453GO, "StateTests/RandomTests/st201503181453GO"}
+ declare_test!{StateTests_RandomTests_st201503181455GO, "StateTests/RandomTests/st201503181455GO"}
+ declare_test!{StateTests_RandomTests_st201503181456CPPJIT, "StateTests/RandomTests/st201503181456CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181457GO, "StateTests/RandomTests/st201503181457GO"}
+ declare_test!{StateTests_RandomTests_st201503181458GO, "StateTests/RandomTests/st201503181458GO"}
+ declare_test!{StateTests_RandomTests_st201503181459GO, "StateTests/RandomTests/st201503181459GO"}
+ declare_test!{StateTests_RandomTests_st201503181500GO, "StateTests/RandomTests/st201503181500GO"}
+ declare_test!{StateTests_RandomTests_st201503181501GO, "StateTests/RandomTests/st201503181501GO"}
+ declare_test!{StateTests_RandomTests_st201503181503GO, "StateTests/RandomTests/st201503181503GO"}
+ declare_test!{StateTests_RandomTests_st201503181504GO, "StateTests/RandomTests/st201503181504GO"}
+ declare_test!{StateTests_RandomTests_st201503181505GO, "StateTests/RandomTests/st201503181505GO"}
+ declare_test!{StateTests_RandomTests_st201503181506CPPJIT, "StateTests/RandomTests/st201503181506CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181507GO, "StateTests/RandomTests/st201503181507GO"}
+ declare_test!{StateTests_RandomTests_st201503181509CPPJIT, "StateTests/RandomTests/st201503181509CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181509GO, "StateTests/RandomTests/st201503181509GO"}
+ declare_test!{StateTests_RandomTests_st201503181510GO, "StateTests/RandomTests/st201503181510GO"}
+ declare_test!{StateTests_RandomTests_st201503181511GO, "StateTests/RandomTests/st201503181511GO"}
+ declare_test!{StateTests_RandomTests_st201503181512GO, "StateTests/RandomTests/st201503181512GO"}
+ declare_test!{StateTests_RandomTests_st201503181513CPPJIT, "StateTests/RandomTests/st201503181513CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181513GO, "StateTests/RandomTests/st201503181513GO"}
+ declare_test!{StateTests_RandomTests_st201503181514CPPJIT, "StateTests/RandomTests/st201503181514CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181514GO, "StateTests/RandomTests/st201503181514GO"}
+ declare_test!{StateTests_RandomTests_st201503181517CPPJIT, "StateTests/RandomTests/st201503181517CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181517GO, "StateTests/RandomTests/st201503181517GO"}
+ declare_test!{StateTests_RandomTests_st201503181519CPPJIT, "StateTests/RandomTests/st201503181519CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181519GO, "StateTests/RandomTests/st201503181519GO"}
+ declare_test!{StateTests_RandomTests_st201503181520CPPJIT, "StateTests/RandomTests/st201503181520CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181520GO, "StateTests/RandomTests/st201503181520GO"}
+ declare_test!{StateTests_RandomTests_st201503181521GO, "StateTests/RandomTests/st201503181521GO"}
+ declare_test!{StateTests_RandomTests_st201503181522GO, "StateTests/RandomTests/st201503181522GO"}
+ declare_test!{StateTests_RandomTests_st201503181524CPPJIT, "StateTests/RandomTests/st201503181524CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181524GO, "StateTests/RandomTests/st201503181524GO"}
+ declare_test!{StateTests_RandomTests_st201503181526GO, "StateTests/RandomTests/st201503181526GO"}
+ declare_test!{StateTests_RandomTests_st201503181527GO, "StateTests/RandomTests/st201503181527GO"}
+ declare_test!{StateTests_RandomTests_st201503181528CPPJIT, "StateTests/RandomTests/st201503181528CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181528GO, "StateTests/RandomTests/st201503181528GO"}
+ declare_test!{StateTests_RandomTests_st201503181528PYTHON, "StateTests/RandomTests/st201503181528PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503181529GO, "StateTests/RandomTests/st201503181529GO"}
+ declare_test!{StateTests_RandomTests_st201503181531CPPJIT, "StateTests/RandomTests/st201503181531CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181533GO, "StateTests/RandomTests/st201503181533GO"}
+ declare_test!{StateTests_RandomTests_st201503181534CPPJIT, "StateTests/RandomTests/st201503181534CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181534GO, "StateTests/RandomTests/st201503181534GO"}
+ declare_test!{StateTests_RandomTests_st201503181536CPPJIT, "StateTests/RandomTests/st201503181536CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181536GO, "StateTests/RandomTests/st201503181536GO"}
+ declare_test!{StateTests_RandomTests_st201503181537GO, "StateTests/RandomTests/st201503181537GO"}
+ declare_test!{StateTests_RandomTests_st201503181538GO, "StateTests/RandomTests/st201503181538GO"}
+ declare_test!{StateTests_RandomTests_st201503181539GO, "StateTests/RandomTests/st201503181539GO"}
+ declare_test!{StateTests_RandomTests_st201503181540CPPJIT, "StateTests/RandomTests/st201503181540CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181540PYTHON, "StateTests/RandomTests/st201503181540PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503181543GO, "StateTests/RandomTests/st201503181543GO"}
+ declare_test!{StateTests_RandomTests_st201503181544CPPJIT, "StateTests/RandomTests/st201503181544CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181544GO, "StateTests/RandomTests/st201503181544GO"}
+ declare_test!{StateTests_RandomTests_st201503181547GO, "StateTests/RandomTests/st201503181547GO"}
+ declare_test!{StateTests_RandomTests_st201503181548CPPJIT, "StateTests/RandomTests/st201503181548CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181548GO, "StateTests/RandomTests/st201503181548GO"}
+ declare_test!{StateTests_RandomTests_st201503181551GO, "StateTests/RandomTests/st201503181551GO"}
+ declare_test!{StateTests_RandomTests_st201503181552CPPJIT, "StateTests/RandomTests/st201503181552CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181553GO, "StateTests/RandomTests/st201503181553GO"}
+ declare_test!{StateTests_RandomTests_st201503181555CPPJIT, "StateTests/RandomTests/st201503181555CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181555GO, "StateTests/RandomTests/st201503181555GO"}
+ declare_test!{StateTests_RandomTests_st201503181557GO, "StateTests/RandomTests/st201503181557GO"}
+ declare_test!{StateTests_RandomTests_st201503181559GO, "StateTests/RandomTests/st201503181559GO"}
+ declare_test!{StateTests_RandomTests_st201503181601CPPJIT, "StateTests/RandomTests/st201503181601CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181601GO, "StateTests/RandomTests/st201503181601GO"}
+ declare_test!{StateTests_RandomTests_st201503181602GO, "StateTests/RandomTests/st201503181602GO"}
+ declare_test!{StateTests_RandomTests_st201503181603GO, "StateTests/RandomTests/st201503181603GO"}
+ declare_test!{StateTests_RandomTests_st201503181604GO, "StateTests/RandomTests/st201503181604GO"}
+ declare_test!{StateTests_RandomTests_st201503181605GO, "StateTests/RandomTests/st201503181605GO"}
+ declare_test!{StateTests_RandomTests_st201503181606GO, "StateTests/RandomTests/st201503181606GO"}
+ declare_test!{StateTests_RandomTests_st201503181607GO, "StateTests/RandomTests/st201503181607GO"}
+ declare_test!{StateTests_RandomTests_st201503181608CPPJIT, "StateTests/RandomTests/st201503181608CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181608GO, "StateTests/RandomTests/st201503181608GO"}
+ declare_test!{StateTests_RandomTests_st201503181609GO, "StateTests/RandomTests/st201503181609GO"}
+ declare_test!{StateTests_RandomTests_st201503181610CPPJIT, "StateTests/RandomTests/st201503181610CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181610GO, "StateTests/RandomTests/st201503181610GO"}
+ declare_test!{StateTests_RandomTests_st201503181611CPPJIT, "StateTests/RandomTests/st201503181611CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181611GO, "StateTests/RandomTests/st201503181611GO"}
+ declare_test!{StateTests_RandomTests_st201503181612GO, "StateTests/RandomTests/st201503181612GO"}
+ declare_test!{StateTests_RandomTests_st201503181614CPPJIT, "StateTests/RandomTests/st201503181614CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181614GO, "StateTests/RandomTests/st201503181614GO"}
+ declare_test!{StateTests_RandomTests_st201503181616CPPJIT, "StateTests/RandomTests/st201503181616CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181616GO, "StateTests/RandomTests/st201503181616GO"}
+ declare_test!{StateTests_RandomTests_st201503181617GO, "StateTests/RandomTests/st201503181617GO"}
+ declare_test!{StateTests_RandomTests_st201503181618GO, "StateTests/RandomTests/st201503181618GO"}
+ declare_test!{StateTests_RandomTests_st201503181619GO, "StateTests/RandomTests/st201503181619GO"}
+ declare_test!{StateTests_RandomTests_st201503181620CPPJIT, "StateTests/RandomTests/st201503181620CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181620GO, "StateTests/RandomTests/st201503181620GO"}
+ declare_test!{StateTests_RandomTests_st201503181621GO, "StateTests/RandomTests/st201503181621GO"}
+ declare_test!{StateTests_RandomTests_st201503181625GO, "StateTests/RandomTests/st201503181625GO"}
+ declare_test!{StateTests_RandomTests_st201503181626CPPJIT, "StateTests/RandomTests/st201503181626CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181626GO, "StateTests/RandomTests/st201503181626GO"}
+ declare_test!{StateTests_RandomTests_st201503181627GO, "StateTests/RandomTests/st201503181627GO"}
+ declare_test!{StateTests_RandomTests_st201503181628GO, "StateTests/RandomTests/st201503181628GO"}
+ declare_test!{StateTests_RandomTests_st201503181629GO, "StateTests/RandomTests/st201503181629GO"}
+ declare_test!{StateTests_RandomTests_st201503181630CPPJIT, "StateTests/RandomTests/st201503181630CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181630GO, "StateTests/RandomTests/st201503181630GO"}
+ declare_test!{StateTests_RandomTests_st201503181630PYTHON, "StateTests/RandomTests/st201503181630PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503181632GO, "StateTests/RandomTests/st201503181632GO"}
+ declare_test!{StateTests_RandomTests_st201503181634CPPJIT, "StateTests/RandomTests/st201503181634CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181635GO, "StateTests/RandomTests/st201503181635GO"}
+ declare_test!{StateTests_RandomTests_st201503181636GO, "StateTests/RandomTests/st201503181636GO"}
+ declare_test!{StateTests_RandomTests_st201503181638GO, "StateTests/RandomTests/st201503181638GO"}
+ declare_test!{StateTests_RandomTests_st201503181639CPPJIT, "StateTests/RandomTests/st201503181639CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181641GO, "StateTests/RandomTests/st201503181641GO"}
+ declare_test!{StateTests_RandomTests_st201503181645GO, "StateTests/RandomTests/st201503181645GO"}
+ declare_test!{StateTests_RandomTests_st201503181646GO, "StateTests/RandomTests/st201503181646GO"}
+ declare_test!{StateTests_RandomTests_st201503181647CPPJIT, "StateTests/RandomTests/st201503181647CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181649CPPJIT, "StateTests/RandomTests/st201503181649CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181650GO, "StateTests/RandomTests/st201503181650GO"}
+ declare_test!{StateTests_RandomTests_st201503181652CPPJIT, "StateTests/RandomTests/st201503181652CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181653GO, "StateTests/RandomTests/st201503181653GO"}
+ declare_test!{StateTests_RandomTests_st201503181654GO, "StateTests/RandomTests/st201503181654GO"}
+ declare_test!{StateTests_RandomTests_st201503181655CPPJIT, "StateTests/RandomTests/st201503181655CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181655GO, "StateTests/RandomTests/st201503181655GO"}
+ declare_test!{StateTests_RandomTests_st201503181656CPPJIT, "StateTests/RandomTests/st201503181656CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181656GO, "StateTests/RandomTests/st201503181656GO"}
+ declare_test!{StateTests_RandomTests_st201503181657GO, "StateTests/RandomTests/st201503181657GO"}
+ declare_test!{StateTests_RandomTests_st201503181658GO, "StateTests/RandomTests/st201503181658GO"}
+ declare_test!{StateTests_RandomTests_st201503181700GO, "StateTests/RandomTests/st201503181700GO"}
+ declare_test!{StateTests_RandomTests_st201503181702GO, "StateTests/RandomTests/st201503181702GO"}
+ declare_test!{StateTests_RandomTests_st201503181703CPPJIT, "StateTests/RandomTests/st201503181703CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181703GO, "StateTests/RandomTests/st201503181703GO"}
+ declare_test!{StateTests_RandomTests_st201503181704GO, "StateTests/RandomTests/st201503181704GO"}
+ declare_test!{StateTests_RandomTests_st201503181706GO, "StateTests/RandomTests/st201503181706GO"}
+ declare_test!{StateTests_RandomTests_st201503181709GO, "StateTests/RandomTests/st201503181709GO"}
+ declare_test!{StateTests_RandomTests_st201503181711CPPJIT, "StateTests/RandomTests/st201503181711CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181711GO, "StateTests/RandomTests/st201503181711GO"}
+ declare_test!{StateTests_RandomTests_st201503181713CPPJIT, "StateTests/RandomTests/st201503181713CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181713GO, "StateTests/RandomTests/st201503181713GO"}
+ declare_test!{StateTests_RandomTests_st201503181714GO, "StateTests/RandomTests/st201503181714GO"}
+ declare_test!{StateTests_RandomTests_st201503181715CPPJIT, "StateTests/RandomTests/st201503181715CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181715GO, "StateTests/RandomTests/st201503181715GO"}
+ declare_test!{StateTests_RandomTests_st201503181716GO, "StateTests/RandomTests/st201503181716GO"}
+ declare_test!{StateTests_RandomTests_st201503181717GO, "StateTests/RandomTests/st201503181717GO"}
+ declare_test!{StateTests_RandomTests_st201503181720CPPJIT, "StateTests/RandomTests/st201503181720CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181722GO, "StateTests/RandomTests/st201503181722GO"}
+ declare_test!{StateTests_RandomTests_st201503181723CPPJIT, "StateTests/RandomTests/st201503181723CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181723GO, "StateTests/RandomTests/st201503181723GO"}
+ declare_test!{StateTests_RandomTests_st201503181724CPPJIT, "StateTests/RandomTests/st201503181724CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181724GO, "StateTests/RandomTests/st201503181724GO"}
+ declare_test!{StateTests_RandomTests_st201503181725GO, "StateTests/RandomTests/st201503181725GO"}
+ declare_test!{StateTests_RandomTests_st201503181728GO, "StateTests/RandomTests/st201503181728GO"}
+ declare_test!{StateTests_RandomTests_st201503181729GO, "StateTests/RandomTests/st201503181729GO"}
+ declare_test!{StateTests_RandomTests_st201503181730GO, "StateTests/RandomTests/st201503181730GO"}
+ declare_test!{StateTests_RandomTests_st201503181731CPPJIT, "StateTests/RandomTests/st201503181731CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181732GO, "StateTests/RandomTests/st201503181732GO"}
+ declare_test!{StateTests_RandomTests_st201503181734CPPJIT, "StateTests/RandomTests/st201503181734CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181734GO, "StateTests/RandomTests/st201503181734GO"}
+ declare_test!{StateTests_RandomTests_st201503181735GO, "StateTests/RandomTests/st201503181735GO"}
+ declare_test!{StateTests_RandomTests_st201503181737CPPJIT, "StateTests/RandomTests/st201503181737CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181737GO, "StateTests/RandomTests/st201503181737GO"}
+ declare_test!{StateTests_RandomTests_st201503181738CPPJIT, "StateTests/RandomTests/st201503181738CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181738GO, "StateTests/RandomTests/st201503181738GO"}
+ declare_test!{StateTests_RandomTests_st201503181739GO, "StateTests/RandomTests/st201503181739GO"}
+ declare_test!{StateTests_RandomTests_st201503181740CPPJIT, "StateTests/RandomTests/st201503181740CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181740GO, "StateTests/RandomTests/st201503181740GO"}
+ declare_test!{StateTests_RandomTests_st201503181742CPPJIT, "StateTests/RandomTests/st201503181742CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181743GO, "StateTests/RandomTests/st201503181743GO"}
+ declare_test!{StateTests_RandomTests_st201503181744GO, "StateTests/RandomTests/st201503181744GO"}
+ declare_test!{StateTests_RandomTests_st201503181745CPPJIT, "StateTests/RandomTests/st201503181745CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181746GO, "StateTests/RandomTests/st201503181746GO"}
+ declare_test!{StateTests_RandomTests_st201503181747GO, "StateTests/RandomTests/st201503181747GO"}
+ declare_test!{StateTests_RandomTests_st201503181748GO, "StateTests/RandomTests/st201503181748GO"}
+ declare_test!{StateTests_RandomTests_st201503181749GO, "StateTests/RandomTests/st201503181749GO"}
+ declare_test!{StateTests_RandomTests_st201503181750CPPJIT, "StateTests/RandomTests/st201503181750CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181750GO, "StateTests/RandomTests/st201503181750GO"}
+ declare_test!{StateTests_RandomTests_st201503181752GO, "StateTests/RandomTests/st201503181752GO"}
+ declare_test!{StateTests_RandomTests_st201503181753CPPJIT, "StateTests/RandomTests/st201503181753CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181754CPPJIT, "StateTests/RandomTests/st201503181754CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181754GO, "StateTests/RandomTests/st201503181754GO"}
+ declare_test!{StateTests_RandomTests_st201503181755CPPJIT, "StateTests/RandomTests/st201503181755CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181755GO, "StateTests/RandomTests/st201503181755GO"}
+ declare_test!{StateTests_RandomTests_st201503181756GO, "StateTests/RandomTests/st201503181756GO"}
+ declare_test!{StateTests_RandomTests_st201503181757CPPJIT, "StateTests/RandomTests/st201503181757CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181757GO, "StateTests/RandomTests/st201503181757GO"}
+ declare_test!{StateTests_RandomTests_st201503181759GO, "StateTests/RandomTests/st201503181759GO"}
+ declare_test!{StateTests_RandomTests_st201503181800GO, "StateTests/RandomTests/st201503181800GO"}
+ declare_test!{StateTests_RandomTests_st201503181801GO, "StateTests/RandomTests/st201503181801GO"}
+ declare_test!{StateTests_RandomTests_st201503181802GO, "StateTests/RandomTests/st201503181802GO"}
+ declare_test!{StateTests_RandomTests_st201503181803CPPJIT, "StateTests/RandomTests/st201503181803CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181803GO, "StateTests/RandomTests/st201503181803GO"}
+ declare_test!{StateTests_RandomTests_st201503181804GO, "StateTests/RandomTests/st201503181804GO"}
+ declare_test!{StateTests_RandomTests_st201503181806GO, "StateTests/RandomTests/st201503181806GO"}
+ declare_test!{StateTests_RandomTests_st201503181808GO, "StateTests/RandomTests/st201503181808GO"}
+ declare_test!{StateTests_RandomTests_st201503181809CPPJIT, "StateTests/RandomTests/st201503181809CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181812CPPJIT, "StateTests/RandomTests/st201503181812CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181812GO, "StateTests/RandomTests/st201503181812GO"}
+ declare_test!{StateTests_RandomTests_st201503181814CPPJIT, "StateTests/RandomTests/st201503181814CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181815GO, "StateTests/RandomTests/st201503181815GO"}
+ declare_test!{StateTests_RandomTests_st201503181816CPPJIT, "StateTests/RandomTests/st201503181816CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181817CPPJIT, "StateTests/RandomTests/st201503181817CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181819GO, "StateTests/RandomTests/st201503181819GO"}
+ declare_test!{StateTests_RandomTests_st201503181821GO, "StateTests/RandomTests/st201503181821GO"}
+ declare_test!{StateTests_RandomTests_st201503181822GO, "StateTests/RandomTests/st201503181822GO"}
+ declare_test!{StateTests_RandomTests_st201503181823GO, "StateTests/RandomTests/st201503181823GO"}
+ declare_test!{StateTests_RandomTests_st201503181824GO, "StateTests/RandomTests/st201503181824GO"}
+ declare_test!{StateTests_RandomTests_st201503181825GO, "StateTests/RandomTests/st201503181825GO"}
+ declare_test!{StateTests_RandomTests_st201503181829GO, "StateTests/RandomTests/st201503181829GO"}
+ declare_test!{StateTests_RandomTests_st201503181830CPPJIT, "StateTests/RandomTests/st201503181830CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181833GO, "StateTests/RandomTests/st201503181833GO"}
+ declare_test!{StateTests_RandomTests_st201503181834CPPJIT, "StateTests/RandomTests/st201503181834CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181834GO, "StateTests/RandomTests/st201503181834GO"}
+ declare_test!{StateTests_RandomTests_st201503181837GO, "StateTests/RandomTests/st201503181837GO"}
+ declare_test!{StateTests_RandomTests_st201503181840GO, "StateTests/RandomTests/st201503181840GO"}
+ declare_test!{StateTests_RandomTests_st201503181842GO, "StateTests/RandomTests/st201503181842GO"}
+ declare_test!{StateTests_RandomTests_st201503181843GO, "StateTests/RandomTests/st201503181843GO"}
+ declare_test!{StateTests_RandomTests_st201503181844GO, "StateTests/RandomTests/st201503181844GO"}
+ declare_test!{StateTests_RandomTests_st201503181845GO, "StateTests/RandomTests/st201503181845GO"}
+ declare_test!{StateTests_RandomTests_st201503181846GO, "StateTests/RandomTests/st201503181846GO"}
+ declare_test!{StateTests_RandomTests_st201503181847GO, "StateTests/RandomTests/st201503181847GO"}
+ declare_test!{StateTests_RandomTests_st201503181848GO, "StateTests/RandomTests/st201503181848GO"}
+ declare_test!{StateTests_RandomTests_st201503181849GO, "StateTests/RandomTests/st201503181849GO"}
+ declare_test!{StateTests_RandomTests_st201503181850GO, "StateTests/RandomTests/st201503181850GO"}
+ declare_test!{StateTests_RandomTests_st201503181851CPPJIT, "StateTests/RandomTests/st201503181851CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181851GO, "StateTests/RandomTests/st201503181851GO"}
+ declare_test!{StateTests_RandomTests_st201503181852CPPJIT, "StateTests/RandomTests/st201503181852CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181854GO, "StateTests/RandomTests/st201503181854GO"}
+ declare_test!{StateTests_RandomTests_st201503181855CPPJIT, "StateTests/RandomTests/st201503181855CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181857PYTHON, "StateTests/RandomTests/st201503181857PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503181859GO, "StateTests/RandomTests/st201503181859GO"}
+ declare_test!{StateTests_RandomTests_st201503181900GO, "StateTests/RandomTests/st201503181900GO"}
+ declare_test!{StateTests_RandomTests_st201503181903GO, "StateTests/RandomTests/st201503181903GO"}
+ declare_test!{StateTests_RandomTests_st201503181904GO, "StateTests/RandomTests/st201503181904GO"}
+ declare_test!{StateTests_RandomTests_st201503181906GO, "StateTests/RandomTests/st201503181906GO"}
+ declare_test!{StateTests_RandomTests_st201503181907GO, "StateTests/RandomTests/st201503181907GO"}
+ declare_test!{StateTests_RandomTests_st201503181910GO, "StateTests/RandomTests/st201503181910GO"}
+ declare_test!{StateTests_RandomTests_st201503181915GO, "StateTests/RandomTests/st201503181915GO"}
+ declare_test!{StateTests_RandomTests_st201503181919CPPJIT, "StateTests/RandomTests/st201503181919CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181919PYTHON, "StateTests/RandomTests/st201503181919PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503181920GO, "StateTests/RandomTests/st201503181920GO"}
+ declare_test!{StateTests_RandomTests_st201503181922GO, "StateTests/RandomTests/st201503181922GO"}
+ declare_test!{StateTests_RandomTests_st201503181926GO, "StateTests/RandomTests/st201503181926GO"}
+ declare_test!{StateTests_RandomTests_st201503181929GO, "StateTests/RandomTests/st201503181929GO"}
+ declare_test!{StateTests_RandomTests_st201503181931CPPJIT, "StateTests/RandomTests/st201503181931CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201503181931GO, "StateTests/RandomTests/st201503181931GO"}
+ declare_test!{StateTests_RandomTests_st201503181931PYTHON, "StateTests/RandomTests/st201503181931PYTHON"}
+ declare_test!{StateTests_RandomTests_st201503191646GO, "StateTests/RandomTests/st201503191646GO"}
+ declare_test!{StateTests_RandomTests_st201503200837JS, "StateTests/RandomTests/st201503200837JS"}
+ declare_test!{StateTests_RandomTests_st201503200838JS, "StateTests/RandomTests/st201503200838JS"}
+ declare_test!{StateTests_RandomTests_st201503200841JS, "StateTests/RandomTests/st201503200841JS"}
+ declare_test!{StateTests_RandomTests_st201503200848JS, "StateTests/RandomTests/st201503200848JS"}
+ declare_test!{StateTests_RandomTests_st201503240609JS, "StateTests/RandomTests/st201503240609JS"}
+ declare_test!{StateTests_RandomTests_st201503302200JS, "StateTests/RandomTests/st201503302200JS"}
+ declare_test!{StateTests_RandomTests_st201503302202JS, "StateTests/RandomTests/st201503302202JS"}
+ declare_test!{StateTests_RandomTests_st201503302206JS, "StateTests/RandomTests/st201503302206JS"}
+ declare_test!{StateTests_RandomTests_st201503302208JS, "StateTests/RandomTests/st201503302208JS"}
+ declare_test!{StateTests_RandomTests_st201503302210JS, "StateTests/RandomTests/st201503302210JS"}
+ declare_test!{StateTests_RandomTests_st201503302211JS, "StateTests/RandomTests/st201503302211JS"}
+ declare_test!{StateTests_RandomTests_st201504011535GO, "StateTests/RandomTests/st201504011535GO"}
+ declare_test!{StateTests_RandomTests_st201504011536GO, "StateTests/RandomTests/st201504011536GO"}
+ declare_test!{StateTests_RandomTests_st201504011547GO, "StateTests/RandomTests/st201504011547GO"}
+ declare_test!{StateTests_RandomTests_st201504011916JS, "StateTests/RandomTests/st201504011916JS"}
+ declare_test!{StateTests_RandomTests_st201504012130JS, "StateTests/RandomTests/st201504012130JS"}
+ declare_test!{StateTests_RandomTests_st201504012259JS, "StateTests/RandomTests/st201504012259JS"}
+ declare_test!{StateTests_RandomTests_st201504012359JS, "StateTests/RandomTests/st201504012359JS"}
+ declare_test!{StateTests_RandomTests_st201504020305JS, "StateTests/RandomTests/st201504020305JS"}
+ declare_test!{StateTests_RandomTests_st201504020400JS, "StateTests/RandomTests/st201504020400JS"}
+ declare_test!{StateTests_RandomTests_st201504020428JS, "StateTests/RandomTests/st201504020428JS"}
+ declare_test!{StateTests_RandomTests_st201504020431JS, "StateTests/RandomTests/st201504020431JS"}
+ declare_test!{StateTests_RandomTests_st201504020444JS, "StateTests/RandomTests/st201504020444JS"}
+ declare_test!{StateTests_RandomTests_st201504020538JS, "StateTests/RandomTests/st201504020538JS"}
+ declare_test!{StateTests_RandomTests_st201504020639JS, "StateTests/RandomTests/st201504020639JS"}
+ declare_test!{StateTests_RandomTests_st201504020836JS, "StateTests/RandomTests/st201504020836JS"}
+ declare_test!{StateTests_RandomTests_st201504020910JS, "StateTests/RandomTests/st201504020910JS"}
+ declare_test!{StateTests_RandomTests_st201504021057JS, "StateTests/RandomTests/st201504021057JS"}
+ declare_test!{StateTests_RandomTests_st201504021104JS, "StateTests/RandomTests/st201504021104JS"}
+ declare_test!{StateTests_RandomTests_st201504021237CPPJIT, "StateTests/RandomTests/st201504021237CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504021237GO, "StateTests/RandomTests/st201504021237GO"}
+ declare_test!{StateTests_RandomTests_st201504021237JS, "StateTests/RandomTests/st201504021237JS"}
+ declare_test!{StateTests_RandomTests_st201504021237PYTHON, "StateTests/RandomTests/st201504021237PYTHON"}
+ declare_test!{StateTests_RandomTests_st201504021949JS, "StateTests/RandomTests/st201504021949JS"}
+ declare_test!{StateTests_RandomTests_st201504022003CPPJIT, "StateTests/RandomTests/st201504022003CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504022124JS, "StateTests/RandomTests/st201504022124JS"}
+ declare_test!{StateTests_RandomTests_st201504030138JS, "StateTests/RandomTests/st201504030138JS"}
+ declare_test!{StateTests_RandomTests_st201504030646JS, "StateTests/RandomTests/st201504030646JS"}
+ declare_test!{StateTests_RandomTests_st201504030709JS, "StateTests/RandomTests/st201504030709JS"}
+ declare_test!{StateTests_RandomTests_st201504031133JS, "StateTests/RandomTests/st201504031133JS"}
+ declare_test!{StateTests_RandomTests_st201504031446JS, "StateTests/RandomTests/st201504031446JS"}
+ declare_test!{StateTests_RandomTests_st201504031841JS, "StateTests/RandomTests/st201504031841JS"}
+ declare_test!{StateTests_RandomTests_st201504041605JS, "StateTests/RandomTests/st201504041605JS"}
+ declare_test!{StateTests_RandomTests_st201504042052JS, "StateTests/RandomTests/st201504042052JS"}
+ declare_test!{StateTests_RandomTests_st201504042226CPPJIT, "StateTests/RandomTests/st201504042226CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504042355CPPJIT, "StateTests/RandomTests/st201504042355CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504050059JS, "StateTests/RandomTests/st201504050059JS"}
+ declare_test!{StateTests_RandomTests_st201504050733JS, "StateTests/RandomTests/st201504050733JS"}
+ declare_test!{StateTests_RandomTests_st201504051540JS, "StateTests/RandomTests/st201504051540JS"}
+ declare_test!{StateTests_RandomTests_st201504051944CPPJIT, "StateTests/RandomTests/st201504051944CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504052008CPPJIT, "StateTests/RandomTests/st201504052008CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504052014GO, "StateTests/RandomTests/st201504052014GO"}
+ declare_test!{StateTests_RandomTests_st201504052031CPPJIT, "StateTests/RandomTests/st201504052031CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504060057CPPJIT, "StateTests/RandomTests/st201504060057CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504060418CPPJIT, "StateTests/RandomTests/st201504060418CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504061106CPPJIT, "StateTests/RandomTests/st201504061106CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504061134CPPJIT, "StateTests/RandomTests/st201504061134CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504062033CPPJIT, "StateTests/RandomTests/st201504062033CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504062046CPPJIT, "StateTests/RandomTests/st201504062046CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504062314CPPJIT, "StateTests/RandomTests/st201504062314CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504070746JS, "StateTests/RandomTests/st201504070746JS"}
+ declare_test!{StateTests_RandomTests_st201504070816CPPJIT, "StateTests/RandomTests/st201504070816CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504070836CPPJIT, "StateTests/RandomTests/st201504070836CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504070839CPPJIT, "StateTests/RandomTests/st201504070839CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504071041CPPJIT, "StateTests/RandomTests/st201504071041CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504071056CPPJIT, "StateTests/RandomTests/st201504071056CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504071621CPPJIT, "StateTests/RandomTests/st201504071621CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504071653CPPJIT, "StateTests/RandomTests/st201504071653CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504071750CPPJIT, "StateTests/RandomTests/st201504071750CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504071905CPPJIT, "StateTests/RandomTests/st201504071905CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504080454CPPJIT, "StateTests/RandomTests/st201504080454CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504080457CPPJIT, "StateTests/RandomTests/st201504080457CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504080650CPPJIT, "StateTests/RandomTests/st201504080650CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504080840CPPJIT, "StateTests/RandomTests/st201504080840CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504080948CPPJIT, "StateTests/RandomTests/st201504080948CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504081100CPPJIT, "StateTests/RandomTests/st201504081100CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504081134CPPJIT, "StateTests/RandomTests/st201504081134CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504081138CPPJIT, "StateTests/RandomTests/st201504081138CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504081611CPPJIT, "StateTests/RandomTests/st201504081611CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504081841JAVA, "StateTests/RandomTests/st201504081841JAVA"}
+ declare_test!{StateTests_RandomTests_st201504081842JAVA, "StateTests/RandomTests/st201504081842JAVA"}
+ declare_test!{StateTests_RandomTests_st201504081843JAVA, "StateTests/RandomTests/st201504081843JAVA"}
+ declare_test!{StateTests_RandomTests_st201504081928CPPJIT, "StateTests/RandomTests/st201504081928CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504081953JAVA, "StateTests/RandomTests/st201504081953JAVA"}
+ declare_test!{StateTests_RandomTests_st201504081954JAVA, "StateTests/RandomTests/st201504081954JAVA"}
+ declare_test!{StateTests_RandomTests_st201504081955JAVA, "StateTests/RandomTests/st201504081955JAVA"}
+ declare_test!{StateTests_RandomTests_st201504081956JAVA, "StateTests/RandomTests/st201504081956JAVA"}
+ declare_test!{StateTests_RandomTests_st201504081957JAVA, "StateTests/RandomTests/st201504081957JAVA"}
+ declare_test!{StateTests_RandomTests_st201504082000JAVA, "StateTests/RandomTests/st201504082000JAVA"}
+ declare_test!{StateTests_RandomTests_st201504082001JAVA, "StateTests/RandomTests/st201504082001JAVA"}
+ declare_test!{StateTests_RandomTests_st201504082002JAVA, "StateTests/RandomTests/st201504082002JAVA"}
+ declare_test!{StateTests_RandomTests_st201504090553CPPJIT, "StateTests/RandomTests/st201504090553CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504090657CPPJIT, "StateTests/RandomTests/st201504090657CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504091403CPPJIT, "StateTests/RandomTests/st201504091403CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504091641CPPJIT, "StateTests/RandomTests/st201504091641CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504092303CPPJIT, "StateTests/RandomTests/st201504092303CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504100125CPPJIT, "StateTests/RandomTests/st201504100125CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504100215CPPJIT, "StateTests/RandomTests/st201504100215CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504100226PYTHON, "StateTests/RandomTests/st201504100226PYTHON"}
+ declare_test!{StateTests_RandomTests_st201504100308CPPJIT, "StateTests/RandomTests/st201504100308CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504100337CPPJIT, "StateTests/RandomTests/st201504100337CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504100341CPPJIT, "StateTests/RandomTests/st201504100341CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504101009CPPJIT, "StateTests/RandomTests/st201504101009CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504101150CPPJIT, "StateTests/RandomTests/st201504101150CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504101223CPPJIT, "StateTests/RandomTests/st201504101223CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504101338CPPJIT, "StateTests/RandomTests/st201504101338CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504101754PYTHON, "StateTests/RandomTests/st201504101754PYTHON"}
+ declare_test!{StateTests_RandomTests_st201504111554CPPJIT, "StateTests/RandomTests/st201504111554CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504130653JS, "StateTests/RandomTests/st201504130653JS"}
+ declare_test!{StateTests_RandomTests_st201504131821CPPJIT, "StateTests/RandomTests/st201504131821CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504140229CPPJIT, "StateTests/RandomTests/st201504140229CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504140236CPPJIT, "StateTests/RandomTests/st201504140236CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504140359CPPJIT, "StateTests/RandomTests/st201504140359CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504140750CPPJIT, "StateTests/RandomTests/st201504140750CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504140818CPPJIT, "StateTests/RandomTests/st201504140818CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504140900CPPJIT, "StateTests/RandomTests/st201504140900CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504150854CPPJIT, "StateTests/RandomTests/st201504150854CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504151057CPPJIT, "StateTests/RandomTests/st201504151057CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504202124CPPJIT, "StateTests/RandomTests/st201504202124CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504210245CPPJIT, "StateTests/RandomTests/st201504210245CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504210957CPPJIT, "StateTests/RandomTests/st201504210957CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504211739CPPJIT, "StateTests/RandomTests/st201504211739CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504212038CPPJIT, "StateTests/RandomTests/st201504212038CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504230729CPPJIT, "StateTests/RandomTests/st201504230729CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504231639CPPJIT, "StateTests/RandomTests/st201504231639CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504231710CPPJIT, "StateTests/RandomTests/st201504231710CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504231742CPPJIT, "StateTests/RandomTests/st201504231742CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504232350CPPJIT, "StateTests/RandomTests/st201504232350CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504240140CPPJIT, "StateTests/RandomTests/st201504240140CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504240220CPPJIT, "StateTests/RandomTests/st201504240220CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504240351CPPJIT, "StateTests/RandomTests/st201504240351CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504240817CPPJIT, "StateTests/RandomTests/st201504240817CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201504241118CPPJIT, "StateTests/RandomTests/st201504241118CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201505021810CPPJIT, "StateTests/RandomTests/st201505021810CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201505050557JS, "StateTests/RandomTests/st201505050557JS"}
+ declare_test!{StateTests_RandomTests_st201505050929GO, "StateTests/RandomTests/st201505050929GO"}
+ declare_test!{StateTests_RandomTests_st201505050942PYTHON, "StateTests/RandomTests/st201505050942PYTHON"}
+ declare_test!{StateTests_RandomTests_st201505051004PYTHON, "StateTests/RandomTests/st201505051004PYTHON"}
+ declare_test!{StateTests_RandomTests_st201505051016PYTHON, "StateTests/RandomTests/st201505051016PYTHON"}
+ declare_test!{StateTests_RandomTests_st201505051114GO, "StateTests/RandomTests/st201505051114GO"}
+ declare_test!{StateTests_RandomTests_st201505051238GO, "StateTests/RandomTests/st201505051238GO"}
+ declare_test!{StateTests_RandomTests_st201505051249GO, "StateTests/RandomTests/st201505051249GO"}
+ declare_test!{StateTests_RandomTests_st201505051558PYTHON, "StateTests/RandomTests/st201505051558PYTHON"}
+ declare_test!{StateTests_RandomTests_st201505051611PYTHON, "StateTests/RandomTests/st201505051611PYTHON"}
+ declare_test!{StateTests_RandomTests_st201505051648JS, "StateTests/RandomTests/st201505051648JS"}
+ declare_test!{StateTests_RandomTests_st201505051710GO, "StateTests/RandomTests/st201505051710GO"}
+ declare_test!{StateTests_RandomTests_st201505052013GO, "StateTests/RandomTests/st201505052013GO"}
+ declare_test!{StateTests_RandomTests_st201505052102JS, "StateTests/RandomTests/st201505052102JS"}
+ declare_test!{StateTests_RandomTests_st201505052235GO, "StateTests/RandomTests/st201505052235GO"}
+ declare_test!{StateTests_RandomTests_st201505052238JS, "StateTests/RandomTests/st201505052238JS"}
+ declare_test!{StateTests_RandomTests_st201505052242PYTHON, "StateTests/RandomTests/st201505052242PYTHON"}
+ declare_test!{StateTests_RandomTests_st201505052343PYTHON, "StateTests/RandomTests/st201505052343PYTHON"}
+ declare_test!{StateTests_RandomTests_st201505060120GO, "StateTests/RandomTests/st201505060120GO"}
+ declare_test!{StateTests_RandomTests_st201505060121GO, "StateTests/RandomTests/st201505060121GO"}
+ declare_test!{StateTests_RandomTests_st201505060136PYTHON, "StateTests/RandomTests/st201505060136PYTHON"}
+ declare_test!{StateTests_RandomTests_st201505060646JS, "StateTests/RandomTests/st201505060646JS"}
+ declare_test!{StateTests_RandomTests_st201505252314CPPJIT, "StateTests/RandomTests/st201505252314CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201505272131CPPJIT, "StateTests/RandomTests/st201505272131CPPJIT"}
+ declare_test!{StateTests_RandomTests_st201506040034GO, "StateTests/RandomTests/st201506040034GO"}
+ declare_test!{StateTests_RandomTests_st201506040157GO, "StateTests/RandomTests/st201506040157GO"}
+ declare_test!{StateTests_RandomTests_st201506052130GO, "StateTests/RandomTests/st201506052130GO"}
+ declare_test!{StateTests_RandomTests_st201506060929GO, "StateTests/RandomTests/st201506060929GO"}
+ declare_test!{StateTests_RandomTests_st201506061255GO, "StateTests/RandomTests/st201506061255GO"}
+ declare_test!{StateTests_RandomTests_st201506062331GO, "StateTests/RandomTests/st201506062331GO"}
+ declare_test!{StateTests_RandomTests_st201506070548GO, "StateTests/RandomTests/st201506070548GO"}
+ declare_test!{StateTests_RandomTests_st201506071050GO, "StateTests/RandomTests/st201506071050GO"}
+ declare_test!{StateTests_RandomTests_st201506071624GO, "StateTests/RandomTests/st201506071624GO"}
+ declare_test!{StateTests_RandomTests_st201506071819GO, "StateTests/RandomTests/st201506071819GO"}
+ declare_test!{StateTests_RandomTests_st201506072007GO, "StateTests/RandomTests/st201506072007GO"}
+ declare_test!{StateTests_RandomTests_st201506080556GO, "StateTests/RandomTests/st201506080556GO"}
+ declare_test!{StateTests_RandomTests_st201506080721GO, "StateTests/RandomTests/st201506080721GO"}
+ declare_test!{StateTests_RandomTests_st201506091836GO, "StateTests/RandomTests/st201506091836GO"}
+ declare_test!{StateTests_RandomTests_st201506092032GO, "StateTests/RandomTests/st201506092032GO"}
+ declare_test!{StateTests_RandomTests_st201506101359JS, "StateTests/RandomTests/st201506101359JS"}
+ declare_test!{StateTests_RandomTests_st201507030359GO, "StateTests/RandomTests/st201507030359GO"}
+}
diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs
index a2dab447518..63bb367b64f 100644
--- a/ethcore/src/miner/miner.rs
+++ b/ethcore/src/miner/miner.rs
@@ -30,7 +30,7 @@ use transaction::{Action, SignedTransaction};
use receipt::{Receipt, RichReceipt};
use spec::Spec;
use engines::Engine;
-use miner::{MinerService, MinerStatus, TransactionQueue, AccountDetails, TransactionOrigin};
+use miner::{MinerService, MinerStatus, TransactionQueue, PrioritizationStrategy, AccountDetails, TransactionOrigin};
use miner::work_notify::WorkPoster;
use client::TransactionImportResult;
use miner::price_info::PriceInfo;
@@ -76,6 +76,8 @@ pub struct MinerOptions {
pub tx_gas_limit: U256,
/// Maximum size of the transaction queue.
pub tx_queue_size: usize,
+ /// Strategy to use for prioritizing transactions in the queue.
+ pub tx_queue_strategy: PrioritizationStrategy,
/// Whether we should fallback to providing all the queue's transactions or just pending.
pub pending_set: PendingSet,
/// How many historical work packages can we store before running out?
@@ -94,12 +96,13 @@ impl Default for MinerOptions {
reseal_on_external_tx: false,
reseal_on_own_tx: true,
tx_gas_limit: !U256::zero(),
- tx_queue_size: 2048,
+ tx_queue_size: 1024,
+ tx_queue_gas_limit: GasLimit::Auto,
+ tx_queue_strategy: PrioritizationStrategy::GasFactorAndGasPrice,
pending_set: PendingSet::AlwaysQueue,
reseal_min_period: Duration::from_secs(2),
work_queue_size: 20,
enable_resubmission: true,
- tx_queue_gas_limit: GasLimit::Auto,
}
}
}
@@ -212,7 +215,9 @@ impl Miner {
GasLimit::Fixed(ref limit) => *limit,
_ => !U256::zero(),
};
- let txq = Arc::new(Mutex::new(TransactionQueue::with_limits(options.tx_queue_size, gas_limit, options.tx_gas_limit)));
+ let txq = Arc::new(Mutex::new(TransactionQueue::with_limits(
+ options.tx_queue_strategy, options.tx_queue_size, gas_limit, options.tx_gas_limit
+ )));
Miner {
transaction_queue: txq,
next_allowed_reseal: Mutex::new(Instant::now()),
@@ -462,8 +467,8 @@ impl Miner {
let mut queue = self.transaction_queue.lock();
queue.set_gas_limit(gas_limit);
if let GasLimit::Auto = self.options.tx_queue_gas_limit {
- // Set total tx queue gas limit to be 2x the block gas limit.
- queue.set_total_gas_limit(gas_limit << 1);
+ // Set total tx queue gas limit to be 20x the block gas limit.
+ queue.set_total_gas_limit(gas_limit * 20.into());
}
}
@@ -1029,7 +1034,7 @@ impl MinerService for Miner {
mod tests {
use std::time::Duration;
- use super::super::MinerService;
+ use super::super::{MinerService, PrioritizationStrategy};
use super::*;
use util::*;
use ethkey::{Generator, Random};
@@ -1083,6 +1088,7 @@ mod tests {
tx_gas_limit: !U256::zero(),
tx_queue_size: 1024,
tx_queue_gas_limit: GasLimit::None,
+ tx_queue_strategy: PrioritizationStrategy::GasFactorAndGasPrice,
pending_set: PendingSet::AlwaysSealing,
work_queue_size: 5,
enable_resubmission: true,
diff --git a/ethcore/src/miner/mod.rs b/ethcore/src/miner/mod.rs
index 8dfddf483a3..5fe8dbf44e7 100644
--- a/ethcore/src/miner/mod.rs
+++ b/ethcore/src/miner/mod.rs
@@ -47,7 +47,7 @@ mod transaction_queue;
mod work_notify;
mod price_info;
-pub use self::transaction_queue::{TransactionQueue, AccountDetails, TransactionOrigin};
+pub use self::transaction_queue::{TransactionQueue, PrioritizationStrategy, AccountDetails, TransactionOrigin};
pub use self::miner::{Miner, MinerOptions, PendingSet, GasPricer, GasPriceCalibratorOptions, GasLimit};
pub use self::external::{ExternalMiner, ExternalMinerService};
pub use client::TransactionImportResult;
diff --git a/ethcore/src/miner/transaction_queue.rs b/ethcore/src/miner/transaction_queue.rs
index fdb652780a6..9e47a846749 100644
--- a/ethcore/src/miner/transaction_queue.rs
+++ b/ethcore/src/miner/transaction_queue.rs
@@ -49,7 +49,7 @@
//! balance: U256::from(1_000_000),
//! };
//!
-//! let mut txq = TransactionQueue::new();
+//! let mut txq = TransactionQueue::default();
//! txq.add(st2.clone(), &default_account_details, TransactionOrigin::External).unwrap();
//! txq.add(st1.clone(), &default_account_details, TransactionOrigin::External).unwrap();
//!
@@ -130,11 +130,20 @@ struct TransactionOrder {
/// (e.g. Tx(nonce:5), State(nonce:0) -> height: 5)
/// High nonce_height = Low priority (processed later)
nonce_height: U256,
- /// Gas specified in the transaction.
- gas: U256,
/// Gas Price of the transaction.
/// Low gas price = Low priority (processed later)
gas_price: U256,
+ /// Gas usage priority factor. Usage depends on strategy.
+ /// Represents the linear increment in required gas price for heavy transactions.
+ ///
+ /// High gas limit + Low gas price = Low priority
+ /// High gas limit + High gas price = High priority
+ gas_factor: U256,
+ /// Gas (limit) of the transaction. Usage depends on strategy.
+ /// Low gas limit = High priority (processed earlier)
+ gas: U256,
+ /// Transaction ordering strategy
+ strategy: PrioritizationStrategy,
/// Hash to identify associated transaction
hash: H256,
/// Origin of the transaction
@@ -145,11 +154,15 @@ struct TransactionOrder {
impl TransactionOrder {
- fn for_transaction(tx: &VerifiedTransaction, base_nonce: U256) -> Self {
+
+ fn for_transaction(tx: &VerifiedTransaction, base_nonce: U256, min_gas_price: U256, strategy: PrioritizationStrategy) -> Self {
+ let factor = (tx.transaction.gas >> 15) * min_gas_price;
TransactionOrder {
nonce_height: tx.nonce() - base_nonce,
- gas: tx.transaction.gas.clone(),
gas_price: tx.transaction.gas_price,
+ gas: tx.transaction.gas,
+ gas_factor: factor,
+ strategy: strategy,
hash: tx.hash(),
origin: tx.origin,
penalties: 0,
@@ -197,11 +210,28 @@ impl Ord for TransactionOrder {
return self.origin.cmp(&b.origin);
}
+ match self.strategy {
+ PrioritizationStrategy::GasAndGasPrice => {
+ if self.gas != b.gas {
+ return self.gas.cmp(&b.gas);
+ }
+ },
+ PrioritizationStrategy::GasFactorAndGasPrice => {
+ // avoiding overflows
+ // (gp1 - g1) > (gp2 - g2) <=>
+ // (gp1 + g2) > (gp2 + g1)
+ let f_a = self.gas_price + b.gas_factor;
+ let f_b = b.gas_price + self.gas_factor;
+ if f_a != f_b {
+ return f_b.cmp(&f_a);
+ }
+ },
+ PrioritizationStrategy::GasPriceOnly => {},
+ }
+
// Then compare gas_prices
- let a_gas = self.gas_price;
- let b_gas = b.gas_price;
- if a_gas != b_gas {
- return b_gas.cmp(&a_gas);
+ if self.gas_price != b.gas_price {
+ return b.gas_price.cmp(&self.gas_price);
}
// Compare hashes
@@ -326,14 +356,14 @@ impl TransactionSet {
let to_drop : Vec<(Address, U256)> = {
self.by_priority
.iter()
- .skip_while(|order| {
+ .filter(|order| {
count = count + 1;
let r = gas.overflowing_add(order.gas);
if r.1 { return false }
gas = r.0;
// Own and retracted transactions are allowed to go above the gas limit, bot not above the count limit.
- (gas <= self.gas_limit || order.origin == TransactionOrigin::Local || order.origin == TransactionOrigin::RetractedBlock) &&
- count <= self.limit
+ (gas > self.gas_limit && order.origin != TransactionOrigin::Local && order.origin != TransactionOrigin::RetractedBlock) ||
+ count > self.limit
})
.map(|order| by_hash.get(&order.hash)
.expect("All transactions in `self.by_priority` and `self.by_address` are kept in sync with `by_hash`."))
@@ -345,6 +375,7 @@ impl TransactionSet {
.fold(HashMap::new(), |mut removed, (sender, nonce)| {
let order = self.drop(&sender, &nonce)
.expect("Transaction has just been found in `by_priority`; so it is in `by_address` also.");
+ trace!(target: "txqueue", "Dropped out of limit transaction: {:?}", order.hash);
by_hash.remove(&order.hash)
.expect("hash is in `by_priorty`; all hashes in `by_priority` must be in `by_hash`; qed");
@@ -414,8 +445,32 @@ pub struct AccountDetails {
/// Transactions with `gas > (gas_limit + gas_limit * Factor(in percents))` are not imported to the queue.
const GAS_LIMIT_HYSTERESIS: usize = 10; // (100/GAS_LIMIT_HYSTERESIS) %
+/// Describes the strategy used to prioritize transactions in the queue.
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub enum PrioritizationStrategy {
+ /// Use only gas price. Disregards the actual computation cost of the transaction.
+ /// i.e. Higher gas price = Higher priority
+ GasPriceOnly,
+ /// Use gas limit and then gas price.
+ /// i.e. Higher gas limit = Lower priority
+ GasAndGasPrice,
+ /// Calculate and use priority based on gas and gas price.
+ /// PRIORITY = GAS_PRICE - GAS/2^15 * MIN_GAS_PRICE
+ ///
+ /// Rationale:
+ /// Heavy transactions are paying linear cost (GAS * GAS_PRICE)
+ /// while the computation might be more expensive.
+ ///
+ /// i.e.
+ /// 1M gas tx with `gas_price=30*min` has the same priority
+ /// as 32k gas tx with `gas_price=min`
+ GasFactorAndGasPrice,
+}
+
/// `TransactionQueue` implementation
pub struct TransactionQueue {
+ /// Prioritization strategy for this queue
+ strategy: PrioritizationStrategy,
/// Gas Price threshold for transactions that can be imported to this queue (defaults to 0)
minimal_gas_price: U256,
/// The maximum amount of gas any individual transaction may use.
@@ -434,18 +489,18 @@ pub struct TransactionQueue {
impl Default for TransactionQueue {
fn default() -> Self {
- TransactionQueue::new()
+ TransactionQueue::new(PrioritizationStrategy::GasPriceOnly)
}
}
impl TransactionQueue {
/// Creates new instance of this Queue
- pub fn new() -> Self {
- Self::with_limits(1024, !U256::zero(), !U256::zero())
+ pub fn new(strategy: PrioritizationStrategy) -> Self {
+ Self::with_limits(strategy, 1024, !U256::zero(), !U256::zero())
}
/// Create new instance of this Queue with specified limits
- pub fn with_limits(limit: usize, gas_limit: U256, tx_gas_limit: U256) -> Self {
+ pub fn with_limits(strategy: PrioritizationStrategy, limit: usize, gas_limit: U256, tx_gas_limit: U256) -> Self {
let current = TransactionSet {
by_priority: BTreeSet::new(),
by_address: Table::new(),
@@ -463,6 +518,7 @@ impl TransactionQueue {
};
TransactionQueue {
+ strategy: strategy,
minimal_gas_price: U256::zero(),
tx_gas_limit: tx_gas_limit,
gas_limit: !U256::zero(),
@@ -678,6 +734,8 @@ impl TransactionQueue {
let nonce = transaction.nonce();
let current_nonce = fetch_account(&sender).nonce;
+ trace!(target: "txqueue", "Removing invalid transaction: {:?}", transaction.hash());
+
// Remove from future
let order = self.future.drop(&sender, &nonce);
if order.is_some() {
@@ -841,6 +899,7 @@ impl TransactionQueue {
return Err(TransactionError::AlreadyImported);
}
+ let min_gas_price = (self.minimal_gas_price, self.strategy);
let address = tx.sender();
let nonce = tx.nonce();
let hash = tx.hash();
@@ -878,7 +937,7 @@ impl TransactionQueue {
if nonce > next_nonce {
// We have a gap - put to future.
// Insert transaction (or replace old one with lower gas price)
- try!(check_too_cheap(Self::replace_transaction(tx, state_nonce, &mut self.future, &mut self.by_hash)));
+ try!(check_too_cheap(Self::replace_transaction(tx, state_nonce, min_gas_price, &mut self.future, &mut self.by_hash)));
// Enforce limit in Future
let removed = self.future.enforce_limit(&mut self.by_hash);
// Return an error if this transaction was not imported because of limit.
@@ -894,7 +953,7 @@ impl TransactionQueue {
self.move_matching_future_to_current(address, nonce + U256::one(), state_nonce);
// Replace transaction if any
- try!(check_too_cheap(Self::replace_transaction(tx, state_nonce, &mut self.current, &mut self.by_hash)));
+ try!(check_too_cheap(Self::replace_transaction(tx, state_nonce, min_gas_price, &mut self.current, &mut self.by_hash)));
// Keep track of highest nonce stored in current
let new_max = self.last_nonces.get(&address).map_or(nonce, |n| cmp::max(nonce, *n));
self.last_nonces.insert(address, new_max);
@@ -931,8 +990,8 @@ impl TransactionQueue {
///
/// Returns `true` if transaction actually got to the queue (`false` if there was already a transaction with higher
/// gas_price)
- fn replace_transaction(tx: VerifiedTransaction, base_nonce: U256, set: &mut TransactionSet, by_hash: &mut HashMap) -> bool {
- let order = TransactionOrder::for_transaction(&tx, base_nonce);
+ fn replace_transaction(tx: VerifiedTransaction, base_nonce: U256, min_gas_price: (U256, PrioritizationStrategy), set: &mut TransactionSet, by_hash: &mut HashMap) -> bool {
+ let order = TransactionOrder::for_transaction(&tx, base_nonce, min_gas_price.0, min_gas_price.1);
let hash = tx.hash();
let address = tx.sender();
let nonce = tx.nonce();
@@ -953,12 +1012,14 @@ impl TransactionQueue {
let old_fee = old.gas_price;
let new_fee = order.gas_price;
if old_fee.cmp(&new_fee) == Ordering::Greater {
+ trace!(target: "txqueue", "Didn't insert transaction because gas price was too low: {:?} ({:?} stays in the queue)", order.hash, old.hash);
// Put back old transaction since it has greater priority (higher gas_price)
set.insert(address, nonce, old);
// and remove new one
by_hash.remove(&order.hash).expect("The hash has been just inserted and no other line is altering `by_hash`.");
false
} else {
+ trace!(target: "txqueue", "Replaced transaction: {:?} with transaction with higher gas price: {:?}", old.hash, order.hash);
// Make sure we remove old transaction entirely
by_hash.remove(&old.hash).expect("The hash is coming from `future` so it has to be in `by_hash`.");
true
@@ -1010,12 +1071,12 @@ mod test {
fn default_gas_val() -> U256 { 100_000.into() }
fn default_gas_price() -> U256 { 1.into() }
- fn new_unsigned_tx(nonce: U256, gas_price: U256) -> Transaction {
+ fn new_unsigned_tx(nonce: U256, gas: U256, gas_price: U256) -> Transaction {
Transaction {
action: Action::Create,
value: U256::from(100),
data: "3331600055".from_hex().unwrap(),
- gas: default_gas_val(),
+ gas: gas,
gas_price: gas_price,
nonce: nonce
}
@@ -1023,7 +1084,12 @@ mod test {
fn new_tx(nonce: U256, gas_price: U256) -> SignedTransaction {
let keypair = Random.generate().unwrap();
- new_unsigned_tx(nonce, gas_price).sign(keypair.secret())
+ new_unsigned_tx(nonce, default_gas_val(), gas_price).sign(keypair.secret())
+ }
+
+ fn new_tx_with_gas(gas: U256, gas_price: U256) -> SignedTransaction {
+ let keypair = Random.generate().unwrap();
+ new_unsigned_tx(default_nonce(), gas, gas_price).sign(keypair.secret())
}
fn new_tx_default() -> SignedTransaction {
@@ -1038,8 +1104,8 @@ mod test {
}
fn new_tx_pair(nonce: U256, gas_price: U256, nonce_increment: U256, gas_price_increment: U256) -> (SignedTransaction, SignedTransaction) {
- let tx1 = new_unsigned_tx(nonce, gas_price);
- let tx2 = new_unsigned_tx(nonce + nonce_increment, gas_price + gas_price_increment);
+ let tx1 = new_unsigned_tx(nonce, default_gas_val(), gas_price);
+ let tx2 = new_unsigned_tx(nonce + nonce_increment, default_gas_val(), gas_price + gas_price_increment);
let keypair = Random.generate().unwrap();
let secret = &keypair.secret();
@@ -1049,8 +1115,8 @@ mod test {
/// Returns two consecutive transactions, both with increased gas price
fn new_tx_pair_with_gas_price_increment(gas_price_increment: U256) -> (SignedTransaction, SignedTransaction) {
let gas = default_gas_price() + gas_price_increment;
- let tx1 = new_unsigned_tx(default_nonce(), gas);
- let tx2 = new_unsigned_tx(default_nonce() + 1.into(), gas);
+ let tx1 = new_unsigned_tx(default_nonce(), default_gas_val(), gas);
+ let tx2 = new_unsigned_tx(default_nonce() + 1.into(), default_gas_val(), gas);
let keypair = Random.generate().unwrap();
let secret = &keypair.secret();
@@ -1077,17 +1143,21 @@ mod test {
assert_eq!(TransactionOrigin::External.cmp(&TransactionOrigin::RetractedBlock), Ordering::Greater);
}
+ fn transaction_order(tx: &VerifiedTransaction, nonce: U256) -> TransactionOrder {
+ TransactionOrder::for_transaction(tx, nonce, 0.into(), PrioritizationStrategy::GasPriceOnly)
+ }
+
#[test]
fn should_return_correct_nonces_when_dropped_because_of_limit() {
// given
- let mut txq = TransactionQueue::with_limits(2, !U256::zero(), !U256::zero());
+ let mut txq = TransactionQueue::with_limits(PrioritizationStrategy::GasPriceOnly, 2, !U256::zero(), !U256::zero());
let (tx1, tx2) = new_tx_pair(123.into(), 1.into(), 1.into(), 0.into());
let sender = tx1.sender().unwrap();
let nonce = tx1.nonce;
txq.add(tx1.clone(), &default_account_details, TransactionOrigin::External).unwrap();
txq.add(tx2.clone(), &default_account_details, TransactionOrigin::External).unwrap();
assert_eq!(txq.status().pending, 2);
- assert_eq!(txq.last_nonce(&sender), Some(nonce + U256::one()));
+ assert_eq!(txq.last_nonce(&sender), Some(nonce + 1.into()));
// when
let tx = new_tx(123.into(), 1.into());
@@ -1133,9 +1203,9 @@ mod test {
x
};
// Insert both transactions
- let order1 = TransactionOrder::for_transaction(&tx1, U256::zero());
+ let order1 = transaction_order(&tx1, U256::zero());
set.insert(tx1.sender(), tx1.nonce(), order1.clone());
- let order2 = TransactionOrder::for_transaction(&tx2, U256::zero());
+ let order2 = transaction_order(&tx2, U256::zero());
set.insert(tx2.sender(), tx2.nonce(), order2.clone());
assert_eq!(set.by_priority.len(), 2);
assert_eq!(set.by_address.len(), 2);
@@ -1176,7 +1246,7 @@ mod test {
x
};
// Insert both transactions
- let order1 = TransactionOrder::for_transaction(&tx1, U256::zero());
+ let order1 = transaction_order(&tx1, U256::zero());
set.insert(tx1.sender(), tx1.nonce(), order1.clone());
assert_eq!(set.by_priority.len(), 1);
assert_eq!(set.by_address.len(), 1);
@@ -1184,7 +1254,7 @@ mod test {
assert_eq!(*set.by_gas_price.iter().next().unwrap().0, 1.into());
assert_eq!(set.by_gas_price.iter().next().unwrap().1.len(), 1);
// Two different orders (imagine nonce changed in the meantime)
- let order2 = TransactionOrder::for_transaction(&tx2, U256::one());
+ let order2 = transaction_order(&tx2, U256::one());
set.insert(tx2.sender(), tx2.nonce(), order2.clone());
assert_eq!(set.by_priority.len(), 1);
assert_eq!(set.by_address.len(), 1);
@@ -1213,10 +1283,10 @@ mod test {
};
let tx = new_tx_default();
let tx1 = VerifiedTransaction::new(tx.clone(), TransactionOrigin::External).unwrap();
- let order1 = TransactionOrder::for_transaction(&tx1, U256::zero());
+ let order1 = TransactionOrder::for_transaction(&tx1, 0.into(), 1.into(), PrioritizationStrategy::GasPriceOnly);
assert!(set.insert(tx1.sender(), tx1.nonce(), order1).is_none());
let tx2 = VerifiedTransaction::new(tx, TransactionOrigin::External).unwrap();
- let order2 = TransactionOrder::for_transaction(&tx2, U256::zero());
+ let order2 = TransactionOrder::for_transaction(&tx2, 0.into(), 1.into(), PrioritizationStrategy::GasPriceOnly);
assert!(set.insert(tx2.sender(), tx2.nonce(), order2).is_some());
}
@@ -1233,7 +1303,7 @@ mod test {
assert_eq!(set.gas_price_entry_limit(), 0.into());
let tx = new_tx_default();
let tx1 = VerifiedTransaction::new(tx.clone(), TransactionOrigin::External).unwrap();
- let order1 = TransactionOrder::for_transaction(&tx1, U256::zero());
+ let order1 = TransactionOrder::for_transaction(&tx1, 0.into(), 1.into(), PrioritizationStrategy::GasPriceOnly);
assert!(set.insert(tx1.sender(), tx1.nonce(), order1.clone()).is_none());
assert_eq!(set.gas_price_entry_limit(), 2.into());
}
@@ -1241,7 +1311,7 @@ mod test {
#[test]
fn should_handle_same_transaction_imported_twice_with_different_state_nonces() {
// given
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
let (tx, tx2) = new_similar_tx_pair();
let prev_nonce = |a: &Address| AccountDetails{ nonce: default_account_details(a).nonce - U256::one(), balance:
!U256::zero() };
@@ -1266,7 +1336,7 @@ mod test {
#[test]
fn should_move_all_transactions_from_future() {
// given
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
let (tx, tx2) = new_tx_pair_default(1.into(), 1.into());
let prev_nonce = |a: &Address| AccountDetails{ nonce: default_account_details(a).nonce - U256::one(), balance:
!U256::zero() };
@@ -1292,7 +1362,7 @@ mod test {
#[test]
fn should_import_tx() {
// given
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
let tx = new_tx_default();
// when
@@ -1304,10 +1374,77 @@ mod test {
assert_eq!(stats.pending, 1);
}
+ #[test]
+ fn should_order_by_gas() {
+ // given
+ let mut txq = TransactionQueue::new(PrioritizationStrategy::GasAndGasPrice);
+ let tx1 = new_tx_with_gas(50000.into(), 40.into());
+ let tx2 = new_tx_with_gas(40000.into(), 30.into());
+ let tx3 = new_tx_with_gas(30000.into(), 10.into());
+ let tx4 = new_tx_with_gas(50000.into(), 20.into());
+ txq.set_minimal_gas_price(15.into());
+
+ // when
+ let res1 = txq.add(tx1, &default_account_details, TransactionOrigin::External);
+ let res2 = txq.add(tx2, &default_account_details, TransactionOrigin::External);
+ let res3 = txq.add(tx3, &default_account_details, TransactionOrigin::External);
+ let res4 = txq.add(tx4, &default_account_details, TransactionOrigin::External);
+
+ // then
+ assert_eq!(res1.unwrap(), TransactionImportResult::Current);
+ assert_eq!(res2.unwrap(), TransactionImportResult::Current);
+ assert_eq!(unwrap_tx_err(res3), TransactionError::InsufficientGasPrice {
+ minimal: U256::from(15),
+ got: U256::from(10),
+ });
+ assert_eq!(res4.unwrap(), TransactionImportResult::Current);
+ let stats = txq.status();
+ assert_eq!(stats.pending, 3);
+ assert_eq!(txq.top_transactions()[0].gas, 40000.into());
+ assert_eq!(txq.top_transactions()[1].gas, 50000.into());
+ assert_eq!(txq.top_transactions()[2].gas, 50000.into());
+ assert_eq!(txq.top_transactions()[1].gas_price, 40.into());
+ assert_eq!(txq.top_transactions()[2].gas_price, 20.into());
+ }
+
+ #[test]
+ fn should_order_by_gas_factor() {
+ // given
+ let mut txq = TransactionQueue::new(PrioritizationStrategy::GasFactorAndGasPrice);
+
+ let tx1 = new_tx_with_gas(150_000.into(), 40.into());
+ let tx2 = new_tx_with_gas(40_000.into(), 16.into());
+ let tx3 = new_tx_with_gas(30_000.into(), 15.into());
+ let tx4 = new_tx_with_gas(150_000.into(), 62.into());
+ txq.set_minimal_gas_price(15.into());
+
+ // when
+ let res1 = txq.add(tx1, &default_account_details, TransactionOrigin::External);
+ let res2 = txq.add(tx2, &default_account_details, TransactionOrigin::External);
+ let res3 = txq.add(tx3, &default_account_details, TransactionOrigin::External);
+ let res4 = txq.add(tx4, &default_account_details, TransactionOrigin::External);
+
+ // then
+ assert_eq!(res1.unwrap(), TransactionImportResult::Current);
+ assert_eq!(res2.unwrap(), TransactionImportResult::Current);
+ assert_eq!(res3.unwrap(), TransactionImportResult::Current);
+ assert_eq!(res4.unwrap(), TransactionImportResult::Current);
+ let stats = txq.status();
+ assert_eq!(stats.pending, 4);
+ assert_eq!(txq.top_transactions()[0].gas, 30_000.into());
+ assert_eq!(txq.top_transactions()[1].gas, 150_000.into());
+ assert_eq!(txq.top_transactions()[2].gas, 40_000.into());
+ assert_eq!(txq.top_transactions()[3].gas, 150_000.into());
+ assert_eq!(txq.top_transactions()[0].gas_price, 15.into());
+ assert_eq!(txq.top_transactions()[1].gas_price, 62.into());
+ assert_eq!(txq.top_transactions()[2].gas_price, 16.into());
+ assert_eq!(txq.top_transactions()[3].gas_price, 40.into());
+ }
+
#[test]
fn gas_limit_should_never_overflow() {
// given
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
txq.set_gas_limit(U256::zero());
assert_eq!(txq.gas_limit, U256::zero());
@@ -1321,7 +1458,7 @@ mod test {
#[test]
fn should_not_import_transaction_above_gas_limit() {
// given
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
let tx = new_tx_default();
let gas = tx.gas;
let limit = gas / U256::from(2);
@@ -1344,7 +1481,7 @@ mod test {
#[test]
fn should_drop_transactions_from_senders_without_balance() {
// given
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
let tx = new_tx_default();
let account = |a: &Address| AccountDetails {
nonce: default_account_details(a).nonce,
@@ -1367,7 +1504,7 @@ mod test {
#[test]
fn should_not_import_transaction_below_min_gas_price_threshold_if_external() {
// given
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
let tx = new_tx_default();
txq.set_minimal_gas_price(tx.gas_price + U256::one());
@@ -1387,7 +1524,7 @@ mod test {
#[test]
fn should_import_transaction_below_min_gas_price_threshold_if_local() {
// given
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
let tx = new_tx_default();
txq.set_minimal_gas_price(tx.gas_price + U256::one());
@@ -1406,8 +1543,8 @@ mod test {
use rlp::{self, RlpStream, Stream};
// given
- let mut txq = TransactionQueue::new();
- let tx = new_unsigned_tx(123.into(), 1.into());
+ let mut txq = TransactionQueue::default();
+ let tx = new_unsigned_tx(123.into(), 100.into(), 1.into());
let stx = {
let mut s = RlpStream::new_list(9);
s.append(&tx.nonce);
@@ -1431,7 +1568,7 @@ mod test {
#[test]
fn should_import_txs_from_same_sender() {
// given
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
@@ -1449,7 +1586,7 @@ mod test {
#[test]
fn should_prioritize_local_transactions_within_same_nonce_height() {
// given
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
let tx = new_tx_default();
// the second one has same nonce but higher `gas_price`
let (_, tx2) = new_similar_tx_pair();
@@ -1470,7 +1607,7 @@ mod test {
#[test]
fn should_prioritize_reimported_transactions_within_same_nonce_height() {
// given
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
let tx = new_tx_default();
// the second one has same nonce but higher `gas_price`
let (_, tx2) = new_similar_tx_pair();
@@ -1491,7 +1628,7 @@ mod test {
#[test]
fn should_not_prioritize_local_transactions_with_different_nonce_height() {
// given
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
// when
@@ -1509,7 +1646,7 @@ mod test {
fn should_penalize_transactions_from_sender_in_future() {
// given
let prev_nonce = |a: &Address| AccountDetails{ nonce: default_account_details(a).nonce - U256::one(), balance: !U256::zero() };
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
// txa, txb - slightly bigger gas price to have consistent ordering
let (txa, txb) = new_tx_pair_default(1.into(), 0.into());
let (tx1, tx2) = new_tx_pair_with_gas_price_increment(3.into());
@@ -1538,7 +1675,7 @@ mod test {
#[test]
fn should_penalize_transactions_from_sender() {
// given
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
// txa, txb - slightly bigger gas price to have consistent ordering
let (txa, txb) = new_tx_pair_default(1.into(), 0.into());
let (tx1, tx2) = new_tx_pair_with_gas_price_increment(3.into());
@@ -1571,7 +1708,7 @@ mod test {
#[test]
fn should_return_pending_hashes() {
// given
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
@@ -1589,7 +1726,7 @@ mod test {
#[test]
fn should_put_transaction_to_futures_if_gap_detected() {
// given
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
let (tx, tx2) = new_tx_pair_default(2.into(), 0.into());
@@ -1615,7 +1752,7 @@ mod test {
!U256::zero() };
let next2_nonce = default_nonce() + U256::from(3);
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
txq.add(tx.clone(), &prev_nonce, TransactionOrigin::External).unwrap();
@@ -1634,12 +1771,12 @@ mod test {
#[test]
fn should_move_transactions_if_gap_filled() {
// given
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
let kp = Random.generate().unwrap();
let secret = kp.secret();
- let tx = new_unsigned_tx(123.into(), 1.into()).sign(secret);
- let tx1 = new_unsigned_tx(124.into(), 1.into()).sign(secret);
- let tx2 = new_unsigned_tx(125.into(), 1.into()).sign(secret);
+ let tx = new_unsigned_tx(123.into(), default_gas_val(), 1.into()).sign(secret);
+ let tx1 = new_unsigned_tx(124.into(), default_gas_val(), 1.into()).sign(secret);
+ let tx2 = new_unsigned_tx(125.into(), default_gas_val(), 1.into()).sign(secret);
txq.add(tx, &default_account_details, TransactionOrigin::External).unwrap();
assert_eq!(txq.status().pending, 1);
@@ -1661,7 +1798,7 @@ mod test {
#[test]
fn should_remove_transaction() {
// given
- let mut txq2 = TransactionQueue::new();
+ let mut txq2 = TransactionQueue::default();
let (tx, tx2) = new_tx_pair_default(3.into(), 0.into());
txq2.add(tx.clone(), &default_account_details, TransactionOrigin::External).unwrap();
txq2.add(tx2.clone(), &default_account_details, TransactionOrigin::External).unwrap();
@@ -1682,7 +1819,7 @@ mod test {
#[test]
fn should_move_transactions_to_future_if_gap_introduced() {
// given
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
let tx3 = new_tx_default();
txq.add(tx2.clone(), &default_account_details, TransactionOrigin::External).unwrap();
@@ -1703,7 +1840,7 @@ mod test {
#[test]
fn should_clear_queue() {
// given
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
// add
@@ -1723,7 +1860,7 @@ mod test {
#[test]
fn should_drop_old_transactions_when_hitting_the_limit() {
// given
- let mut txq = TransactionQueue::with_limits(1, !U256::zero(), !U256::zero());
+ let mut txq = TransactionQueue::with_limits(PrioritizationStrategy::GasPriceOnly, 1, !U256::zero(), !U256::zero());
let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
let sender = tx.sender().unwrap();
let nonce = tx.nonce;
@@ -1744,7 +1881,7 @@ mod test {
#[test]
fn should_limit_future_transactions() {
- let mut txq = TransactionQueue::with_limits(1, !U256::zero(), !U256::zero());
+ let mut txq = TransactionQueue::with_limits(PrioritizationStrategy::GasPriceOnly, 1, !U256::zero(), !U256::zero());
txq.current.set_limit(10);
let (tx1, tx2) = new_tx_pair_default(4.into(), 1.into());
let (tx3, tx4) = new_tx_pair_default(4.into(), 2.into());
@@ -1763,23 +1900,28 @@ mod test {
#[test]
fn should_limit_by_gas() {
- let mut txq = TransactionQueue::with_limits(100, default_gas_val() * U256::from(2), !U256::zero());
+ let mut txq = TransactionQueue::with_limits(PrioritizationStrategy::GasPriceOnly, 100, default_gas_val() * U256::from(2), !U256::zero());
let (tx1, tx2) = new_tx_pair_default(U256::from(1), U256::from(1));
let (tx3, tx4) = new_tx_pair_default(U256::from(1), U256::from(2));
- txq.add(tx1.clone(), &default_account_details, TransactionOrigin::External).ok();
- txq.add(tx2.clone(), &default_account_details, TransactionOrigin::External).ok();
- txq.add(tx3.clone(), &default_account_details, TransactionOrigin::External).ok();
- txq.add(tx4.clone(), &default_account_details, TransactionOrigin::External).ok();
+ txq.add(tx1.clone(), &default_account_details, TransactionOrigin::External).unwrap();
+ txq.add(tx2.clone(), &default_account_details, TransactionOrigin::External).unwrap();
+ txq.add(tx3.clone(), &default_account_details, TransactionOrigin::External).unwrap();
+ // limited by gas
+ txq.add(tx4.clone(), &default_account_details, TransactionOrigin::External).unwrap_err();
assert_eq!(txq.status().pending, 2);
}
#[test]
fn should_keep_own_transactions_above_gas_limit() {
- let mut txq = TransactionQueue::with_limits(100, default_gas_val() * U256::from(2), !U256::zero());
+ let mut txq = TransactionQueue::with_limits(PrioritizationStrategy::GasPriceOnly, 100, default_gas_val() * U256::from(2), !U256::zero());
let (tx1, tx2) = new_tx_pair_default(U256::from(1), U256::from(1));
let (tx3, tx4) = new_tx_pair_default(U256::from(1), U256::from(2));
+ let (tx5, tx6) = new_tx_pair_default(U256::from(1), U256::from(2));
txq.add(tx1.clone(), &default_account_details, TransactionOrigin::Local).unwrap();
txq.add(tx2.clone(), &default_account_details, TransactionOrigin::Local).unwrap();
+ txq.add(tx5.clone(), &default_account_details, TransactionOrigin::External).unwrap();
+ // Not accepted because of limit
+ txq.add(tx6.clone(), &default_account_details, TransactionOrigin::External).unwrap_err();
txq.add(tx3.clone(), &default_account_details, TransactionOrigin::Local).unwrap();
txq.add(tx4.clone(), &default_account_details, TransactionOrigin::Local).unwrap();
assert_eq!(txq.status().pending, 4);
@@ -1787,10 +1929,10 @@ mod test {
#[test]
fn should_drop_transactions_with_old_nonces() {
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
let tx = new_tx_default();
let last_nonce = tx.nonce + U256::one();
- let fetch_last_nonce = |_a: &Address| AccountDetails{ nonce: last_nonce, balance: !U256::zero() };
+ let fetch_last_nonce = |_a: &Address| AccountDetails { nonce: last_nonce, balance: !U256::zero() };
// when
let res = txq.add(tx, &fetch_last_nonce, TransactionOrigin::External);
@@ -1807,7 +1949,7 @@ mod test {
// given
let nonce = |a: &Address| AccountDetails { nonce: default_account_details(a).nonce + U256::one(),
balance: !U256::zero() };
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
let (_tx1, tx2) = new_tx_pair_default(1.into(), 0.into());
txq.add(tx2.clone(), &default_account_details, TransactionOrigin::External).unwrap();
assert_eq!(txq.status().future, 1);
@@ -1826,7 +1968,7 @@ mod test {
#[test]
fn should_accept_same_transaction_twice_if_removed() {
// given
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into());
txq.add(tx1.clone(), &default_account_details, TransactionOrigin::External).unwrap();
txq.add(tx2.clone(), &default_account_details, TransactionOrigin::External).unwrap();
@@ -1847,7 +1989,7 @@ mod test {
#[test]
fn should_not_move_to_future_if_state_nonce_is_higher() {
// given
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
let tx3 = new_tx_default();
txq.add(tx2.clone(), &default_account_details, TransactionOrigin::External).unwrap();
@@ -1870,9 +2012,9 @@ mod test {
fn should_replace_same_transaction_when_has_higher_fee() {
init_log();
// given
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
let keypair = Random.generate().unwrap();
- let tx = new_unsigned_tx(123.into(), 1.into()).sign(keypair.secret());
+ let tx = new_unsigned_tx(123.into(), default_gas_val(), 1.into()).sign(keypair.secret());
let tx2 = {
let mut tx2 = (*tx).clone();
tx2.gas_price = U256::from(200);
@@ -1893,9 +2035,9 @@ mod test {
#[test]
fn should_replace_same_transaction_when_importing_to_futures() {
// given
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
let keypair = Random.generate().unwrap();
- let tx0 = new_unsigned_tx(123.into(), 1.into()).sign(keypair.secret());
+ let tx0 = new_unsigned_tx(123.into(), default_gas_val(), 1.into()).sign(keypair.secret());
let tx1 = {
let mut tx1 = (*tx0).clone();
tx1.nonce = U256::from(124);
@@ -1927,7 +2069,7 @@ mod test {
!U256::zero() };
let next_nonce = |a: &Address| AccountDetails{ nonce: default_account_details(a).nonce + U256::one(), balance:
!U256::zero() };
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into());
txq.add(tx1.clone(), &previous_nonce, TransactionOrigin::External).unwrap();
txq.add(tx2, &previous_nonce, TransactionOrigin::External).unwrap();
@@ -1945,7 +2087,7 @@ mod test {
#[test]
fn should_return_none_when_transaction_from_given_address_does_not_exist() {
// given
- let txq = TransactionQueue::new();
+ let txq = TransactionQueue::default();
// then
assert_eq!(txq.last_nonce(&Address::default()), None);
@@ -1954,7 +2096,7 @@ mod test {
#[test]
fn should_return_correct_nonce_when_transactions_from_given_address_exist() {
// given
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
let tx = new_tx_default();
let from = tx.sender().unwrap();
let nonce = tx.nonce;
@@ -1970,7 +2112,7 @@ mod test {
#[test]
fn should_remove_old_transaction_even_if_newer_transaction_was_not_known() {
// given
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into());
let (nonce1, nonce2) = (tx1.nonce, tx2.nonce);
let details1 = |_a: &Address| AccountDetails { nonce: nonce1, balance: !U256::zero() };
@@ -1988,7 +2130,7 @@ mod test {
#[test]
fn should_return_valid_last_nonce_after_remove_all() {
// given
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
let (tx1, tx2) = new_tx_pair_default(4.into(), 0.into());
let sender = tx1.sender().unwrap();
let (nonce1, nonce2) = (tx1.nonce, tx2.nonce);
@@ -2012,7 +2154,7 @@ mod test {
#[test]
fn should_return_true_if_there_is_local_transaction_pending() {
// given
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into());
assert_eq!(txq.has_local_pending_transactions(), false);
@@ -2028,7 +2170,7 @@ mod test {
#[test]
fn should_keep_right_order_in_future() {
// given
- let mut txq = TransactionQueue::with_limits(1, !U256::zero(), !U256::zero());
+ let mut txq = TransactionQueue::with_limits(PrioritizationStrategy::GasPriceOnly, 1, !U256::zero(), !U256::zero());
let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into());
let prev_nonce = |a: &Address| AccountDetails { nonce: default_account_details(a).nonce - U256::one(), balance:
default_account_details(a).balance };
@@ -2045,15 +2187,16 @@ mod test {
#[test]
fn should_return_correct_last_nonce() {
// given
- let mut txq = TransactionQueue::new();
+ let mut txq = TransactionQueue::default();
let (tx1, tx2, tx2_2, tx3) = {
let keypair = Random.generate().unwrap();
let secret = &keypair.secret();
let nonce = 123.into();
- let tx = new_unsigned_tx(nonce, 1.into());
- let tx2 = new_unsigned_tx(nonce + 1.into(), 1.into());
- let tx2_2 = new_unsigned_tx(nonce + 1.into(), 5.into());
- let tx3 = new_unsigned_tx(nonce + 2.into(), 1.into());
+ let gas = default_gas_val();
+ let tx = new_unsigned_tx(nonce, gas, 1.into());
+ let tx2 = new_unsigned_tx(nonce + 1.into(), gas, 1.into());
+ let tx2_2 = new_unsigned_tx(nonce + 1.into(), gas, 5.into());
+ let tx3 = new_unsigned_tx(nonce + 2.into(), gas, 1.into());
(tx.sign(secret), tx2.sign(secret), tx2_2.sign(secret), tx3.sign(secret))
diff --git a/ethcore/src/snapshot/account.rs b/ethcore/src/snapshot/account.rs
index bc1faea3f5b..30f2cd95677 100644
--- a/ethcore/src/snapshot/account.rs
+++ b/ethcore/src/snapshot/account.rs
@@ -19,12 +19,20 @@
use account_db::{AccountDB, AccountDBMut};
use snapshot::Error;
-use util::{U256, FixedHash, H256, Bytes, HashDB, SHA3_EMPTY};
+use util::{U256, FixedHash, H256, Bytes, HashDB, SHA3_EMPTY, SHA3_NULL_RLP};
use util::trie::{TrieDB, Trie};
use rlp::{Rlp, RlpStream, Stream, UntrustedRlp, View};
use std::collections::{HashMap, HashSet};
+// An empty account -- these are replaced with RLP null data for a space optimization.
+const ACC_EMPTY: Account = Account {
+ nonce: U256([0, 0, 0, 0]),
+ balance: U256([0, 0, 0, 0]),
+ storage_root: SHA3_NULL_RLP,
+ code_hash: SHA3_EMPTY,
+};
+
// whether an encoded account has code and how it is referred to.
#[repr(u8)]
enum CodeState {
@@ -88,6 +96,10 @@ impl Account {
// walk the account's storage trie, returning an RLP item containing the
// account properties and the storage.
pub fn to_fat_rlp(&self, acct_db: &AccountDB, used_code: &mut HashSet) -> Result {
+ if self == &ACC_EMPTY {
+ return Ok(::rlp::NULL_RLP.to_vec());
+ }
+
let db = try!(TrieDB::new(acct_db, &self.storage_root));
let mut pairs = Vec::new();
@@ -142,6 +154,11 @@ impl Account {
) -> Result<(Self, Option), Error> {
use util::{TrieDBMut, TrieMut};
+ // check for special case of empty account.
+ if rlp.is_empty() {
+ return Ok((ACC_EMPTY, None));
+ }
+
let nonce = try!(rlp.val_at(0));
let balance = try!(rlp.val_at(1));
let code_state: CodeState = {
@@ -214,7 +231,7 @@ mod tests {
use std::collections::{HashSet, HashMap};
- use super::Account;
+ use super::{ACC_EMPTY, Account};
#[test]
fn encoding_basic() {
@@ -310,4 +327,14 @@ mod tests {
assert_eq!(maybe_code, Some(b"this is definitely code".to_vec()));
assert_eq!(acc, account1);
}
+
+ #[test]
+ fn encoding_empty_acc() {
+ let mut db = get_temp_state_db();
+ let mut used_code = HashSet::new();
+ let code_map = HashMap::new();
+
+ assert_eq!(ACC_EMPTY.to_fat_rlp(&AccountDB::new(db.as_hashdb(), &Address::default()), &mut used_code).unwrap(), ::rlp::NULL_RLP.to_vec());
+ assert_eq!(Account::from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &Address::default()), UntrustedRlp::new(&::rlp::NULL_RLP), &code_map).unwrap(), (ACC_EMPTY, None));
+ }
}
diff --git a/ethcore/src/snapshot/service.rs b/ethcore/src/snapshot/service.rs
index 5243a47929f..63232ad5bde 100644
--- a/ethcore/src/snapshot/service.rs
+++ b/ethcore/src/snapshot/service.rs
@@ -346,7 +346,7 @@ impl Service {
self.taking_snapshot.store(false, Ordering::SeqCst);
if let Err(e) = res {
- if client.chain_info().best_block_number >= num + ::client::HISTORY {
+ if client.chain_info().best_block_number >= num + client.pruning_history() {
// "Cancelled" is mincing words a bit -- what really happened
// is that the state we were snapshotting got pruned out
// before we could finish.
diff --git a/ethcore/src/state/mod.rs b/ethcore/src/state/mod.rs
index 39c8bbc1114..6e34e93676b 100644
--- a/ethcore/src/state/mod.rs
+++ b/ethcore/src/state/mod.rs
@@ -239,15 +239,15 @@ impl State {
/// Create a recoverable snaphot of this state.
pub fn snapshot(&mut self) {
- self.snapshots.borrow_mut().push(HashMap::new());
+ self.snapshots.get_mut().push(HashMap::new());
}
/// Merge last snapshot with previous.
pub fn discard_snapshot(&mut self) {
// merge with previous snapshot
- let last = self.snapshots.borrow_mut().pop();
+ let last = self.snapshots.get_mut().pop();
if let Some(mut snapshot) = last {
- if let Some(ref mut prev) = self.snapshots.borrow_mut().last_mut() {
+ if let Some(ref mut prev) = self.snapshots.get_mut().last_mut() {
if prev.is_empty() {
**prev = snapshot;
} else {
@@ -261,11 +261,11 @@ impl State {
/// Revert to the last snapshot and discard it.
pub fn revert_to_snapshot(&mut self) {
- if let Some(mut snapshot) = self.snapshots.borrow_mut().pop() {
+ if let Some(mut snapshot) = self.snapshots.get_mut().pop() {
for (k, v) in snapshot.drain() {
match v {
Some(v) => {
- match self.cache.borrow_mut().entry(k) {
+ match self.cache.get_mut().entry(k) {
Entry::Occupied(mut e) => {
// Merge snapshotted changes back into the main account
// storage preserving the cache.
@@ -277,7 +277,7 @@ impl State {
}
},
None => {
- match self.cache.borrow_mut().entry(k) {
+ match self.cache.get_mut().entry(k) {
Entry::Occupied(e) => {
if e.get().is_dirty() {
e.remove();
@@ -578,14 +578,14 @@ impl State {
}
fn query_pod(&mut self, query: &PodState) {
- for (address, pod_account) in query.get() {
- self.ensure_cached(address, RequireCache::Code, |a| {
- if a.is_some() {
- for key in pod_account.storage.keys() {
- self.storage_at(address, key);
- }
- }
- });
+ for (address, pod_account) in query.get().into_iter()
+ .filter(|&(ref a, _)| self.ensure_cached(a, RequireCache::Code, |a| a.is_some()))
+ {
+ // needs to be split into two parts for the refcell code here
+ // to work.
+ for key in pod_account.storage.keys() {
+ self.storage_at(address, key);
+ }
}
}
@@ -1797,4 +1797,20 @@ fn create_empty() {
assert_eq!(state.root().hex(), "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421");
}
+#[test]
+fn should_not_panic_on_state_diff_with_storage() {
+ let state = get_temp_state();
+ let mut state = state.reference().clone();
+
+ let a: Address = 0xa.into();
+ state.init_code(&a, b"abcdefg".to_vec());
+ state.add_balance(&a, &256.into());
+ state.set_storage(&a, 0xb.into(), 0xc.into());
+
+ let mut new_state = state.clone();
+ new_state.set_storage(&a, 0xb.into(), 0xd.into());
+
+ new_state.diff_from(state);
+}
+
}
diff --git a/ethcore/src/state_db.rs b/ethcore/src/state_db.rs
index 8724a5d73e9..01f3845709d 100644
--- a/ethcore/src/state_db.rs
+++ b/ethcore/src/state_db.rs
@@ -31,8 +31,7 @@ pub const DEFAULT_ACCOUNT_PRESET: usize = 1000000;
pub const ACCOUNT_BLOOM_HASHCOUNT_KEY: &'static [u8] = b"account_hash_count";
-const STATE_CACHE_BLOCKS: usize = 8;
-
+const STATE_CACHE_BLOCKS: usize = 12;
/// Shared canonical state cache.
struct AccountCache {
@@ -182,19 +181,24 @@ impl StateDB {
Ok(())
}
- /// Commit all recent insert operations and canonical historical commits' removals from the
- /// old era to the backing database, reverting any non-canonical historical commit's inserts.
- pub fn commit(&mut self, batch: &mut DBTransaction, now: u64, id: &H256, end: Option<(u64, H256)>) -> Result {
+ /// Journal all recent operations under the given era and ID.
+ pub fn journal_under(&mut self, batch: &mut DBTransaction, now: u64, id: &H256) -> Result {
{
let mut bloom_lock = self.account_bloom.lock();
try!(Self::commit_bloom(batch, bloom_lock.drain_journal()));
}
- let records = try!(self.db.commit(batch, now, id, end));
+ let records = try!(self.db.journal_under(batch, now, id));
self.commit_hash = Some(id.clone());
self.commit_number = Some(now);
Ok(records)
}
+ /// Mark a given candidate from an ancient era as canonical, enacting its removals from the
+ /// backing database and reverting any non-canonical historical commit's insertions.
+ pub fn mark_canonical(&mut self, batch: &mut DBTransaction, end_era: u64, canon_id: &H256) -> Result {
+ self.db.mark_canonical(batch, end_era, canon_id)
+ }
+
/// Propagate local cache into the global cache and synchonize
/// the global cache with the best block state.
/// This function updates the global cache by removing entries
@@ -448,30 +452,30 @@ mod tests {
// balance [ 5 5 4 3 2 2 ]
let mut s = state_db.boxed_clone_canon(&root_parent);
s.add_to_account_cache(address, Some(Account::new_basic(2.into(), 0.into())), false);
- s.commit(&mut batch, 0, &h0, None).unwrap();
+ s.journal_under(&mut batch, 0, &h0).unwrap();
s.sync_cache(&[], &[], true);
let mut s = state_db.boxed_clone_canon(&h0);
- s.commit(&mut batch, 1, &h1a, None).unwrap();
+ s.journal_under(&mut batch, 1, &h1a).unwrap();
s.sync_cache(&[], &[], true);
let mut s = state_db.boxed_clone_canon(&h0);
s.add_to_account_cache(address, Some(Account::new_basic(3.into(), 0.into())), true);
- s.commit(&mut batch, 1, &h1b, None).unwrap();
+ s.journal_under(&mut batch, 1, &h1b).unwrap();
s.sync_cache(&[], &[], false);
let mut s = state_db.boxed_clone_canon(&h1b);
s.add_to_account_cache(address, Some(Account::new_basic(4.into(), 0.into())), true);
- s.commit(&mut batch, 2, &h2b, None).unwrap();
+ s.journal_under(&mut batch, 2, &h2b).unwrap();
s.sync_cache(&[], &[], false);
let mut s = state_db.boxed_clone_canon(&h1a);
s.add_to_account_cache(address, Some(Account::new_basic(5.into(), 0.into())), true);
- s.commit(&mut batch, 2, &h2a, None).unwrap();
+ s.journal_under(&mut batch, 2, &h2a).unwrap();
s.sync_cache(&[], &[], true);
let mut s = state_db.boxed_clone_canon(&h2a);
- s.commit(&mut batch, 3, &h3a, None).unwrap();
+ s.journal_under(&mut batch, 3, &h3a).unwrap();
s.sync_cache(&[], &[], true);
let s = state_db.boxed_clone_canon(&h3a);
@@ -489,7 +493,7 @@ mod tests {
// reorg to 3b
// blocks [ 3b(c) 3a 2a 2b(c) 1b 1a 0 ]
let mut s = state_db.boxed_clone_canon(&h2b);
- s.commit(&mut batch, 3, &h3b, None).unwrap();
+ s.journal_under(&mut batch, 3, &h3b).unwrap();
s.sync_cache(&[h1b.clone(), h2b.clone(), h3b.clone()], &[h1a.clone(), h2a.clone(), h3a.clone()], true);
let s = state_db.boxed_clone_canon(&h3a);
assert!(s.get_cached_account(&address).is_none());
diff --git a/ethcore/src/tests/client.rs b/ethcore/src/tests/client.rs
index 067f28d3918..de99d6d057e 100644
--- a/ethcore/src/tests/client.rs
+++ b/ethcore/src/tests/client.rs
@@ -24,6 +24,7 @@ use common::*;
use devtools::*;
use miner::Miner;
use rlp::{Rlp, View};
+use spec::Spec;
#[test]
fn imports_from_empty() {
@@ -238,3 +239,27 @@ fn can_mine() {
assert_eq!(*b.block().header().parent_hash(), BlockView::new(&dummy_blocks[0]).header_view().sha3());
}
+
+#[test]
+fn change_history_size() {
+ let dir = RandomTempPath::new();
+ let test_spec = Spec::new_null();
+ let mut config = ClientConfig::default();
+ let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS);
+ config.history = 2;
+ let address = Address::random();
+ {
+ let client = Client::new(ClientConfig::default(), &test_spec, dir.as_path(), Arc::new(Miner::with_spec(&test_spec)), IoChannel::disconnected(), &db_config).unwrap();
+ for _ in 0..20 {
+ let mut b = client.prepare_open_block(Address::default(), (3141562.into(), 31415620.into()), vec![]);
+ b.block_mut().fields_mut().state.add_balance(&address, &5.into());
+ b.block_mut().fields_mut().state.commit().unwrap();
+ let b = b.close_and_lock().seal(&*test_spec.engine, vec![]).unwrap();
+ client.import_sealed_block(b).unwrap(); // account change is in the journal overlay
+ }
+ }
+ let mut config = ClientConfig::default();
+ config.history = 10;
+ let client = Client::new(config, &test_spec, dir.as_path(), Arc::new(Miner::with_spec(&test_spec)), IoChannel::disconnected(), &db_config).unwrap();
+ assert_eq!(client.state().balance(&address), 100.into());
+}
diff --git a/ethcore/src/tests/helpers.rs b/ethcore/src/tests/helpers.rs
index 787f90262cb..2fab04214cc 100644
--- a/ethcore/src/tests/helpers.rs
+++ b/ethcore/src/tests/helpers.rs
@@ -35,19 +35,20 @@ use db::COL_STATE;
pub enum ChainEra {
Frontier,
Homestead,
- DaoHardfork,
+ Eip150,
+ TransitionTest,
}
pub struct TestEngine {
engine: Arc,
- max_depth: usize
+ max_depth: usize,
}
impl TestEngine {
pub fn new(max_depth: usize) -> TestEngine {
TestEngine {
engine: ethereum::new_frontier_test().engine,
- max_depth: max_depth
+ max_depth: max_depth,
}
}
}
diff --git a/ethstore/src/account/safe_account.rs b/ethstore/src/account/safe_account.rs
index 315fd283b58..5dab3525135 100644
--- a/ethstore/src/account/safe_account.rs
+++ b/ethstore/src/account/safe_account.rs
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see .
-use ethkey::{KeyPair, sign, Address, Secret, Signature, Message};
+use ethkey::{KeyPair, sign, Address, Secret, Signature, Message, Public};
use {json, Error, crypto};
use crypto::Keccak256;
use random::Random;
@@ -180,6 +180,11 @@ impl SafeAccount {
crypto::ecies::decrypt(&secret, shared_mac, message).map_err(From::from)
}
+ pub fn public(&self, password: &str) -> Result {
+ let secret = try!(self.crypto.secret(password));
+ Ok(try!(KeyPair::from_secret(secret)).public().clone())
+ }
+
pub fn change_password(&self, old_password: &str, new_password: &str, iterations: u32) -> Result {
let secret = try!(self.crypto.secret(old_password));
let result = SafeAccount {
diff --git a/ethstore/src/bin/ethstore.rs b/ethstore/src/bin/ethstore.rs
index 94823dc061f..9d499723b3f 100644
--- a/ethstore/src/bin/ethstore.rs
+++ b/ethstore/src/bin/ethstore.rs
@@ -37,6 +37,7 @@ Usage:
ethstore import-wallet [--dir DIR]
ethstore remove [--dir DIR]
ethstore sign [--dir DIR]
+ ethstore public
ethstore [-h | --help]
Options:
@@ -56,6 +57,7 @@ Commands:
import-wallet Import presale wallet.
remove Remove account.
sign Sign message.
+ public Displays public key for an address.
"#;
#[derive(Debug, RustcDecodable)]
@@ -67,6 +69,7 @@ struct Args {
cmd_import_wallet: bool,
cmd_remove: bool,
cmd_sign: bool,
+ cmd_public: bool,
arg_secret: String,
arg_password: String,
arg_old_pwd: String,
@@ -103,7 +106,7 @@ fn key_dir(location: &str) -> Result, Error> {
fn format_accounts(accounts: &[Address]) -> String {
accounts.iter()
.enumerate()
- .map(|(i, a)| format!("{:2}: {}", i, a))
+ .map(|(i, a)| format!("{:2}: 0x{:?}", i, a))
.collect::>()
.join("\n")
}
@@ -128,7 +131,7 @@ fn execute(command: I) -> Result where I: IntoIterator- (command: I) -> Result where I: IntoIterator
- (command: I) -> Result where I: IntoIterator
- Result {
+ let account = try!(self.get(account));
+ account.public(password)
+ }
+
fn uuid(&self, address: &Address) -> Result {
let account = try!(self.get(address));
Ok(account.id.into())
diff --git a/ethstore/src/secret_store.rs b/ethstore/src/secret_store.rs
index aa79cb8b678..06f38922b3d 100644
--- a/ethstore/src/secret_store.rs
+++ b/ethstore/src/secret_store.rs
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see .
-use ethkey::{Address, Message, Signature, Secret};
+use ethkey::{Address, Message, Signature, Secret, Public};
use Error;
use json::UUID;
@@ -27,6 +27,7 @@ pub trait SecretStore: Send + Sync {
fn sign(&self, account: &Address, password: &str, message: &Message) -> Result;
fn decrypt(&self, account: &Address, password: &str, shared_mac: &[u8], message: &[u8]) -> Result, Error>;
+ fn public(&self, account: &Address, password: &str) -> Result;
fn accounts(&self) -> Result, Error>;
fn uuid(&self, account: &Address) -> Result;
diff --git a/json/src/spec/engine.rs b/json/src/spec/engine.rs
index 3813b1756ef..5c8f887587d 100644
--- a/json/src/spec/engine.rs
+++ b/json/src/spec/engine.rs
@@ -63,7 +63,7 @@ mod tests {
"durationLimit": "0x0d",
"blockReward": "0x4563918244F40000",
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
- "frontierCompatibilityModeLimit" : "0x",
+ "homesteadTransition" : "0x",
"daoHardforkTransition": "0xffffffffffffffff",
"daoHardforkBeneficiary": "0x0000000000000000000000000000000000000000",
"daoHardforkAccounts": []
diff --git a/json/src/spec/ethash.rs b/json/src/spec/ethash.rs
index d20ab39922e..025ae847501 100644
--- a/json/src/spec/ethash.rs
+++ b/json/src/spec/ethash.rs
@@ -44,8 +44,8 @@ pub struct EthashParams {
pub registrar: Option,
/// See main EthashParams docs.
- #[serde(rename="frontierCompatibilityModeLimit")]
- pub frontier_compatibility_mode_limit: Option,
+ #[serde(rename="homesteadTransition")]
+ pub homestead_transition: Option,
/// See main EthashParams docs.
#[serde(rename="daoHardforkTransition")]
@@ -66,6 +66,10 @@ pub struct EthashParams {
/// See main EthashParams docs.
#[serde(rename="bombDefuseTransition")]
pub bomb_defuse_transition: Option,
+
+ /// See main EthashParams docs.
+ #[serde(rename="eip150Transition")]
+ pub eip150_transition: Option,
}
/// Ethash engine deserialization.
@@ -90,7 +94,7 @@ mod tests {
"durationLimit": "0x0d",
"blockReward": "0x4563918244F40000",
"registrar": "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
- "frontierCompatibilityModeLimit": "0x42",
+ "homesteadTransition": "0x42",
"daoHardforkTransition": "0x08",
"daoHardforkBeneficiary": "0xabcabcabcabcabcabcabcabcabcabcabcabcabca",
"daoHardforkAccounts": [
@@ -117,7 +121,8 @@ mod tests {
],
"difficultyHardforkTransition": "0x59d9",
"difficultyHardforkBoundDivisor": "0x0200",
- "bombDefuseTransition": "0x42"
+ "bombDefuseTransition": "0x42",
+ "eip150Transition": "0x42"
}
}"#;
diff --git a/json/src/spec/params.rs b/json/src/spec/params.rs
index 676feff9312..ba81fb48ad9 100644
--- a/json/src/spec/params.rs
+++ b/json/src/spec/params.rs
@@ -53,7 +53,7 @@ mod tests {
#[test]
fn params_deserialization() {
let s = r#"{
- "frontierCompatibilityModeLimit": "0x118c30",
+ "homesteadTransition": "0x118c30",
"maximumExtraDataSize": "0x20",
"networkID" : "0x1",
"subprotocolName" : "exp",
diff --git a/json/src/spec/spec.rs b/json/src/spec/spec.rs
index 27c27ce0a04..544407cb8d9 100644
--- a/json/src/spec/spec.rs
+++ b/json/src/spec/spec.rs
@@ -66,7 +66,7 @@ mod tests {
"durationLimit": "0x0d",
"blockReward": "0x4563918244F40000",
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
- "frontierCompatibilityModeLimit" : "0x",
+ "homesteadTransition" : "0x",
"daoHardforkTransition": "0xffffffffffffffff",
"daoHardforkBeneficiary": "0x0000000000000000000000000000000000000000",
"daoHardforkAccounts": []
@@ -75,7 +75,7 @@ mod tests {
},
"params": {
"accountStartNonce": "0x0100000",
- "frontierCompatibilityModeLimit": "0x789b0",
+ "homesteadTransition": "0x789b0",
"maximumExtraDataSize": "0x20",
"minGasLimit": "0x1388",
"networkID" : "0x2",
diff --git a/parity/blockchain.rs b/parity/blockchain.rs
index d4a4d8217bc..1909450ba37 100644
--- a/parity/blockchain.rs
+++ b/parity/blockchain.rs
@@ -77,6 +77,7 @@ pub struct ImportBlockchain {
pub file_path: Option,
pub format: Option,
pub pruning: Pruning,
+ pub pruning_history: u64,
pub compaction: DatabaseCompactionProfile,
pub wal: bool,
pub mode: Mode,
@@ -94,6 +95,7 @@ pub struct ExportBlockchain {
pub file_path: Option,
pub format: Option,
pub pruning: Pruning,
+ pub pruning_history: u64,
pub compaction: DatabaseCompactionProfile,
pub wal: bool,
pub mode: Mode,
@@ -156,7 +158,7 @@ fn execute_import(cmd: ImportBlockchain) -> Result {
try!(execute_upgrades(&db_dirs, algorithm, cmd.compaction.compaction_profile()));
// prepare client config
- let client_config = to_client_config(&cmd.cache_config, cmd.mode, tracing, fat_db, cmd.compaction, cmd.wal, cmd.vm_type, "".into(), algorithm);
+ let client_config = to_client_config(&cmd.cache_config, cmd.mode, tracing, fat_db, cmd.compaction, cmd.wal, cmd.vm_type, "".into(), algorithm, cmd.pruning_history);
// build client
let service = try!(ClientService::start(
@@ -307,7 +309,7 @@ fn execute_export(cmd: ExportBlockchain) -> Result {
try!(execute_upgrades(&db_dirs, algorithm, cmd.compaction.compaction_profile()));
// prepare client config
- let client_config = to_client_config(&cmd.cache_config, cmd.mode, tracing, fat_db, cmd.compaction, cmd.wal, VMType::default(), "".into(), algorithm);
+ let client_config = to_client_config(&cmd.cache_config, cmd.mode, tracing, fat_db, cmd.compaction, cmd.wal, VMType::default(), "".into(), algorithm, cmd.pruning_history);
let service = try!(ClientService::start(
client_config,
diff --git a/parity/cli/config.full.toml b/parity/cli/config.full.toml
index 8cbfadef46f..b71bd936121 100644
--- a/parity/cli/config.full.toml
+++ b/parity/cli/config.full.toml
@@ -67,8 +67,9 @@ usd_per_eth = "auto"
price_update_period = "hourly"
gas_floor_target = "4700000"
gas_cap = "6283184"
-tx_queue_size = 2048
+tx_queue_size = 1024
tx_queue_gas = "auto"
+tx_queue_strategy = "gas_factor"
tx_gas_limit = "6283184"
extra_data = "Parity"
remove_solved = false
@@ -77,6 +78,7 @@ notify_work = ["http://localhost:3001"]
[footprint]
tracing = "auto"
pruning = "auto"
+pruning_history = 64
cache_size_db = 64
cache_size_blocks = 8
cache_size_queue = 50
diff --git a/parity/cli/config.toml b/parity/cli/config.toml
index d54b0254cf5..02ff9c0dd85 100644
--- a/parity/cli/config.toml
+++ b/parity/cli/config.toml
@@ -40,12 +40,13 @@ force_sealing = true
reseal_on_txs = "all"
reseal_min_period = 4000
price_update_period = "hourly"
-tx_queue_size = 2048
+tx_queue_size = 1024
tx_queue_gas = "auto"
[footprint]
tracing = "on"
pruning = "fast"
+pruning_history = 64
cache_size_db = 128
cache_size_blocks = 16
cache_size_queue = 100
diff --git a/parity/cli/mod.rs b/parity/cli/mod.rs
index f1f9efa8425..d4398b6f5b9 100644
--- a/parity/cli/mod.rs
+++ b/parity/cli/mod.rs
@@ -193,10 +193,12 @@ usage! {
or |c: &Config| otry!(c.mining).gas_cap.clone(),
flag_extra_data: Option = None,
or |c: &Config| otry!(c.mining).extra_data.clone().map(Some),
- flag_tx_queue_size: usize = 2048usize,
+ flag_tx_queue_size: usize = 1024usize,
or |c: &Config| otry!(c.mining).tx_queue_size.clone(),
flag_tx_queue_gas: String = "auto",
or |c: &Config| otry!(c.mining).tx_queue_gas.clone(),
+ flag_tx_queue_strategy: String = "gas_factor",
+ or |c: &Config| otry!(c.mining).tx_queue_strategy.clone(),
flag_remove_solved: bool = false,
or |c: &Config| otry!(c.mining).remove_solved.clone(),
flag_notify_work: Option = None,
@@ -207,6 +209,8 @@ usage! {
or |c: &Config| otry!(c.footprint).tracing.clone(),
flag_pruning: String = "auto",
or |c: &Config| otry!(c.footprint).pruning.clone(),
+ flag_pruning_history: u64 = 64u64,
+ or |c: &Config| otry!(c.footprint).pruning_history.clone(),
flag_cache_size_db: u32 = 64u32,
or |c: &Config| otry!(c.footprint).cache_size_db.clone(),
flag_cache_size_blocks: u32 = 8u32,
@@ -353,6 +357,7 @@ struct Mining {
extra_data: Option,
tx_queue_size: Option,
tx_queue_gas: Option,
+ tx_queue_strategy: Option,
remove_solved: Option,
notify_work: Option>,
}
@@ -361,6 +366,7 @@ struct Mining {
struct Footprint {
tracing: Option,
pruning: Option,
+ pruning_history: Option,
fast_and_loose: Option,
cache_size: Option,
cache_size_db: Option,
@@ -528,14 +534,16 @@ mod tests {
flag_gas_floor_target: "4700000".into(),
flag_gas_cap: "6283184".into(),
flag_extra_data: Some("Parity".into()),
- flag_tx_queue_size: 2048usize,
+ flag_tx_queue_size: 1024usize,
flag_tx_queue_gas: "auto".into(),
+ flag_tx_queue_strategy: "gas_factor".into(),
flag_remove_solved: false,
flag_notify_work: Some("http://localhost:3001".into()),
// -- Footprint Options
flag_tracing: "auto".into(),
flag_pruning: "auto".into(),
+ flag_pruning_history: 64u64,
flag_cache_size_db: 64u32,
flag_cache_size_blocks: 8u32,
flag_cache_size_queue: 50u32,
@@ -680,8 +688,9 @@ mod tests {
price_update_period: Some("hourly".into()),
gas_floor_target: None,
gas_cap: None,
- tx_queue_size: Some(2048),
+ tx_queue_size: Some(1024),
tx_queue_gas: Some("auto".into()),
+ tx_queue_strategy: None,
tx_gas_limit: None,
extra_data: None,
remove_solved: None,
@@ -690,6 +699,7 @@ mod tests {
footprint: Some(Footprint {
tracing: Some("on".into()),
pruning: Some("fast".into()),
+ pruning_history: Some(64),
fast_and_loose: None,
cache_size: None,
cache_size_db: Some(128),
diff --git a/parity/cli/usage.txt b/parity/cli/usage.txt
index 75501cdd199..736af583459 100644
--- a/parity/cli/usage.txt
+++ b/parity/cli/usage.txt
@@ -186,8 +186,14 @@ Sealing/Mining Options:
to be included in next block) (default: {flag_tx_queue_size}).
--tx-queue-gas LIMIT Maximum amount of total gas for external transactions in
the queue. LIMIT can be either an amount of gas or
- 'auto' or 'off'. 'auto' sets the limit to be 2x
+ 'auto' or 'off'. 'auto' sets the limit to be 20x
the current block gas limit. (default: {flag_tx_queue_gas}).
+ --tx-queue-strategy S Prioritization strategy used to order transactions
+ in the queue. S may be:
+ gas - Prioritize txs with low gas limit;
+ gas_price - Prioritize txs with high gas price;
+ gas_factor - Prioritize txs using gas price
+ and gas limit ratio (default: {flag_tx_queue_strategy}).
--remove-solved Move solved blocks from the work package queue
instead of cloning them. This gives a slightly
faster import speed, but means that extra solutions
@@ -209,6 +215,8 @@ Footprint Options:
fast - maintain journal overlay. Fast but 50MB used.
auto - use the method most recently synced or
default to fast if none synced (default: {flag_pruning}).
+ --pruning-history NUM Set a number of recent states to keep when pruning
+ is active. [default: {flag_pruning_history}].
--cache-size-db MB Override database cache size (default: {flag_cache_size_db}).
--cache-size-blocks MB Specify the prefered size of the blockchain cache in
megabytes (default: {flag_cache_size_blocks}).
diff --git a/parity/configuration.rs b/parity/configuration.rs
index ffcea2c60ec..9043a814fce 100644
--- a/parity/configuration.rs
+++ b/parity/configuration.rs
@@ -30,7 +30,7 @@ use rpc::{IpcConfiguration, HttpConfiguration};
use ethcore_rpc::NetworkSettings;
use cache::CacheConfig;
use helpers::{to_duration, to_mode, to_block_id, to_u256, to_pending_set, to_price, replace_home,
-geth_ipc_path, parity_ipc_path, to_bootnodes, to_addresses, to_address, to_gas_limit};
+geth_ipc_path, parity_ipc_path, to_bootnodes, to_addresses, to_address, to_gas_limit, to_queue_strategy};
use params::{ResealPolicy, AccountsConfig, GasPricerConfig, MinerExtras};
use ethcore_logger::Config as LogConfig;
use dir::Directories;
@@ -73,6 +73,7 @@ impl Configuration {
pub fn into_command(self) -> Result {
let dirs = self.directories();
let pruning = try!(self.args.flag_pruning.parse());
+ let pruning_history = self.args.flag_pruning_history;
let vm_type = try!(self.vm_type());
let mode = try!(to_mode(&self.args.flag_mode, self.args.flag_mode_timeout, self.args.flag_mode_alarm));
let miner_options = try!(self.miner_options());
@@ -145,6 +146,7 @@ impl Configuration {
file_path: self.args.arg_file.clone(),
format: format,
pruning: pruning,
+ pruning_history: pruning_history,
compaction: compaction,
wal: wal,
mode: mode,
@@ -162,6 +164,7 @@ impl Configuration {
file_path: self.args.arg_file.clone(),
format: format,
pruning: pruning,
+ pruning_history: pruning_history,
compaction: compaction,
wal: wal,
mode: mode,
@@ -177,6 +180,7 @@ impl Configuration {
dirs: dirs,
spec: spec,
pruning: pruning,
+ pruning_history: pruning_history,
logger_config: logger_config,
mode: mode,
tracing: tracing,
@@ -194,6 +198,7 @@ impl Configuration {
dirs: dirs,
spec: spec,
pruning: pruning,
+ pruning_history: pruning_history,
logger_config: logger_config,
mode: mode,
tracing: tracing,
@@ -217,6 +222,7 @@ impl Configuration {
dirs: dirs,
spec: spec,
pruning: pruning,
+ pruning_history: pruning_history,
daemon: daemon,
logger_config: logger_config,
miner_options: miner_options,
@@ -354,6 +360,7 @@ impl Configuration {
},
tx_queue_size: self.args.flag_tx_queue_size,
tx_queue_gas_limit: try!(to_gas_limit(&self.args.flag_tx_queue_gas)),
+ tx_queue_strategy: try!(to_queue_strategy(&self.args.flag_tx_queue_strategy)),
pending_set: try!(to_pending_set(&self.args.flag_relay_set)),
reseal_min_period: Duration::from_millis(self.args.flag_reseal_min_period),
work_queue_size: self.args.flag_work_queue_size,
@@ -641,6 +648,7 @@ mod tests {
use cli::Args;
use ethcore_rpc::NetworkSettings;
use ethcore::client::{VMType, BlockID};
+ use ethcore::miner::{MinerOptions, PrioritizationStrategy};
use helpers::{replace_home, default_network_config};
use run::RunCmd;
use signer::Configuration as SignerConfiguration;
@@ -721,6 +729,7 @@ mod tests {
file_path: Some("blockchain.json".into()),
format: Default::default(),
pruning: Default::default(),
+ pruning_history: 64,
compaction: Default::default(),
wal: true,
mode: Default::default(),
@@ -741,6 +750,7 @@ mod tests {
dirs: Default::default(),
file_path: Some("blockchain.json".into()),
pruning: Default::default(),
+ pruning_history: 64,
format: Default::default(),
compaction: Default::default(),
wal: true,
@@ -763,6 +773,7 @@ mod tests {
dirs: Default::default(),
file_path: Some("blockchain.json".into()),
pruning: Default::default(),
+ pruning_history: 64,
format: Some(DataFormat::Hex),
compaction: Default::default(),
wal: true,
@@ -791,6 +802,7 @@ mod tests {
dirs: Default::default(),
spec: Default::default(),
pruning: Default::default(),
+ pruning_history: 64,
daemon: None,
logger_config: Default::default(),
miner_options: Default::default(),
@@ -820,6 +832,27 @@ mod tests {
}));
}
+ #[test]
+ fn should_parse_mining_options() {
+ // given
+ let mut mining_options = MinerOptions::default();
+
+ // when
+ let conf0 = parse(&["parity"]);
+ let conf1 = parse(&["parity", "--tx-queue-strategy", "gas_factor"]);
+ let conf2 = parse(&["parity", "--tx-queue-strategy", "gas_price"]);
+ let conf3 = parse(&["parity", "--tx-queue-strategy", "gas"]);
+
+ // then
+ assert_eq!(conf0.miner_options().unwrap(), mining_options);
+ mining_options.tx_queue_strategy = PrioritizationStrategy::GasFactorAndGasPrice;
+ assert_eq!(conf1.miner_options().unwrap(), mining_options);
+ mining_options.tx_queue_strategy = PrioritizationStrategy::GasPriceOnly;
+ assert_eq!(conf2.miner_options().unwrap(), mining_options);
+ mining_options.tx_queue_strategy = PrioritizationStrategy::GasAndGasPrice;
+ assert_eq!(conf3.miner_options().unwrap(), mining_options);
+ }
+
#[test]
fn should_parse_network_settings() {
// given
diff --git a/parity/helpers.rs b/parity/helpers.rs
index 6c02d4e5ac5..af947329b65 100644
--- a/parity/helpers.rs
+++ b/parity/helpers.rs
@@ -22,7 +22,7 @@ use std::fs::File;
use util::{clean_0x, U256, Uint, Address, path, CompactionProfile};
use util::journaldb::Algorithm;
use ethcore::client::{Mode, BlockID, VMType, DatabaseCompactionProfile, ClientConfig};
-use ethcore::miner::{PendingSet, GasLimit};
+use ethcore::miner::{PendingSet, GasLimit, PrioritizationStrategy};
use cache::CacheConfig;
use dir::DatabaseDirectories;
use upgrade::upgrade;
@@ -101,6 +101,15 @@ pub fn to_gas_limit(s: &str) -> Result {
}
}
+pub fn to_queue_strategy(s: &str) -> Result {
+ match s {
+ "gas" => Ok(PrioritizationStrategy::GasAndGasPrice),
+ "gas_price" => Ok(PrioritizationStrategy::GasPriceOnly),
+ "gas_factor" => Ok(PrioritizationStrategy::GasFactorAndGasPrice),
+ other => Err(format!("Invalid queue strategy: {}", other)),
+ }
+}
+
pub fn to_address(s: Option) -> Result {
match s {
Some(ref a) => clean_0x(a).parse().map_err(|_| format!("Invalid address: {:?}", a)),
@@ -205,6 +214,7 @@ pub fn to_client_config(
vm_type: VMType,
name: String,
pruning: Algorithm,
+ pruning_history: u64,
) -> ClientConfig {
let mut client_config = ClientConfig::default();
@@ -232,6 +242,7 @@ pub fn to_client_config(
client_config.tracing.enabled = tracing;
client_config.fat_db = fat_db;
client_config.pruning = pruning;
+ client_config.history = pruning_history;
client_config.db_compaction = compaction;
client_config.db_wal = wal;
client_config.vm_type = vm_type;
diff --git a/parity/params.rs b/parity/params.rs
index ee3038ebfac..faba029b2b8 100644
--- a/parity/params.rs
+++ b/parity/params.rs
@@ -206,7 +206,7 @@ impl Default for MinerExtras {
extra_data: version_data(),
gas_floor_target: U256::from(4_700_000),
gas_ceil_target: U256::from(6_283_184),
- transactions_limit: 2048,
+ transactions_limit: 1024,
}
}
}
diff --git a/parity/run.rs b/parity/run.rs
index 254765983b9..4610b6f2e7b 100644
--- a/parity/run.rs
+++ b/parity/run.rs
@@ -61,6 +61,7 @@ pub struct RunCmd {
pub dirs: Directories,
pub spec: SpecType,
pub pruning: Pruning,
+ pub pruning_history: u64,
/// Some if execution should be daemonized. Contains pid_file path.
pub daemon: Option,
pub logger_config: LogConfig,
@@ -193,6 +194,7 @@ pub fn execute(cmd: RunCmd) -> Result<(), String> {
cmd.vm_type,
cmd.name,
algorithm,
+ cmd.pruning_history,
);
// set up bootnodes
diff --git a/parity/snapshot.rs b/parity/snapshot.rs
index 6b2efeed582..dd5c611d30c 100644
--- a/parity/snapshot.rs
+++ b/parity/snapshot.rs
@@ -54,6 +54,7 @@ pub struct SnapshotCommand {
pub dirs: Directories,
pub spec: SpecType,
pub pruning: Pruning,
+ pub pruning_history: u64,
pub logger_config: LogConfig,
pub mode: Mode,
pub tracing: Switch,
@@ -162,7 +163,7 @@ impl SnapshotCommand {
try!(execute_upgrades(&db_dirs, algorithm, self.compaction.compaction_profile()));
// prepare client config
- let client_config = to_client_config(&self.cache_config, self.mode, tracing, fat_db, self.compaction, self.wal, VMType::default(), "".into(), algorithm);
+ let client_config = to_client_config(&self.cache_config, self.mode, tracing, fat_db, self.compaction, self.wal, VMType::default(), "".into(), algorithm, self.pruning_history);
let service = try!(ClientService::start(
client_config,
diff --git a/rpc/src/v1/helpers/dispatch.rs b/rpc/src/v1/helpers/dispatch.rs
index df2d8cbd3e2..56124108a5b 100644
--- a/rpc/src/v1/helpers/dispatch.rs
+++ b/rpc/src/v1/helpers/dispatch.rs
@@ -14,58 +14,60 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see .
-use util::{Address, H256, U256, Uint};
+use util::{Address, H256, U256, Uint, Bytes};
use util::bytes::ToPretty;
+use ethkey::Signature;
use ethcore::miner::MinerService;
use ethcore::client::MiningBlockChainClient;
use ethcore::transaction::{Action, SignedTransaction, Transaction};
use ethcore::account_provider::AccountProvider;
use jsonrpc_core::{Error, Value, to_value};
use v1::helpers::TransactionRequest;
-use v1::types::{H256 as RpcH256, H520 as RpcH520};
+use v1::types::{H256 as RpcH256, H520 as RpcH520, Bytes as RpcBytes};
use v1::helpers::errors;
-fn prepare_transaction(client: &C, miner: &M, request: TransactionRequest) -> Transaction where C: MiningBlockChainClient, M: MinerService {
- Transaction {
- nonce: request.nonce
- .or_else(|| miner
- .last_nonce(&request.from)
- .map(|nonce| nonce + U256::one()))
- .unwrap_or_else(|| client.latest_nonce(&request.from)),
-
- action: request.to.map_or(Action::Create, Action::Call),
- gas: request.gas.unwrap_or_else(|| miner.sensible_gas_limit()),
- gas_price: request.gas_price.unwrap_or_else(|| default_gas_price(client, miner)),
- value: request.value.unwrap_or_else(U256::zero),
- data: request.data.map_or_else(Vec::new, |b| b.to_vec()),
- }
-}
+pub const DEFAULT_MAC: [u8; 2] = [0, 0];
pub fn dispatch_transaction(client: &C, miner: &M, signed_transaction: SignedTransaction) -> Result
where C: MiningBlockChainClient, M: MinerService {
let hash = RpcH256::from(signed_transaction.hash());
- let import = miner.import_own_transaction(client, signed_transaction);
-
- import
+ miner.import_own_transaction(client, signed_transaction)
.map_err(errors::from_transaction_error)
.map(|_| hash)
}
-pub fn signature_with_password(accounts: &AccountProvider, address: Address, hash: H256, pass: String) -> Result {
- accounts.sign_with_password(address, pass, hash)
- .map_err(errors::from_password_error)
- .map(|hash| to_value(&RpcH520::from(hash)))
+fn signature(accounts: &AccountProvider, address: Address, password: Option, hash: H256) -> Result {
+ accounts.sign(address, password.clone(), hash).map_err(|e| match password {
+ Some(_) => errors::from_password_error(e),
+ None => errors::from_signing_error(e),
+ })
}
-pub fn unlock_sign_and_dispatch(client: &C, miner: &M, request: TransactionRequest, account_provider: &AccountProvider, password: String) -> Result
+pub fn sign(accounts: &AccountProvider, address: Address, password: Option, hash: H256) -> Result {
+ signature(accounts, address, password, hash)
+ .map(RpcH520::from)
+ .map(to_value)
+}
+
+pub fn decrypt(accounts: &AccountProvider, address: Address, password: Option, msg: Bytes) -> Result {
+ accounts.decrypt(address, password.clone(), &DEFAULT_MAC, &msg)
+ .map_err(|e| match password {
+ Some(_) => errors::from_password_error(e),
+ None => errors::from_signing_error(e),
+ })
+ .map(RpcBytes::from)
+ .map(to_value)
+}
+
+pub fn sign_and_dispatch(client: &C, miner: &M, accounts: &AccountProvider, request: TransactionRequest, password: Option) -> Result
where C: MiningBlockChainClient, M: MinerService {
let address = request.from;
let signed_transaction = {
let t = prepare_transaction(client, miner, request);
let hash = t.hash();
- let signature = try!(account_provider.sign_with_password(address, password, hash).map_err(errors::from_password_error));
+ let signature = try!(signature(accounts, address, password, hash));
t.with_signature(signature)
};
@@ -73,18 +75,20 @@ pub fn unlock_sign_and_dispatch(client: &C, miner: &M, request: Transactio
dispatch_transaction(&*client, &*miner, signed_transaction).map(to_value)
}
-pub fn sign_and_dispatch(client: &C, miner: &M, request: TransactionRequest, account_provider: &AccountProvider, address: Address) -> Result
- where C: MiningBlockChainClient, M: MinerService {
-
- let signed_transaction = {
- let t = prepare_transaction(client, miner, request);
- let hash = t.hash();
- let signature = try!(account_provider.sign(address, hash).map_err(errors::from_signing_error));
- t.with_signature(signature)
- };
+fn prepare_transaction(client: &C, miner: &M, request: TransactionRequest) -> Transaction where C: MiningBlockChainClient, M: MinerService {
+ Transaction {
+ nonce: request.nonce
+ .or_else(|| miner
+ .last_nonce(&request.from)
+ .map(|nonce| nonce + U256::one()))
+ .unwrap_or_else(|| client.latest_nonce(&request.from)),
- trace!(target: "miner", "send_transaction: dispatching tx: {}", ::rlp::encode(&signed_transaction).to_vec().pretty());
- dispatch_transaction(&*client, &*miner, signed_transaction).map(to_value)
+ action: request.to.map_or(Action::Create, Action::Call),
+ gas: request.gas.unwrap_or_else(|| miner.sensible_gas_limit()),
+ gas_price: request.gas_price.unwrap_or_else(|| default_gas_price(client, miner)),
+ value: request.value.unwrap_or_else(U256::zero),
+ data: request.data.map_or_else(Vec::new, |b| b.to_vec()),
+ }
}
pub fn default_gas_price(client: &C, miner: &M) -> U256 where C: MiningBlockChainClient, M: MinerService {
diff --git a/rpc/src/v1/helpers/errors.rs b/rpc/src/v1/helpers/errors.rs
index 0d7902897af..c54cd9c34d8 100644
--- a/rpc/src/v1/helpers/errors.rs
+++ b/rpc/src/v1/helpers/errors.rs
@@ -43,6 +43,7 @@ mod codes {
pub const REQUEST_REJECTED_LIMIT: i64 = -32041;
pub const REQUEST_NOT_FOUND: i64 = -32042;
pub const COMPILATION_ERROR: i64 = -32050;
+ pub const ENCRYPTION_ERROR: i64 = -32055;
pub const FETCH_ERROR: i64 = -32060;
}
@@ -166,6 +167,14 @@ pub fn signer_disabled() -> Error {
}
}
+pub fn encryption_error(error: T) -> Error {
+ Error {
+ code: ErrorCode::ServerError(codes::ENCRYPTION_ERROR),
+ message: "Encryption error.".into(),
+ data: Some(Value::String(format!("{:?}", error))),
+ }
+}
+
pub fn from_fetch_error(error: FetchError) -> Error {
Error {
code: ErrorCode::ServerError(codes::FETCH_ERROR),
diff --git a/rpc/src/v1/helpers/requests.rs b/rpc/src/v1/helpers/requests.rs
index 6a30d80bb7e..5cb6108c1df 100644
--- a/rpc/src/v1/helpers/requests.rs
+++ b/rpc/src/v1/helpers/requests.rs
@@ -103,4 +103,6 @@ pub enum ConfirmationPayload {
Transaction(FilledTransactionRequest),
/// Sign request
Sign(Address, H256),
+ /// Decrypt request
+ Decrypt(Address, Bytes),
}
diff --git a/rpc/src/v1/impls/eth_signing.rs b/rpc/src/v1/impls/eth_signing.rs
index 9290a942512..e8b81d0c867 100644
--- a/rpc/src/v1/impls/eth_signing.rs
+++ b/rpc/src/v1/impls/eth_signing.rs
@@ -24,9 +24,9 @@ use util::{U256, Address, H256, Mutex};
use transient_hashmap::TransientHashMap;
use ethcore::account_provider::AccountProvider;
use v1::helpers::{errors, SigningQueue, ConfirmationPromise, ConfirmationResult, ConfirmationPayload, TransactionRequest as TRequest, FilledTransactionRequest as FilledRequest, SignerService};
-use v1::helpers::dispatch::{default_gas_price, sign_and_dispatch};
+use v1::helpers::dispatch::{default_gas_price, sign_and_dispatch, sign, decrypt};
use v1::traits::EthSigning;
-use v1::types::{TransactionRequest, H160 as RpcH160, H256 as RpcH256, H520 as RpcH520, U256 as RpcU256, Bytes as RpcBytes};
+use v1::types::{TransactionRequest, H160 as RpcH160, H256 as RpcH256, U256 as RpcU256, Bytes as RpcBytes};
fn fill_optional_fields(request: TRequest, client: &C, miner: &M) -> FilledRequest
where C: MiningBlockChainClient, M: MinerService {
@@ -76,41 +76,59 @@ impl EthSigningQueueClient where C: MiningBlockChainClient, M: Miner
Ok(())
}
+ fn add_to_queue(&self, sender: Address, when_unlocked: WhenUnlocked, payload: Payload)
+ -> Result where
+ WhenUnlocked: Fn(&AccountProvider) -> Result,
+ Payload: Fn() -> ConfirmationPayload, {
+
+ let accounts = take_weak!(self.accounts);
+ if accounts.is_unlocked(sender) {
+ return when_unlocked(&accounts).map(DispatchResult::Value);
+ }
+
+ take_weak!(self.signer).add_request(payload())
+ .map(DispatchResult::Promise)
+ .map_err(|_| errors::request_rejected_limit())
+ }
+
+ fn handle_dispatch(&self, res: Result, ready: Ready) {
+ match res {
+ Ok(DispatchResult::Value(v)) => ready.ready(Ok(v)),
+ Ok(DispatchResult::Promise(promise)) => {
+ promise.wait_for_result(move |result| {
+ ready.ready(result.unwrap_or_else(|| Err(errors::request_rejected())))
+ })
+ },
+ Err(e) => ready.ready(Err(e)),
+ }
+ }
+
fn dispatch_sign(&self, params: Params) -> Result {
from_params::<(RpcH160, RpcH256)>(params).and_then(|(address, msg)| {
let address: Address = address.into();
let msg: H256 = msg.into();
- let accounts = take_weak!(self.accounts);
- if accounts.is_unlocked(address) {
- return Ok(DispatchResult::Value(to_value(&accounts.sign(address, msg).ok().map_or_else(RpcH520::default, Into::into))))
- }
-
- let signer = take_weak!(self.signer);
- signer.add_request(ConfirmationPayload::Sign(address, msg))
- .map(DispatchResult::Promise)
- .map_err(|_| errors::request_rejected_limit())
+ self.add_to_queue(
+ address,
+ |accounts| sign(accounts, address, None, msg.clone()),
+ || ConfirmationPayload::Sign(address, msg.clone()),
+ )
})
}
fn dispatch_transaction(&self, params: Params) -> Result {
- from_params::<(TransactionRequest, )>(params)
- .and_then(|(request, )| {
- let request: TRequest = request.into();
- let accounts = take_weak!(self.accounts);
- let (client, miner) = (take_weak!(self.client), take_weak!(self.miner));
-
- if accounts.is_unlocked(request.from) {
- let sender = request.from;
- return sign_and_dispatch(&*client, &*miner, request, &*accounts, sender).map(DispatchResult::Value);
+ from_params::<(TransactionRequest, )>(params).and_then(|(request, )| {
+ let request: TRequest = request.into();
+ let (client, miner) = (take_weak!(self.client), take_weak!(self.miner));
+ self.add_to_queue(
+ request.from,
+ |accounts| sign_and_dispatch(&*client, &*miner, accounts, request.clone(), None),
+ || {
+ let request = fill_optional_fields(request.clone(), &*client, &*miner);
+ ConfirmationPayload::Transaction(request)
}
-
- let signer = take_weak!(self.signer);
- let request = fill_optional_fields(request, &*client, &*miner);
- signer.add_request(ConfirmationPayload::Transaction(request))
- .map(DispatchResult::Promise)
- .map_err(|_| errors::request_rejected_limit())
- })
+ )
+ })
}
}
@@ -118,19 +136,6 @@ impl EthSigning for EthSigningQueueClient
where C: MiningBlockChainClient + 'static, M: MinerService + 'static
{
- fn sign(&self, params: Params, ready: Ready) {
- let res = self.active().and_then(|_| self.dispatch_sign(params));
- match res {
- Ok(DispatchResult::Promise(promise)) => {
- promise.wait_for_result(move |result| {
- ready.ready(result.unwrap_or_else(|| Err(errors::request_rejected())))
- })
- },
- Ok(DispatchResult::Value(v)) => ready.ready(Ok(v)),
- Err(e) => ready.ready(Err(e)),
- }
- }
-
fn post_sign(&self, params: Params) -> Result {
try!(self.active());
self.dispatch_sign(params).map(|result| match result {
@@ -143,19 +148,6 @@ impl EthSigning for EthSigningQueueClient
})
}
- fn send_transaction(&self, params: Params, ready: Ready) {
- let res = self.active().and_then(|_| self.dispatch_transaction(params));
- match res {
- Ok(DispatchResult::Promise(promise)) => {
- promise.wait_for_result(move |result| {
- ready.ready(result.unwrap_or_else(|| Err(errors::request_rejected())))
- })
- },
- Ok(DispatchResult::Value(v)) => ready.ready(Ok(v)),
- Err(e) => ready.ready(Err(e)),
- }
- }
-
fn post_transaction(&self, params: Params) -> Result {
try!(self.active());
self.dispatch_transaction(params).map(|result| match result {
@@ -168,13 +160,6 @@ impl EthSigning for EthSigningQueueClient
})
}
- fn decrypt_message(&self, params: Params) -> Result {
- try!(self.active());
- from_params::<(RpcH160, RpcBytes)>(params).and_then(|(_account, _ciphertext)| {
- Err(errors::unimplemented())
- })
- }
-
fn check_request(&self, params: Params) -> Result {
try!(self.active());
let mut pending = self.pending.lock();
@@ -192,6 +177,32 @@ impl EthSigning for EthSigningQueueClient
res
})
}
+
+ fn sign(&self, params: Params, ready: Ready) {
+ let res = self.active().and_then(|_| self.dispatch_sign(params));
+ self.handle_dispatch(res, ready);
+ }
+
+ fn send_transaction(&self, params: Params, ready: Ready) {
+ let res = self.active().and_then(|_| self.dispatch_transaction(params));
+ self.handle_dispatch(res, ready);
+ }
+
+ fn decrypt_message(&self, params: Params, ready: Ready) {
+ let res = self.active()
+ .and_then(|_| from_params::<(RpcH160, RpcBytes)>(params))
+ .and_then(|(address, msg)| {
+ let address: Address = address.into();
+
+ self.add_to_queue(
+ address,
+ |accounts| decrypt(accounts, address, None, msg.clone().into()),
+ || ConfirmationPayload::Decrypt(address, msg.clone().into())
+ )
+ });
+
+ self.handle_dispatch(res, ready);
+ }
}
/// Implementation of functions that require signing when no trusted signer is used.
@@ -232,9 +243,7 @@ impl EthSigning for EthSigningUnsafeClient where
ready.ready(self.active()
.and_then(|_| from_params::<(RpcH160, RpcH256)>(params))
.and_then(|(address, msg)| {
- let address: Address = address.into();
- let msg: H256 = msg.into();
- Ok(to_value(&take_weak!(self.accounts).sign(address, msg).ok().map_or_else(RpcH520::default, Into::into)))
+ sign(&*take_weak!(self.accounts), address.into(), None, msg.into())
}))
}
@@ -242,18 +251,16 @@ impl EthSigning for EthSigningUnsafeClient where
ready.ready(self.active()
.and_then(|_| from_params::<(TransactionRequest, )>(params))
.and_then(|(request, )| {
- let request: TRequest = request.into();
- let sender = request.from;
- sign_and_dispatch(&*take_weak!(self.client), &*take_weak!(self.miner), request, &*take_weak!(self.accounts), sender)
+ sign_and_dispatch(&*take_weak!(self.client), &*take_weak!(self.miner), &*take_weak!(self.accounts), request.into(), None)
}))
}
- fn decrypt_message(&self, params: Params) -> Result {
- try!(self.active());
- from_params::<(RpcH160, RpcBytes)>(params).and_then(|(address, ciphertext)| {
- let s = try!(take_weak!(self.accounts).decrypt(address.into(), &[0; 0], &ciphertext.0).map_err(|_| Error::internal_error()));
- Ok(to_value(RpcBytes::from(s)))
- })
+ fn decrypt_message(&self, params: Params, ready: Ready) {
+ ready.ready(self.active()
+ .and_then(|_| from_params::<(RpcH160, RpcBytes)>(params))
+ .and_then(|(address, ciphertext)| {
+ decrypt(&*take_weak!(self.accounts), address.into(), None, ciphertext.0)
+ }))
}
fn post_sign(&self, _: Params) -> Result {
diff --git a/rpc/src/v1/impls/ethcore.rs b/rpc/src/v1/impls/ethcore.rs
index 3b756342d2f..b430a710c59 100644
--- a/rpc/src/v1/impls/ethcore.rs
+++ b/rpc/src/v1/impls/ethcore.rs
@@ -35,6 +35,7 @@ use jsonrpc_core::Error;
use v1::traits::Ethcore;
use v1::types::{Bytes, U256, H160, H256, H512, Peers, Transaction, RpcSettings};
use v1::helpers::{errors, SigningQueue, SignerService, NetworkSettings};
+use v1::helpers::dispatch::DEFAULT_MAC;
use v1::helpers::auto_args::Ready;
/// Ethcore implementation.
@@ -265,8 +266,8 @@ impl Ethcore for EthcoreClient where
fn encrypt_message(&self, key: H512, phrase: Bytes) -> Result {
try!(self.active());
- ecies::encrypt(&key.into(), &[0; 0], &phrase.0)
- .map_err(|_| Error::internal_error())
+ ecies::encrypt(&key.into(), &DEFAULT_MAC, &phrase.0)
+ .map_err(errors::encryption_error)
.map(Into::into)
}
diff --git a/rpc/src/v1/impls/personal.rs b/rpc/src/v1/impls/personal.rs
index 009f173b322..0830effd5b0 100644
--- a/rpc/src/v1/impls/personal.rs
+++ b/rpc/src/v1/impls/personal.rs
@@ -22,9 +22,9 @@ use jsonrpc_core::*;
use ethkey::{Brain, Generator};
use v1::traits::Personal;
use v1::types::{H160 as RpcH160, TransactionRequest};
-use v1::helpers::{errors, TransactionRequest as TRequest};
+use v1::helpers::errors;
use v1::helpers::params::expect_no_params;
-use v1::helpers::dispatch::unlock_sign_and_dispatch;
+use v1::helpers::dispatch::sign_and_dispatch;
use ethcore::account_provider::AccountProvider;
use ethcore::client::MiningBlockChainClient;
use ethcore::miner::MinerService;
@@ -139,10 +139,13 @@ impl Personal for PersonalClient where C: MiningBl
try!(self.active());
from_params::<(TransactionRequest, String)>(params)
.and_then(|(request, password)| {
- let request: TRequest = request.into();
- let accounts = take_weak!(self.accounts);
-
- unlock_sign_and_dispatch(&*take_weak!(self.client), &*take_weak!(self.miner), request, &*accounts, password)
+ sign_and_dispatch(
+ &*take_weak!(self.client),
+ &*take_weak!(self.miner),
+ &*take_weak!(self.accounts),
+ request.into(),
+ Some(password)
+ )
})
}
diff --git a/rpc/src/v1/impls/personal_signer.rs b/rpc/src/v1/impls/personal_signer.rs
index 441ed679bbb..b3a93736a2b 100644
--- a/rpc/src/v1/impls/personal_signer.rs
+++ b/rpc/src/v1/impls/personal_signer.rs
@@ -25,7 +25,7 @@ use v1::traits::PersonalSigner;
use v1::types::{TransactionModification, ConfirmationRequest, U256};
use v1::helpers::{errors, SignerService, SigningQueue, ConfirmationPayload};
use v1::helpers::params::expect_no_params;
-use v1::helpers::dispatch::{unlock_sign_and_dispatch, signature_with_password};
+use v1::helpers::dispatch::{sign_and_dispatch, sign, decrypt};
/// Transactions confirmation (personal) rpc implementation.
pub struct SignerClient where C: MiningBlockChainClient, M: MinerService {
@@ -87,12 +87,14 @@ impl PersonalSigner for SignerClient where C: Mini
if let Some(gas_price) = modification.gas_price {
request.gas_price = gas_price.into();
}
-
- unlock_sign_and_dispatch(&*client, &*miner, request.into(), &*accounts, pass)
+ sign_and_dispatch(&*client, &*miner, &*accounts, request.into(), Some(pass))
},
ConfirmationPayload::Sign(address, hash) => {
- signature_with_password(&*accounts, address, hash, pass)
- }
+ sign(&*accounts, address, Some(pass), hash)
+ },
+ ConfirmationPayload::Decrypt(address, msg) => {
+ decrypt(&*accounts, address, Some(pass), msg)
+ },
};
if let Ok(ref response) = result {
signer.request_confirmed(id, Ok(response.clone()));
diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs
index 97e4d3bea5c..5d748155131 100644
--- a/rpc/src/v1/tests/eth.rs
+++ b/rpc/src/v1/tests/eth.rs
@@ -24,7 +24,7 @@ use ethcore::spec::{Genesis, Spec};
use ethcore::block::Block;
use ethcore::views::BlockView;
use ethcore::ethereum;
-use ethcore::miner::{MinerOptions, GasPricer, MinerService, ExternalMiner, Miner, PendingSet, GasLimit};
+use ethcore::miner::{MinerOptions, GasPricer, MinerService, ExternalMiner, Miner, PendingSet, PrioritizationStrategy, GasLimit};
use ethcore::account_provider::AccountProvider;
use devtools::RandomTempPath;
use util::Hashable;
@@ -33,9 +33,10 @@ use util::{U256, H256, Uint, Address};
use jsonrpc_core::IoHandler;
use ethjson::blockchain::BlockChain;
-use v1::types::U256 as NU256;
-use v1::traits::eth::{Eth, EthSigning};
use v1::impls::{EthClient, EthSigningUnsafeClient};
+use v1::types::U256 as NU256;
+use v1::traits::eth::Eth;
+use v1::traits::eth_signing::EthSigning;
use v1::tests::helpers::{TestSyncProvider, Config};
fn account_provider() -> Arc {
@@ -58,6 +59,7 @@ fn miner_service(spec: &Spec, accounts: Arc) -> Arc {
reseal_on_own_tx: true,
tx_queue_size: 1024,
tx_gas_limit: !U256::zero(),
+ tx_queue_strategy: PrioritizationStrategy::GasPriceOnly,
tx_queue_gas_limit: GasLimit::None,
pending_set: PendingSet::SealingOrElseQueue,
reseal_min_period: Duration::from_secs(0),
@@ -208,7 +210,7 @@ const TRANSACTION_COUNT_SPEC: &'static [u8] = br#"{
"durationLimit": "0x0d",
"blockReward": "0x4563918244F40000",
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
- "frontierCompatibilityModeLimit": "0xffffffffffffffff",
+ "homesteadTransition": "0xffffffffffffffff",
"daoHardforkTransition": "0xffffffffffffffff",
"daoHardforkBeneficiary": "0x0000000000000000000000000000000000000000",
"daoHardforkAccounts": []
@@ -256,7 +258,7 @@ const POSITIVE_NONCE_SPEC: &'static [u8] = br#"{
"durationLimit": "0x0d",
"blockReward": "0x4563918244F40000",
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
- "frontierCompatibilityModeLimit": "0xffffffffffffffff",
+ "homesteadTransition": "0xffffffffffffffff",
"daoHardforkTransition": "0xffffffffffffffff",
"daoHardforkBeneficiary": "0x0000000000000000000000000000000000000000",
"daoHardforkAccounts": []
diff --git a/rpc/src/v1/tests/mocked/eth.rs b/rpc/src/v1/tests/mocked/eth.rs
index eb3fbaf6e74..e41ca323109 100644
--- a/rpc/src/v1/tests/mocked/eth.rs
+++ b/rpc/src/v1/tests/mocked/eth.rs
@@ -264,7 +264,7 @@ fn rpc_eth_sign() {
let account = tester.accounts_provider.new_account("abcd").unwrap();
tester.accounts_provider.unlock_account_permanently(account, "abcd".into()).unwrap();
let message = H256::from("0x0cc175b9c0f1b6a831c399e26977266192eb5ffee6ae2fec3ad71c777531578f");
- let signed = tester.accounts_provider.sign(account, message).unwrap();
+ let signed = tester.accounts_provider.sign(account, None, message).unwrap();
let req = r#"{
"jsonrpc": "2.0",
@@ -709,7 +709,7 @@ fn rpc_eth_send_transaction() {
value: U256::from(0x9184e72au64),
data: vec![]
};
- let signature = tester.accounts_provider.sign(address, t.hash()).unwrap();
+ let signature = tester.accounts_provider.sign(address, None, t.hash()).unwrap();
let t = t.with_signature(signature);
let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#;
@@ -726,7 +726,7 @@ fn rpc_eth_send_transaction() {
value: U256::from(0x9184e72au64),
data: vec![]
};
- let signature = tester.accounts_provider.sign(address, t.hash()).unwrap();
+ let signature = tester.accounts_provider.sign(address, None, t.hash()).unwrap();
let t = t.with_signature(signature);
let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#;
@@ -791,7 +791,7 @@ fn rpc_eth_send_raw_transaction() {
value: U256::from(0x9184e72au64),
data: vec![]
};
- let signature = tester.accounts_provider.sign(address, t.hash()).unwrap();
+ let signature = tester.accounts_provider.sign(address, None, t.hash()).unwrap();
let t = t.with_signature(signature);
let rlp = ::rlp::encode(&t).to_vec().to_hex();
diff --git a/rpc/src/v1/tests/mocked/eth_signing.rs b/rpc/src/v1/tests/mocked/eth_signing.rs
index 1bf901e5f88..fc5800cd717 100644
--- a/rpc/src/v1/tests/mocked/eth_signing.rs
+++ b/rpc/src/v1/tests/mocked/eth_signing.rs
@@ -16,16 +16,20 @@
use std::str::FromStr;
use std::sync::Arc;
-use jsonrpc_core::{IoHandler, to_value};
+use jsonrpc_core::{IoHandler, to_value, Success};
use v1::impls::EthSigningQueueClient;
-use v1::traits::EthSigning;
+use v1::traits::{EthSigning, Ethcore};
use v1::helpers::{SignerService, SigningQueue};
-use v1::types::{H256 as RpcH256, H520 as RpcH520};
+use v1::types::{H256 as RpcH256, H520 as RpcH520, Bytes};
use v1::tests::helpers::TestMinerService;
+use v1::tests::mocked::ethcore;
+
use util::{Address, FixedHash, Uint, U256, H256, H520};
use ethcore::account_provider::AccountProvider;
use ethcore::client::TestBlockChainClient;
use ethcore::transaction::{Transaction, Action};
+use ethstore::ethkey::{Generator, Random};
+use serde_json;
struct EthSigningTester {
pub signer: Arc,
@@ -178,7 +182,7 @@ fn should_sign_if_account_is_unlocked() {
let acc = tester.accounts.new_account("test").unwrap();
tester.accounts.unlock_account_permanently(acc, "test".into()).unwrap();
- let signature = tester.accounts.sign(acc, hash).unwrap();
+ let signature = tester.accounts.sign(acc, None, hash).unwrap();
// when
let request = r#"{
@@ -242,7 +246,7 @@ fn should_dispatch_transaction_if_account_is_unlock() {
value: U256::from(0x9184e72au64),
data: vec![]
};
- let signature = tester.accounts.sign(acc, t.hash()).unwrap();
+ let signature = tester.accounts.sign(acc, None, t.hash()).unwrap();
let t = t.with_signature(signature);
// when
@@ -263,3 +267,65 @@ fn should_dispatch_transaction_if_account_is_unlock() {
// then
assert_eq!(tester.io.handle_request_sync(&request), Some(response.to_owned()));
}
+
+#[test]
+fn should_decrypt_message_if_account_is_unlocked() {
+ // given
+ let tester = eth_signing();
+ let sync = ethcore::sync_provider();
+ let net = ethcore::network_service();
+ let ethcore_client = ethcore::ethcore_client(&tester.client, &tester.miner, &sync, &net);
+ tester.io.add_delegate(ethcore_client.to_delegate());
+ let (address, public) = tester.accounts.new_account_and_public("test").unwrap();
+ tester.accounts.unlock_account_permanently(address, "test".into()).unwrap();
+
+
+ // First encrypt message
+ let request = format!("{}0x{:?}{}",
+ r#"{"jsonrpc": "2.0", "method": "ethcore_encryptMessage", "params":[""#,
+ public,
+ r#"", "0x01020304"], "id": 1}"#
+ );
+ let encrypted: Success = serde_json::from_str(&tester.io.handle_request_sync(&request).unwrap()).unwrap();
+
+ // then call decrypt
+ let request = format!("{}{:?}{}{:?}{}",
+ r#"{"jsonrpc": "2.0", "method": "ethcore_decryptMessage", "params":["0x"#,
+ address,
+ r#"","#,
+ encrypted.result,
+ r#"], "id": 1}"#
+ );
+ println!("Request: {:?}", request);
+ let response = r#"{"jsonrpc":"2.0","result":"0x01020304","id":1}"#;
+
+ // then
+ assert_eq!(tester.io.handle_request_sync(&request), Some(response.into()));
+}
+
+#[test]
+fn should_add_decryption_to_the_queue() {
+ // given
+ let tester = eth_signing();
+ let acc = Random.generate().unwrap();
+ assert_eq!(tester.signer.requests().len(), 0);
+
+ // when
+ let request = r#"{
+ "jsonrpc": "2.0",
+ "method": "ethcore_decryptMessage",
+ "params": ["0x"#.to_owned() + &format!("{:?}", acc.address()) + r#"",
+ "0x012345"],
+ "id": 1
+ }"#;
+ let response = r#"{"jsonrpc":"2.0","result":"0x0102","id":1}"#;
+
+ // then
+ let async_result = tester.io.handle_request(&request).unwrap();
+ assert_eq!(tester.signer.requests().len(), 1);
+ // respond
+ tester.signer.request_confirmed(U256::from(1), Ok(to_value(Bytes(vec![0x1, 0x2]))));
+ assert!(async_result.on_result(move |res| {
+ assert_eq!(res, response.to_owned());
+ }));
+}
diff --git a/rpc/src/v1/tests/mocked/ethcore.rs b/rpc/src/v1/tests/mocked/ethcore.rs
index f09d84d5bf6..4cf23d46e2c 100644
--- a/rpc/src/v1/tests/mocked/ethcore.rs
+++ b/rpc/src/v1/tests/mocked/ethcore.rs
@@ -19,6 +19,7 @@ use util::log::RotatingLogger;
use util::U256;
use ethsync::ManageNetwork;
use ethcore::client::{TestBlockChainClient};
+use ethstore::ethkey::{Generator, Random};
use jsonrpc_core::IoHandler;
use v1::{Ethcore, EthcoreClient};
@@ -34,7 +35,7 @@ fn client_service() -> Arc {
Arc::new(TestBlockChainClient::default())
}
-fn sync_provider() -> Arc {
+pub fn sync_provider() -> Arc {
Arc::new(TestSyncProvider::new(Config {
network_id: U256::from(3),
num_peers: 120,
@@ -56,13 +57,13 @@ fn settings() -> Arc {
})
}
-fn network_service() -> Arc {
+pub fn network_service() -> Arc {
Arc::new(TestManageNetwork)
}
-type TestEthcoreClient = EthcoreClient;
+pub type TestEthcoreClient = EthcoreClient;
-fn ethcore_client(
+pub fn ethcore_client(
client: &Arc,
miner: &Arc,
sync: &Arc,
@@ -324,3 +325,17 @@ fn rpc_ethcore_pending_transactions() {
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
}
+
+#[test]
+fn rpc_ethcore_encrypt() {
+ let miner = miner_service();
+ let client = client_service();
+ let sync = sync_provider();
+ let net = network_service();
+ let io = IoHandler::new();
+ io.add_delegate(ethcore_client(&client, &miner, &sync, &net).to_delegate());
+ let key = format!("{:?}", Random.generate().unwrap().public());
+
+ let request = r#"{"jsonrpc": "2.0", "method": "ethcore_encryptMessage", "params":["0x"#.to_owned() + &key + r#"", "0x01"], "id": 1}"#;
+ assert!(io.handle_request_sync(&request).unwrap().contains("result"), "Should return success.");
+}
diff --git a/rpc/src/v1/tests/mocked/personal.rs b/rpc/src/v1/tests/mocked/personal.rs
index aa4bf29c119..c3c3d2954cd 100644
--- a/rpc/src/v1/tests/mocked/personal.rs
+++ b/rpc/src/v1/tests/mocked/personal.rs
@@ -227,7 +227,7 @@ fn sign_and_send_transaction() {
data: vec![]
};
tester.accounts.unlock_account_temporarily(address, "password123".into()).unwrap();
- let signature = tester.accounts.sign(address, t.hash()).unwrap();
+ let signature = tester.accounts.sign(address, None, t.hash()).unwrap();
let t = t.with_signature(signature);
let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#;
@@ -245,7 +245,7 @@ fn sign_and_send_transaction() {
data: vec![]
};
tester.accounts.unlock_account_temporarily(address, "password123".into()).unwrap();
- let signature = tester.accounts.sign(address, t.hash()).unwrap();
+ let signature = tester.accounts.sign(address, None, t.hash()).unwrap();
let t = t.with_signature(signature);
let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#;
diff --git a/rpc/src/v1/tests/mocked/personal_signer.rs b/rpc/src/v1/tests/mocked/personal_signer.rs
index 04ae829ee62..650f1655303 100644
--- a/rpc/src/v1/tests/mocked/personal_signer.rs
+++ b/rpc/src/v1/tests/mocked/personal_signer.rs
@@ -186,7 +186,7 @@ fn should_confirm_transaction_and_dispatch() {
data: vec![]
};
tester.accounts.unlock_account_temporarily(address, "test".into()).unwrap();
- let signature = tester.accounts.sign(address, t.hash()).unwrap();
+ let signature = tester.accounts.sign(address, None, t.hash()).unwrap();
let t = t.with_signature(signature);
assert_eq!(tester.signer.requests().len(), 1);
diff --git a/rpc/src/v1/traits/eth.rs b/rpc/src/v1/traits/eth.rs
index 62301e21fb5..7d9aa47f3ec 100644
--- a/rpc/src/v1/traits/eth.rs
+++ b/rpc/src/v1/traits/eth.rs
@@ -15,7 +15,6 @@
// along with Parity. If not, see .
//! Eth rpc interface.
-use std::sync::Arc;
use jsonrpc_core::*;
use v1::types::{Block, BlockNumber, Bytes, CallRequest, Filter, FilterChanges, Index};
@@ -198,46 +197,3 @@ build_rpc_trait! {
fn uninstall_filter(&self, Index) -> Result;
}
}
-
-/// Signing methods implementation relying on unlocked accounts.
-pub trait EthSigning: Sized + Send + Sync + 'static {
- /// Signs the data with given address signature.
- fn sign(&self, _: Params, _: Ready);
-
- /// Posts sign request asynchronously.
- /// Will return a confirmation ID for later use with check_transaction.
- fn post_sign(&self, _: Params) -> Result;
-
- /// Sends transaction; will block for 20s to try to return the
- /// transaction hash.
- /// If it cannot yet be signed, it will return a transaction ID for
- /// later use with check_transaction.
- fn send_transaction(&self, _: Params, _: Ready);
-
- /// Posts transaction asynchronously.
- /// Will return a transaction ID for later use with check_transaction.
- fn post_transaction(&self, _: Params) -> Result;
-
- /// Checks the progress of a previously posted request (transaction/sign).
- /// Should be given a valid send_transaction ID.
- /// Returns the transaction hash, the zero hash (not yet available),
- /// or the signature,
- /// or an error.
- fn check_request(&self, _: Params) -> Result;
-
- /// Decrypt some ECIES-encrypted message.
- /// First parameter is the address with which it is encrypted, second is the ciphertext.
- fn decrypt_message(&self, _: Params) -> Result;
-
- /// Should be used to convert object to io delegate.
- fn to_delegate(self) -> IoDelegate {
- let mut delegate = IoDelegate::new(Arc::new(self));
- delegate.add_async_method("eth_sign", EthSigning::sign);
- delegate.add_async_method("eth_sendTransaction", EthSigning::send_transaction);
- delegate.add_method("eth_postSign", EthSigning::post_sign);
- delegate.add_method("eth_postTransaction", EthSigning::post_transaction);
- delegate.add_method("eth_checkRequest", EthSigning::check_request);
- delegate.add_method("ethcore_decryptMessage", EthSigning::decrypt_message);
- delegate
- }
-}
diff --git a/rpc/src/v1/traits/eth_signing.rs b/rpc/src/v1/traits/eth_signing.rs
new file mode 100644
index 00000000000..1d6f6e5019d
--- /dev/null
+++ b/rpc/src/v1/traits/eth_signing.rs
@@ -0,0 +1,63 @@
+// Copyright 2015, 2016 Ethcore (UK) Ltd.
+// This file is part of Parity.
+
+// Parity is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity. If not, see .
+
+//! Eth rpc interface.
+use std::sync::Arc;
+use jsonrpc_core::*;
+
+/// Signing methods implementation relying on unlocked accounts.
+pub trait EthSigning: Sized + Send + Sync + 'static {
+ /// Signs the data with given address signature.
+ fn sign(&self, _: Params, _: Ready);
+
+ /// Posts sign request asynchronously.
+ /// Will return a confirmation ID for later use with check_transaction.
+ fn post_sign(&self, _: Params) -> Result;
+
+ /// Sends transaction; will block for 20s to try to return the
+ /// transaction hash.
+ /// If it cannot yet be signed, it will return a transaction ID for
+ /// later use with check_transaction.
+ fn send_transaction(&self, _: Params, _: Ready);
+
+ /// Posts transaction asynchronously.
+ /// Will return a transaction ID for later use with check_transaction.
+ fn post_transaction(&self, _: Params) -> Result;
+
+ /// Checks the progress of a previously posted request (transaction/sign).
+ /// Should be given a valid send_transaction ID.
+ /// Returns the transaction hash, the zero hash (not yet available),
+ /// or the signature,
+ /// or an error.
+ fn check_request(&self, _: Params) -> Result;
+
+ /// Decrypt some ECIES-encrypted message.
+ /// First parameter is the address with which it is encrypted, second is the ciphertext.
+ fn decrypt_message(&self, _: Params, _: Ready);
+
+ /// Should be used to convert object to io delegate.
+ fn to_delegate(self) -> IoDelegate {
+ let mut delegate = IoDelegate::new(Arc::new(self));
+ delegate.add_async_method("eth_sign", EthSigning::sign);
+ delegate.add_async_method("eth_sendTransaction", EthSigning::send_transaction);
+ delegate.add_async_method("ethcore_decryptMessage", EthSigning::decrypt_message);
+
+ delegate.add_method("eth_postSign", EthSigning::post_sign);
+ delegate.add_method("eth_postTransaction", EthSigning::post_transaction);
+ delegate.add_method("eth_checkRequest", EthSigning::check_request);
+ delegate
+ }
+}
diff --git a/rpc/src/v1/traits/mod.rs b/rpc/src/v1/traits/mod.rs
index 3ca11b65436..e804c55536e 100644
--- a/rpc/src/v1/traits/mod.rs
+++ b/rpc/src/v1/traits/mod.rs
@@ -18,6 +18,7 @@
pub mod web3;
pub mod eth;
+pub mod eth_signing;
pub mod net;
pub mod personal;
pub mod ethcore;
@@ -26,7 +27,8 @@ pub mod traces;
pub mod rpc;
pub use self::web3::Web3;
-pub use self::eth::{Eth, EthFilter, EthSigning};
+pub use self::eth::{Eth, EthFilter};
+pub use self::eth_signing::EthSigning;
pub use self::net::Net;
pub use self::personal::{Personal, PersonalSigner};
pub use self::ethcore::Ethcore;
@@ -34,4 +36,3 @@ pub use self::ethcore_set::EthcoreSet;
pub use self::traces::Traces;
pub use self::rpc::Rpc;
-
diff --git a/rpc/src/v1/types/confirmations.rs b/rpc/src/v1/types/confirmations.rs
index c074df4431c..c5ef4efa98f 100644
--- a/rpc/src/v1/types/confirmations.rs
+++ b/rpc/src/v1/types/confirmations.rs
@@ -16,7 +16,7 @@
//! Types used in Confirmations queue (Trusted Signer)
-use v1::types::{U256, TransactionRequest, H160, H256};
+use v1::types::{U256, TransactionRequest, H160, H256, Bytes};
use v1::helpers;
@@ -47,6 +47,15 @@ pub struct SignRequest {
pub hash: H256,
}
+/// Decrypt request
+#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize)]
+pub struct DecryptRequest {
+ /// Address
+ pub address: H160,
+ /// Message to decrypt
+ pub msg: Bytes,
+}
+
/// Confirmation payload, i.e. the thing to be confirmed
#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize)]
pub enum ConfirmationPayload {
@@ -56,6 +65,9 @@ pub enum ConfirmationPayload {
/// Signature
#[serde(rename="sign")]
Sign(SignRequest),
+ /// Decryption
+ #[serde(rename="decrypt")]
+ Decrypt(DecryptRequest),
}
impl From for ConfirmationPayload {
@@ -66,6 +78,10 @@ impl From for ConfirmationPayload {
address: address.into(),
hash: hash.into(),
}),
+ helpers::ConfirmationPayload::Decrypt(address, msg) => ConfirmationPayload::Decrypt(DecryptRequest {
+ address: address.into(),
+ msg: msg.into(),
+ }),
}
}
}
diff --git a/signer/Cargo.toml b/signer/Cargo.toml
index cc09695155d..892b5009ced 100644
--- a/signer/Cargo.toml
+++ b/signer/Cargo.toml
@@ -29,3 +29,4 @@ clippy = { version = "0.0.90", optional = true}
dev = ["clippy"]
ui = ["parity-dapps-glue", "parity-ui"]
use-precompiled-js = ["parity-ui/use-precompiled-js"]
+
diff --git a/signer/src/ws_server/session.rs b/signer/src/ws_server/session.rs
index 424302a2cbd..45146f98853 100644
--- a/signer/src/ws_server/session.rs
+++ b/signer/src/ws_server/session.rs
@@ -50,6 +50,7 @@ mod ui {
mod ui {
pub struct File {
pub content: &'static str,
+ pub content: &'static [u8],
pub content_type: &'static str,
}
diff --git a/util/src/journaldb/archivedb.rs b/util/src/journaldb/archivedb.rs
index 5f1eb71d438..efedfb766c3 100644
--- a/util/src/journaldb/archivedb.rs
+++ b/util/src/journaldb/archivedb.rs
@@ -35,8 +35,8 @@ const AUX_FLAG: u8 = 255;
///
/// Like `OverlayDB`, there is a memory overlay; `commit()` must be called in order to
/// write operations out to disk. Unlike `OverlayDB`, `remove()` operations do not take effect
-/// immediately. Rather some age (based on a linear but arbitrary metric) must pass before
-/// the removals actually take effect.
+/// immediately. As this is an "archive" database, nothing is ever removed. This means
+/// that the states of any block the node has ever processed will be accessible.
pub struct ArchiveDB {
overlay: MemoryDB,
backing: Arc,
@@ -156,7 +156,7 @@ impl JournalDB for ArchiveDB {
self.latest_era.is_none()
}
- fn commit(&mut self, batch: &mut DBTransaction, now: u64, _id: &H256, _end: Option<(u64, H256)>) -> Result {
+ fn journal_under(&mut self, batch: &mut DBTransaction, now: u64, _id: &H256) -> Result {
let mut inserts = 0usize;
let mut deletes = 0usize;
@@ -184,6 +184,11 @@ impl JournalDB for ArchiveDB {
Ok((inserts + deletes) as u32)
}
+ fn mark_canonical(&mut self, _batch: &mut DBTransaction, _end_era: u64, _canon_id: &H256) -> Result {
+ // keep everything! it's an archive, after all.
+ Ok(0)
+ }
+
fn inject(&mut self, batch: &mut DBTransaction) -> Result {
let mut inserts = 0usize;
let mut deletes = 0usize;
diff --git a/util/src/journaldb/earlymergedb.rs b/util/src/journaldb/earlymergedb.rs
index bbb4ed827d9..ef9868d4130 100644
--- a/util/src/journaldb/earlymergedb.rs
+++ b/util/src/journaldb/earlymergedb.rs
@@ -61,6 +61,49 @@ enum RemoveFrom {
/// write operations out to disk. Unlike `OverlayDB`, `remove()` operations do not take effect
/// immediately. Rather some age (based on a linear but arbitrary metric) must pass before
/// the removals actually take effect.
+///
+/// journal format:
+/// [era, 0] => [ id, [insert_0, ...], [remove_0, ...] ]
+/// [era, 1] => [ id, [insert_0, ...], [remove_0, ...] ]
+/// [era, n] => [ ... ]
+///
+/// When we make a new commit, we make a journal of all blocks in the recent history and record
+/// all keys that were inserted and deleted. The journal is ordered by era; multiple commits can
+/// share the same era. This forms a data structure similar to a queue but whose items are tuples.
+/// By the time comes to remove a tuple from the queue (i.e. then the era passes from recent history
+/// into ancient history) then only one commit from the tuple is considered canonical. This commit
+/// is kept in the main backing database, whereas any others from the same era are reverted.
+///
+/// It is possible that a key, properly available in the backing database be deleted and re-inserted
+/// in the recent history queue, yet have both operations in commits that are eventually non-canonical.
+/// To avoid the original, and still required, key from being deleted, we maintain a reference count
+/// which includes an original key, if any.
+///
+/// The semantics of the `counter` are:
+/// insert key k:
+/// counter already contains k: count += 1
+/// counter doesn't contain k:
+/// backing db contains k: count = 1
+/// backing db doesn't contain k: insert into backing db, count = 0
+/// delete key k:
+/// counter contains k (count is asserted to be non-zero):
+/// count > 1: counter -= 1
+/// count == 1: remove counter
+/// count == 0: remove key from backing db
+/// counter doesn't contain k: remove key from backing db
+///
+/// Practically, this means that for each commit block turning from recent to ancient we do the
+/// following:
+/// is_canonical:
+/// inserts: Ignored (left alone in the backing database).
+/// deletes: Enacted; however, recent history queue is checked for ongoing references. This is
+/// reduced as a preference to deletion from the backing database.
+/// !is_canonical:
+/// inserts: Reverted; however, recent history queue is checked for ongoing references. This is
+/// reduced as a preference to deletion from the backing database.
+/// deletes: Ignored (they were never inserted).
+///
+/// TODO: store_reclaim_period
pub struct EarlyMergeDB {
overlay: MemoryDB,
backing: Arc,
@@ -336,55 +379,12 @@ impl JournalDB for EarlyMergeDB {
self.backing.get_by_prefix(self.column, &id[0..DB_PREFIX_LEN]).map(|b| b.to_vec())
}
- #[cfg_attr(feature="dev", allow(cyclomatic_complexity))]
- fn commit(&mut self, batch: &mut DBTransaction, now: u64, id: &H256, end: Option<(u64, H256)>) -> Result {
- // journal format:
- // [era, 0] => [ id, [insert_0, ...], [remove_0, ...] ]
- // [era, 1] => [ id, [insert_0, ...], [remove_0, ...] ]
- // [era, n] => [ ... ]
-
- // TODO: store reclaim_period.
-
- // When we make a new commit, we make a journal of all blocks in the recent history and record
- // all keys that were inserted and deleted. The journal is ordered by era; multiple commits can
- // share the same era. This forms a data structure similar to a queue but whose items are tuples.
- // By the time comes to remove a tuple from the queue (i.e. then the era passes from recent history
- // into ancient history) then only one commit from the tuple is considered canonical. This commit
- // is kept in the main backing database, whereas any others from the same era are reverted.
- //
- // It is possible that a key, properly available in the backing database be deleted and re-inserted
- // in the recent history queue, yet have both operations in commits that are eventually non-canonical.
- // To avoid the original, and still required, key from being deleted, we maintain a reference count
- // which includes an original key, if any.
- //
- // The semantics of the `counter` are:
- // insert key k:
- // counter already contains k: count += 1
- // counter doesn't contain k:
- // backing db contains k: count = 1
- // backing db doesn't contain k: insert into backing db, count = 0
- // delete key k:
- // counter contains k (count is asserted to be non-zero):
- // count > 1: counter -= 1
- // count == 1: remove counter
- // count == 0: remove key from backing db
- // counter doesn't contain k: remove key from backing db
- //
- // Practically, this means that for each commit block turning from recent to ancient we do the
- // following:
- // is_canonical:
- // inserts: Ignored (left alone in the backing database).
- // deletes: Enacted; however, recent history queue is checked for ongoing references. This is
- // reduced as a preference to deletion from the backing database.
- // !is_canonical:
- // inserts: Reverted; however, recent history queue is checked for ongoing references. This is
- // reduced as a preference to deletion from the backing database.
- // deletes: Ignored (they were never inserted).
- //
+ fn journal_under(&mut self, batch: &mut DBTransaction, now: u64, id: &H256) -> Result {
+ let trace = false;
// record new commit's details.
let mut refs = self.refs.as_ref().unwrap().write();
- let trace = false;
+
{
let mut index = 0usize;
let mut last;
@@ -403,7 +403,7 @@ impl JournalDB for EarlyMergeDB {
let drained = self.overlay.drain();
if trace {
- trace!(target: "jdb", "commit: #{} ({}), end era: {:?}", now, id, end);
+ trace!(target: "jdb", "commit: #{} ({})", now, id);
}
let removes: Vec = drained
@@ -431,86 +431,87 @@ impl JournalDB for EarlyMergeDB {
inserts.iter().foreach(|&(k, _)| {r.append(&k);});
r.append(&removes);
Self::insert_keys(&inserts, &self.backing, self.column, &mut refs, batch, trace);
+
+ let ins = inserts.iter().map(|&(k, _)| k).collect::>();
+
if trace {
- let ins = inserts.iter().map(|&(k, _)| k).collect::>();
- trace!(target: "jdb.ops", " Inserts: {:?}", ins);
trace!(target: "jdb.ops", " Deletes: {:?}", removes);
+ trace!(target: "jdb.ops", " Inserts: {:?}", ins);
}
+
batch.put(self.column, &last, r.as_raw());
if self.latest_era.map_or(true, |e| now > e) {
batch.put(self.column, &LATEST_ERA_KEY, &encode(&now));
self.latest_era = Some(now);
}
+
+ Ok((ins.len() + removes.len()) as u32)
}
+ }
- // apply old commits' details
- if let Some((end_era, canon_id)) = end {
- let mut index = 0usize;
- let mut last;
- while let Some(rlp_data) = try!(self.backing.get(self.column, {
- let mut r = RlpStream::new_list(3);
- r.append(&end_era);
- r.append(&index);
- r.append(&&PADDING[..]);
- last = r.drain();
- &last
- })) {
- let rlp = Rlp::new(&rlp_data);
- let inserts: Vec = rlp.val_at(1);
+ #[cfg_attr(feature="dev", allow(cyclomatic_complexity))]
+ fn mark_canonical(&mut self, batch: &mut DBTransaction, end_era: u64, canon_id: &H256) -> Result {
+ let trace = false;
- if canon_id == rlp.val_at(0) {
- // Collect keys to be removed. Canon block - remove the (enacted) deletes.
- let deletes: Vec = rlp.val_at(2);
- if trace {
- trace!(target: "jdb.ops", " Expunging: {:?}", deletes);
- }
- Self::remove_keys(&deletes, &mut refs, batch, self.column, RemoveFrom::Archive, trace);
+ let mut refs = self.refs.as_ref().unwrap().write();
- if trace {
- trace!(target: "jdb.ops", " Finalising: {:?}", inserts);
- }
- for k in &inserts {
- match refs.get(k).cloned() {
- None => {
- // [in archive] -> SHIFT remove -> SHIFT insert None->Some{queue_refs: 1, in_archive: true} -> TAKE remove Some{queue_refs: 1, in_archive: true}->None -> TAKE insert
- // already expunged from the queue (which is allowed since the key is in the archive).
- // leave well alone.
- }
- Some( RefInfo{queue_refs: 1, in_archive: false} ) => {
- // just delete the refs entry.
- refs.remove(k);
- }
- Some( RefInfo{queue_refs: x, in_archive: false} ) => {
- // must set already in; ,
- Self::set_already_in(batch, self.column, k);
- refs.insert(k.clone(), RefInfo{ queue_refs: x - 1, in_archive: true });
- }
- Some( RefInfo{in_archive: true, ..} ) => {
- // Invalid! Reinserted the same key twice.
- warn!("Key {} inserted twice into same fork.", k);
- }
+ // apply old commits' details
+ let mut index = 0usize;
+ let mut last;
+
+ while let Some(rlp_data) = try!(self.backing.get(self.column, {
+ let mut r = RlpStream::new_list(3);
+ r.append(&end_era);
+ r.append(&index);
+ r.append(&&PADDING[..]);
+ last = r.drain();
+ &last
+ })) {
+ let rlp = Rlp::new(&rlp_data);
+ let inserts: Vec = rlp.val_at(1);
+
+ if canon_id == &rlp.val_at::(0) {
+ // Collect keys to be removed. Canon block - remove the (enacted) deletes.
+ let deletes: Vec = rlp.val_at(2);
+ trace!(target: "jdb.ops", " Expunging: {:?}", deletes);
+ Self::remove_keys(&deletes, &mut refs, batch, self.column, RemoveFrom::Archive, trace);
+
+ trace!(target: "jdb.ops", " Finalising: {:?}", inserts);
+ for k in &inserts {
+ match refs.get(k).cloned() {
+ None => {
+ // [in archive] -> SHIFT remove -> SHIFT insert None->Some{queue_refs: 1, in_archive: true} -> TAKE remove Some{queue_refs: 1, in_archive: true}->None -> TAKE insert
+ // already expunged from the queue (which is allowed since the key is in the archive).
+ // leave well alone.
+ }
+ Some( RefInfo{queue_refs: 1, in_archive: false} ) => {
+ // just delete the refs entry.
+ refs.remove(k);
+ }
+ Some( RefInfo{queue_refs: x, in_archive: false} ) => {
+ // must set already in; ,
+ Self::set_already_in(batch, self.column, k);
+ refs.insert(k.clone(), RefInfo{ queue_refs: x - 1, in_archive: true });
+ }
+ Some( RefInfo{in_archive: true, ..} ) => {
+ // Invalid! Reinserted the same key twice.
+ warn!("Key {} inserted twice into same fork.", k);
}
}
- } else {
- // Collect keys to be removed. Non-canon block - remove the (reverted) inserts.
- if trace {
- trace!(target: "jdb.ops", " Reverting: {:?}", inserts);
- }
- Self::remove_keys(&inserts, &mut refs, batch, self.column, RemoveFrom::Queue, trace);
}
-
- batch.delete(self.column, &last);
- index += 1;
- }
- if trace {
- trace!(target: "jdb", "EarlyMergeDB: delete journal for time #{}.{}, (canon was {})", end_era, index, canon_id);
+ } else {
+ // Collect keys to be removed. Non-canon block - remove the (reverted) inserts.
+ trace!(target: "jdb.ops", " Reverting: {:?}", inserts);
+ Self::remove_keys(&inserts, &mut refs, batch, self.column, RemoveFrom::Queue, trace);
}
- }
- if trace {
- trace!(target: "jdb", "OK: {:?}", refs.clone());
+ batch.delete(self.column, &last);
+ index += 1;
}
+ trace!(target: "jdb", "EarlyMergeDB: delete journal for time #{}.{}, (canon was {})", end_era, index, canon_id);
+ trace!(target: "jdb", "OK: {:?}", refs.clone());
+
Ok(0)
}
diff --git a/util/src/journaldb/overlayrecentdb.rs b/util/src/journaldb/overlayrecentdb.rs
index bd14eb161bf..bf01567fb88 100644
--- a/util/src/journaldb/overlayrecentdb.rs
+++ b/util/src/journaldb/overlayrecentdb.rs
@@ -70,6 +70,7 @@ struct JournalOverlay {
pending_overlay: H256FastMap, // Nodes being transfered from backing_overlay to backing db
journal: HashMap>,
latest_era: Option,
+ earliest_era: Option,
}
#[derive(PartialEq)]
@@ -123,7 +124,10 @@ impl OverlayRecentDB {
fn can_reconstruct_refs(&self) -> bool {
let reconstructed = Self::read_overlay(&self.backing, self.column);
let journal_overlay = self.journal_overlay.read();
- *journal_overlay == reconstructed
+ journal_overlay.backing_overlay == reconstructed.backing_overlay &&
+ journal_overlay.pending_overlay == reconstructed.pending_overlay &&
+ journal_overlay.journal == reconstructed.journal &&
+ journal_overlay.latest_era == reconstructed.latest_era
}
fn payload(&self, key: &H256) -> Option {
@@ -135,6 +139,7 @@ impl OverlayRecentDB {
let mut overlay = MemoryDB::new();
let mut count = 0;
let mut latest_era = None;
+ let mut earliest_era = None;
if let Some(val) = db.get(col, &LATEST_ERA_KEY).expect("Low-level database error.") {
let mut era = decode::(&val);
latest_era = Some(era);
@@ -166,6 +171,7 @@ impl OverlayRecentDB {
deletions: deletions,
});
index += 1;
+ earliest_era = Some(era);
};
if index == 0 || era == 0 {
break;
@@ -178,9 +184,12 @@ impl OverlayRecentDB {
backing_overlay: overlay,
pending_overlay: HashMap::default(),
journal: journal,
- latest_era: latest_era }
+ latest_era: latest_era,
+ earliest_era: earliest_era,
+ }
}
+
}
#[inline]
@@ -214,6 +223,8 @@ impl JournalDB for OverlayRecentDB {
fn latest_era(&self) -> Option { self.journal_overlay.read().latest_era }
+ fn earliest_era(&self) -> Option { self.journal_overlay.read().earliest_era }
+
fn state(&self, key: &H256) -> Option {
let journal_overlay = self.journal_overlay.read();
let key = to_short_key(key);
@@ -222,92 +233,107 @@ impl JournalDB for OverlayRecentDB {
.or_else(|| self.backing.get_by_prefix(self.column, &key[0..DB_PREFIX_LEN]).map(|b| b.to_vec()))
}
- fn commit(&mut self, batch: &mut DBTransaction, now: u64, id: &H256, end: Option<(u64, H256)>) -> Result {
- // record new commit's details.
- trace!("commit: #{} ({}), end era: {:?}", now, id, end);
+ fn journal_under(&mut self, batch: &mut DBTransaction, now: u64, id: &H256) -> Result {
+ trace!(target: "journaldb", "entry: #{} ({})", now, id);
+
let mut journal_overlay = self.journal_overlay.write();
+
// flush previous changes
journal_overlay.pending_overlay.clear();
- {
- let mut r = RlpStream::new_list(3);
- let mut tx = self.transaction_overlay.drain();
- let inserted_keys: Vec<_> = tx.iter().filter_map(|(k, &(_, c))| if c > 0 { Some(k.clone()) } else { None }).collect();
- let removed_keys: Vec<_> = tx.iter().filter_map(|(k, &(_, c))| if c < 0 { Some(k.clone()) } else { None }).collect();
- // Increase counter for each inserted key no matter if the block is canonical or not.
- let insertions = tx.drain().filter_map(|(k, (v, c))| if c > 0 { Some((k, v)) } else { None });
- r.append(id);
- r.begin_list(inserted_keys.len());
- for (k, v) in insertions {
- r.begin_list(2);
- r.append(&k);
- r.append(&v);
- journal_overlay.backing_overlay.emplace(to_short_key(&k), v);
- }
- r.append(&removed_keys);
-
- let mut k = RlpStream::new_list(3);
- let index = journal_overlay.journal.get(&now).map_or(0, |j| j.len());
- k.append(&now);
- k.append(&index);
- k.append(&&PADDING[..]);
- batch.put_vec(self.column, &k.drain(), r.out());
- if journal_overlay.latest_era.map_or(true, |e| now > e) {
- batch.put_vec(self.column, &LATEST_ERA_KEY, encode(&now).to_vec());
- journal_overlay.latest_era = Some(now);
- }
- journal_overlay.journal.entry(now).or_insert_with(Vec::new).push(JournalEntry { id: id.clone(), insertions: inserted_keys, deletions: removed_keys });
+
+ let mut r = RlpStream::new_list(3);
+ let mut tx = self.transaction_overlay.drain();
+ let inserted_keys: Vec<_> = tx.iter().filter_map(|(k, &(_, c))| if c > 0 { Some(k.clone()) } else { None }).collect();
+ let removed_keys: Vec<_> = tx.iter().filter_map(|(k, &(_, c))| if c < 0 { Some(k.clone()) } else { None }).collect();
+ let ops = inserted_keys.len() + removed_keys.len();
+
+ // Increase counter for each inserted key no matter if the block is canonical or not.
+ let insertions = tx.drain().filter_map(|(k, (v, c))| if c > 0 { Some((k, v)) } else { None });
+
+ r.append(id);
+ r.begin_list(inserted_keys.len());
+ for (k, v) in insertions {
+ r.begin_list(2);
+ r.append(&k);
+ r.append(&v);
+ journal_overlay.backing_overlay.emplace(to_short_key(&k), v);
+ }
+ r.append(&removed_keys);
+
+ let mut k = RlpStream::new_list(3);
+ let index = journal_overlay.journal.get(&now).map_or(0, |j| j.len());
+ k.append(&now);
+ k.append(&index);
+ k.append(&&PADDING[..]);
+ batch.put_vec(self.column, &k.drain(), r.out());
+ if journal_overlay.latest_era.map_or(true, |e| now > e) {
+ batch.put_vec(self.column, &LATEST_ERA_KEY, encode(&now).to_vec());
+ journal_overlay.latest_era = Some(now);
}
+ journal_overlay.journal.entry(now).or_insert_with(Vec::new).push(JournalEntry { id: id.clone(), insertions: inserted_keys, deletions: removed_keys });
+ Ok(ops as u32)
+ }
+
+ fn mark_canonical(&mut self, batch: &mut DBTransaction, end_era: u64, canon_id: &H256) -> Result {
+ trace!(target: "journaldb", "canonical: #{} ({})", end_era, canon_id);
+
+ let mut journal_overlay = self.journal_overlay.write();
let journal_overlay = &mut *journal_overlay;
+
+ let mut ops = 0;
// apply old commits' details
- if let Some((end_era, canon_id)) = end {
- if let Some(ref mut records) = journal_overlay.journal.get_mut(&end_era) {
- let mut canon_insertions: Vec<(H256, Bytes)> = Vec::new();
- let mut canon_deletions: Vec = Vec::new();
- let mut overlay_deletions: Vec = Vec::new();
- let mut index = 0usize;
- for mut journal in records.drain(..) {
- //delete the record from the db
- let mut r = RlpStream::new_list(3);
- r.append(&end_era);
- r.append(&index);
- r.append(&&PADDING[..]);
- batch.delete(self.column, &r.drain());
- trace!("commit: Delete journal for time #{}.{}: {}, (canon was {}): +{} -{} entries", end_era, index, journal.id, canon_id, journal.insertions.len(), journal.deletions.len());
- {
- if canon_id == journal.id {
- for h in &journal.insertions {
- if let Some((d, rc)) = journal_overlay.backing_overlay.raw(&to_short_key(h)) {
- if rc > 0 {
- canon_insertions.push((h.clone(), d.to_owned())); //TODO: optimize this to avoid data copy
- }
+ if let Some(ref mut records) = journal_overlay.journal.get_mut(&end_era) {
+ let mut canon_insertions: Vec<(H256, Bytes)> = Vec::new();
+ let mut canon_deletions: Vec = Vec::new();
+ let mut overlay_deletions: Vec = Vec::new();
+ let mut index = 0usize;
+ for mut journal in records.drain(..) {
+ //delete the record from the db
+ let mut r = RlpStream::new_list(3);
+ r.append(&end_era);
+ r.append(&index);
+ r.append(&&PADDING[..]);
+ batch.delete(self.column, &r.drain());
+ trace!(target: "journaldb", "Delete journal for time #{}.{}: {}, (canon was {}): +{} -{} entries", end_era, index, journal.id, canon_id, journal.insertions.len(), journal.deletions.len());
+ {
+ if *canon_id == journal.id {
+ for h in &journal.insertions {
+ if let Some((d, rc)) = journal_overlay.backing_overlay.raw(&to_short_key(h)) {
+ if rc > 0 {
+ canon_insertions.push((h.clone(), d.to_owned())); //TODO: optimize this to avoid data copy
}
}
- canon_deletions = journal.deletions;
}
- overlay_deletions.append(&mut journal.insertions);
+ canon_deletions = journal.deletions;
}
- index += 1;
- }
- // apply canon inserts first
- for (k, v) in canon_insertions {
- batch.put(self.column, &k, &v);
- journal_overlay.pending_overlay.insert(to_short_key(&k), v);
- }
- // update the overlay
- for k in overlay_deletions {
- journal_overlay.backing_overlay.remove_and_purge(&to_short_key(&k));
+ overlay_deletions.append(&mut journal.insertions);
}
- // apply canon deletions
- for k in canon_deletions {
- if !journal_overlay.backing_overlay.contains(&to_short_key(&k)) {
- batch.delete(self.column, &k);
- }
+ index += 1;
+ }
+
+ ops += canon_insertions.len();
+ ops += canon_deletions.len();
+
+ // apply canon inserts first
+ for (k, v) in canon_insertions {
+ batch.put(self.column, &k, &v);
+ journal_overlay.pending_overlay.insert(to_short_key(&k), v);
+ }
+ // update the overlay
+ for k in overlay_deletions {
+ journal_overlay.backing_overlay.remove_and_purge(&to_short_key(&k));
+ }
+ // apply canon deletions
+ for k in canon_deletions {
+ if !journal_overlay.backing_overlay.contains(&to_short_key(&k)) {
+ batch.delete(self.column, &k);
}
}
- journal_overlay.journal.remove(&end_era);
}
- Ok(0)
+ journal_overlay.journal.remove(&end_era);
+
+ Ok(ops as u32)
}
fn flush(&self) {
diff --git a/util/src/journaldb/refcounteddb.rs b/util/src/journaldb/refcounteddb.rs
index 5e3f096063e..e6a0f5dccfc 100644
--- a/util/src/journaldb/refcounteddb.rs
+++ b/util/src/journaldb/refcounteddb.rs
@@ -34,6 +34,17 @@ use std::env;
/// write operations out to disk. Unlike `OverlayDB`, `remove()` operations do not take effect
/// immediately. Rather some age (based on a linear but arbitrary metric) must pass before
/// the removals actually take effect.
+///
+/// journal format:
+/// [era, 0] => [ id, [insert_0, ...], [remove_0, ...] ]
+/// [era, 1] => [ id, [insert_0, ...], [remove_0, ...] ]
+/// [era, n] => [ ... ]
+///
+/// when we make a new commit, we journal the inserts and removes.
+/// for each end_era that we journaled that we are no passing by,
+/// we remove all of its removes assuming it is canonical and all
+/// of its inserts otherwise.
+// TODO: store last_era, reclaim_period.
pub struct RefCountedDB {
forward: OverlayDB,
backing: Arc,
@@ -109,77 +120,66 @@ impl JournalDB for RefCountedDB {
self.backing.get_by_prefix(self.column, &id[0..DB_PREFIX_LEN]).map(|b| b.to_vec())
}
- fn commit(&mut self, batch: &mut DBTransaction, now: u64, id: &H256, end: Option<(u64, H256)>) -> Result {
- // journal format:
- // [era, 0] => [ id, [insert_0, ...], [remove_0, ...] ]
- // [era, 1] => [ id, [insert_0, ...], [remove_0, ...] ]
- // [era, n] => [ ... ]
-
- // TODO: store last_era, reclaim_period.
-
- // when we make a new commit, we journal the inserts and removes.
- // for each end_era that we journaled that we are no passing by,
- // we remove all of its removes assuming it is canonical and all
- // of its inserts otherwise.
-
+ fn journal_under(&mut self, batch: &mut DBTransaction, now: u64, id: &H256) -> Result {
// record new commit's details.
- {
- let mut index = 0usize;
- let mut last;
-
- while try!(self.backing.get(self.column, {
- let mut r = RlpStream::new_list(3);
- r.append(&now);
- r.append(&index);
- r.append(&&PADDING[..]);
- last = r.drain();
- &last
- })).is_some() {
- index += 1;
- }
+ let mut index = 0usize;
+ let mut last;
+ while try!(self.backing.get(self.column, {
let mut r = RlpStream::new_list(3);
- r.append(id);
- r.append(&self.inserts);
- r.append(&self.removes);
- batch.put(self.column, &last, r.as_raw());
+ r.append(&now);
+ r.append(&index);
+ r.append(&&PADDING[..]);
+ last = r.drain();
+ &last
+ })).is_some() {
+ index += 1;
+ }
- trace!(target: "rcdb", "new journal for time #{}.{} => {}: inserts={:?}, removes={:?}", now, index, id, self.inserts, self.removes);
+ let mut r = RlpStream::new_list(3);
+ r.append(id);
+ r.append(&self.inserts);
+ r.append(&self.removes);
+ batch.put(self.column, &last, r.as_raw());
- self.inserts.clear();
- self.removes.clear();
+ let ops = self.inserts.len() + self.removes.len();
- if self.latest_era.map_or(true, |e| now > e) {
- batch.put(self.column, &LATEST_ERA_KEY, &encode(&now));
- self.latest_era = Some(now);
- }
+ trace!(target: "rcdb", "new journal for time #{}.{} => {}: inserts={:?}, removes={:?}", now, index, id, self.inserts, self.removes);
+
+ self.inserts.clear();
+ self.removes.clear();
+
+ if self.latest_era.map_or(true, |e| now > e) {
+ batch.put(self.column, &LATEST_ERA_KEY, &encode(&now));
+ self.latest_era = Some(now);
}
+ Ok(ops as u32)
+ }
+
+ fn mark_canonical(&mut self, batch: &mut DBTransaction, end_era: u64, canon_id: &H256) -> Result {
// apply old commits' details
- if let Some((end_era, canon_id)) = end {
- let mut index = 0usize;
- let mut last;
- while let Some(rlp_data) = {
-// trace!(target: "rcdb", "checking for journal #{}.{}", end_era, index);
- try!(self.backing.get(self.column, {
- let mut r = RlpStream::new_list(3);
- r.append(&end_era);
- r.append(&index);
- r.append(&&PADDING[..]);
- last = r.drain();
- &last
- }))
- } {
- let rlp = Rlp::new(&rlp_data);
- let our_id: H256 = rlp.val_at(0);
- let to_remove: Vec = rlp.val_at(if canon_id == our_id {2} else {1});
- trace!(target: "rcdb", "delete journal for time #{}.{}=>{}, (canon was {}): deleting {:?}", end_era, index, our_id, canon_id, to_remove);
- for i in &to_remove {
- self.forward.remove(i);
- }
- batch.delete(self.column, &last);
- index += 1;
+ let mut index = 0usize;
+ let mut last;
+ while let Some(rlp_data) = {
+ try!(self.backing.get(self.column, {
+ let mut r = RlpStream::new_list(3);
+ r.append(&end_era);
+ r.append(&index);
+ r.append(&&PADDING[..]);
+ last = r.drain();
+ &last
+ }))
+ } {
+ let rlp = Rlp::new(&rlp_data);
+ let our_id: H256 = rlp.val_at(0);
+ let to_remove: Vec = rlp.val_at(if *canon_id == our_id {2} else {1});
+ trace!(target: "rcdb", "delete journal for time #{}.{}=>{}, (canon was {}): deleting {:?}", end_era, index, our_id, canon_id, to_remove);
+ for i in &to_remove {
+ self.forward.remove(i);
}
+ batch.delete(self.column, &last);
+ index += 1;
}
let r = try!(self.forward.commit_to_batch(batch));
diff --git a/util/src/journaldb/traits.rs b/util/src/journaldb/traits.rs
index 85cc7fe58b5..7acf20519df 100644
--- a/util/src/journaldb/traits.rs
+++ b/util/src/journaldb/traits.rs
@@ -32,12 +32,18 @@ pub trait JournalDB: HashDB {
/// Check if this database has any commits
fn is_empty(&self) -> bool;
+ /// Get the earliest era in the DB. None if there isn't yet any data in there.
+ fn earliest_era(&self) -> Option { None }
+
/// Get the latest era in the DB. None if there isn't yet any data in there.
fn latest_era(&self) -> Option;
- /// Commit all recent insert operations and canonical historical commits' removals from the
- /// old era to the backing database, reverting any non-canonical historical commit's inserts.
- fn commit(&mut self, batch: &mut DBTransaction, now: u64, id: &H256, end: Option<(u64, H256)>) -> Result;
+ /// Journal recent database operations as being associated with a given era and id.
+ // TODO: give the overlay to this function so journaldbs don't manage the overlays themeselves.
+ fn journal_under(&mut self, batch: &mut DBTransaction, now: u64, id: &H256) -> Result;
+
+ /// Mark a given block as canonical, indicating that competing blocks' states may be pruned out.
+ fn mark_canonical(&mut self, batch: &mut DBTransaction, era: u64, id: &H256) -> Result