diff --git a/Cargo.lock b/Cargo.lock index 8aef27629..7ccc384e9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1959,6 +1959,7 @@ dependencies = [ "parity-hash-fetch 1.9.0", "parity-reactor 0.1.0", "parity-ui 1.9.0", + "parity-ui-deprecation 1.10.0", "parity-version 1.10.0", "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2175,6 +2176,13 @@ dependencies = [ "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parity-ui-deprecation" +version = "1.10.0" +dependencies = [ + "parity-dapps-glue 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "parity-ui-dev" version = "1.9.0" diff --git a/dapps/Cargo.toml b/dapps/Cargo.toml index bbe695427..cd95452dc 100644 --- a/dapps/Cargo.toml +++ b/dapps/Cargo.toml @@ -35,6 +35,7 @@ node-health = { path = "./node-health" } parity-hash-fetch = { path = "../hash-fetch" } parity-reactor = { path = "../util/reactor" } parity-ui = { path = "./ui" } +parity-ui-deprecation = { path = "./ui-deprecation" } keccak-hash = { path = "../util/hash" } parity-version = { path = "../util/version" } diff --git a/dapps/src/apps/mod.rs b/dapps/src/apps/mod.rs index c065a0847..21947b928 100644 --- a/dapps/src/apps/mod.rs +++ b/dapps/src/apps/mod.rs @@ -23,8 +23,6 @@ use page; use proxypac::ProxyPac; use web::Web; use fetch::Fetch; -use parity_dapps::WebApp; -use parity_ui; use {WebProxyTokens, ParentFrameSettings}; mod app; @@ -44,11 +42,15 @@ pub const WEB_PATH: &'static str = "web"; pub const URL_REFERER: &'static str = "__referer="; pub fn utils(pool: CpuPool) -> Box { - Box::new(page::builtin::Dapp::new(pool, parity_ui::App::default())) + Box::new(page::builtin::Dapp::new(pool, ::parity_ui::App::default())) } pub fn ui(pool: CpuPool) -> Box { - Box::new(page::builtin::Dapp::with_fallback_to_index(pool, parity_ui::App::default())) + Box::new(page::builtin::Dapp::with_fallback_to_index(pool, ::parity_ui::App::default())) +} + +pub fn ui_deprecation(pool: CpuPool) -> Box { + Box::new(page::builtin::Dapp::with_fallback_to_index(pool, ::parity_ui_deprecation::App::default())) } pub fn ui_redirection(embeddable: Option) -> Box { @@ -76,25 +78,28 @@ pub fn all_endpoints( } // NOTE [ToDr] Dapps will be currently embeded on 8180 - insert::(&mut pages, "ui", Embeddable::Yes(embeddable.clone()), pool.clone()); + pages.insert( + "ui".into(), + Box::new(page::builtin::Dapp::new_safe_to_embed(pool.clone(), ::parity_ui::App::default(), embeddable.clone())) + ); // old version - insert::(&mut pages, "v1", Embeddable::Yes(embeddable.clone()), pool.clone()); - - pages.insert("proxy".into(), ProxyPac::boxed(embeddable.clone(), dapps_domain.to_owned())); - pages.insert(WEB_PATH.into(), Web::boxed(embeddable.clone(), web_proxy_tokens.clone(), fetch.clone(), pool.clone())); + pages.insert( + "v1".into(), + Box::new({ + let mut page = page::builtin::Dapp::new_safe_to_embed(pool.clone(), ::parity_ui::old::App::default(), embeddable.clone()); + // allow JS eval on old Wallet + page.allow_js_eval(); + page + }) + ); + pages.insert( + "proxy".into(), + ProxyPac::boxed(embeddable.clone(), dapps_domain.to_owned()) + ); + pages.insert( + WEB_PATH.into(), + Web::boxed(embeddable.clone(), web_proxy_tokens.clone(), fetch.clone(), pool.clone()) + ); (local_endpoints, pages) } - -fn insert(pages: &mut Endpoints, id: &str, embed_at: Embeddable, pool: CpuPool) { - pages.insert(id.to_owned(), Box::new(match embed_at { - Embeddable::Yes(address) => page::builtin::Dapp::new_safe_to_embed(pool, T::default(), address), - Embeddable::No => page::builtin::Dapp::new(pool, T::default()), - })); -} - -enum Embeddable { - Yes(Option), - #[allow(dead_code)] - No, -} diff --git a/dapps/src/lib.rs b/dapps/src/lib.rs index 6f901e4be..b0bb9e170 100644 --- a/dapps/src/lib.rs +++ b/dapps/src/lib.rs @@ -39,6 +39,7 @@ extern crate node_health; extern crate parity_dapps_glue as parity_dapps; extern crate parity_hash_fetch as hash_fetch; extern crate parity_ui; +extern crate parity_ui_deprecation; extern crate keccak_hash as hash; extern crate parity_version; @@ -158,6 +159,7 @@ impl Middleware { registrar: Arc, sync_status: Arc, fetch: F, + info_page_only: bool, ) -> Self { let content_fetcher = Arc::new(apps::fetcher::ContentFetcher::new( hash_fetch::urlhint::URLHintContract::new(registrar), @@ -165,6 +167,23 @@ impl Middleware { fetch.clone(), pool.clone(), ).embeddable_on(None).allow_dapps(false)); + + if info_page_only { + let mut special = HashMap::default(); + special.insert(router::SpecialEndpoint::Home, Some(apps::ui_deprecation(pool.clone()))); + + return Middleware { + endpoints: Default::default(), + router: router::Router::new( + content_fetcher, + None, + special, + None, + dapps_domain.to_owned(), + ), + } + } + let special = { let mut special = special_endpoints( pool.clone(), diff --git a/dapps/src/page/builtin.rs b/dapps/src/page/builtin.rs index 827fe27a3..150cfe864 100644 --- a/dapps/src/page/builtin.rs +++ b/dapps/src/page/builtin.rs @@ -75,6 +75,11 @@ impl Dapp { fallback_to_index_html: false, } } + + /// Allow the dapp to use `unsafe-eval` to run JS. + pub fn allow_js_eval(&mut self) { + self.info.allow_js_eval = Some(true); + } } impl Endpoint for Dapp { diff --git a/dapps/src/router.rs b/dapps/src/router.rs index e5770ca72..d5f464704 100644 --- a/dapps/src/router.rs +++ b/dapps/src/router.rs @@ -150,10 +150,20 @@ impl Router { } }, // RPC by default - _ => { + _ if self.special.contains_key(&SpecialEndpoint::Rpc) => { trace!(target: "dapps", "Resolving to RPC call."); Response::None(req) - } + }, + // 404 otherwise + _ => { + Response::Some(Box::new(future::ok(handlers::ContentHandler::error( + hyper::StatusCode::NotFound, + "404 Not Found", + "Requested content was not found.", + None, + self.embeddable_on.clone(), + ).into()))) + }, }) } } diff --git a/dapps/src/tests/helpers/mod.rs b/dapps/src/tests/helpers/mod.rs index 312f7998a..601f4db24 100644 --- a/dapps/src/tests/helpers/mod.rs +++ b/dapps/src/tests/helpers/mod.rs @@ -240,6 +240,7 @@ impl Server { registrar, sync_status, fetch, + false, ) } else { Middleware::dapps( diff --git a/dapps/ui-deprecation/Cargo.toml b/dapps/ui-deprecation/Cargo.toml new file mode 100644 index 000000000..f4479c236 --- /dev/null +++ b/dapps/ui-deprecation/Cargo.toml @@ -0,0 +1,18 @@ +[package] +description = "Parity UI deprecation notice." +name = "parity-ui-deprecation" +version = "1.10.0" +license = "GPL-3.0" +authors = ["Parity Technologies "] +build = "build.rs" + +[features] +default = ["with-syntex", "use-precompiled-js"] +use-precompiled-js = ["parity-dapps-glue/use-precompiled-js"] +with-syntex = ["parity-dapps-glue/with-syntex"] + +[build-dependencies] +parity-dapps-glue = "1.9" + +[dependencies] +parity-dapps-glue = "1.9" diff --git a/dapps/ui-deprecation/build.rs b/dapps/ui-deprecation/build.rs new file mode 100644 index 000000000..c427f3d54 --- /dev/null +++ b/dapps/ui-deprecation/build.rs @@ -0,0 +1,21 @@ +// Copyright 2015-2018 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 . + +extern crate parity_dapps_glue; + +fn main() { + parity_dapps_glue::generate(); +} diff --git a/dapps/ui-deprecation/build/index.html b/dapps/ui-deprecation/build/index.html new file mode 100644 index 000000000..9267ebf6a --- /dev/null +++ b/dapps/ui-deprecation/build/index.html @@ -0,0 +1,119 @@ + + + + + + Parity + + + +
+
+
+

Parity browser UI is deprecated.

+

Get a standalone Parity UI from here

+

+ +

+
+
+
+ + diff --git a/dapps/ui-deprecation/src/lib.rs b/dapps/ui-deprecation/src/lib.rs new file mode 100644 index 000000000..79a4a4249 --- /dev/null +++ b/dapps/ui-deprecation/src/lib.rs @@ -0,0 +1,21 @@ +// Copyright 2015-2018 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 = "with-syntex")] +include!(concat!(env!("OUT_DIR"), "/lib.rs")); + +#[cfg(not(feature = "with-syntex"))] +include!("lib.rs.in"); diff --git a/dapps/ui-deprecation/src/lib.rs.in b/dapps/ui-deprecation/src/lib.rs.in new file mode 100644 index 000000000..892ebbded --- /dev/null +++ b/dapps/ui-deprecation/src/lib.rs.in @@ -0,0 +1,55 @@ +// Copyright 2015-2018 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 . + +extern crate parity_dapps_glue; + +use std::collections::HashMap; +use parity_dapps_glue::{WebApp, File, Info}; + +#[derive(WebAppFiles)] +#[webapp(path = "../build")] +pub struct App { + pub files: HashMap<&'static str, File>, +} + +impl Default for App { + fn default() -> App { + App { + files: Self::files(), + } + } +} + +impl WebApp for App { + fn file(&self, path: &str) -> Option<&File> { + self.files.get(path) + } + + fn info(&self) -> Info { + Info { + name: "Parity Wallet info page", + version: env!("CARGO_PKG_VERSION"), + author: "Parity ", + description: "Deprecation notice for Parity Wallet", + icon_url: "icon.png", + } + } +} + +#[test] +fn test_js() { + parity_dapps_glue::js::build(env!("CARGO_MANIFEST_DIR"), "build"); +} diff --git a/ethcore/res/ethereum/musicoin.json b/ethcore/res/ethereum/musicoin.json index efe81c588..6d5f6835b 100644 --- a/ethcore/res/ethereum/musicoin.json +++ b/ethcore/res/ethereum/musicoin.json @@ -10,9 +10,9 @@ "homesteadTransition":"0x118c30", "eip100bTransition":"0x21e88e", "eip150Transition":"0x21e88e", - "eip160Transition":"0x7fffffffffffff", - "eip161abcTransition":"0x7fffffffffffff", - "eip161dTransition":"0x7fffffffffffff", + "eip160Transition":"0x21e88e", + "eip161abcTransition":"0x21e88e", + "eip161dTransition":"0x21e88e", "eip649Transition":"0x21e88e", "blockReward":"0x1105a0185b50a80000", "mcip3Transition":"0x124f81", @@ -40,8 +40,7 @@ "eip211Transition":"0x21e88e", "eip214Transition":"0x21e88e", "eip658Transition":"0x21e88e", - "maxCodeSize":"0x6000", - "maxCodeSizeTransition": "0x7fffffffffffff" + "maxCodeSize":"0x6000" }, "genesis":{ "seal":{ diff --git a/ethcore/src/state/mod.rs b/ethcore/src/state/mod.rs index 1b868c97b..4b2f8f324 100644 --- a/ethcore/src/state/mod.rs +++ b/ethcore/src/state/mod.rs @@ -833,16 +833,26 @@ impl State { })) } - fn query_pod(&mut self, query: &PodState) -> trie::Result<()> { - for (address, pod_account) in query.get() { + // Return a list of all touched addresses in cache. + fn touched_addresses(&self) -> Vec
{ + assert!(self.checkpoints.borrow().is_empty()); + self.cache.borrow().iter().map(|(add, _)| *add).collect() + } + + fn query_pod(&mut self, query: &PodState, touched_addresses: &[Address]) -> trie::Result<()> { + let pod = query.get(); + + for address in touched_addresses { if !self.ensure_cached(address, RequireCache::Code, true, |a| a.is_some())? { continue } - // 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)?; + if let Some(pod_account) = pod.get(address) { + // 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)?; + } } } @@ -852,9 +862,10 @@ impl State { /// Returns a `StateDiff` describing the difference from `orig` to `self`. /// Consumes self. pub fn diff_from(&self, orig: State) -> trie::Result { + let addresses_post = self.touched_addresses(); let pod_state_post = self.to_pod(); let mut state_pre = orig; - state_pre.query_pod(&pod_state_post)?; + state_pre.query_pod(&pod_state_post, &addresses_post)?; Ok(pod_state::diff_pod(&state_pre.to_pod(), &pod_state_post)) } @@ -2180,4 +2191,37 @@ mod tests { assert!(state.exists(&d).unwrap()); assert!(!state.exists(&e).unwrap()); } + + #[test] + fn should_trace_diff_suicided_accounts() { + use pod_account; + + let a = 10.into(); + let db = get_temp_state_db(); + let (root, db) = { + let mut state = State::new(db, U256::from(0), Default::default()); + state.add_balance(&a, &100.into(), CleanupMode::ForceCreate).unwrap(); + state.commit().unwrap(); + state.drop() + }; + + let mut state = State::from_existing(db, root, U256::from(0u8), Default::default()).unwrap(); + let original = state.clone(); + state.kill_account(&a); + + assert_eq!(original.touched_addresses(), vec![]); + assert_eq!(state.touched_addresses(), vec![a]); + + let diff = state.diff_from(original).unwrap(); + let diff_map = diff.get(); + assert_eq!(diff_map.len(), 1); + assert!(diff_map.get(&a).is_some()); + assert_eq!(diff_map.get(&a), + pod_account::diff_pod(Some(&PodAccount { + balance: U256::from(100), + nonce: U256::zero(), + code: Some(Default::default()), + storage: Default::default() + }), None).as_ref()); + } } diff --git a/ethcore/src/verification/queue/kind.rs b/ethcore/src/verification/queue/kind.rs index b437dba7a..898435eb2 100644 --- a/ethcore/src/verification/queue/kind.rs +++ b/ethcore/src/verification/queue/kind.rs @@ -69,7 +69,7 @@ pub mod blocks { use super::{Kind, BlockLike}; use engines::EthEngine; - use error::Error; + use error::{Error, BlockError}; use header::Header; use verification::{PreverifiedBlock, verify_block_basic, verify_block_unordered}; @@ -88,6 +88,10 @@ pub mod blocks { fn create(input: Self::Input, engine: &EthEngine) -> Result { match verify_block_basic(&input.header, &input.bytes, engine) { Ok(()) => Ok(input), + Err(Error::Block(BlockError::TemporarilyInvalid(oob))) => { + debug!(target: "client", "Block received too early {}: {:?}", input.hash(), oob); + Err(BlockError::TemporarilyInvalid(oob).into()) + }, Err(e) => { warn!(target: "client", "Stage 1 block verification failed for {}: {:?}", input.hash(), e); Err(e) diff --git a/parity/cli/mod.rs b/parity/cli/mod.rs index c41b59598..148597f8f 100644 --- a/parity/cli/mod.rs +++ b/parity/cli/mod.rs @@ -384,6 +384,10 @@ usage! { "--no-serve-light", "Disable serving of light peers.", + ARG arg_warp_barrier: (Option) = None, or |c: &Config| c.network.as_ref()?.warp_barrier.clone(), + "--warp-barrier=[NUM]", + "When warp enabled never attempt regular sync before warping to block NUM.", + ARG arg_port: (u16) = 30303u16, or |c: &Config| c.network.as_ref()?.port.clone(), "--port=[PORT]", "Override the port on which the node should listen.", @@ -1034,6 +1038,7 @@ struct Ui { #[serde(deny_unknown_fields)] struct Network { warp: Option, + warp_barrier: Option, port: Option, min_peers: Option, max_peers: Option, @@ -1613,6 +1618,7 @@ mod tests { flag_geth: false, flag_testnet: false, flag_import_geth_keys: false, + arg_warp_barrier: None, arg_datadir: None, arg_networkid: None, arg_peers: None, @@ -1717,6 +1723,7 @@ mod tests { }), network: Some(Network { warp: Some(false), + warp_barrier: None, port: None, min_peers: Some(10), max_peers: Some(20), diff --git a/parity/configuration.rs b/parity/configuration.rs index e0b76ef95..9214b98d7 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -143,7 +143,7 @@ impl Configuration { if self.args.cmd_signer_new_token { Cmd::SignerToken(ws_conf, ui_conf, logger_config.clone()) } else if self.args.cmd_signer_sign { - let pwfile = self.args.arg_password.first().map(|pwfile| { + let pwfile = self.accounts_config()?.password_files.first().map(|pwfile| { PathBuf::from(pwfile) }); Cmd::SignerSign { @@ -180,7 +180,7 @@ impl Configuration { iterations: self.args.arg_keys_iterations, path: dirs.keys, spec: spec, - password_file: self.args.arg_password.first().map(|x| x.to_owned()), + password_file: self.accounts_config()?.password_files.first().map(|x| x.to_owned()), }; AccountCmd::New(new_acc) } else if self.args.cmd_account_list { @@ -214,8 +214,8 @@ impl Configuration { iterations: self.args.arg_keys_iterations, path: dirs.keys, spec: spec, - wallet_path: self.args.arg_wallet_import_path.unwrap().clone(), - password_file: self.args.arg_password.first().map(|x| x.to_owned()), + wallet_path: self.args.arg_wallet_import_path.clone().unwrap(), + password_file: self.accounts_config()?.password_files.first().map(|x| x.to_owned()), }; Cmd::ImportPresaleWallet(presale_cmd) } else if self.args.cmd_import { @@ -356,6 +356,7 @@ impl Configuration { wal: wal, vm_type: vm_type, warp_sync: warp_sync, + warp_barrier: self.args.arg_warp_barrier, public_node: public_node, geth_compatibility: geth_compatibility, net_settings: self.network_settings()?, @@ -438,7 +439,7 @@ impl Configuration { LogConfig { mode: self.args.arg_logging.clone(), color: !self.args.flag_no_color && !cfg!(windows), - file: self.args.arg_log_file.clone(), + file: self.args.arg_log_file.as_ref().map(|log_file| replace_home(&self.directories().base, log_file)), } } @@ -487,7 +488,7 @@ impl Configuration { iterations: self.args.arg_keys_iterations, refresh_time: self.args.arg_accounts_refresh, testnet: self.args.flag_testnet, - password_files: self.args.arg_password.clone(), + password_files: self.args.arg_password.iter().map(|s| replace_home(&self.directories().base, s)).collect(), unlocked_accounts: to_addresses(&self.args.arg_unlock)?, enable_hardware_wallets: !self.args.flag_no_hardware_wallets, enable_fast_unlock: self.args.flag_fast_unlock, @@ -560,11 +561,13 @@ impl Configuration { } fn ui_config(&self) -> UiConfiguration { + let ui = self.ui_enabled(); UiConfiguration { - enabled: self.ui_enabled(), + enabled: ui.enabled, interface: self.ui_interface(), port: self.ui_port(), hosts: self.ui_hosts(), + info_page_only: ui.info_page_only, } } @@ -703,8 +706,10 @@ impl Configuration { match self.args.arg_reserved_peers { Some(ref path) => { + let path = replace_home(&self.directories().base, path); + let mut buffer = String::new(); - let mut node_file = File::open(path).map_err(|e| format!("Error opening reserved nodes file: {}", e))?; + let mut node_file = File::open(&path).map_err(|e| format!("Error opening reserved nodes file: {}", e))?; node_file.read_to_string(&mut buffer).map_err(|_| "Error reading reserved node file")?; let lines = buffer.lines().map(|s| s.trim().to_owned()).filter(|s| !s.is_empty() && !s.starts_with("#")).collect::>(); @@ -1111,16 +1116,22 @@ impl Configuration { }) } - fn ui_enabled(&self) -> bool { + fn ui_enabled(&self) -> UiEnabled { if self.args.flag_force_ui { - return true; + return UiEnabled { + enabled: true, + info_page_only: false, + }; } let ui_disabled = self.args.arg_unlock.is_some() || self.args.flag_geth || self.args.flag_no_ui; - self.args.cmd_ui && !ui_disabled && cfg!(feature = "ui-enabled") + return UiEnabled { + enabled: (self.args.cmd_ui || !ui_disabled) && cfg!(feature = "ui-enabled"), + info_page_only: !self.args.cmd_ui, + } } fn verifier_settings(&self) -> VerifierSettings { @@ -1141,6 +1152,12 @@ impl Configuration { } } +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +struct UiEnabled { + pub enabled: bool, + pub info_page_only: bool, +} + #[cfg(test)] mod tests { use std::io::Write; @@ -1345,14 +1362,15 @@ mod tests { origins: Some(vec!["parity://*".into(),"chrome-extension://*".into(), "moz-extension://*".into()]), hosts: Some(vec![]), signer_path: expected.into(), - ui_address: None, + ui_address: Some("127.0.0.1:8180".into()), dapps_address: Some("127.0.0.1:8545".into()), support_token_api: true }, UiConfiguration { - enabled: false, + enabled: true, interface: "127.0.0.1".into(), port: 8180, hosts: Some(vec![]), + info_page_only: true, }, LogConfig { color: true, mode: None, @@ -1388,6 +1406,7 @@ mod tests { network_id: None, public_node: false, warp_sync: true, + warp_barrier: None, acc_conf: Default::default(), gas_pricer_conf: Default::default(), miner_extras: Default::default(), @@ -1599,10 +1618,26 @@ mod tests { // when let conf0 = parse(&["parity", "--geth"]); let conf1 = parse(&["parity", "--geth", "--force-ui"]); + let conf2 = parse(&["parity", "--geth", "ui"]); + let conf3 = parse(&["parity"]); // then - assert_eq!(conf0.ui_enabled(), false); - assert_eq!(conf1.ui_enabled(), true); + assert_eq!(conf0.ui_enabled(), UiEnabled { + enabled: false, + info_page_only: true, + }); + assert_eq!(conf1.ui_enabled(), UiEnabled { + enabled: true, + info_page_only: false, + }); + assert_eq!(conf2.ui_enabled(), UiEnabled { + enabled: true, + info_page_only: false, + }); + assert_eq!(conf3.ui_enabled(), UiEnabled { + enabled: true, + info_page_only: true, + }); } #[test] @@ -1613,7 +1648,10 @@ mod tests { let conf0 = parse(&["parity", "--unlock", "0x0"]); // then - assert_eq!(conf0.ui_enabled(), false); + assert_eq!(conf0.ui_enabled(), UiEnabled { + enabled: false, + info_page_only: true, + }); } #[test] @@ -1631,11 +1669,45 @@ mod tests { // then assert_eq!(conf0.directories().signer, "signer".to_owned()); assert_eq!(conf0.ui_config(), UiConfiguration { - enabled: false, + enabled: true, interface: "127.0.0.1".into(), port: 8180, hosts: Some(vec![]), + info_page_only: true, }); + + assert!(conf1.ws_config().unwrap().hosts.is_some()); + assert_eq!(conf1.ws_config().unwrap().origins, None); + assert_eq!(conf1.directories().signer, "signer".to_owned()); + assert_eq!(conf1.ui_config(), UiConfiguration { + enabled: true, + interface: "127.0.0.1".into(), + port: 8180, + hosts: Some(vec![]), + info_page_only: true, + }); + assert_eq!(conf1.dapps_config().extra_embed_on, vec![("127.0.0.1".to_owned(), 3000)]); + + assert!(conf2.ws_config().unwrap().hosts.is_some()); + assert_eq!(conf2.directories().signer, "signer".to_owned()); + assert_eq!(conf2.ui_config(), UiConfiguration { + enabled: true, + interface: "127.0.0.1".into(), + port: 3123, + hosts: Some(vec![]), + info_page_only: true, + }); + + assert!(conf3.ws_config().unwrap().hosts.is_some()); + assert_eq!(conf3.directories().signer, "signer".to_owned()); + assert_eq!(conf3.ui_config(), UiConfiguration { + enabled: true, + interface: "test".into(), + port: 8180, + hosts: Some(vec![]), + info_page_only: true, + }); + assert!(conf4.ws_config().unwrap().hosts.is_some()); assert_eq!(conf4.directories().signer, "signer".to_owned()); assert_eq!(conf4.ui_config(), UiConfiguration { @@ -1643,8 +1715,9 @@ mod tests { interface: "127.0.0.1".into(), port: 8180, hosts: Some(vec![]), + info_page_only: false, }); - assert!(conf5.ws_config().unwrap().hosts.is_some()); + assert!(conf5.ws_config().unwrap().hosts.is_some()); assert_eq!(conf5.directories().signer, "signer".to_owned()); assert_eq!(conf5.ui_config(), UiConfiguration { @@ -1652,33 +1725,8 @@ mod tests { interface: "127.0.0.1".into(), port: 8180, hosts: Some(vec![]), + info_page_only: false, }); - assert!(conf5.ws_config().unwrap().hosts.is_some()); - assert_eq!(conf1.directories().signer, "signer".to_owned()); - assert_eq!(conf1.ui_config(), UiConfiguration { - enabled: false, - interface: "127.0.0.1".into(), - port: 8180, - hosts: Some(vec![]), - }); - assert_eq!(conf1.dapps_config().extra_embed_on, vec![("127.0.0.1".to_owned(), 3000)]); - assert_eq!(conf1.ws_config().unwrap().origins, None); - assert_eq!(conf2.directories().signer, "signer".to_owned()); - assert_eq!(conf2.ui_config(), UiConfiguration { - enabled: false, - interface: "127.0.0.1".into(), - port: 3123, - hosts: Some(vec![]), - }); - assert!(conf2.ws_config().unwrap().hosts.is_some()); - assert_eq!(conf3.directories().signer, "signer".to_owned()); - assert_eq!(conf3.ui_config(), UiConfiguration { - enabled: false, - interface: "test".into(), - port: 8180, - hosts: Some(vec![]), - }); - assert!(conf3.ws_config().unwrap().hosts.is_some()); } #[test] diff --git a/parity/dapps.rs b/parity/dapps.rs index b0a9ce277..c4cdb0f80 100644 --- a/parity/dapps.rs +++ b/parity/dapps.rs @@ -160,6 +160,7 @@ pub struct Dependencies { pub pool: CpuPool, pub signer: Arc, pub ui_address: Option<(String, u16)>, + pub info_page_only: bool, } pub fn new(configuration: Configuration, deps: Dependencies) -> Result, String> { @@ -277,6 +278,7 @@ mod server { deps.contract_client, deps.sync_status, deps.fetch, + deps.info_page_only, )) } diff --git a/parity/rpc.rs b/parity/rpc.rs index 41b10ba87..36e2eff18 100644 --- a/parity/rpc.rs +++ b/parity/rpc.rs @@ -74,6 +74,7 @@ pub struct UiConfiguration { pub interface: String, pub port: u16, pub hosts: Option>, + pub info_page_only: bool, } impl UiConfiguration { @@ -110,10 +111,11 @@ impl From for HttpConfiguration { impl Default for UiConfiguration { fn default() -> Self { UiConfiguration { - enabled: false, + enabled: cfg!(feature = "ui-enabled"), port: 8180, interface: "127.0.0.1".into(), hosts: Some(vec![]), + info_page_only: true, } } } @@ -166,7 +168,7 @@ impl Default for WsConfiguration { hosts: Some(Vec::new()), signer_path: replace_home(&data_dir, "$BASE/signer").into(), support_token_api: true, - ui_address: None, + ui_address: Some("127.0.0.1:8180".into()), dapps_address: Some("127.0.0.1:8545".into()), } } diff --git a/parity/run.rs b/parity/run.rs index ce9e5f03f..57601c62c 100644 --- a/parity/run.rs +++ b/parity/run.rs @@ -99,6 +99,7 @@ pub struct RunCmd { pub net_conf: ethsync::NetworkConfiguration, pub network_id: Option, pub warp_sync: bool, + pub warp_barrier: Option, pub public_node: bool, pub acc_conf: AccountsConfig, pub gas_pricer_conf: GasPricerConfig, @@ -342,6 +343,7 @@ fn execute_light_impl(cmd: RunCmd, can_restart: bool, logger: Arc) } sync_config.fork_block = spec.fork_block(); - let mut warp_sync = cmd.warp_sync; + let mut warp_sync = spec.engine.supports_warp() && cmd.warp_sync; if warp_sync { // Logging is not initialized yet, so we print directly to stderr if fat_db { @@ -511,7 +513,11 @@ pub fn execute_impl(cmd: RunCmd, can_restart: bool, logger: Arc) warp_sync = false; } } - sync_config.warp_sync = spec.engine.supports_warp() && warp_sync; + sync_config.warp_sync = match (warp_sync, cmd.warp_barrier) { + (true, Some(block)) => ethsync::WarpSync::OnlyAndAfter(block), + (true, _) => ethsync::WarpSync::Enabled, + _ => ethsync::WarpSync::Disabled, + }; sync_config.download_old_blocks = cmd.download_old_blocks; sync_config.serve_light = cmd.serve_light; @@ -738,6 +744,7 @@ pub fn execute_impl(cmd: RunCmd, can_restart: bool, logger: Arc) pool: cpu_pool.clone(), signer: signer_service.clone(), ui_address: cmd.ui_conf.redirection_address(), + info_page_only: cmd.ui_conf.info_page_only, }) }; let dapps_middleware = dapps::new(cmd.dapps_conf.clone(), dapps_deps.clone())?; @@ -878,7 +885,7 @@ pub fn execute_impl(cmd: RunCmd, can_restart: bool, logger: Arc) } pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc) -> Result<(bool, Option), String> { - if cmd.ui_conf.enabled { + if cmd.ui_conf.enabled && !cmd.ui_conf.info_page_only { warn!("{}", Style::new().bold().paint("Parity browser interface is deprecated. It's going to be removed in the next version, use standalone Parity UI instead.")); warn!("{}", Style::new().bold().paint("Standalone Parity UI: https://github.com/Parity-JS/shell/releases")); } diff --git a/sync/src/api.rs b/sync/src/api.rs index d0f55d53c..e5e56d9e4 100644 --- a/sync/src/api.rs +++ b/sync/src/api.rs @@ -44,6 +44,41 @@ pub const ETH_PROTOCOL: ProtocolId = *b"eth"; /// Ethereum light protocol pub const LIGHT_PROTOCOL: ProtocolId = *b"pip"; +/// Determine warp sync status. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum WarpSync { + /// Warp sync is enabled. + Enabled, + /// Warp sync is disabled. + Disabled, + /// Only warp sync is allowed (no regular sync) and only after given block number. + OnlyAndAfter(BlockNumber), +} + +impl WarpSync { + /// Returns true if warp sync is enabled. + pub fn is_enabled(&self) -> bool { + match *self { + WarpSync::Enabled => true, + WarpSync::OnlyAndAfter(_) => true, + WarpSync::Disabled => false, + } + } + + /// Returns `true` if we are in warp-only mode. + /// + /// i.e. we will never fall back to regular sync + /// until given block number is reached by + /// successfuly finding and restoring from a snapshot. + pub fn is_warp_only(&self) -> bool { + if let WarpSync::OnlyAndAfter(_) = *self { + true + } else { + false + } + } +} + /// Sync configuration #[derive(Debug, Clone, Copy)] pub struct SyncConfig { @@ -60,7 +95,7 @@ pub struct SyncConfig { /// Fork block to check pub fork_block: Option<(BlockNumber, H256)>, /// Enable snapshot sync - pub warp_sync: bool, + pub warp_sync: WarpSync, /// Enable light client server. pub serve_light: bool, } @@ -74,7 +109,7 @@ impl Default for SyncConfig { subprotocol_name: ETH_PROTOCOL, light_subprotocol_name: LIGHT_PROTOCOL, fork_block: None, - warp_sync: false, + warp_sync: WarpSync::Disabled, serve_light: false, } } diff --git a/sync/src/chain.rs b/sync/src/chain.rs index c5c291bd0..9023bc59f 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -105,7 +105,7 @@ use ethcore::snapshot::{ManifestData, RestorationStatus}; use transaction::PendingTransaction; use sync_io::SyncIo; use time; -use super::SyncConfig; +use super::{WarpSync, SyncConfig}; use block_sync::{BlockDownloader, BlockRequest, BlockDownloaderImportError as DownloaderImportError, DownloadAction}; use rand::Rng; use snapshot::{Snapshot, ChunkType}; @@ -385,7 +385,7 @@ pub struct ChainSync { /// Enable ancient block downloading download_old_blocks: bool, /// Enable warp sync. - enable_warp_sync: bool, + warp_sync: WarpSync, } type RlpResponseResult = Result, PacketDecodeError>; @@ -394,9 +394,16 @@ impl ChainSync { /// Create a new instance of syncing strategy. pub fn new(config: SyncConfig, chain: &BlockChainClient) -> ChainSync { let chain_info = chain.chain_info(); + let best_block = chain.chain_info().best_block_number; + let state = match config.warp_sync { + WarpSync::Enabled => SyncState::WaitingPeers, + WarpSync::OnlyAndAfter(block) if block > best_block => SyncState::WaitingPeers, + _ => SyncState::Idle, + }; + let mut sync = ChainSync { - state: if config.warp_sync { SyncState::WaitingPeers } else { SyncState::Idle }, - starting_block: chain.chain_info().best_block_number, + state, + starting_block: best_block, highest_block: None, peers: HashMap::new(), handshaking_peers: HashMap::new(), @@ -410,7 +417,7 @@ impl ChainSync { snapshot: Snapshot::new(), sync_start_time: None, transactions_stats: TransactionsStats::default(), - enable_warp_sync: config.warp_sync, + warp_sync: config.warp_sync, }; sync.update_targets(chain); sync @@ -508,10 +515,12 @@ impl ChainSync { } fn maybe_start_snapshot_sync(&mut self, io: &mut SyncIo) { - if !self.enable_warp_sync || io.snapshot_service().supported_versions().is_none() { + if !self.warp_sync.is_enabled() || io.snapshot_service().supported_versions().is_none() { + trace!(target: "sync", "Skipping warp sync. Disabled or not supported."); return; } if self.state != SyncState::WaitingPeers && self.state != SyncState::Blocks && self.state != SyncState::Waiting { + trace!(target: "sync", "Skipping warp sync. State: {:?}", self.state); return; } // Make sure the snapshot block is not too far away from best block and network best block and @@ -520,11 +529,16 @@ impl ChainSync { let fork_block = self.fork_block.as_ref().map(|&(n, _)| n).unwrap_or(0); let (best_hash, max_peers, snapshot_peers) = { + let expected_warp_block = match self.warp_sync { + WarpSync::OnlyAndAfter(block) => block, + _ => 0, + }; //collect snapshot infos from peers let snapshots = self.peers.iter() .filter(|&(_, p)| p.is_allowed() && p.snapshot_number.map_or(false, |sn| our_best_block < sn && (sn - our_best_block) > SNAPSHOT_RESTORE_THRESHOLD && sn > fork_block && + sn > expected_warp_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()))) @@ -554,7 +568,7 @@ impl ChainSync { trace!(target: "sync", "Starting unconfirmed snapshot sync {:?} with {:?}", hash, peers); self.start_snapshot_sync(io, peers); } - } else if timeout { + } else if timeout && !self.warp_sync.is_warp_only() { trace!(target: "sync", "No snapshots found, starting full sync"); self.state = SyncState::Idle; self.continue_sync(io); @@ -626,10 +640,6 @@ impl ChainSync { block_set: None, }; - if self.sync_start_time.is_none() { - self.sync_start_time = Some(time::precise_time_ns()); - } - trace!(target: "sync", "New peer {} (protocol: {}, network: {:?}, difficulty: {:?}, latest:{}, genesis:{}, snapshot:{:?})", peer_id, peer.protocol_version, peer.network_id, peer.difficulty, peer.latest_hash, peer.genesis, peer.snapshot_number); if io.is_expired() { @@ -658,6 +668,10 @@ impl ChainSync { return Ok(()); } + if self.sync_start_time.is_none() { + self.sync_start_time = Some(time::precise_time_ns()); + } + self.peers.insert(peer_id.clone(), peer); // Don't activate peer immediatelly when searching for common block. // Let the current sync round complete first. @@ -1167,9 +1181,14 @@ impl ChainSync { self.sync_peer(io, p, false); } } - if (self.state != SyncState::WaitingPeers && self.state != SyncState::SnapshotWaiting && self.state != SyncState::Waiting && self.state != SyncState::Idle) - && !self.peers.values().any(|p| p.asking != PeerAsking::Nothing && p.block_set != Some(BlockSet::OldBlocks) && p.can_sync()) { + if + self.state != SyncState::WaitingPeers && + self.state != SyncState::SnapshotWaiting && + self.state != SyncState::Waiting && + self.state != SyncState::Idle && + !self.peers.values().any(|p| p.asking != PeerAsking::Nothing && p.block_set != Some(BlockSet::OldBlocks) && p.can_sync()) + { self.complete_sync(io); } } @@ -1220,7 +1239,13 @@ impl ChainSync { if force || higher_difficulty || self.old_blocks.is_some() { match self.state { SyncState::WaitingPeers => { - trace!(target: "sync", "Checking snapshot sync: {} vs {}", peer_snapshot_number, chain_info.best_block_number); + trace!( + target: "sync", + "Checking snapshot sync: {} vs {} (peer: {})", + peer_snapshot_number, + chain_info.best_block_number, + peer_id + ); self.maybe_start_snapshot_sync(io); }, SyncState::Idle | SyncState::Blocks | SyncState::NewBlocks => { diff --git a/sync/src/tests/chain.rs b/sync/src/tests/chain.rs index f9ce17b5b..e7d750152 100644 --- a/sync/src/tests/chain.rs +++ b/sync/src/tests/chain.rs @@ -18,7 +18,7 @@ use std::sync::Arc; use ethcore::client::{TestBlockChainClient, BlockChainClient, BlockId, EachBlockWith}; use chain::{SyncState}; use super::helpers::*; -use SyncConfig; +use {SyncConfig, WarpSync}; #[test] fn two_peers() { @@ -161,7 +161,7 @@ fn status_empty() { let net = TestNet::new(2); assert_eq!(net.peer(0).sync.read().status().state, SyncState::Idle); let mut config = SyncConfig::default(); - config.warp_sync = true; + config.warp_sync = WarpSync::Enabled; let net = TestNet::new_with_config(2, config); assert_eq!(net.peer(0).sync.read().status().state, SyncState::WaitingPeers); } diff --git a/sync/src/tests/snapshot.rs b/sync/src/tests/snapshot.rs index 516e3d7e2..2f6441f4f 100644 --- a/sync/src/tests/snapshot.rs +++ b/sync/src/tests/snapshot.rs @@ -24,7 +24,7 @@ use ethcore::snapshot::{SnapshotService, ManifestData, RestorationStatus}; use ethcore::header::BlockNumber; use ethcore::client::{EachBlockWith}; use super::helpers::*; -use SyncConfig; +use {SyncConfig, WarpSync}; pub struct TestSnapshotService { manifest: Option, @@ -127,7 +127,7 @@ impl SnapshotService for TestSnapshotService { fn snapshot_sync() { ::env_logger::init().ok(); let mut config = SyncConfig::default(); - config.warp_sync = true; + config.warp_sync = WarpSync::Enabled; let mut net = TestNet::new_with_config(5, config); let snapshot_service = Arc::new(TestSnapshotService::new_with_snapshot(16, H256::new(), 500000)); for i in 0..4 { diff --git a/util/network/src/host.rs b/util/network/src/host.rs index ea3d560a4..84a9bb343 100644 --- a/util/network/src/host.rs +++ b/util/network/src/host.rs @@ -732,11 +732,11 @@ impl Host { }; match TcpStream::connect(&address) { Ok(socket) => { - trace!(target: "network", "Connecting to {:?}", address); + trace!(target: "network", "{}: Connecting to {:?}", id, address); socket }, Err(e) => { - debug!(target: "network", "Can't connect to address {:?}: {:?}", address, e); + debug!(target: "network", "{}: Can't connect to address {:?}: {:?}", id, address, e); return; } } @@ -752,6 +752,7 @@ impl Host { let mut sessions = self.sessions.write(); let token = sessions.insert_with_opt(|token| { + trace!(target: "network", "{}: Initiating session {:?}", token, id); match Session::new(io, socket, token, id, &nonce, self.stats.clone(), &self.info.read()) { Ok(s) => Some(Arc::new(Mutex::new(s))), Err(e) => {