From 8cb4bc212789661d77944e5f0e2f1a85dadb78c7 Mon Sep 17 00:00:00 2001 From: Nicolas Gotchac Date: Wed, 14 Jun 2017 12:35:36 +0200 Subject: [PATCH 01/14] Fix wrongly called timeouts --- js/src/api/subscriptions/signer.js | 2 +- js/src/api/transport/http/http.js | 4 ++-- js/src/views/Signer/store.js | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/js/src/api/subscriptions/signer.js b/js/src/api/subscriptions/signer.js index d4acce163..2215ed7f3 100644 --- a/js/src/api/subscriptions/signer.js +++ b/js/src/api/subscriptions/signer.js @@ -57,7 +57,7 @@ export default class Signer { this._updateSubscriptions('signer_requestsToConfirm', null, requests); nextTimeout(); }) - .catch(nextTimeout); + .catch(() => nextTimeout()); } _postTransaction (data) { diff --git a/js/src/api/transport/http/http.js b/js/src/api/transport/http/http.js index f7ef4579d..66ef2dec7 100644 --- a/js/src/api/transport/http/http.js +++ b/js/src/api/transport/http/http.js @@ -93,8 +93,8 @@ export default class Http extends JsonRpcBase { this .execute('net_listening') - .then(nextTimeout) - .catch(nextTimeout); + .then(() => nextTimeout()) + .catch(() => nextTimeout()); } set url (url) { diff --git a/js/src/views/Signer/store.js b/js/src/views/Signer/store.js index e99333159..a18f4e209 100644 --- a/js/src/views/Signer/store.js +++ b/js/src/views/Signer/store.js @@ -101,7 +101,7 @@ export default class SignerStore { this.setLocalHashes(keys); }) - .then(nextTimeout) - .catch(nextTimeout); + .then(() => nextTimeout()) + .catch(() => nextTimeout()); } } From ba6e41cf076dbeedb120649dbb36f3529d39bbb6 Mon Sep 17 00:00:00 2001 From: maciejhirsz Date: Fri, 16 Jun 2017 14:00:30 +0200 Subject: [PATCH 02/14] Fixed account selection for Dapps on public node --- js/src/api/local/accounts/accounts.js | 10 +++++++++- js/src/api/local/localAccountsMiddleware.js | 14 ++++++++++---- js/src/api/transport/middleware.js | 4 ++++ 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/js/src/api/local/accounts/accounts.js b/js/src/api/local/accounts/accounts.js index d0d100862..823ab3624 100644 --- a/js/src/api/local/accounts/accounts.js +++ b/js/src/api/local/accounts/accounts.js @@ -129,6 +129,8 @@ export default class Accounts { set dappsDefaultAddress (value) { this._dappsDefaultAddress = value.toLowerCase(); + + this.persist(); } get (address) { @@ -191,10 +193,16 @@ export default class Accounts { this.persist(); } - addresses () { + allAddresses () { return Object.keys(this._store); } + accountAddresses () { + return Object + .keys(this._store) + .filter((address) => this._store[address].uuid); + } + map (mapper) { const result = {}; diff --git a/js/src/api/local/localAccountsMiddleware.js b/js/src/api/local/localAccountsMiddleware.js index 457574715..c8e767f89 100644 --- a/js/src/api/local/localAccountsMiddleware.js +++ b/js/src/api/local/localAccountsMiddleware.js @@ -29,7 +29,7 @@ export default class LocalAccountsMiddleware extends Middleware { const register = this.register.bind(this); register('eth_accounts', () => { - return accounts.addresses(); + return accounts.accountAddresses(); }); register('eth_coinbase', () => { @@ -73,7 +73,7 @@ export default class LocalAccountsMiddleware extends Middleware { }); register('parity_defaultAccount', () => { - return accounts.lastAddress; + return accounts.dappsDefaultAddress; }); register('parity_exportAccount', ([address, password]) => { @@ -98,11 +98,11 @@ export default class LocalAccountsMiddleware extends Middleware { }); register('parity_getNewDappsAddresses', () => { - return []; + return accounts.accountAddresses(); }); register('parity_getNewDappsDefaultAddress', () => { - return accounts.lastAddress; + return accounts.dappsDefaultAddress; }); register('parity_hardwareAccountsInfo', () => { @@ -149,6 +149,8 @@ export default class LocalAccountsMiddleware extends Middleware { register('parity_setNewDappsDefaultAddress', ([address]) => { accounts.dappsDefaultAddress = address; + + return true; }); register('parity_postTransaction', ([tx]) => { @@ -210,6 +212,10 @@ export default class LocalAccountsMiddleware extends Middleware { return account.isValidPassword(password); }); + register('parity_upgradeReady', () => { + return false; + }); + register('signer_confirmRequest', ([id, modify, password]) => { const { gasPrice, diff --git a/js/src/api/transport/middleware.js b/js/src/api/transport/middleware.js index 7d7199f95..ef029b1cb 100644 --- a/js/src/api/transport/middleware.js +++ b/js/src/api/transport/middleware.js @@ -21,6 +21,10 @@ export default class Middleware { } register (method, handler) { + if (method in this._handlers) { + throw new Error(`${method} is already defined in the middleware!`); + } + this._handlers[method] = handler; } From 41fed96d96b23442e695b0b95c85aec5320f4174 Mon Sep 17 00:00:00 2001 From: Guanqun Lu Date: Sun, 18 Jun 2017 22:15:44 +0800 Subject: [PATCH 03/14] convert try!() to ? --- ethcore/src/ethereum/ethash.rs | 6 +++--- secret_store/src/key_server_cluster/io/deadline.rs | 2 +- sync/src/api.rs | 4 ++-- sync/src/light_sync/mod.rs | 2 +- sync/src/light_sync/response.rs | 10 +++++----- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 1013612e8..a7c9f9db2 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -255,13 +255,13 @@ impl Engine for Arc { fn on_new_block(&self, block: &mut ExecutedBlock, last_hashes: Arc) -> Result<(), Error> { let parent_hash = block.fields().header.parent_hash().clone(); - try!(::engines::common::push_last_hash(block, last_hashes, self, &parent_hash)); + ::engines::common::push_last_hash(block, last_hashes, self, &parent_hash)?; if block.fields().header.number() == self.ethash_params.dao_hardfork_transition { let state = block.fields_mut().state; for child in &self.ethash_params.dao_hardfork_accounts { let beneficiary = &self.ethash_params.dao_hardfork_beneficiary; - try!(state.balance(child) - .and_then(|b| state.transfer_balance(child, beneficiary, &b, CleanupMode::NoEmpty))); + state.balance(child) + .and_then(|b| state.transfer_balance(child, beneficiary, &b, CleanupMode::NoEmpty))?; } } Ok(()) diff --git a/secret_store/src/key_server_cluster/io/deadline.rs b/secret_store/src/key_server_cluster/io/deadline.rs index 7b8c4d0ed..501a69057 100644 --- a/secret_store/src/key_server_cluster/io/deadline.rs +++ b/secret_store/src/key_server_cluster/io/deadline.rs @@ -24,7 +24,7 @@ type DeadlineBox where F: Future = BoxFuture, F::Erro /// Complete a passed future or fail if it is not completed within timeout. pub fn deadline(duration: Duration, handle: &Handle, future: F) -> Result, io::Error> where F: Future + Send + 'static, T: 'static { - let timeout = try!(Timeout::new(duration, handle)).map(|_| DeadlineStatus::Timeout).boxed(); + let timeout = Timeout::new(duration, handle)?.map(|_| DeadlineStatus::Timeout).boxed(); let future = future.map(DeadlineStatus::Meet).boxed(); let deadline = Deadline { future: timeout.select(future), diff --git a/sync/src/api.rs b/sync/src/api.rs index edf83ee17..737456167 100644 --- a/sync/src/api.rs +++ b/sync/src/api.rs @@ -709,7 +709,7 @@ impl LightSync { }; let mut light_proto = LightProtocol::new(params.client.clone(), light_params); - let sync_handler = Arc::new(try!(SyncHandler::new(params.client.clone()))); + let sync_handler = Arc::new(SyncHandler::new(params.client.clone())?); light_proto.add_handler(sync_handler.clone()); for handler in params.handlers { @@ -719,7 +719,7 @@ impl LightSync { (sync_handler, Arc::new(light_proto)) }; - let service = try!(NetworkService::new(params.network_config)); + let service = NetworkService::new(params.network_config)?; Ok(LightSync { proto: light_proto, diff --git a/sync/src/light_sync/mod.rs b/sync/src/light_sync/mod.rs index 2bc179a21..2cfbafa17 100644 --- a/sync/src/light_sync/mod.rs +++ b/sync/src/light_sync/mod.rs @@ -551,7 +551,7 @@ impl LightSync { peers: RwLock::new(HashMap::new()), pending_reqs: Mutex::new(HashSet::new()), client: client, - rng: Mutex::new(try!(OsRng::new())), + rng: Mutex::new(OsRng::new()?), state: Mutex::new(SyncState::Idle), }) } diff --git a/sync/src/light_sync/response.rs b/sync/src/light_sync/response.rs index d85d2548d..73ce58b39 100644 --- a/sync/src/light_sync/response.rs +++ b/sync/src/light_sync/response.rs @@ -47,7 +47,7 @@ impl From for BasicError { impl fmt::Display for BasicError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "Header response verification error: ")); + write!(f, "Header response verification error: ")?; match *self { BasicError::WrongSkip(ref exp, ref got) @@ -78,13 +78,13 @@ pub fn verify(headers: &[encoded::Header], request: &HeadersRequest) -> Result try!(StartsAtNumber(*num).verify(&headers, reverse)), - HashOrNumber::Hash(ref hash) => try!(StartsAtHash(*hash).verify(&headers, reverse)), + HashOrNumber::Number(ref num) => StartsAtNumber(*num).verify(&headers, reverse)?, + HashOrNumber::Hash(ref hash) => StartsAtHash(*hash).verify(&headers, reverse)?, } - try!(SkipsBetween(request.skip).verify(&headers, reverse)); + SkipsBetween(request.skip).verify(&headers, reverse)?; Ok(headers) } From 7f07f7d567bc0bfde9fae460b1c9563ebfe928ff Mon Sep 17 00:00:00 2001 From: Guanqun Lu Date: Sat, 10 Jun 2017 00:13:50 +0800 Subject: [PATCH 04/14] ArchiveDB: add a contains() test for long history test case --- util/src/journaldb/archivedb.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/util/src/journaldb/archivedb.rs b/util/src/journaldb/archivedb.rs index 1f9381c99..b86064d8f 100644 --- a/util/src/journaldb/archivedb.rs +++ b/util/src/journaldb/archivedb.rs @@ -239,6 +239,7 @@ mod tests { jdb.commit_batch(3, &b"3".sha3(), Some((0, b"0".sha3()))).unwrap(); assert!(jdb.contains(&h)); jdb.commit_batch(4, &b"4".sha3(), Some((1, b"1".sha3()))).unwrap(); + assert!(jdb.contains(&h)); } #[test] From a5531e83fd8a6ba1d2c52f71ae3d49474097ce63 Mon Sep 17 00:00:00 2001 From: Guanqun Lu Date: Sat, 10 Jun 2017 00:23:25 +0800 Subject: [PATCH 05/14] ArchiveDB: add a new test case --- util/src/journaldb/archivedb.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/util/src/journaldb/archivedb.rs b/util/src/journaldb/archivedb.rs index b86064d8f..9099ff03b 100644 --- a/util/src/journaldb/archivedb.rs +++ b/util/src/journaldb/archivedb.rs @@ -242,6 +242,20 @@ mod tests { assert!(jdb.contains(&h)); } + #[test] + #[should_panic] + fn multiple_owed_removal_not_allowed() { + let mut jdb = ArchiveDB::new_temp(); + let h = jdb.insert(b"foo"); + jdb.commit_batch(0, &b"0".sha3(), None).unwrap(); + assert!(jdb.contains(&h)); + jdb.remove(&h); + jdb.remove(&h); + // commit_batch would call journal_under(), + // and we don't allow multiple owned removals. + jdb.commit_batch(1, &b"1".sha3(), None).unwrap(); + } + #[test] fn complex() { // history is 1 From 4eff7abf3b0e2a2eadacfe9cd991407c9d491dff Mon Sep 17 00:00:00 2001 From: Guanqun Lu Date: Sun, 11 Jun 2017 22:41:16 +0800 Subject: [PATCH 06/14] StateDB: change spaces to tab --- ethcore/src/state_db.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethcore/src/state_db.rs b/ethcore/src/state_db.rs index a5823f50b..de5a3f75b 100644 --- a/ethcore/src/state_db.rs +++ b/ethcore/src/state_db.rs @@ -477,7 +477,7 @@ mod tests { let mut batch = DBTransaction::new(); // blocks [ 3a(c) 2a(c) 2b 1b 1a(c) 0 ] - // balance [ 5 5 4 3 2 2 ] + // 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.journal_under(&mut batch, 0, &h0).unwrap(); From c1e5c36f7efd176a18bab5b0ecf1d36a4f7beee0 Mon Sep 17 00:00:00 2001 From: Guanqun Lu Date: Sun, 11 Jun 2017 22:41:37 +0800 Subject: [PATCH 07/14] EthStore: add a Chinese path to tests in ethstore --- ethstore/src/dir/vault.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/ethstore/src/dir/vault.rs b/ethstore/src/dir/vault.rs index 31c99fcc4..a7b351643 100755 --- a/ethstore/src/dir/vault.rs +++ b/ethstore/src/dir/vault.rs @@ -296,6 +296,7 @@ mod test { assert!(check_vault_name("vault_with_underscores")); assert!(check_vault_name("vault-with-dashes")); assert!(check_vault_name("vault-with-digits-123")); + assert!(check_vault_name("vault中文名字")); } #[test] From c50dacff17742cd4f7ca5685b12d809825602a53 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 19 Jun 2017 11:29:09 +0200 Subject: [PATCH 08/14] all executables are workspace members (#5865) * ethstore-cli and ethkey-cli are workspace projects * evmbin is now a workspace project --- Cargo.lock | 21 ++++++++++++++++--- Cargo.toml | 4 +--- ethcore/Cargo.toml | 2 -- ethkey/Cargo.toml | 10 --------- ethkey/cli/Cargo.toml | 14 +++++++++++++ ethkey/{src/bin/ethkey.rs => cli/src/main.rs} | 0 ethkey/src/bin/main.rs | 21 ------------------- ethstore/Cargo.toml | 9 -------- ethstore/cli/Cargo.toml | 14 +++++++++++++ .../{src/bin/ethstore.rs => cli/src/main.rs} | 0 ethstore/src/bin/main.rs | 21 ------------------- 11 files changed, 47 insertions(+), 69 deletions(-) create mode 100644 ethkey/cli/Cargo.toml rename ethkey/{src/bin/ethkey.rs => cli/src/main.rs} (100%) delete mode 100644 ethkey/src/bin/main.rs create mode 100644 ethstore/cli/Cargo.toml rename ethstore/{src/bin/ethstore.rs => cli/src/main.rs} (100%) delete mode 100644 ethstore/src/bin/main.rs diff --git a/Cargo.lock b/Cargo.lock index ace76b1f7..8647a52b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -692,7 +692,6 @@ name = "ethkey" version = "0.2.0" dependencies = [ "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "docopt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "eth-secp256k1 0.5.6 (git+https://github.com/paritytech/rust-secp256k1)", "ethcore-bigint 0.1.3", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -703,10 +702,18 @@ dependencies = [ ] [[package]] -name = "ethstore" +name = "ethkey-cli" version = "0.1.0" dependencies = [ "docopt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethkey 0.2.0", + "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ethstore" +version = "0.1.0" +dependencies = [ "ethcore-bigint 0.1.3", "ethcrypto 0.1.0", "ethkey 0.2.0", @@ -727,6 +734,15 @@ dependencies = [ "tiny-keccak 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ethstore-cli" +version = "0.1.0" +dependencies = [ + "docopt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethstore 0.1.0", + "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ethsync" version = "1.7.0" @@ -1569,7 +1585,6 @@ dependencies = [ "ethcore-util 1.7.0", "ethkey 0.2.0", "ethsync 1.7.0", - "evmbin 0.1.0", "fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 497078c62..b1d8c6699 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,7 +40,6 @@ ethcore-light = { path = "ethcore/light" } ethcore-logger = { path = "logger" } ethcore-stratum = { path = "stratum" } ethkey = { path = "ethkey" } -evmbin = { path = "evmbin" } rlp = { path = "util/rlp" } rpc-cli = { path = "rpc_cli" } parity-hash-fetch = { path = "hash-fetch" } @@ -86,8 +85,6 @@ jit = ["ethcore/jit"] dev = ["clippy", "ethcore/dev", "ethcore-util/dev", "ethsync/dev", "parity-rpc/dev", "parity-dapps/dev"] json-tests = ["ethcore/json-tests"] test-heavy = ["ethcore/test-heavy"] -ethkey-cli = ["ethcore/ethkey-cli"] -ethstore-cli = ["ethcore/ethstore-cli"] evm-debug = ["ethcore/evm-debug"] evm-debug-tests = ["ethcore/evm-debug-tests"] slow-blocks = ["ethcore/slow-blocks"] @@ -104,3 +101,4 @@ lto = false panic = "abort" [workspace] +members = ["ethstore/cli", "ethkey/cli", "evmbin"] diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index b207ae2b3..168cf803c 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -66,5 +66,3 @@ dev = ["clippy"] default = [] benches = [] ipc = [] -ethkey-cli = ["ethkey/cli"] -ethstore-cli = ["ethstore/cli"] diff --git a/ethkey/Cargo.toml b/ethkey/Cargo.toml index e99e1cbe7..7d038a7f7 100644 --- a/ethkey/Cargo.toml +++ b/ethkey/Cargo.toml @@ -9,16 +9,6 @@ lazy_static = "0.2" tiny-keccak = "1.2" eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1" } rustc-serialize = "0.3" -docopt = { version = "0.7", optional = true } ethcore-bigint = { path = "../util/bigint" } rust-crypto = "0.2" byteorder = "1.0" - -[features] -default = [] -cli = ["docopt"] - -[[bin]] -name = "ethkey" -path = "src/bin/main.rs" -doc = false diff --git a/ethkey/cli/Cargo.toml b/ethkey/cli/Cargo.toml new file mode 100644 index 000000000..01cc9849f --- /dev/null +++ b/ethkey/cli/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "ethkey-cli" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] +ethkey = { path = "../" } +rustc-serialize = "0.3" +docopt = "0.7" + +[[bin]] +name = "ethkey" +path = "src/main.rs" +doc = false diff --git a/ethkey/src/bin/ethkey.rs b/ethkey/cli/src/main.rs similarity index 100% rename from ethkey/src/bin/ethkey.rs rename to ethkey/cli/src/main.rs diff --git a/ethkey/src/bin/main.rs b/ethkey/src/bin/main.rs deleted file mode 100644 index 14dfa34ff..000000000 --- a/ethkey/src/bin/main.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -#[cfg(feature = "cli")] -include!("ethkey.rs"); - -#[cfg(not(feature = "cli"))] -fn main() {} diff --git a/ethstore/Cargo.toml b/ethstore/Cargo.toml index 4c6ece5f5..a2efaf286 100755 --- a/ethstore/Cargo.toml +++ b/ethstore/Cargo.toml @@ -14,7 +14,6 @@ serde_derive = "0.9" rustc-serialize = "0.3" rust-crypto = "0.2.36" tiny-keccak = "1.0" -docopt = { version = "0.7", optional = true } time = "0.1.34" itertools = "0.5" parking_lot = "0.4" @@ -24,12 +23,4 @@ smallvec = "0.4" parity-wordlist = "1.0" tempdir = "0.3" -[features] -cli = ["docopt"] - [lib] - -[[bin]] -name = "ethstore" -path = "src/bin/main.rs" -doc = false diff --git a/ethstore/cli/Cargo.toml b/ethstore/cli/Cargo.toml new file mode 100644 index 000000000..28e210cec --- /dev/null +++ b/ethstore/cli/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "ethstore-cli" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] +rustc-serialize = "0.3" +docopt = "0.7" +ethstore = { path = "../" } + +[[bin]] +name = "ethstore" +path = "src/main.rs" +doc = false diff --git a/ethstore/src/bin/ethstore.rs b/ethstore/cli/src/main.rs similarity index 100% rename from ethstore/src/bin/ethstore.rs rename to ethstore/cli/src/main.rs diff --git a/ethstore/src/bin/main.rs b/ethstore/src/bin/main.rs deleted file mode 100644 index a0c9441f4..000000000 --- a/ethstore/src/bin/main.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -#[cfg(feature = "cli")] -include!("ethstore.rs"); - -#[cfg(not(feature = "cli"))] -fn main() {} From 575c51f5a017099320f025ad55fdcb9a676c8952 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 19 Jun 2017 11:41:46 +0200 Subject: [PATCH 09/14] eip214, #4833 (#4851) --- ethcore/res/ethereum/frontier_like_test.json | 2 +- ethcore/res/ethereum/transition_test.json | 2 +- ethcore/src/client/test_client.rs | 4 +- ethcore/src/engines/authority_round.rs | 8 +-- ethcore/src/engines/instant_seal.rs | 7 -- ethcore/src/engines/mod.rs | 4 +- ethcore/src/engines/tendermint/mod.rs | 6 -- ethcore/src/ethereum/ethash.rs | 8 +-- ethcore/src/evm/evm.rs | 4 +- ethcore/src/evm/ext.rs | 21 +++--- ethcore/src/evm/instructions.rs | 3 + ethcore/src/evm/interpreter/gasometer.rs | 2 +- ethcore/src/evm/interpreter/mod.rs | 9 ++- ethcore/src/evm/schedule.rs | 37 ++++++++-- ethcore/src/evm/tests.rs | 21 +++--- ethcore/src/executive.rs | 33 +++++++-- ethcore/src/externalities.rs | 71 +++++++++++++------- ethcore/src/json_tests/executive.rs | 23 ++++--- ethcore/src/spec/spec.rs | 3 + ethcore/src/types/executed.rs | 7 ++ ethcore/src/types/trace_types/error.rs | 6 ++ json/src/spec/params.rs | 3 + rpc/src/v1/types/trace.rs | 4 ++ 23 files changed, 185 insertions(+), 103 deletions(-) diff --git a/ethcore/res/ethereum/frontier_like_test.json b/ethcore/res/ethereum/frontier_like_test.json index aab433033..fde04f6b5 100644 --- a/ethcore/res/ethereum/frontier_like_test.json +++ b/ethcore/res/ethereum/frontier_like_test.json @@ -12,7 +12,7 @@ "homesteadTransition": "0x118c30", "daoHardforkTransition": "0x1d4c00", "daoHardforkBeneficiary": "0xbf4ed7b27f1d666546e30d74d50d173d20bca754", - "daoHardforkAccounts": [ + "daoHardforkAccounts": [ "0xd4fe7bc31cedb7bfb8a345f31e668033056b2728", "0xb3fb0e5aba0e20e5c49d252dfd30e102b171a425", "0x2c19c7f9ae8b751e37aeb2d93a699722395ae18f", diff --git a/ethcore/res/ethereum/transition_test.json b/ethcore/res/ethereum/transition_test.json index 41251dc8c..7709ba015 100644 --- a/ethcore/res/ethereum/transition_test.json +++ b/ethcore/res/ethereum/transition_test.json @@ -12,7 +12,7 @@ "homesteadTransition": "0x5", "daoHardforkTransition": "0x8", "daoHardforkBeneficiary": "0xbf4ed7b27f1d666546e30d74d50d173d20bca754", - "daoHardforkAccounts": [ + "daoHardforkAccounts": [ "0xd4fe7bc31cedb7bfb8a345f31e668033056b2728", "0xb3fb0e5aba0e20e5c49d252dfd30e102b171a425", "0x2c19c7f9ae8b751e37aeb2d93a699722395ae18f", diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index a823e295f..19c208b45 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -55,7 +55,7 @@ pub struct TestBlockChainClient { /// Blocks. pub blocks: RwLock>, /// Mapping of numbers to hashes. - pub numbers: RwLock>, + pub numbers: RwLock>, /// Genesis block hash. pub genesis_hash: H256, /// Last block hash. @@ -353,7 +353,7 @@ pub fn get_temp_state_db() -> GuardedTempResult { impl MiningBlockChainClient for TestBlockChainClient { fn latest_schedule(&self) -> Schedule { - Schedule::new_post_eip150(24576, true, true, true, true) + Schedule::new_post_eip150(24576, true, true, true) } fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes) -> OpenBlock { diff --git a/ethcore/src/engines/authority_round.rs b/ethcore/src/engines/authority_round.rs index 84c1df8fc..22860ebbd 100644 --- a/ethcore/src/engines/authority_round.rs +++ b/ethcore/src/engines/authority_round.rs @@ -26,9 +26,8 @@ use account_provider::AccountProvider; use block::*; use spec::CommonParams; use engines::{Call, Engine, Seal, EngineError}; -use header::{Header, BlockNumber}; +use header::Header; use error::{Error, TransactionError, BlockError}; -use evm::Schedule; use ethjson; use io::{IoContext, IoHandler, TimerToken, IoService}; use builtin::Builtin; @@ -296,11 +295,6 @@ impl Engine for AuthorityRound { ] } - fn schedule(&self, block_number: BlockNumber) -> Schedule { - let eip86 = block_number >= self.params.eip86_transition; - Schedule::new_post_eip150(usize::max_value(), true, true, true, eip86) - } - fn populate_from_parent(&self, header: &mut Header, parent: &Header, gas_floor_target: U256, _gas_ceil_target: U256) { // Chain scoring: total weight is sqrt(U256::max_value())*height - step let new_difficulty = U256::from(U128::max_value()) + header_step(parent).expect("Header has been verified; qed").into() - self.step.load().into(); diff --git a/ethcore/src/engines/instant_seal.rs b/ethcore/src/engines/instant_seal.rs index 702afde4f..249aa8ac2 100644 --- a/ethcore/src/engines/instant_seal.rs +++ b/ethcore/src/engines/instant_seal.rs @@ -19,9 +19,7 @@ use util::{Address, HashMap}; use builtin::Builtin; use engines::{Engine, Seal}; use spec::CommonParams; -use evm::Schedule; use block::ExecutedBlock; -use header::BlockNumber; /// An engine which does not provide any consensus mechanism, just seals blocks internally. pub struct InstantSeal { @@ -58,11 +56,6 @@ impl Engine for InstantSeal { &self.builtins } - fn schedule(&self, block_number: BlockNumber) -> Schedule { - let eip86 = block_number >= self.params.eip86_transition; - Schedule::new_post_eip150(usize::max_value(), true, true, true, eip86) - } - fn seals_internally(&self) -> Option { Some(true) } fn generate_seal(&self, _block: &ExecutedBlock) -> Seal { diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index 7d3963eac..849e08cf2 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -147,7 +147,9 @@ pub trait Engine : Sync + Send { fn params(&self) -> &CommonParams; /// Get the EVM schedule for the given `block_number`. - fn schedule(&self, block_number: BlockNumber) -> Schedule; + fn schedule(&self, block_number: BlockNumber) -> Schedule { + Schedule::from_params(block_number, self.params()) + } /// Builtin-contracts we would like to see in the chain. /// (In principle these are just hints for the engine since that has the last word on them.) diff --git a/ethcore/src/engines/tendermint/mod.rs b/ethcore/src/engines/tendermint/mod.rs index 98e274e9b..1a462a634 100644 --- a/ethcore/src/engines/tendermint/mod.rs +++ b/ethcore/src/engines/tendermint/mod.rs @@ -38,7 +38,6 @@ use account_provider::AccountProvider; use block::*; use spec::CommonParams; use engines::{Engine, Seal, EngineError}; -use evm::Schedule; use state::CleanupMode; use io::IoService; use super::signer::EngineSigner; @@ -404,11 +403,6 @@ impl Engine for Tendermint { ] } - fn schedule(&self, block_number: BlockNumber) -> Schedule { - let eip86 = block_number >= self.params.eip86_transition; - Schedule::new_post_eip150(usize::max_value(), true, true, true, eip86) - } - fn populate_from_parent(&self, header: &mut Header, parent: &Header, gas_floor_target: U256, _gas_ceil_target: U256) { // Chain scoring: total weight is sqrt(U256::max_value())*height - view let new_difficulty = U256::from(U128::max_value()) + consensus_view(parent).expect("Header has been verified; qed").into() - self.view.load(AtomicOrdering::SeqCst).into(); diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 1013612e8..256684666 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -196,13 +196,13 @@ impl Engine for Arc { } else if block_number < self.ethash_params.eip150_transition { Schedule::new_homestead() } else { - Schedule::new_post_eip150( + let mut schedule = Schedule::new_post_eip150( self.ethash_params.max_code_size as usize, block_number >= self.ethash_params.eip160_transition, block_number >= self.ethash_params.eip161abc_transition, - block_number >= self.ethash_params.eip161d_transition, - block_number >= self.params.eip86_transition - ) + block_number >= self.ethash_params.eip161d_transition); + schedule.apply_params(block_number, self.params()); + schedule } } diff --git a/ethcore/src/evm/evm.rs b/ethcore/src/evm/evm.rs index a644fd255..31ecb13f8 100644 --- a/ethcore/src/evm/evm.rs +++ b/ethcore/src/evm/evm.rs @@ -62,7 +62,8 @@ pub enum Error { }, /// Built-in contract failed on given input BuiltIn(&'static str), - /// Returned on evm internal error. Should never be ignored during development. + /// When execution tries to modify the state in static context + MutableCallInStaticContext, /// Likely to cause consensus issues. Internal(String), } @@ -90,6 +91,7 @@ impl fmt::Display for Error { OutOfStack { instruction, wanted, limit } => write!(f, "Out of stack {} {}/{}", instruction, wanted, limit), BuiltIn(name) => write!(f, "Built-in failed: {}", name), Internal(ref msg) => write!(f, "Internal error: {}", msg), + MutableCallInStaticContext => write!(f, "Mutable call in static context"), } } } diff --git a/ethcore/src/evm/ext.rs b/ethcore/src/evm/ext.rs index 2eb99fe7c..c66d1d3ff 100644 --- a/ethcore/src/evm/ext.rs +++ b/ethcore/src/evm/ext.rs @@ -53,25 +53,24 @@ pub enum CreateContractAddress { } /// Externalities interface for EVMs -// TODO: [rob] associated error type instead of `trie::Result`. Not all EVMs are trie powered. pub trait Ext { /// Returns a value for given key. - fn storage_at(&self, key: &H256) -> trie::Result; + fn storage_at(&self, key: &H256) -> evm::Result; /// Stores a value for given key. - fn set_storage(&mut self, key: H256, value: H256) -> trie::Result<()>; + fn set_storage(&mut self, key: H256, value: H256) -> evm::Result<()>; /// Determine whether an account exists. - fn exists(&self, address: &Address) -> trie::Result; + fn exists(&self, address: &Address) -> evm::Result; /// Determine whether an account exists and is not null (zero balance/nonce, no code). - fn exists_and_not_null(&self, address: &Address) -> trie::Result; + fn exists_and_not_null(&self, address: &Address) -> evm::Result; /// Balance of the origin account. - fn origin_balance(&self) -> trie::Result; + fn origin_balance(&self) -> evm::Result; /// Returns address balance. - fn balance(&self, address: &Address) -> trie::Result; + fn balance(&self, address: &Address) -> evm::Result; /// Returns the hash of one of the 256 most recent complete blocks. fn blockhash(&mut self, number: &U256) -> H256; @@ -99,13 +98,13 @@ pub trait Ext { ) -> MessageCallResult; /// Returns code at given address - fn extcode(&self, address: &Address) -> trie::Result>; + fn extcode(&self, address: &Address) -> evm::Result>; /// Returns code size at given address - fn extcodesize(&self, address: &Address) -> trie::Result; + fn extcodesize(&self, address: &Address) -> evm::Result; /// Creates log entry with given topics and data - fn log(&mut self, topics: Vec, data: &[u8]); + fn log(&mut self, topics: Vec, data: &[u8]) -> evm::Result<()>; /// Should be called when transaction calls `RETURN` opcode. /// Returns gas_left if cost of returning the data is not too high. @@ -113,7 +112,7 @@ pub trait Ext { /// Should be called when contract commits suicide. /// Address to which funds should be refunded. - fn suicide(&mut self, refund_address: &Address) -> trie::Result<()> ; + fn suicide(&mut self, refund_address: &Address) -> evm::Result<()> ; /// Returns schedule. fn schedule(&self) -> &Schedule; diff --git a/ethcore/src/evm/instructions.rs b/ethcore/src/evm/instructions.rs index 351517386..83be0c954 100644 --- a/ethcore/src/evm/instructions.rs +++ b/ethcore/src/evm/instructions.rs @@ -298,6 +298,7 @@ lazy_static! { arr[CALLCODE as usize] = InstructionInfo::new("CALLCODE", 7, 1, GasPriceTier::Special); arr[RETURN as usize] = InstructionInfo::new("RETURN", 2, 0, GasPriceTier::Zero); arr[DELEGATECALL as usize] = InstructionInfo::new("DELEGATECALL", 6, 1, GasPriceTier::Special); + arr[STATICCALL as usize] = InstructionInfo::new("STATICCALL", 6, 1, GasPriceTier::Special); arr[SUICIDE as usize] = InstructionInfo::new("SUICIDE", 1, 0, GasPriceTier::Special); arr[CREATE2 as usize] = InstructionInfo::new("CREATE2", 3, 1, GasPriceTier::Special); arr[REVERT as usize] = InstructionInfo::new("REVERT", 2, 0, GasPriceTier::Zero); @@ -584,6 +585,8 @@ pub const DELEGATECALL: Instruction = 0xf4; pub const CREATE2: Instruction = 0xfb; /// stop execution and revert state changes. Return output data. pub const REVERT: Instruction = 0xfd; +/// like CALL but it does not take value, nor modify the state +pub const STATICCALL: Instruction = 0xfa; /// halt execution and register account for later deletion pub const SUICIDE: Instruction = 0xff; diff --git a/ethcore/src/evm/interpreter/gasometer.rs b/ethcore/src/evm/interpreter/gasometer.rs index e76a5971e..426b8ffd0 100644 --- a/ethcore/src/evm/interpreter/gasometer.rs +++ b/ethcore/src/evm/interpreter/gasometer.rs @@ -213,7 +213,7 @@ impl Gasometer { Request::GasMemProvide(gas, mem, Some(requested)) }, - instructions::DELEGATECALL => { + instructions::DELEGATECALL | instructions::STATICCALL => { let gas = Gas::from(schedule.call_gas); let mem = cmp::max( mem_needed(stack.peek(4), stack.peek(5))?, diff --git a/ethcore/src/evm/interpreter/mod.rs b/ethcore/src/evm/interpreter/mod.rs index 32d010daf..a4ff69c2a 100644 --- a/ethcore/src/evm/interpreter/mod.rs +++ b/ethcore/src/evm/interpreter/mod.rs @@ -199,6 +199,7 @@ impl Interpreter { if (instruction == instructions::DELEGATECALL && !schedule.have_delegate_call) || (instruction == instructions::CREATE2 && !schedule.have_create2) || + (instruction == instructions::STATICCALL && !schedule.have_static_call) || (instruction == instructions::REVERT && !schedule.have_revert) { return Err(evm::Error::BadInstruction { @@ -312,14 +313,15 @@ impl Interpreter { } }; }, - instructions::CALL | instructions::CALLCODE | instructions::DELEGATECALL => { + instructions::CALL | instructions::CALLCODE | instructions::DELEGATECALL | instructions::STATICCALL => { assert!(ext.schedule().call_value_transfer_gas > ext.schedule().call_stipend, "overflow possible"); + 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); - let value = if instruction == instructions::DELEGATECALL { + let value = if instruction == instructions::DELEGATECALL || instruction == instructions::STATICCALL { None } else { Some(stack.pop_back()) @@ -347,6 +349,7 @@ impl Interpreter { (¶ms.address, ¶ms.address, has_balance, CallType::CallCode) }, instructions::DELEGATECALL => (¶ms.sender, ¶ms.address, true, CallType::DelegateCall), + instructions::STATICCALL => (¶ms.sender, ¶ms.address, true, CallType::StaticCall), _ => panic!(format!("Unexpected instruction {} in CALL branch.", instruction)) }; @@ -405,7 +408,7 @@ impl Interpreter { .iter() .map(H256::from) .collect(); - ext.log(topics, self.mem.read_slice(offset, size)); + ext.log(topics, self.mem.read_slice(offset, size))?; }, instructions::PUSH1...instructions::PUSH32 => { let bytes = instructions::get_push_bytes(instruction); diff --git a/ethcore/src/evm/schedule.rs b/ethcore/src/evm/schedule.rs index 7fafb2e12..de4406767 100644 --- a/ethcore/src/evm/schedule.rs +++ b/ethcore/src/evm/schedule.rs @@ -15,6 +15,7 @@ // along with Parity. If not, see . //! Cost schedule and other parameterisations for the EVM. +use spec::CommonParams; /// Definition of the cost schedule and other parameterisations for the EVM. pub struct Schedule { @@ -105,6 +106,8 @@ pub struct Schedule { pub kill_empty: bool, /// Blockhash instruction gas cost. pub blockhash_gas: usize, + /// Static Call opcode enabled. + pub have_static_call: bool, } impl Schedule { @@ -119,12 +122,12 @@ impl Schedule { } /// Schedule for the post-EIP-150-era of the Ethereum main net. - pub fn new_post_eip150(max_code_size: usize, fix_exp: bool, no_empty: bool, kill_empty: bool, have_metropolis_instructions: bool) -> Schedule { + pub fn new_post_eip150(max_code_size: usize, fix_exp: bool, no_empty: bool, kill_empty: bool) -> Schedule { Schedule { exceptional_failed_code_deposit: true, have_delegate_call: true, - have_create2: have_metropolis_instructions, - have_revert: have_metropolis_instructions, + have_create2: false, + have_revert: false, stack_limit: 1024, max_depth: 1024, tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0], @@ -163,13 +166,36 @@ impl Schedule { sub_gas_cap_divisor: Some(64), no_empty: no_empty, kill_empty: kill_empty, - blockhash_gas: if have_metropolis_instructions { 350 } else { 20 }, + blockhash_gas: 20, + have_static_call: false, + } + } + + /// Schedule for the Metropolis era from common spec params. + pub fn from_params(block_number: u64, params: &CommonParams) -> Schedule { + let mut schedule = Schedule::new_post_eip150(usize::max_value(), true, true, true); + schedule.apply_params(block_number, params); + schedule + } + + /// Apply common spec config parameters to the schedule. + pub fn apply_params(&mut self, block_number: u64, params: &CommonParams) { + self.have_create2 = block_number >= params.eip86_transition; + self.have_revert = block_number >= params.eip140_transition; + self.have_static_call = block_number >= params.eip214_transition; + if block_number >= params.eip210_transition { + self.blockhash_gas = 350; } } /// Schedule for the Metropolis of the Ethereum main net. pub fn new_metropolis() -> Schedule { - Self::new_post_eip150(24576, true, true, true, true) + let mut schedule = Self::new_post_eip150(24576, true, true, true); + schedule.have_create2 = true; + schedule.have_revert = true; + schedule.have_static_call = true; + schedule.blockhash_gas = 350; + schedule } fn new(efcd: bool, hdc: bool, tcg: usize) -> Schedule { @@ -217,6 +243,7 @@ impl Schedule { no_empty: false, kill_empty: false, blockhash_gas: 20, + have_static_call: false, } } } diff --git a/ethcore/src/evm/tests.rs b/ethcore/src/evm/tests.rs index 462a632b4..7f3cf0e1c 100644 --- a/ethcore/src/evm/tests.rs +++ b/ethcore/src/evm/tests.rs @@ -87,28 +87,28 @@ impl Default for Schedule { } impl Ext for FakeExt { - fn storage_at(&self, key: &H256) -> trie::Result { + fn storage_at(&self, key: &H256) -> evm::Result { Ok(self.store.get(key).unwrap_or(&H256::new()).clone()) } - fn set_storage(&mut self, key: H256, value: H256) -> trie::Result<()> { + fn set_storage(&mut self, key: H256, value: H256) -> evm::Result<()> { self.store.insert(key, value); Ok(()) } - fn exists(&self, address: &Address) -> trie::Result { + fn exists(&self, address: &Address) -> evm::Result { Ok(self.balances.contains_key(address)) } - fn exists_and_not_null(&self, address: &Address) -> trie::Result { + fn exists_and_not_null(&self, address: &Address) -> evm::Result { Ok(self.balances.get(address).map_or(false, |b| !b.is_zero())) } - fn origin_balance(&self) -> trie::Result { + fn origin_balance(&self) -> evm::Result { unimplemented!() } - fn balance(&self, address: &Address) -> trie::Result { + fn balance(&self, address: &Address) -> evm::Result { Ok(self.balances[address]) } @@ -152,26 +152,27 @@ impl Ext for FakeExt { MessageCallResult::Success(*gas, ReturnData::empty()) } - fn extcode(&self, address: &Address) -> trie::Result> { + fn extcode(&self, address: &Address) -> evm::Result> { Ok(self.codes.get(address).unwrap_or(&Arc::new(Bytes::new())).clone()) } - fn extcodesize(&self, address: &Address) -> trie::Result { + fn extcodesize(&self, address: &Address) -> evm::Result { Ok(self.codes.get(address).map_or(0, |c| c.len())) } - fn log(&mut self, topics: Vec, data: &[u8]) { + fn log(&mut self, topics: Vec, data: &[u8]) -> evm::Result<()> { self.logs.push(FakeLogEntry { topics: topics, data: data.to_vec() }); + Ok(()) } fn ret(self, _gas: &U256, _data: &ReturnData) -> evm::Result { unimplemented!(); } - fn suicide(&mut self, _refund_address: &Address) -> trie::Result<()> { + fn suicide(&mut self, _refund_address: &Address) -> evm::Result<()> { unimplemented!(); } diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index 4dbee6bde..7e582ccae 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -76,6 +76,7 @@ pub struct Executive<'a, B: 'a + StateBackend, E: 'a + Engine + ?Sized> { info: &'a EnvInfo, engine: &'a E, depth: usize, + static_flag: bool, } impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { @@ -86,16 +87,18 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { info: info, engine: engine, depth: 0, + static_flag: false, } } /// Populates executive from parent properties. Increments executive depth. - pub fn from_parent(state: &'a mut State, info: &'a EnvInfo, engine: &'a E, parent_depth: usize) -> Self { + pub fn from_parent(state: &'a mut State, info: &'a EnvInfo, engine: &'a E, parent_depth: usize, static_flag: bool) -> Self { Executive { state: state, info: info, engine: engine, depth: parent_depth + 1, + static_flag: static_flag, } } @@ -106,9 +109,11 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { substate: &'any mut Substate, output: OutputPolicy<'any, 'any>, tracer: &'any mut T, - vm_tracer: &'any mut V + vm_tracer: &'any mut V, + static_call: bool, ) -> Externalities<'any, T, V, B, E> where T: Tracer, V: VMTracer { - Externalities::new(self.state, self.info, self.engine, self.depth, origin_info, substate, output, tracer, vm_tracer) + let is_static = self.static_flag || static_call; + Externalities::new(self.state, self.info, self.engine, self.depth, origin_info, substate, output, tracer, vm_tracer, is_static) } /// This function should be used to execute transaction. @@ -246,11 +251,12 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { ) -> evm::Result where T: Tracer, V: VMTracer { let depth_threshold = ::io::LOCAL_STACK_SIZE.with(|sz| sz.get() / STACK_SIZE_PER_DEPTH); + let static_call = params.call_type == CallType::StaticCall; // Ordinary execution - keep VM in same thread if (self.depth + 1) % depth_threshold != 0 { let vm_factory = self.state.vm_factory(); - let mut ext = self.as_externalities(OriginInfo::from(¶ms), unconfirmed_substate, output_policy, tracer, vm_tracer); + let mut ext = self.as_externalities(OriginInfo::from(¶ms), unconfirmed_substate, output_policy, tracer, vm_tracer, static_call); trace!(target: "executive", "ext.schedule.have_delegate_call: {}", ext.schedule().have_delegate_call); return vm_factory.create(params.gas).exec(params, &mut ext).finalize(ext); } @@ -260,7 +266,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { // https://github.com/aturon/crossbeam/issues/16 crossbeam::scope(|scope| { let vm_factory = self.state.vm_factory(); - let mut ext = self.as_externalities(OriginInfo::from(¶ms), unconfirmed_substate, output_policy, tracer, vm_tracer); + let mut ext = self.as_externalities(OriginInfo::from(¶ms), unconfirmed_substate, output_policy, tracer, vm_tracer, static_call); scope.spawn(move || { vm_factory.create(params.gas).exec(params, &mut ext).finalize(ext) @@ -280,6 +286,15 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { tracer: &mut T, vm_tracer: &mut V ) -> evm::Result<(U256, ReturnData)> where T: Tracer, V: VMTracer { + + trace!("Executive::call(params={:?}) self.env_info={:?}", params, self.info); + if (params.call_type == CallType::StaticCall || + ((params.call_type == CallType::Call || params.call_type == CallType::DelegateCall) && + self.static_flag)) + && params.value.value() > 0.into() { + return Err(evm::Error::MutableCallInStaticContext); + } + // backup used in case of running out of gas self.state.checkpoint(); @@ -289,7 +304,6 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { if let ActionValue::Transfer(val) = params.value { self.state.transfer_balance(¶ms.sender, ¶ms.address, &val, substate.to_cleanup_mode(&schedule))?; } - trace!("Executive::call(params={:?}) self.env_info={:?}", params, self.info); // if destination is builtin, try to execute it if let Some(builtin) = self.engine.builtin(¶ms.code_address, self.info.number) { @@ -403,6 +417,12 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { return Err(evm::Error::OutOfGas); } + if params.call_type == CallType::StaticCall || self.static_flag { + let trace_info = tracer.prepare_trace_create(¶ms); + tracer.trace_failed_create(trace_info, vec![], evm::Error::MutableCallInStaticContext.into()); + return Err(evm::Error::MutableCallInStaticContext); + } + // backup used in case of running out of gas self.state.checkpoint(); @@ -541,6 +561,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { | Err(evm::Error::StackUnderflow {..}) | Err(evm::Error::BuiltIn {..}) | Err(evm::Error::OutOfStack {..}) + | Err(evm::Error::MutableCallInStaticContext) | Ok(FinalizationResult { apply_state: false, .. }) => { self.state.revert_to_checkpoint(); }, diff --git a/ethcore/src/externalities.rs b/ethcore/src/externalities.rs index d0895306e..72c13f062 100644 --- a/ethcore/src/externalities.rs +++ b/ethcore/src/externalities.rs @@ -40,7 +40,7 @@ pub struct OriginInfo { address: Address, origin: Address, gas_price: U256, - value: U256 + value: U256, } impl OriginInfo { @@ -52,7 +52,7 @@ impl OriginInfo { gas_price: params.gas_price, value: match params.value { ActionValue::Transfer(val) | ActionValue::Apparent(val) => val - } + }, } } } @@ -71,6 +71,7 @@ pub struct Externalities<'a, T: 'a, V: 'a, B: 'a, E: 'a + Engine + ?Sized> output: OutputPolicy<'a, 'a>, tracer: &'a mut T, vm_tracer: &'a mut V, + static_flag: bool, } impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Externalities<'a, T, V, B, E> @@ -87,6 +88,7 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Externalities<'a, T, V, B, E> output: OutputPolicy<'a, 'a>, tracer: &'a mut T, vm_tracer: &'a mut V, + static_flag: bool, ) -> Self { Externalities { state: state, @@ -99,6 +101,7 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Externalities<'a, T, V, B, E> output: output, tracer: tracer, vm_tracer: vm_tracer, + static_flag: static_flag, } } } @@ -106,26 +109,32 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Externalities<'a, T, V, B, E> impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E> where T: Tracer, V: VMTracer, B: StateBackend, E: Engine + ?Sized { - fn storage_at(&self, key: &H256) -> trie::Result { - self.state.storage_at(&self.origin_info.address, key) + fn storage_at(&self, key: &H256) -> evm::Result { + self.state.storage_at(&self.origin_info.address, key).map_err(Into::into) } - fn set_storage(&mut self, key: H256, value: H256) -> trie::Result<()> { - self.state.set_storage(&self.origin_info.address, key, value) + fn set_storage(&mut self, key: H256, value: H256) -> evm::Result<()> { + if self.static_flag { + Err(evm::Error::MutableCallInStaticContext) + } else { + self.state.set_storage(&self.origin_info.address, key, value).map_err(Into::into) + } } - fn exists(&self, address: &Address) -> trie::Result { - self.state.exists(address) + fn exists(&self, address: &Address) -> evm::Result { + self.state.exists(address).map_err(Into::into) } - fn exists_and_not_null(&self, address: &Address) -> trie::Result { - self.state.exists_and_not_null(address) + fn exists_and_not_null(&self, address: &Address) -> evm::Result { + self.state.exists_and_not_null(address).map_err(Into::into) } - fn origin_balance(&self) -> trie::Result { self.balance(&self.origin_info.address) } + fn origin_balance(&self) -> evm::Result { + self.balance(&self.origin_info.address).map_err(Into::into) + } - fn balance(&self, address: &Address) -> trie::Result { - self.state.balance(address) + fn balance(&self, address: &Address) -> evm::Result { + self.state.balance(address).map_err(Into::into) } fn blockhash(&mut self, number: &U256) -> H256 { @@ -208,7 +217,7 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E> return ContractCreateResult::Failed } } - let mut ex = Executive::from_parent(self.state, self.env_info, self.engine, self.depth); + let mut ex = Executive::from_parent(self.state, self.env_info, self.engine, self.depth, self.static_flag); // TODO: handle internal error separately match ex.create(params, self.substate, self.tracer, self.vm_tracer) { @@ -258,7 +267,7 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E> params.value = ActionValue::Transfer(value); } - let mut ex = Executive::from_parent(self.state, self.env_info, self.engine, self.depth); + let mut ex = Executive::from_parent(self.state, self.env_info, self.engine, self.depth, self.static_flag); match ex.call(params, self.substate, BytesRef::Fixed(output), self.tracer, self.vm_tracer) { Ok((gas_left, return_data)) => MessageCallResult::Success(gas_left, return_data), @@ -266,11 +275,11 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E> } } - fn extcode(&self, address: &Address) -> trie::Result> { + fn extcode(&self, address: &Address) -> evm::Result> { Ok(self.state.code(address)?.unwrap_or_else(|| Arc::new(vec![]))) } - fn extcodesize(&self, address: &Address) -> trie::Result { + fn extcodesize(&self, address: &Address) -> evm::Result { Ok(self.state.code_size(address)?.unwrap_or(0)) } @@ -312,18 +321,28 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E> } } - fn log(&mut self, topics: Vec, data: &[u8]) { + fn log(&mut self, topics: Vec, data: &[u8]) -> evm::Result<()> { use log_entry::LogEntry; + if self.static_flag { + return Err(evm::Error::MutableCallInStaticContext); + } + let address = self.origin_info.address.clone(); self.substate.logs.push(LogEntry { address: address, topics: topics, data: data.to_vec() }); + + Ok(()) } - fn suicide(&mut self, refund_address: &Address) -> trie::Result<()> { + fn suicide(&mut self, refund_address: &Address) -> evm::Result<()> { + if self.static_flag { + return Err(evm::Error::MutableCallInStaticContext); + } + let address = self.origin_info.address.clone(); let balance = self.balance(&address)?; if &address == refund_address { @@ -434,7 +453,7 @@ mod tests { let mut tracer = NoopTracer; let mut vm_tracer = NoopVMTracer; - let ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer); + let ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false); assert_eq!(ext.env_info().number, 100); } @@ -446,7 +465,7 @@ mod tests { let mut tracer = NoopTracer; let mut vm_tracer = NoopVMTracer; - let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer); + let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false); let hash = ext.blockhash(&U256::from_str("0000000000000000000000000000000000000000000000000000000000120000").unwrap()); @@ -470,7 +489,7 @@ mod tests { let mut tracer = NoopTracer; let mut vm_tracer = NoopVMTracer; - let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer); + let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false); let hash = ext.blockhash(&U256::from_str("0000000000000000000000000000000000000000000000000000000000120000").unwrap()); @@ -485,7 +504,7 @@ mod tests { let mut tracer = NoopTracer; let mut vm_tracer = NoopVMTracer; - let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer); + let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false); let mut output = vec![]; @@ -513,8 +532,8 @@ mod tests { let mut vm_tracer = NoopVMTracer; { - let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer); - ext.log(log_topics, &log_data); + let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false); + ext.log(log_topics, &log_data).unwrap(); } assert_eq!(setup.sub_state.logs.len(), 1); @@ -530,7 +549,7 @@ mod tests { let mut vm_tracer = NoopVMTracer; { - let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer); + let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false); ext.suicide(refund_account).unwrap(); } diff --git a/ethcore/src/json_tests/executive.rs b/ethcore/src/json_tests/executive.rs index b21259090..7e37818f2 100644 --- a/ethcore/src/json_tests/executive.rs +++ b/ethcore/src/json_tests/executive.rs @@ -75,9 +75,10 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> TestExt<'a, T, V, B, E> tracer: &'a mut T, vm_tracer: &'a mut V, ) -> trie::Result { + let static_call = false; Ok(TestExt { nonce: state.nonce(&address)?, - ext: Externalities::new(state, info, engine, depth, origin_info, substate, output, tracer, vm_tracer), + ext: Externalities::new(state, info, engine, depth, origin_info, substate, output, tracer, vm_tracer, static_call), callcreates: vec![], sender: address, }) @@ -87,27 +88,27 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> TestExt<'a, T, V, B, E> impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for TestExt<'a, T, V, B, E> where T: Tracer, V: VMTracer, B: StateBackend, E: Engine + ?Sized { - fn storage_at(&self, key: &H256) -> trie::Result { + fn storage_at(&self, key: &H256) -> evm::Result { self.ext.storage_at(key) } - fn set_storage(&mut self, key: H256, value: H256) -> trie::Result<()> { + fn set_storage(&mut self, key: H256, value: H256) -> evm::Result<()> { self.ext.set_storage(key, value) } - fn exists(&self, address: &Address) -> trie::Result { + fn exists(&self, address: &Address) -> evm::Result { self.ext.exists(address) } - fn exists_and_not_null(&self, address: &Address) -> trie::Result { + fn exists_and_not_null(&self, address: &Address) -> evm::Result { self.ext.exists_and_not_null(address) } - fn balance(&self, address: &Address) -> trie::Result { + fn balance(&self, address: &Address) -> evm::Result { self.ext.balance(address) } - fn origin_balance(&self) -> trie::Result { + fn origin_balance(&self) -> evm::Result { self.ext.origin_balance() } @@ -145,15 +146,15 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for TestExt<'a, T, V, B, E> MessageCallResult::Success(*gas, ReturnData::empty()) } - fn extcode(&self, address: &Address) -> trie::Result> { + fn extcode(&self, address: &Address) -> evm::Result> { self.ext.extcode(address) } - fn extcodesize(&self, address: &Address) -> trie::Result { + fn extcodesize(&self, address: &Address) -> evm::Result { self.ext.extcodesize(address) } - fn log(&mut self, topics: Vec, data: &[u8]) { + fn log(&mut self, topics: Vec, data: &[u8]) -> evm::Result<()> { self.ext.log(topics, data) } @@ -161,7 +162,7 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for TestExt<'a, T, V, B, E> self.ext.ret(gas, data) } - fn suicide(&mut self, refund_address: &Address) -> trie::Result<()> { + fn suicide(&mut self, refund_address: &Address) -> evm::Result<()> { self.ext.suicide(refund_address) } diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index 819964aef..d1a7ce484 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -74,6 +74,8 @@ pub struct CommonParams { pub eip210_contract_gas: U256, /// Number of first block where EIP-211 (Metropolis: RETURNDATASIZE/RETURNDATACOPY) rules begin. pub eip211_transition: BlockNumber, + /// Number of first block where EIP-214 rules begin. + pub eip214_transition: BlockNumber, } impl From for CommonParams { @@ -97,6 +99,7 @@ impl From for CommonParams { Into::into), eip210_contract_gas: p.eip210_contract_gas.map_or(1000000.into(), Into::into), eip211_transition: p.eip211_transition.map_or(BlockNumber::max_value(), Into::into), + eip214_transition: p.eip214_transition.map_or(BlockNumber::max_value(), Into::into), } } } diff --git a/ethcore/src/types/executed.rs b/ethcore/src/types/executed.rs index f18bd1bee..571d8af97 100644 --- a/ethcore/src/types/executed.rs +++ b/ethcore/src/types/executed.rs @@ -36,6 +36,8 @@ pub enum CallType { CallCode, /// DELEGATECALL. DelegateCall, + /// STATICCALL + StaticCall, } impl Encodable for CallType { @@ -45,6 +47,7 @@ impl Encodable for CallType { CallType::Call => 1, CallType::CallCode => 2, CallType::DelegateCall => 3, + CallType::StaticCall => 4, }; Encodable::rlp_append(&v, s); } @@ -57,6 +60,7 @@ impl Decodable for CallType { 1 => CallType::Call, 2 => CallType::CallCode, 3 => CallType::DelegateCall, + 4 => CallType::StaticCall, _ => return Err(DecoderError::Custom("Invalid value of CallType item")), })) } @@ -145,6 +149,8 @@ pub enum ExecutionError { /// Actual balance. got: U512 }, + /// When execution tries to modify the state in static context + MutableCallInStaticContext, /// Returned when internal evm error occurs. Internal(String), /// Returned when generic transaction occurs @@ -172,6 +178,7 @@ impl fmt::Display for ExecutionError { NotEnoughCash { ref required, ref got } => format!("Cost of transaction exceeds sender balance. {} is required \ but the sender only has {}", required, got), + MutableCallInStaticContext => "Mutable Call in static context".to_owned(), Internal(ref msg) => msg.clone(), TransactionMalformed(ref err) => format!("Malformed transaction: {}", err), }; diff --git a/ethcore/src/types/trace_types/error.rs b/ethcore/src/types/trace_types/error.rs index 758c78eec..0348fc2a4 100644 --- a/ethcore/src/types/trace_types/error.rs +++ b/ethcore/src/types/trace_types/error.rs @@ -40,6 +40,8 @@ pub enum Error { /// Returned on evm internal error. Should never be ignored during development. /// Likely to cause consensus issues. Internal, + /// When execution tries to modify the state in static context + MutableCallInStaticContext, } impl<'a> From<&'a EvmError> for Error { @@ -52,6 +54,7 @@ impl<'a> From<&'a EvmError> for Error { EvmError::OutOfStack { .. } => Error::OutOfStack, EvmError::BuiltIn { .. } => Error::BuiltIn, EvmError::Internal(_) => Error::Internal, + EvmError::MutableCallInStaticContext => Error::MutableCallInStaticContext, } } } @@ -73,6 +76,7 @@ impl fmt::Display for Error { OutOfStack => "Out of stack", BuiltIn => "Built-in failed", Internal => "Internal error", + MutableCallInStaticContext => "Mutable Call In Static Context", }; message.fmt(f) } @@ -89,6 +93,7 @@ impl Encodable for Error { OutOfStack => 4, Internal => 5, BuiltIn => 6, + MutableCallInStaticContext => 7, }; s.append_internal(&value); @@ -107,6 +112,7 @@ impl Decodable for Error { 4 => Ok(OutOfStack), 5 => Ok(Internal), 6 => Ok(BuiltIn), + 7 => Ok(MutableCallInStaticContext), _ => Err(DecoderError::Custom("Invalid error type")), } } diff --git a/json/src/spec/params.rs b/json/src/spec/params.rs index fc69435c9..b17067426 100644 --- a/json/src/spec/params.rs +++ b/json/src/spec/params.rs @@ -78,6 +78,9 @@ pub struct Params { /// See `CommonParams` docs. #[serde(rename="eip211Transition")] pub eip211_transition: Option, + /// See `CommonParams` docs. + #[serde(rename="eip214Transition")] + pub eip214_transition: Option, } #[cfg(test)] diff --git a/rpc/src/v1/types/trace.rs b/rpc/src/v1/types/trace.rs index f91100421..084c19cd1 100644 --- a/rpc/src/v1/types/trace.rs +++ b/rpc/src/v1/types/trace.rs @@ -251,6 +251,9 @@ pub enum CallType { /// Delegate call #[serde(rename="delegatecall")] DelegateCall, + /// Static call + #[serde(rename="staticcall")] + StaticCall, } impl From for CallType { @@ -260,6 +263,7 @@ impl From for CallType { executed::CallType::Call => CallType::Call, executed::CallType::CallCode => CallType::CallCode, executed::CallType::DelegateCall => CallType::DelegateCall, + executed::CallType::StaticCall => CallType::StaticCall, } } } From a7da8eb59363c521fec9fd365d933937fb071efd Mon Sep 17 00:00:00 2001 From: Saulius Valatka Date: Mon, 19 Jun 2017 12:42:29 +0300 Subject: [PATCH 10/14] Make config file optional (#5847) --- scripts/parity.service | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/parity.service b/scripts/parity.service index b798908bb..31d9011ea 100644 --- a/scripts/parity.service +++ b/scripts/parity.service @@ -3,7 +3,7 @@ Description=Parity Daemon After=network.target [Service] -EnvironmentFile=%h/.parity/parity.conf +EnvironmentFile=-%h/.parity/parity.conf ExecStart=/usr/bin/parity $ARGS [Install] From d168479a85f5f18f6fc75510ea8a81996a1ce808 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Mon, 19 Jun 2017 16:24:07 +0200 Subject: [PATCH 11/14] blacklist bad manifest hashes upon failure --- sync/src/chain.rs | 13 +++++++++++-- sync/src/snapshot.rs | 22 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index edf6f13d2..badd784a4 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -521,7 +521,8 @@ impl ChainSync { sn > fork_block && self.highest_block.map_or(true, |highest| highest >= sn && (highest - sn) <= SNAPSHOT_RESTORE_THRESHOLD) )) - .filter_map(|(p, peer)| peer.snapshot_hash.map(|hash| (p, hash.clone()))); + .filter_map(|(p, peer)| peer.snapshot_hash.map(|hash| (p, hash.clone()))) + .filter(|&(_, ref hash)| !self.snapshot.is_known_bad(hash)); let mut snapshot_peers = HashMap::new(); let mut max_peers: usize = 0; @@ -1075,10 +1076,18 @@ impl ChainSync { } // check service status - match io.snapshot_service().status() { + let status = io.snapshot_service().status(); + match status { RestorationStatus::Inactive | RestorationStatus::Failed => { trace!(target: "sync", "{}: Snapshot restoration aborted", peer_id); self.state = SyncState::WaitingPeers; + + // only note bad if restoration failed. + if let (Some(hash), RestorationStatus::Failed) = (self.snapshot.snapshot_hash(), status) { + trace!(target: "sync", "Noting snapshot hash {} as bad", hash); + self.snapshot.note_bad(hash); + } + self.snapshot.clear(); self.continue_sync(io); return Ok(()); diff --git a/sync/src/snapshot.rs b/sync/src/snapshot.rs index 727991caa..ffdaecd79 100644 --- a/sync/src/snapshot.rs +++ b/sync/src/snapshot.rs @@ -31,6 +31,7 @@ pub struct Snapshot { downloading_chunks: HashSet, completed_chunks: HashSet, snapshot_hash: Option, + bad_hashes: HashSet, } impl Snapshot { @@ -42,6 +43,7 @@ impl Snapshot { downloading_chunks: HashSet::new(), completed_chunks: HashSet::new(), snapshot_hash: None, + bad_hashes: HashSet::new(), } } @@ -109,6 +111,16 @@ impl Snapshot { self.downloading_chunks.remove(hash); } + // note snapshot hash as bad. + pub fn note_bad(&mut self, hash: H256) { + self.bad_hashes.insert(hash); + } + + // whether snapshot hash is known to be bad. + pub fn is_known_bad(&self, hash: &H256) -> bool { + self.bad_hashes.contains(hash) + } + pub fn snapshot_hash(&self) -> Option { self.snapshot_hash } @@ -205,5 +217,15 @@ mod test { assert_eq!(snapshot.done_chunks(), snapshot.total_chunks()); assert_eq!(snapshot.snapshot_hash(), Some(manifest.into_rlp().sha3())); } + + #[test] + fn tracks_known_bad() { + let mut snapshot = Snapshot::new(); + let hash = H256::random(); + + assert_eq!(snapshot.is_known_bad(&hash), false); + snapshot.note_bad(hash); + assert_eq!(snapshot.is_known_bad(&hash), true); + } } From 367a5c998d0661ff6f3fed8eada94923d520760c Mon Sep 17 00:00:00 2001 From: GitLab Build Bot Date: Mon, 19 Jun 2017 14:58:49 +0000 Subject: [PATCH 12/14] [ci skip] js-precompiled 20170619-145413 --- Cargo.lock | 2 +- js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8647a52b8..40cd81fa1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1818,7 +1818,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/paritytech/js-precompiled.git#bebd4fc6ab48574cc976f3570357359f6e831a71" +source = "git+https://github.com/paritytech/js-precompiled.git#259741a8ff42f0d4cd0a2c60cc7fab4f0b55aa4f" dependencies = [ "parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/js/package.json b/js/package.json index 77b643da8..b31d650c4 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "1.7.91", + "version": "1.7.92", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", From a19be3cb516a5cd97f70d8bd007a19f30e8950a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 19 Jun 2017 18:35:56 +0200 Subject: [PATCH 13/14] Initial token should allow full access. (#5873) --- rpc/src/v1/extractors.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/rpc/src/v1/extractors.rs b/rpc/src/v1/extractors.rs index b93ca7b87..261d3bfbf 100644 --- a/rpc/src/v1/extractors.rs +++ b/rpc/src/v1/extractors.rs @@ -81,7 +81,7 @@ impl ws::MetaExtractor for WsExtractor { let dapp = req.origin.as_ref().map(|origin| (&**origin).into()).unwrap_or_default(); metadata.origin = match self.authcodes_path { Some(ref path) => { - let authorization = req.protocols.get(0).and_then(|p| auth_token_hash(&path, p)); + let authorization = req.protocols.get(0).and_then(|p| auth_token_hash(&path, p, true)); match authorization { Some(id) => Origin::Signer { session: id.into(), dapp: dapp }, None => Origin::Ws { session: id.into(), dapp: dapp }, @@ -117,7 +117,7 @@ impl ws::RequestMiddleware for WsExtractor { let protocols = req.protocols().ok().unwrap_or_else(Vec::new); if let Some(ref path) = self.authcodes_path { if protocols.len() == 1 { - let authorization = auth_token_hash(&path, protocols[0]); + let authorization = auth_token_hash(&path, protocols[0], false); if authorization.is_none() { warn!( "Blocked connection from {} using invalid token.", @@ -142,7 +142,7 @@ fn add_security_headers(res: &mut ws::ws::Response) { headers.push(("X-Content-Type-Options".into(), b"nosniff".to_vec())); } -fn auth_token_hash(codes_path: &Path, protocol: &str) -> Option { +fn auth_token_hash(codes_path: &Path, protocol: &str, save_file: bool) -> Option { let mut split = protocol.split('_'); let auth = split.next().and_then(|v| v.parse().ok()); let time = split.next().and_then(|v| u64::from_str_radix(v, 10).ok()); @@ -156,9 +156,12 @@ fn auth_token_hash(codes_path: &Path, protocol: &str) -> Option { codes.clear_garbage(); let res = codes.is_valid(&auth, time); - // make sure to save back authcodes - it might have been modified - if codes.to_file(codes_path).is_err() { - warn!(target: "signer", "Couldn't save authorization codes to file."); + + if save_file { + // make sure to save back authcodes - it might have been modified + if codes.to_file(codes_path).is_err() { + warn!(target: "signer", "Couldn't save authorization codes to file."); + } } if res { From d152fa3e8502d610a3ad8fa32342808dc6075d4c Mon Sep 17 00:00:00 2001 From: Stewart Mackenzie Date: Tue, 20 Jun 2017 00:56:37 +0800 Subject: [PATCH 14/14] Ethereum Classic Monetary Policy (#5741) * Ethereum Classic Monetary Policy Create a new parameter `ecip1017EraRounds`. When the block number passes one era rounds, the reward is reduced by 20%. See https://github.com/ethereumproject/ECIPs/blob/master/ECIPs/ECIP-1017.md * Update rewards for uncle miners for ECIP1017 In the monetary policy, the rewards are changed from "up to 7/8 of the reward" to "1/32 of the reward". * Fix an off-by-one error in ECIP1017 era calculation According to https://github.com/ethereumproject/ECIPs/blob/master/ECIPs/ECIP-1017.md, when in block number 5,000,000, it should still be in Era 1 (which in our code `era == 0`). So we need to check whether the `rem` equals to zero and act accordingly when calculating the era. * `ecip1017_era_rounds` missing from EthashParams when run in build bot * strip out ecip1017_eras_block_reward function and add unit test --- ethcore/res/ethereum/classic.json | 1 + ethcore/src/ethereum/ethash.rs | 73 ++++++++++++++++++++++++++++--- ethcore/src/tests/helpers.rs | 1 + json/src/spec/ethash.rs | 4 ++ 4 files changed, 73 insertions(+), 6 deletions(-) diff --git a/ethcore/res/ethereum/classic.json b/ethcore/res/ethereum/classic.json index f7cb4daca..6edfef460 100644 --- a/ethcore/res/ethereum/classic.json +++ b/ethcore/res/ethereum/classic.json @@ -16,6 +16,7 @@ "eip160Transition": 3000000, "ecip1010PauseTransition": 3000000, "ecip1010ContinueTransition": 5000000, + "ecip1017EraRounds": 5000000, "eip161abcTransition": "0x7fffffffffffffff", "eip161dTransition": "0x7fffffffffffffff" diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index a89ec82ac..8d4d18911 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -86,6 +86,8 @@ pub struct EthashParams { pub ecip1010_pause_transition: u64, /// Number of first block where ECIP-1010 ends. pub ecip1010_continue_transition: u64, + /// Total block number for one ECIP-1017 era. + pub ecip1017_era_rounds: u64, /// Maximum amount of code that can be deploying into a contract. pub max_code_size: u64, /// Number of first block where the max gas limit becomes effective. @@ -124,6 +126,7 @@ impl From for EthashParams { eip161d_transition: p.eip161d_transition.map_or(u64::max_value(), Into::into), ecip1010_pause_transition: p.ecip1010_pause_transition.map_or(u64::max_value(), Into::into), ecip1010_continue_transition: p.ecip1010_continue_transition.map_or(u64::max_value(), Into::into), + ecip1017_era_rounds: p.ecip1017_era_rounds.map_or(u64::max_value(), Into::into), max_code_size: p.max_code_size.map_or(u64::max_value(), Into::into), max_gas_limit_transition: p.max_gas_limit_transition.map_or(u64::max_value(), Into::into), max_gas_limit: p.max_gas_limit.map_or(U256::max_value(), Into::into), @@ -272,6 +275,8 @@ impl Engine for Arc { fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> { let reward = self.ethash_params.block_reward; let fields = block.fields_mut(); + let eras_rounds = self.ethash_params.ecip1017_era_rounds; + let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, reward, fields.header.number()); // Bestow block reward fields.state.add_balance( @@ -283,11 +288,19 @@ impl Engine for Arc { // Bestow uncle rewards let current_number = fields.header.number(); for u in fields.uncles.iter() { - fields.state.add_balance( - u.author(), - &(reward * U256::from(8 + u.number() - current_number) / U256::from(8)), - CleanupMode::NoEmpty - )?; + if eras == 0 { + fields.state.add_balance( + u.author(), + &(reward * U256::from(8 + u.number() - current_number) / U256::from(8)), + CleanupMode::NoEmpty + ) + } else { + fields.state.add_balance( + u.author(), + &(reward / U256::from(32)), + CleanupMode::NoEmpty + ) + }?; } // Commit state so that we can actually figure out the state root. @@ -413,6 +426,18 @@ fn round_block_gas_limit(gas_limit: U256, lower_limit: U256, upper_limit: U256) } } +fn ecip1017_eras_block_reward(era_rounds: u64, mut reward: U256, block_number:u64) -> (u64, U256){ + let eras = if block_number != 0 && block_number % era_rounds == 0 { + block_number / era_rounds - 1 + } else { + block_number / era_rounds + }; + for _ in 0..eras { + reward = reward / U256::from(5) * U256::from(4); + } + (eras, reward) +} + #[cfg_attr(feature="dev", allow(wrong_self_convention))] impl Ethash { fn calculate_difficulty(&self, header: &Header, parent: &Header) -> U256 { @@ -524,7 +549,7 @@ mod tests { use error::{BlockError, Error}; use header::Header; use super::super::{new_morden, new_homestead_test}; - use super::{Ethash, EthashParams, PARITY_GAS_LIMIT_DETERMINANT}; + use super::{Ethash, EthashParams, PARITY_GAS_LIMIT_DETERMINANT, ecip1017_eras_block_reward}; use rlp; #[test] @@ -760,6 +785,42 @@ mod tests { assert_eq!(U256::from_str("1fc50f118efe").unwrap(), difficulty); } + #[test] + fn has_valid_ecip1017_eras_block_reward() { + let ethparams = EthashParams { + // see ethcore/res/ethereum/classic.json + ecip1017_era_rounds: 5000000, + block_reward: U256::from_str("4563918244F40000").unwrap(), + ..get_default_ethash_params() + }; + let eras_rounds = ethparams.ecip1017_era_rounds; + let reward = ethparams.block_reward; + let block_number = 0; + let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, reward, block_number); + assert_eq!(0, eras); + assert_eq!(U256::from_str("4563918244F40000").unwrap(), reward); + let reward = ethparams.block_reward; + let block_number = 5000000; + let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, reward, block_number); + assert_eq!(0, eras); + assert_eq!(U256::from_str("4563918244F40000").unwrap(), reward); + let reward = ethparams.block_reward; + let block_number = 10000000; + let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, reward, block_number); + assert_eq!(1, eras); + assert_eq!(U256::from_str("3782DACE9D900000").unwrap(), reward); + let reward = ethparams.block_reward; + let block_number = 20000000; + let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, reward, block_number); + assert_eq!(3, eras); + assert_eq!(U256::from_str("2386F26FC1000000").unwrap(), reward); + let reward = ethparams.block_reward; + let block_number = 80000000; + let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, reward, block_number); + assert_eq!(15, eras); + assert_eq!(U256::from_str("271000000000000").unwrap(), reward); + } + #[test] fn difficulty_classic_bomb_delay() { let spec = new_homestead_test(); diff --git a/ethcore/src/tests/helpers.rs b/ethcore/src/tests/helpers.rs index ed77657ad..c54933fd1 100644 --- a/ethcore/src/tests/helpers.rs +++ b/ethcore/src/tests/helpers.rs @@ -418,6 +418,7 @@ pub fn get_default_ethash_params() -> EthashParams{ eip161d_transition: u64::max_value(), ecip1010_pause_transition: u64::max_value(), ecip1010_continue_transition: u64::max_value(), + ecip1017_era_rounds: u64::max_value(), max_code_size: u64::max_value(), max_gas_limit_transition: u64::max_value(), max_gas_limit: U256::max_value(), diff --git a/json/src/spec/ethash.rs b/json/src/spec/ethash.rs index ff435b72a..44edb5288 100644 --- a/json/src/spec/ethash.rs +++ b/json/src/spec/ethash.rs @@ -100,6 +100,10 @@ pub struct EthashParams { #[serde(rename="ecip1010ContinueTransition")] pub ecip1010_continue_transition: Option, + /// See main EthashParams docs. + #[serde(rename="ecip1017EraRounds")] + pub ecip1017_era_rounds: Option, + /// See main EthashParams docs. #[serde(rename="maxCodeSize")] pub max_code_size: Option,