From defd24c40e9db3ad1a11faa956331cae9cb16ad9 Mon Sep 17 00:00:00 2001 From: Artem Vorotnikov Date: Fri, 14 Aug 2020 13:24:16 +0300 Subject: [PATCH] Remove updater --- Cargo.lock | 64 +- Cargo.toml | 7 +- ethcore/src/client/client.rs | 16 - parity/cli/mod.rs | 47 - parity/cli/presets/config.dev-insecure.toml | 1 - parity/cli/presets/config.insecure.toml | 3 - parity/cli/tests/config.full.toml | 6 - parity/configuration.rs | 120 +- parity/lib.rs | 34 +- parity/main.rs | 352 +---- parity/params.rs | 2 +- parity/rpc_apis.rs | 6 +- parity/run.rs | 71 +- rpc/Cargo.toml | 2 - rpc/src/lib.rs | 2 - rpc/src/v1/impls/parity.rs | 29 +- rpc/src/v1/impls/parity_set.rs | 28 +- rpc/src/v1/tests/helpers/mod.rs | 2 - rpc/src/v1/tests/helpers/update_service.rs | 111 -- rpc/src/v1/tests/mocked/parity.rs | 52 +- rpc/src/v1/tests/mocked/parity_set.rs | 79 +- rpc/src/v1/traits/parity.rs | 17 +- rpc/src/v1/traits/parity_set.rs | 10 +- rpc/src/v1/types/consensus_status.rs | 163 --- rpc/src/v1/types/mod.rs | 2 - updater/Cargo.toml | 37 - updater/hash-fetch/Cargo.toml | 29 - updater/hash-fetch/res/urlhint.json | 6 - updater/hash-fetch/src/client.rs | 327 ----- updater/hash-fetch/src/lib.rs | 52 - updater/hash-fetch/src/urlhint.rs | 395 ----- updater/res/operations.json | 597 -------- updater/src/lib.rs | 58 - updater/src/service.rs | 38 - updater/src/types/all.rs | 67 - updater/src/types/mod.rs | 27 - updater/src/types/release_track.rs | 122 -- updater/src/types/version_info.rs | 78 - updater/src/updater.rs | 1462 ------------------- util/dir/src/lib.rs | 13 - util/version/Cargo.toml | 14 - util/version/build.rs | 10 - util/version/src/lib.rs | 4 +- 43 files changed, 60 insertions(+), 4502 deletions(-) delete mode 100644 rpc/src/v1/tests/helpers/update_service.rs delete mode 100644 rpc/src/v1/types/consensus_status.rs delete mode 100644 updater/Cargo.toml delete mode 100644 updater/hash-fetch/Cargo.toml delete mode 100644 updater/hash-fetch/res/urlhint.json delete mode 100644 updater/hash-fetch/src/client.rs delete mode 100644 updater/hash-fetch/src/lib.rs delete mode 100644 updater/hash-fetch/src/urlhint.rs delete mode 100644 updater/res/operations.json delete mode 100644 updater/src/lib.rs delete mode 100644 updater/src/service.rs delete mode 100644 updater/src/types/all.rs delete mode 100644 updater/src/types/mod.rs delete mode 100644 updater/src/types/release_track.rs delete mode 100644 updater/src/types/version_info.rs delete mode 100644 updater/src/updater.rs diff --git a/Cargo.lock b/Cargo.lock index 97ab1a660..7058fb91e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2279,15 +2279,6 @@ name = "mime" version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "mime_guess" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "mio" version = "0.6.19" @@ -2623,6 +2614,7 @@ dependencies = [ "ethstore 0.2.1", "fake-fetch 0.0.1", "fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fetch 0.1.0", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "ipnetwork 0.12.8 (registry+https://github.com/rust-lang/crates.io-index)", "journaldb 0.2.0", @@ -2639,13 +2631,11 @@ dependencies = [ "panic_hook 0.1.0", "parity-bytes 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-daemonize 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-hash-fetch 1.12.0", "parity-ipfs-api 1.12.0", "parity-local-store 0.1.0", "parity-path 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "parity-rpc 1.12.0", "parity-runtime 0.1.0", - "parity-updater 1.12.0", "parity-version 2.5.13", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2666,29 +2656,6 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "parity-hash-fetch" -version = "1.12.0" -dependencies = [ - "ethabi 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-contract 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-derive 6.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "fake-fetch 0.0.1", - "fetch 0.1.0", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-bytes 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-runtime 0.1.0", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "registrar 0.0.1", - "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "parity-ipfs-api" version = "1.12.0" @@ -2788,14 +2755,12 @@ dependencies = [ "parity-bytes 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-crypto 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-runtime 0.1.0", - "parity-updater 1.12.0", "parity-version 2.5.13", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2869,32 +2834,6 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "parity-updater" -version = "1.12.0" -dependencies = [ - "common-types 0.1.0", - "ethabi 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-contract 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-derive 6.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 1.12.0", - "ethcore-sync 1.12.0", - "ethereum-types 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-bytes 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-hash-fetch 1.12.0", - "parity-path 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-version 2.5.13", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "parity-version" version = "2.5.13" @@ -4927,7 +4866,6 @@ dependencies = [ "checksum memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94da53143d45f6bad3753f532e56ad57a6a26c0ca6881794583310c7cb4c885f" "checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" "checksum mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "dd1d63acd1b78403cc0c325605908475dd9b9a3acbf65ed8bcab97e27014afcf" -"checksum mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a0ed03949aef72dbdf3116a383d7b38b4768e6f960528cd6a6044aa9ed68599" "checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23" "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" "checksum mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f5e374eff525ce1c5b7687c4cef63943e7686524a387933ad27ca7ec43779cb3" diff --git a/Cargo.toml b/Cargo.toml index 419508769..1e3fbe2b0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,16 +47,15 @@ ethcore-sync = { path = "ethcore/sync" } ethereum-types = "0.4" ethkey = { path = "accounts/ethkey" } ethstore = { path = "accounts/ethstore" } +fetch = { path = "util/fetch" } node-filter = { path = "ethcore/node-filter" } rlp = { version = "0.3.0", features = ["ethereum"] } cli-signer= { path = "cli-signer" } parity-daemonize = "0.3" -parity-hash-fetch = { path = "updater/hash-fetch" } parity-ipfs-api = { path = "ipfs" } parity-local-store = { path = "miner/local-store" } parity-runtime = { path = "util/runtime" } parity-rpc = { path = "rpc" } -parity-updater = { path = "updater" } parity-version = { path = "util/version" } parity-path = "0.1" dir = { path = "util/dir" } @@ -104,10 +103,6 @@ deadlock_detection = ["parking_lot/deadlock_detection"] # `valgrind --tool=massif /path/to/parity ` # and `massif-visualizer` for visualization memory_profiling = [] -# hardcode version number 1.3.7 of parity to force an update -# in order to manually test that parity fall-over to the local version -# in case of invalid or deprecated command line arguments are entered -test-updater = ["parity-updater/test-updater"] [lib] path = "parity/lib.rs" diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 870a314a1..055c923a6 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -194,11 +194,6 @@ struct Importer { /// Call `import_block()` to import a block asynchronously; `flush_queue()` flushes the queue. pub struct Client { /// Flag used to disable the client forever. Not to be confused with `liveness`. - /// - /// For example, auto-updater will disable client forever if there is a - /// hard fork registered on-chain that we don't have capability for. - /// When hard fork block rolls around, the client (if `update` is false) - /// knows it can't proceed further. enabled: AtomicBool, /// Operating mode for the client @@ -1003,17 +998,6 @@ impl Client { self.notify.write().push(Arc::downgrade(&target)); } - /// Set a closure to call when the client wants to be restarted. - /// - /// The parameter passed to the callback is the name of the new chain spec to use after - /// the restart. - pub fn set_exit_handler(&self, f: F) - where - F: Fn(String) + 'static + Send, - { - *self.exit_handler.lock() = Some(Box::new(f)); - } - /// Returns engine reference. pub fn engine(&self) -> &dyn EthEngine { &*self.engine diff --git a/parity/cli/mod.rs b/parity/cli/mod.rs index 21b3eb507..07f429413 100644 --- a/parity/cli/mod.rs +++ b/parity/cli/mod.rs @@ -234,18 +234,6 @@ usage! { { // Global flags and arguments ["Operating Options"] - FLAG flag_no_download: (bool) = false, or |c: &Config| c.parity.as_ref()?.no_download.clone(), - "--no-download", - "Normally new releases will be downloaded ready for updating. This disables it. Not recommended.", - - FLAG flag_no_consensus: (bool) = false, or |c: &Config| c.parity.as_ref()?.no_consensus.clone(), - "--no-consensus", - "Force the binary to run even if there are known issues regarding consensus. Not recommended.", - - FLAG flag_force_direct: (bool) = false, or |_| None, - "--force-direct", - "Run the originally installed version of Parity, ignoring any updates that have since been installed.", - ARG arg_mode: (String) = "last", or |c: &Config| c.parity.as_ref()?.mode.clone(), "--mode=[MODE]", "Set the operating mode. MODE can be one of: last - Uses the last-used mode, active if none; active - Parity continuously syncs the chain; passive - Parity syncs initially, then sleeps and wakes regularly to resync; dark - Parity syncs only when the JSON-RPC is active; offline - Parity doesn't sync.", @@ -258,22 +246,6 @@ usage! { "--mode-alarm=[SECS]", "Specify the number of seconds before auto sleep reawake timeout occurs when mode is passive", - ARG arg_auto_update: (String) = "critical", or |c: &Config| c.parity.as_ref()?.auto_update.clone(), - "--auto-update=[SET]", - "Set a releases set to automatically update and install. SET can be one of: all - All updates in the our release track; critical - Only consensus/security updates; none - No updates will be auto-installed.", - - ARG arg_auto_update_delay: (u16) = 100u16, or |c: &Config| c.parity.as_ref()?.auto_update_delay.clone(), - "--auto-update-delay=[NUM]", - "Specify the maximum number of blocks used for randomly delaying updates.", - - ARG arg_auto_update_check_frequency: (u16) = 20u16, or |c: &Config| c.parity.as_ref()?.auto_update_check_frequency.clone(), - "--auto-update-check-frequency=[NUM]", - "Specify the number of blocks between each auto-update check.", - - ARG arg_release_track: (String) = "current", or |c: &Config| c.parity.as_ref()?.release_track.clone(), - "--release-track=[TRACK]", - "Set which release track we should use for updates. TRACK can be one of: stable - Stable releases; beta - Beta releases; nightly - Nightly releases (unstable); testing - Testing releases (do not use); current - Whatever track this executable was released on.", - ARG arg_chain: (String) = "foundation", or |c: &Config| c.parity.as_ref()?.chain.clone(), "--chain=[CHAIN]", "Specify the blockchain type. CHAIN may be either a JSON chain specification file or ethereum, classic, poacore, xdai, volta, ewc, musicoin, ellaism, mix, callisto, morden, mordor, ropsten, kovan, rinkeby, goerli, kotti, poasokol, testnet, or dev.", @@ -896,12 +868,6 @@ struct Operating { mode: Option, mode_timeout: Option, mode_alarm: Option, - auto_update: Option, - auto_update_delay: Option, - auto_update_check_frequency: Option, - release_track: Option, - no_download: Option, - no_consensus: Option, chain: Option, base_path: Option, db_path: Option, @@ -1344,19 +1310,12 @@ mod tests { arg_mode: "last".into(), arg_mode_timeout: 300u64, arg_mode_alarm: 3600u64, - arg_auto_update: "none".into(), - arg_auto_update_delay: 200u16, - arg_auto_update_check_frequency: 50u16, - arg_release_track: "current".into(), - flag_no_download: false, - flag_no_consensus: false, arg_chain: "xyz".into(), arg_base_path: Some("$HOME/.parity".into()), arg_db_path: Some("$HOME/.parity/chains".into()), arg_keys_path: "$HOME/.parity/keys".into(), arg_identity: "".into(), flag_no_persistent_txqueue: false, - flag_force_direct: false, // -- Convenience Options arg_config: "$BASE/config.toml".into(), @@ -1574,12 +1533,6 @@ mod tests { mode: Some("dark".into()), mode_timeout: Some(15u64), mode_alarm: Some(10u64), - auto_update: None, - auto_update_delay: None, - auto_update_check_frequency: None, - release_track: None, - no_download: None, - no_consensus: None, chain: Some("./chain.json".into()), base_path: None, db_path: None, diff --git a/parity/cli/presets/config.dev-insecure.toml b/parity/cli/presets/config.dev-insecure.toml index e4c2c9f47..fcefb174e 100644 --- a/parity/cli/presets/config.dev-insecure.toml +++ b/parity/cli/presets/config.dev-insecure.toml @@ -1,5 +1,4 @@ [parity] -no_consensus = true chain = "dev" [mining] diff --git a/parity/cli/presets/config.insecure.toml b/parity/cli/presets/config.insecure.toml index 18859c9cc..15e6e87b5 100644 --- a/parity/cli/presets/config.insecure.toml +++ b/parity/cli/presets/config.insecure.toml @@ -1,6 +1,3 @@ -[parity] -no_consensus = true - [rpc] interface = "all" apis = ["all"] diff --git a/parity/cli/tests/config.full.toml b/parity/cli/tests/config.full.toml index 63b10941b..ff7437280 100644 --- a/parity/cli/tests/config.full.toml +++ b/parity/cli/tests/config.full.toml @@ -2,12 +2,6 @@ mode = "last" mode_timeout = 300 mode_alarm = 3600 -auto_update = "none" -auto_update_delay = 200 -auto_update_check_frequency = 50 -release_track = "current" -no_download = false -no_consensus = false no_persistent_txqueue = false chain = "homestead" diff --git a/parity/configuration.rs b/parity/configuration.rs index d63e7714d..c80a4fae0 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -47,7 +47,7 @@ use blockchain::{ }; use cache::CacheConfig; use dir::{ - self, default_data_path, default_hypervisor_path, default_local_path, + self, default_data_path, default_local_path, helpers::{replace_home, replace_home_and_local}, Directories, }; @@ -70,7 +70,6 @@ use secretstore::{ }; use snapshot::{self, SnapshotCommand}; use types::data_format::DataFormat; -use updater::{ReleaseTrack, UpdateFilter, UpdatePolicy}; const DEFAULT_MAX_PEERS: u16 = 50; const DEFAULT_MIN_PEERS: u16 = 25; @@ -146,7 +145,6 @@ impl Configuration { self.args.arg_mode_alarm, )?), }; - let update_policy = self.update_policy()?; let logger_config = self.logger_config(); let ws_conf = self.ws_config()?; let snapshot_conf = self.snapshot_config()?; @@ -411,7 +409,6 @@ impl Configuration { gas_pricer_conf: self.gas_pricer_config()?, miner_extras: self.miner_extras()?, stratum: self.stratum_options()?, - update_policy: update_policy, allow_missing_blocks: self.args.flag_jsonrpc_allow_missing_blocks, mode: mode, tracing: tracing, @@ -1036,41 +1033,6 @@ impl Configuration { }) } - fn update_policy(&self) -> Result { - Ok(UpdatePolicy { - enable_downloading: !self.args.flag_no_download, - require_consensus: !self.args.flag_no_consensus, - filter: match self.args.arg_auto_update.as_ref() { - "none" => UpdateFilter::None, - "critical" => UpdateFilter::Critical, - "all" => UpdateFilter::All, - _ => { - return Err( - "Invalid value for `--auto-update`. See `--help` for more information." - .into(), - ) - } - }, - track: match self.args.arg_release_track.as_ref() { - "stable" => ReleaseTrack::Stable, - "beta" => ReleaseTrack::Beta, - "nightly" => ReleaseTrack::Nightly, - "testing" => ReleaseTrack::Testing, - "current" => ReleaseTrack::Unknown, - _ => { - return Err( - "Invalid value for `--releases-track`. See `--help` for more information." - .into(), - ) - } - }, - path: default_hypervisor_path(), - max_size: 128 * 1024 * 1024, - max_delay: self.args.arg_auto_update_delay as u64, - frequency: self.args.arg_auto_update_check_frequency as u64, - }) - } - fn directories(&self) -> Directories { let local_path = default_local_path(); let base_path = self @@ -1318,7 +1280,7 @@ mod tests { use account::{AccountCmd, ImportAccounts, ListAccounts, NewAccount}; use blockchain::{BlockchainCmd, ExportBlockchain, ExportState, ImportBlockchain}; use cli::Args; - use dir::{default_hypervisor_path, Directories}; + use dir::Directories; use ethcore::{client::VMType, miner::MinerOptions}; use helpers::default_network_config; use miner::pool::PrioritizationStrategy; @@ -1330,7 +1292,6 @@ mod tests { use run::RunCmd; use tempdir::TempDir; use types::{data_format::DataFormat, ids::BlockId}; - use updater::{ReleaseTrack, UpdateFilter, UpdatePolicy}; use network::{AllowIP, IpFilter}; @@ -1611,16 +1572,6 @@ mod tests { acc_conf: Default::default(), gas_pricer_conf: Default::default(), miner_extras: Default::default(), - update_policy: UpdatePolicy { - enable_downloading: true, - require_consensus: true, - filter: UpdateFilter::Critical, - track: ReleaseTrack::Unknown, - path: default_hypervisor_path(), - max_size: 128 * 1024 * 1024, - max_delay: 100, - frequency: 20, - }, mode: Default::default(), tracing: Default::default(), compaction: Default::default(), @@ -1677,71 +1628,6 @@ mod tests { assert!(conf.miner_options().is_err()); } - #[test] - fn should_parse_updater_options() { - // when - let conf0 = parse(&["parity", "--release-track=testing"]); - let conf1 = parse(&[ - "parity", - "--auto-update", - "all", - "--no-consensus", - "--auto-update-delay", - "300", - ]); - let conf2 = parse(&[ - "parity", - "--no-download", - "--auto-update=all", - "--release-track=beta", - "--auto-update-delay=300", - "--auto-update-check-frequency=100", - ]); - let conf3 = parse(&["parity", "--auto-update=xxx"]); - - // then - assert_eq!( - conf0.update_policy().unwrap(), - UpdatePolicy { - enable_downloading: true, - require_consensus: true, - filter: UpdateFilter::Critical, - track: ReleaseTrack::Testing, - path: default_hypervisor_path(), - max_size: 128 * 1024 * 1024, - max_delay: 100, - frequency: 20, - } - ); - assert_eq!( - conf1.update_policy().unwrap(), - UpdatePolicy { - enable_downloading: true, - require_consensus: false, - filter: UpdateFilter::All, - track: ReleaseTrack::Unknown, - path: default_hypervisor_path(), - max_size: 128 * 1024 * 1024, - max_delay: 300, - frequency: 20, - } - ); - assert_eq!( - conf2.update_policy().unwrap(), - UpdatePolicy { - enable_downloading: false, - require_consensus: true, - filter: UpdateFilter::All, - track: ReleaseTrack::Beta, - path: default_hypervisor_path(), - max_size: 128 * 1024 * 1024, - max_delay: 300, - frequency: 100, - } - ); - assert!(conf3.update_policy().is_err()); - } - #[test] fn should_parse_network_settings() { // given @@ -1922,7 +1808,6 @@ mod tests { let conf = Configuration::parse_cli(&args).unwrap(); match conf.into_command().unwrap().cmd { Cmd::Run(c) => { - assert_eq!(c.update_policy.require_consensus, false); assert_eq!(c.net_settings.rpc_interface, "0.0.0.0"); match c.http_conf.apis { ApiSet::List(set) => assert_eq!(set, ApiSet::All.list_apis()), @@ -1945,7 +1830,6 @@ mod tests { assert_eq!(c.net_settings.chain, "dev"); assert_eq!(c.gas_pricer_conf, GasPricerConfig::Fixed(0.into())); assert_eq!(c.miner_options.reseal_min_period, Duration::from_millis(0)); - assert_eq!(c.update_policy.require_consensus, false); assert_eq!(c.net_settings.rpc_interface, "0.0.0.0"); match c.http_conf.apis { ApiSet::List(set) => assert_eq!(set, ApiSet::All.list_apis()), diff --git a/parity/lib.rs b/parity/lib.rs index 2cee8f962..e8b9b6466 100644 --- a/parity/lib.rs +++ b/parity/lib.rs @@ -55,18 +55,17 @@ extern crate ethcore_sync as sync; extern crate ethereum_types; extern crate ethkey; extern crate ethstore; +extern crate fetch; extern crate journaldb; extern crate keccak_hash as hash; extern crate kvdb; extern crate node_filter; extern crate parity_bytes as bytes; -extern crate parity_hash_fetch as hash_fetch; extern crate parity_ipfs_api; extern crate parity_local_store as local_store; extern crate parity_path as path; extern crate parity_rpc; extern crate parity_runtime; -extern crate parity_updater as updater; extern crate parity_version; extern crate registrar; @@ -182,22 +181,13 @@ pub enum ExecutionAction { Running(RunningClient), } -fn execute( - command: Execute, - logger: Arc, - on_client_rq: Cr, - on_updater_rq: Rr, -) -> Result -where - Cr: Fn(String) + 'static + Send, - Rr: Fn() + 'static + Send, -{ +fn execute(command: Execute, logger: Arc) -> Result { #[cfg(feature = "deadlock_detection")] run_deadlock_detection_thread(); match command.cmd { Cmd::Run(run_cmd) => { - let outcome = run::execute(run_cmd, logger, on_client_rq, on_updater_rq)?; + let outcome = run::execute(run_cmd, logger)?; Ok(ExecutionAction::Running(outcome)) } Cmd::Version => Ok(ExecutionAction::Instant(Some(Args::print_version()))), @@ -237,25 +227,11 @@ where /// Starts the parity client. /// -/// `on_client_rq` is the action to perform when the client receives an RPC request to be restarted -/// with a different chain. -/// -/// `on_updater_rq` is the action to perform when the updater has a new binary to execute. -/// /// The first parameter is the command line arguments that you would pass when running the parity /// binary. /// /// On error, returns what to print on stderr. // FIXME: totally independent logging capability, see https://github.com/paritytech/parity-ethereum/issues/10252 -pub fn start( - conf: Configuration, - logger: Arc, - on_client_rq: Cr, - on_updater_rq: Rr, -) -> Result -where - Cr: Fn(String) + 'static + Send, - Rr: Fn() + 'static + Send, -{ - execute(conf.into_command()?, logger, on_client_rq, on_updater_rq) +pub fn start(conf: Configuration, logger: Arc) -> Result { + execute(conf.into_command()?, logger) } diff --git a/parity/main.rs b/parity/main.rs index eff0323fb..542ea8dc8 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -34,11 +34,7 @@ extern crate ethcore_logger; extern crate winapi; use std::{ - env, - ffi::OsString, - fs::{create_dir_all, metadata, remove_file, File}, - io::{Read, Write}, - path::PathBuf, + io::Write, process, sync::{ atomic::{AtomicBool, Ordering}, @@ -48,148 +44,12 @@ use std::{ use ansi_term::Colour; use ctrlc::CtrlC; -use dir::default_hypervisor_path; use ethcore_logger::setup_log; use fdlimit::raise_fd_limit; use parity_daemonize::AsHandle; use parity_ethereum::{start, ExecutionAction}; use parking_lot::{Condvar, Mutex}; -const PLEASE_RESTART_EXIT_CODE: i32 = 69; -const PARITY_EXECUTABLE_NAME: &str = "parity"; - -#[derive(Debug)] -enum Error { - BinaryNotFound, - ExitCode(i32), - Restart, - Unknown, -} - -fn update_path(name: &str) -> PathBuf { - let mut dest = default_hypervisor_path(); - dest.push(name); - dest -} - -fn latest_exe_path() -> Result { - File::open(update_path("latest")) - .and_then(|mut f| { - let mut exe_path = String::new(); - trace!(target: "updater", "latest binary path: {:?}", f); - f.read_to_string(&mut exe_path) - .map(|_| update_path(&exe_path)) - }) - .or(Err(Error::BinaryNotFound)) -} - -fn latest_binary_is_newer( - current_binary: &Option, - latest_binary: &Option, -) -> bool { - match ( - current_binary - .as_ref() - .and_then(|p| metadata(p.as_path()).ok()) - .and_then(|m| m.modified().ok()), - latest_binary - .as_ref() - .and_then(|p| metadata(p.as_path()).ok()) - .and_then(|m| m.modified().ok()), - ) { - (Some(latest_exe_time), Some(this_exe_time)) if latest_exe_time > this_exe_time => true, - _ => false, - } -} - -fn set_spec_name_override(spec_name: &str) { - if let Err(e) = create_dir_all(default_hypervisor_path()).and_then(|_| { - File::create(update_path("spec_name_override")) - .and_then(|mut f| f.write_all(spec_name.as_bytes())) - }) { - warn!( - "Couldn't override chain spec: {} at {:?}", - e, - update_path("spec_name_override") - ); - } -} - -fn take_spec_name_override() -> Option { - let p = update_path("spec_name_override"); - let r = File::open(p.clone()).ok().and_then(|mut f| { - let mut spec_name = String::new(); - f.read_to_string(&mut spec_name).ok().map(|_| spec_name) - }); - let _ = remove_file(p); - r -} - -#[cfg(windows)] -fn global_cleanup() { - // We need to cleanup all sockets before spawning another Parity process. This makes sure everything is cleaned up. - // The loop is required because of internal reference counter for winsock dll. We don't know how many crates we use do - // initialize it. There's at least 2 now. - for _ in 0..10 { - unsafe { - ::winapi::um::winsock2::WSACleanup(); - } - } -} - -#[cfg(not(windows))] -fn global_init() {} - -#[cfg(windows)] -fn global_init() { - // When restarting in the same process this reinits windows sockets. - unsafe { - const WS_VERSION: u16 = 0x202; - let mut wsdata: ::winapi::um::winsock2::WSADATA = ::std::mem::zeroed(); - ::winapi::um::winsock2::WSAStartup(WS_VERSION, &mut wsdata); - } -} - -#[cfg(not(windows))] -fn global_cleanup() {} - -// Starts parity binary installed via `parity-updater` and returns the code it exits with. -fn run_parity() -> Result<(), Error> { - global_init(); - - let prefix = vec![ - OsString::from("--can-restart"), - OsString::from("--force-direct"), - ]; - - let res: Result<(), Error> = latest_exe_path().and_then(|exe| { - process::Command::new(exe) - .args( - &(env::args_os() - .skip(1) - .chain(prefix.into_iter()) - .collect::>()), - ) - .status() - .ok() - .map_or(Err(Error::Unknown), |es| { - match es.code() { - // Process success - Some(0) => Ok(()), - // Please restart - Some(PLEASE_RESTART_EXIT_CODE) => Err(Error::Restart), - // Process error code `c` - Some(c) => Err(Error::ExitCode(c)), - // Unknown error, couldn't determine error code - _ => Err(Error::Unknown), - } - }) - }); - - global_cleanup(); - res -} - #[derive(Debug)] /// Status used to exit or restart the program. struct ExitStatus { @@ -197,18 +57,10 @@ struct ExitStatus { panicking: bool, /// Whether the program should exit. should_exit: bool, - /// Whether the program should restart. - should_restart: bool, - /// If a restart happens, whether a new chain spec should be used. - spec_name_override: Option, } -// Run `locally installed version` of parity (i.e, not installed via `parity-updater`) -// Returns the exit error code. -fn main_direct(force_can_restart: bool) -> i32 { - global_init(); - - let mut conf = { +fn main() -> Result<(), i32> { + let conf = { let args = std::env::args().collect::>(); parity_ethereum::Configuration::parse_cli(&args).unwrap_or_else(|e| e.exit()) }; @@ -218,10 +70,6 @@ fn main_direct(force_can_restart: bool) -> i32 { process::exit(2) }); - if let Some(spec_override) = take_spec_name_override() { - conf.args.arg_chain = spec_override; - } - // FIXME: `pid_file` shouldn't need to cloned here // see: `https://github.com/paritytech/parity-daemonize/pull/13` for more info let handle = if let Some(pid) = conf.args.arg_daemon_pid_file.clone() { @@ -235,15 +83,13 @@ fn main_direct(force_can_restart: bool) -> i32 { Ok(h) => Some(h), Err(e) => { error!("{}", Colour::Red.paint(format!("{}", e))); - return 1; + return Err(1); } } } else { None }; - let can_restart = force_can_restart || conf.args.flag_can_restart; - // increase max number of open files raise_fd_limit(); @@ -251,8 +97,6 @@ fn main_direct(force_can_restart: bool) -> i32 { Mutex::new(ExitStatus { panicking: false, should_exit: false, - should_restart: false, - spec_name_override: None, }), Condvar::new(), )); @@ -261,53 +105,16 @@ fn main_direct(force_can_restart: bool) -> i32 { // again. let exiting = Arc::new(AtomicBool::new(false)); - let exec = if can_restart { - start( - conf, - logger, - { - let e = exit.clone(); - let exiting = exiting.clone(); - move |new_chain: String| { - if !exiting.swap(true, Ordering::SeqCst) { - *e.0.lock() = ExitStatus { - panicking: false, - should_exit: true, - should_restart: true, - spec_name_override: Some(new_chain), - }; - e.1.notify_all(); - } - } - }, - { - let e = exit.clone(); - let exiting = exiting.clone(); - move || { - if !exiting.swap(true, Ordering::SeqCst) { - *e.0.lock() = ExitStatus { - panicking: false, - should_exit: true, - should_restart: true, - spec_name_override: None, - }; - e.1.notify_all(); - } - } - }, - ) - } else { - trace!(target: "mode", "Not hypervised: not setting exit handlers."); - start(conf, logger, move |_| {}, move || {}) - }; + trace!(target: "mode", "Not hypervised: not setting exit handlers."); + let exec = start(conf, logger); - let res = match exec { + match exec { Ok(result) => match result { - ExecutionAction::Instant(Some(s)) => { - println!("{}", s); - 0 + ExecutionAction::Instant(output) => { + if let Some(s) = output { + println!("{}", s); + } } - ExecutionAction::Instant(None) => 0, ExecutionAction::Running(client) => { panic_hook::set_with({ let e = exit.clone(); @@ -319,8 +126,6 @@ fn main_direct(force_can_restart: bool) -> i32 { *e.0.lock() = ExitStatus { panicking: true, should_exit: true, - should_restart: false, - spec_name_override: None, }; e.1.notify_all(); } @@ -335,8 +140,6 @@ fn main_direct(force_can_restart: bool) -> i32 { *e.0.lock() = ExitStatus { panicking: false, should_exit: true, - should_restart: false, - spec_name_override: None, }; e.1.notify_all(); } @@ -357,17 +160,8 @@ fn main_direct(force_can_restart: bool) -> i32 { client.shutdown(); - if lock.should_restart { - if let Some(ref spec_name) = lock.spec_name_override { - set_spec_name_override(&spec_name.clone()); - } - PLEASE_RESTART_EXIT_CODE - } else { - if lock.panicking { - 1 - } else { - 0 - } + if lock.panicking { + return Err(1); } } }, @@ -378,125 +172,9 @@ fn main_direct(force_can_restart: bool) -> i32 { handle.detach_with_msg(format!("{}", Colour::Red.paint(&err))) } eprintln!("{}", err); - 1 + return Err(1); } }; - global_cleanup(); - res -} - -fn println_trace_main(s: String) { - if env::var("RUST_LOG") - .ok() - .and_then(|s| s.find("main=trace")) - .is_some() - { - println!("{}", s); - } -} - -macro_rules! trace_main { - ($arg:expr) => (println_trace_main($arg.into())); - ($($arg:tt)*) => (println_trace_main(format!("{}", format_args!($($arg)*)))); -} - -fn main() { - panic_hook::set_abort(); - - // the user has specified to run its originally installed binary (not via `parity-updater`) - let force_direct = std::env::args().any(|arg| arg == "--force-direct"); - - // absolute path to the current `binary` - let exe_path = std::env::current_exe().ok(); - - // the binary is named `target/xx/yy` - let development = exe_path - .as_ref() - .and_then(|p| { - p.parent() - .and_then(|p| p.parent()) - .and_then(|p| p.file_name()) - .map(|n| n == "target") - }) - .unwrap_or(false); - - // the binary is named `parity` - let same_name = exe_path.as_ref().map_or(false, |p| { - p.file_stem().map_or(false, |n| n == PARITY_EXECUTABLE_NAME) - }); - - trace_main!( - "Starting up {} (force-direct: {}, development: {}, same-name: {})", - std::env::current_exe() - .ok() - .map_or_else(|| "".into(), |x| format!("{}", x.display())), - force_direct, - development, - same_name - ); - - if !force_direct && !development && same_name { - // Try to run the latest installed version of `parity`, - // Upon failure it falls back to the locally installed version of `parity` - // Everything run inside a loop, so we'll be able to restart from the child into a new version seamlessly. - loop { - // `Path` to the latest downloaded binary - let latest_exe = latest_exe_path().ok(); - - // `Latest´ binary exist - let have_update = latest_exe.as_ref().map_or(false, |p| p.exists()); - - // Canonicalized path to the current binary is not the same as to latest binary - let canonicalized_path_not_same = exe_path.as_ref().map_or(false, |exe| { - latest_exe.as_ref().map_or(false, |lexe| { - exe.canonicalize().ok() != lexe.canonicalize().ok() - }) - }); - - // Downloaded `binary` is newer - let update_is_newer = latest_binary_is_newer(&latest_exe, &exe_path); - trace_main!( - "Starting... (have-update: {}, non-updated-current: {}, update-is-newer: {})", - have_update, - canonicalized_path_not_same, - update_is_newer - ); - - let exit_code = if have_update && canonicalized_path_not_same && update_is_newer { - trace_main!( - "Attempting to run latest update ({})...", - latest_exe - .as_ref() - .expect( - "guarded by have_update; latest_exe must exist for have_update; qed" - ) - .display() - ); - match run_parity() { - Ok(_) => 0, - // Restart parity - Err(Error::Restart) => PLEASE_RESTART_EXIT_CODE, - // Fall back to local version - Err(e) => { - error!(target: "updater", "Updated binary could not be executed error: {:?}. Falling back to local version", e); - main_direct(true) - } - } - } else { - trace_main!("No latest update. Attempting to direct..."); - main_direct(true) - }; - trace_main!("Latest binary exited with exit code: {}", exit_code); - if exit_code != PLEASE_RESTART_EXIT_CODE { - trace_main!("Quitting..."); - process::exit(exit_code); - } - trace!(target: "updater", "Re-running updater loop"); - } - } else { - trace_main!("Running direct"); - // Otherwise, we're presumably running the version we want. Just run and fall-through. - process::exit(main_direct(false)); - } + Ok(()) } diff --git a/parity/params.rs b/parity/params.rs index 48c3f563e..b02f2e27a 100644 --- a/parity/params.rs +++ b/parity/params.rs @@ -22,7 +22,7 @@ use ethcore::{ spec::{Spec, SpecParams}, }; use ethereum_types::{Address, U256}; -use hash_fetch::fetch::Client as FetchClient; +use fetch::Client as FetchClient; use journaldb::Algorithm; use miner::{ gas_price_calibrator::{GasPriceCalibrator, GasPriceCalibratorOptions}, diff --git a/parity/rpc_apis.rs b/parity/rpc_apis.rs index 120b51bb0..3f02bfa09 100644 --- a/parity/rpc_apis.rs +++ b/parity/rpc_apis.rs @@ -22,7 +22,7 @@ use account_utils::{self, AccountProvider}; use ethcore::{client::Client, miner::Miner, snapshot::SnapshotService}; use ethcore_logger::RotatingLogger; use ethcore_service::PrivateTxService; -use hash_fetch::fetch::Client as FetchClient; +use fetch::Client as FetchClient; use jsonrpc_core::{self as core, MetaIoHandler}; use miner::external::ExternalMiner; use parity_rpc::{ @@ -33,7 +33,6 @@ use parity_rpc::{ use parity_runtime::Executor; use parking_lot::Mutex; use sync::{ManageNetwork, SyncProvider}; -use updater::Updater; #[derive(Debug, PartialEq, Clone, Eq, Hash)] pub enum Api { @@ -198,7 +197,6 @@ pub struct FullDependencies { pub logger: Arc, pub settings: Arc, pub net_service: Arc, - pub updater: Arc, pub experimental_rpcs: bool, pub ws_address: Option, pub fetch: FetchClient, @@ -326,7 +324,6 @@ impl FullDependencies { self.client.clone(), self.miner.clone(), self.sync.clone(), - self.updater.clone(), self.net_service.clone(), self.logger.clone(), self.settings.clone(), @@ -373,7 +370,6 @@ impl FullDependencies { ParitySetClient::new( &self.client, &self.miner, - &self.updater, &self.net_service, self.fetch.clone(), ) diff --git a/parity/run.rs b/parity/run.rs index 5ce6bfe53..0c2f428c2 100644 --- a/parity/run.rs +++ b/parity/run.rs @@ -23,15 +23,11 @@ use std::{ use account_utils; use ansi_term::Colour; -use bytes::Bytes; use cache::CacheConfig; -use call_contract::CallContract; use db; use dir::{DatabaseDirectories, Directories}; use ethcore::{ - client::{ - BlockChainClient, BlockId, BlockInfo, Client, DatabaseCompactionProfile, Mode, VMType, - }, + client::{BlockChainClient, BlockInfo, Client, DatabaseCompactionProfile, Mode, VMType}, miner::{self, stratum, Miner, MinerOptions, MinerService}, snapshot::{self, SnapshotConfiguration}, verification::queue::VerifierSettings, @@ -39,9 +35,6 @@ use ethcore::{ use ethcore_logger::{Config as LogConfig, RotatingLogger}; use ethcore_private_tx::{EncryptorConfig, ProviderConfig, SecretStoreEncryptor}; use ethcore_service::ClientService; -use ethereum_types::Address; -use futures::IntoFuture; -use hash_fetch::{self, fetch}; use helpers::{execute_upgrades, passwords_from_files, to_client_config}; use informant::{FullNodeInformantData, Informant}; use ipfs; @@ -60,13 +53,11 @@ use parity_rpc::{ }; use parity_runtime::Runtime; use parity_version::version; -use registrar::{Asynchronous, RegistrarClient}; use rpc; use rpc_apis; use secretstore; use signer; use sync::{self, PrivateTxHandler, SyncConfig}; -use updater::{UpdatePolicy, Updater}; use user_defaults::UserDefaults; // how often to take periodic snapshots. @@ -102,7 +93,6 @@ pub struct RunCmd { pub acc_conf: AccountsConfig, pub gas_pricer_conf: GasPricerConfig, pub miner_extras: MinerExtras, - pub update_policy: UpdatePolicy, pub mode: Option, pub tracing: Switch, pub fat_db: Switch, @@ -154,22 +144,8 @@ impl ::local_store::NodeInfo for FullNodeInfo { /// Executes the given run command. /// -/// `on_client_rq` is the action to perform when the client receives an RPC request to be restarted -/// with a different chain. -/// -/// `on_updater_rq` is the action to perform when the updater has a new binary to execute. -/// /// On error, returns what to print on stderr. -pub fn execute( - cmd: RunCmd, - logger: Arc, - on_client_rq: Cr, - on_updater_rq: Rr, -) -> Result -where - Cr: Fn(String) + 'static + Send, - Rr: Fn() + 'static + Send, -{ +pub fn execute(cmd: RunCmd, logger: Arc) -> Result { // load spec let spec = cmd.spec.spec(&cmd.dirs.cache)?; @@ -206,9 +182,6 @@ where _ => true, }; - // get the update policy - let update_policy = cmd.update_policy; - // prepare client and snapshot paths. let client_path = db_dirs.client_path(algorithm); let snapshot_path = db_dirs.snapshot_path(); @@ -523,41 +496,6 @@ where chain_notify.start(); } - let contract_client = { - struct FullRegistrar { - client: Arc, - } - impl RegistrarClient for FullRegistrar { - type Call = Asynchronous; - fn registrar_address(&self) -> Result { - self.client - .registrar_address() - .ok_or_else(|| "Registrar not defined.".into()) - } - fn call_contract(&self, address: Address, data: Bytes) -> Self::Call { - Box::new( - self.client - .call_contract(BlockId::Latest, address, data) - .into_future(), - ) - } - } - - Arc::new(FullRegistrar { - client: client.clone(), - }) - }; - - // the updater service - let updater_fetch = fetch.clone(); - let updater = Updater::new( - &Arc::downgrade(&(service.client() as Arc)), - &Arc::downgrade(&sync_provider), - update_policy, - hash_fetch::Client::with_fetch(contract_client.clone(), updater_fetch, runtime.executor()), - ); - service.add_notify(updater.clone()); - // set up dependencies for rpc servers let rpc_stats = Arc::new(informant::RpcStats::default()); let secret_store = account_provider.clone(); @@ -575,7 +513,6 @@ where logger: logger.clone(), settings: Arc::new(cmd.net_settings.clone()), net_service: manage_network.clone(), - updater: updater.clone(), experimental_rpcs: cmd.experimental_rpcs, ws_address: cmd.ws_conf.address(), fetch: fetch.clone(), @@ -672,9 +609,6 @@ where } }; - client.set_exit_handler(on_client_rq); - updater.set_exit_handler(on_updater_rq); - Ok(RunningClient { inner: RunningClientInner::Full { rpc: rpc_direct, @@ -683,7 +617,6 @@ where client_service: Arc::new(service), keep_alive: Box::new(( watcher, - updater, ws_server, http_server, ipc_server, diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 163fec402..67408a904 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -17,7 +17,6 @@ order-stat = "0.1" parking_lot = "0.7" rand = "0.4" rustc-hex = "1.0" -semver = "0.9" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" @@ -54,7 +53,6 @@ ethstore = { path = "../accounts/ethstore" } fetch = { path = "../util/fetch" } keccak-hash = "0.1.2" parity-runtime = { path = "../util/runtime" } -parity-updater = { path = "../updater" } parity-version = { path = "../util/version" } rlp = { version = "0.3.0", features = ["ethereum"] } stats = { path = "../util/stats" } diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index a3dcb009f..0f06abc03 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -48,7 +48,6 @@ extern crate order_stat; extern crate parking_lot; extern crate rand; extern crate rustc_hex; -extern crate semver; extern crate serde; extern crate serde_json; extern crate tokio_timer; @@ -77,7 +76,6 @@ extern crate keccak_hash as hash; extern crate parity_bytes as bytes; extern crate parity_crypto as crypto; extern crate parity_runtime; -extern crate parity_updater as updater; extern crate parity_version as version; extern crate rlp; extern crate stats; diff --git a/rpc/src/v1/impls/parity.rs b/rpc/src/v1/impls/parity.rs index aafb2fbcc..d99ffe825 100644 --- a/rpc/src/v1/impls/parity.rs +++ b/rpc/src/v1/impls/parity.rs @@ -31,7 +31,6 @@ use ethstore::random_phrase; use jsonrpc_core::{futures::future, BoxFuture, Result}; use sync::{ManageNetwork, SyncProvider}; use types::ids::BlockId; -use updater::Service as UpdateService; use version::version_data; use v1::{ @@ -45,18 +44,17 @@ use v1::{ metadata::Metadata, traits::Parity, types::{ - block_number_to_id, BlockNumber, Bytes, CallRequest, ChainStatus, ConsensusCapability, - Histogram, LocalTransactionStatus, OperationsInfo, Peers, Receipt, RecoveredAccount, - RichHeader, RpcSettings, Transaction, TransactionStats, VersionInfo, + block_number_to_id, BlockNumber, Bytes, CallRequest, ChainStatus, Histogram, + LocalTransactionStatus, Peers, Receipt, RecoveredAccount, RichHeader, RpcSettings, + Transaction, TransactionStats, }, }; use Host; /// Parity implementation. -pub struct ParityClient { +pub struct ParityClient { client: Arc, miner: Arc, - updater: Arc, sync: Arc, net: Arc, logger: Arc, @@ -66,7 +64,7 @@ pub struct ParityClient { snapshot: Option>, } -impl ParityClient +impl ParityClient where C: BlockChainClient, { @@ -75,7 +73,6 @@ where client: Arc, miner: Arc, sync: Arc, - updater: Arc, net: Arc, logger: Arc, settings: Arc, @@ -87,7 +84,6 @@ where client, miner, sync, - updater, net, logger, settings, @@ -98,7 +94,7 @@ where } } -impl Parity for ParityClient +impl Parity for ParityClient where S: StateInfo + 'static, C: miner::BlockChainClient @@ -107,7 +103,6 @@ where + Call + 'static, M: MinerService + 'static, - U: UpdateService + 'static, { type Metadata = Metadata; @@ -330,18 +325,6 @@ where self.sync.enode().ok_or_else(errors::network_disabled) } - fn consensus_capability(&self) -> Result { - Ok(self.updater.capability().into()) - } - - fn version_info(&self) -> Result { - Ok(self.updater.version_info().into()) - } - - fn releases_info(&self) -> Result> { - Ok(self.updater.info().map(Into::into)) - } - fn chain_status(&self) -> Result { let chain_info = self.client.chain_info(); diff --git a/rpc/src/v1/impls/parity_set.rs b/rpc/src/v1/impls/parity_set.rs index 42578af91..499af25bd 100644 --- a/rpc/src/v1/impls/parity_set.rs +++ b/rpc/src/v1/impls/parity_set.rs @@ -27,13 +27,12 @@ use ethkey; use fetch::{self, Fetch}; use hash::keccak_buffer; use sync::ManageNetwork; -use updater::Service as UpdateService; use jsonrpc_core::{futures::Future, BoxFuture, Result}; use v1::{ helpers::errors, traits::ParitySet, - types::{Bytes, ReleaseInfo, Transaction}, + types::{Bytes, Transaction}, }; #[cfg(any(test, feature = "accounts"))] @@ -82,41 +81,32 @@ pub mod accounts { } /// Parity-specific rpc interface for operations altering the settings. -pub struct ParitySetClient { +pub struct ParitySetClient { client: Arc, miner: Arc, - updater: Arc, net: Arc, fetch: F, } -impl ParitySetClient +impl ParitySetClient where C: BlockChainClient + 'static, { /// Creates new `ParitySetClient` with given `Fetch`. - pub fn new( - client: &Arc, - miner: &Arc, - updater: &Arc, - net: &Arc, - fetch: F, - ) -> Self { + pub fn new(client: &Arc, miner: &Arc, net: &Arc, fetch: F) -> Self { ParitySetClient { client: client.clone(), miner: miner.clone(), - updater: updater.clone(), net: net.clone(), fetch, } } } -impl ParitySet for ParitySetClient +impl ParitySet for ParitySetClient where C: BlockChainClient + 'static, M: MinerService + 'static, - U: UpdateService + 'static, F: Fetch + 'static, { fn set_min_gas_price(&self, gas_price: U256) -> Result { @@ -239,14 +229,6 @@ where Box::new(future) } - fn upgrade_ready(&self) -> Result> { - Ok(self.updater.upgrade_ready().map(Into::into)) - } - - fn execute_upgrade(&self) -> Result { - Ok(self.updater.execute_upgrade()) - } - fn remove_transaction(&self, hash: H256) -> Result> { Ok(self .miner diff --git a/rpc/src/v1/tests/helpers/mod.rs b/rpc/src/v1/tests/helpers/mod.rs index ca39fb0ae..f4a53c481 100644 --- a/rpc/src/v1/tests/helpers/mod.rs +++ b/rpc/src/v1/tests/helpers/mod.rs @@ -19,11 +19,9 @@ mod miner_service; mod snapshot_service; mod sync_provider; -mod update_service; pub use self::{ miner_service::TestMinerService, snapshot_service::TestSnapshotService, sync_provider::{Config, TestSyncProvider}, - update_service::TestUpdater, }; diff --git a/rpc/src/v1/tests/helpers/update_service.rs b/rpc/src/v1/tests/helpers/update_service.rs deleted file mode 100644 index 8ba2b828b..000000000 --- a/rpc/src/v1/tests/helpers/update_service.rs +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . - -//! Test implementation of fetch client. - -use semver::Version; -use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; -use updater::{ - CapState, OperationsInfo, ReleaseInfo, ReleaseTrack, Service as UpdateService, VersionInfo, -}; - -/// Test implementation of fetcher. Will always return the same file. -#[derive(Default)] -pub struct TestUpdater { - updated: AtomicBool, - current_block: AtomicUsize, -} - -impl TestUpdater { - /// Update the (faked) current block. - pub fn set_current_block(&self, n: usize) { - self.current_block.store(n, Ordering::Relaxed); - } - - /// Update the (faked) current block. - pub fn set_updated(&self, v: bool) { - self.updated.store(v, Ordering::Relaxed); - } -} - -impl UpdateService for TestUpdater { - fn capability(&self) -> CapState { - if self.updated.load(Ordering::Relaxed) { - CapState::Capable - } else { - if self.current_block.load(Ordering::Relaxed) < 15100 { - CapState::CapableUntil(15100) - } else { - CapState::IncapableSince(15100) - } - } - } - - fn upgrade_ready(&self) -> Option { - if self.updated.load(Ordering::Relaxed) { - None - } else { - self.info().map(|i| i.track) - } - } - - fn execute_upgrade(&self) -> bool { - if self.updated.load(Ordering::Relaxed) { - false - } else { - self.updated.store(true, Ordering::Relaxed); - true - } - } - - fn version_info(&self) -> VersionInfo { - VersionInfo { - track: ReleaseTrack::Beta, - version: Version { - major: 1, - minor: 5, - patch: 0, - build: vec![], - pre: vec![], - }, - hash: 150.into(), - } - } - - fn info(&self) -> Option { - Some(OperationsInfo { - fork: 15100, - this_fork: Some(15000), - track: ReleaseInfo { - version: VersionInfo { - track: ReleaseTrack::Beta, - version: Version { - major: 1, - minor: 5, - patch: 1, - build: vec![], - pre: vec![], - }, - hash: 151.into(), - }, - is_critical: true, - fork: 15100, - binary: Some(1510.into()), - }, - minor: None, - }) - } -} diff --git a/rpc/src/v1/tests/mocked/parity.rs b/rpc/src/v1/tests/mocked/parity.rs index 223ba43b4..f654a0450 100644 --- a/rpc/src/v1/tests/mocked/parity.rs +++ b/rpc/src/v1/tests/mocked/parity.rs @@ -28,18 +28,17 @@ use jsonrpc_core::IoHandler; use v1::{ helpers::{external_signer::SignerService, NetworkSettings}, metadata::Metadata, - tests::helpers::{Config, TestMinerService, TestSyncProvider, TestUpdater}, + tests::helpers::{Config, TestMinerService, TestSyncProvider}, Parity, ParityClient, }; use Host; -pub type TestParityClient = ParityClient; +pub type TestParityClient = ParityClient; pub struct Dependencies { pub miner: Arc, pub client: Arc, pub sync: Arc, - pub updater: Arc, pub logger: Arc, pub settings: Arc, pub network: Arc, @@ -55,7 +54,6 @@ impl Dependencies { network_id: 3, num_peers: 120, })), - updater: Arc::new(TestUpdater::default()), logger: Arc::new(RotatingLogger::new("rpc=trace".to_owned())), settings: Arc::new(NetworkSettings { name: "mynode".to_owned(), @@ -76,7 +74,6 @@ impl Dependencies { self.client.clone(), self.miner.clone(), self.sync.clone(), - self.updater.clone(), self.network.clone(), self.logger.clone(), self.settings.clone(), @@ -99,51 +96,6 @@ impl Dependencies { } } -#[test] -fn rpc_parity_consensus_capability() { - let deps = Dependencies::new(); - let io = deps.default_client(); - - let request = - r#"{"jsonrpc": "2.0", "method": "parity_consensusCapability", "params": [], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":{"capableUntil":15100},"id":1}"#; - assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); - - deps.updater.set_current_block(15101); - - let request = - r#"{"jsonrpc": "2.0", "method": "parity_consensusCapability", "params": [], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":{"incapableSince":15100},"id":1}"#; - assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); - - deps.updater.set_updated(true); - - let request = - r#"{"jsonrpc": "2.0", "method": "parity_consensusCapability", "params": [], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":"capable","id":1}"#; - assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); -} - -#[test] -fn rpc_parity_version_info() { - let deps = Dependencies::new(); - let io = deps.default_client(); - - let request = r#"{"jsonrpc": "2.0", "method": "parity_versionInfo", "params": [], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":{"hash":"0x0000000000000000000000000000000000000096","track":"beta","version":{"major":1,"minor":5,"patch":0}},"id":1}"#; - assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); -} - -#[test] -fn rpc_parity_releases_info() { - let deps = Dependencies::new(); - let io = deps.default_client(); - - let request = r#"{"jsonrpc": "2.0", "method": "parity_releasesInfo", "params": [], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":{"fork":15100,"minor":null,"this_fork":15000,"track":{"binary":"0x00000000000000000000000000000000000000000000000000000000000005e6","fork":15100,"is_critical":true,"version":{"hash":"0x0000000000000000000000000000000000000097","track":"beta","version":{"major":1,"minor":5,"patch":1}}}},"id":1}"#; - assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); -} - #[test] fn rpc_parity_extra_data() { let deps = Dependencies::new(); diff --git a/rpc/src/v1/tests/mocked/parity_set.rs b/rpc/src/v1/tests/mocked/parity_set.rs index 974f19ba1..2d822896f 100644 --- a/rpc/src/v1/tests/mocked/parity_set.rs +++ b/rpc/src/v1/tests/mocked/parity_set.rs @@ -23,10 +23,7 @@ use sync::ManageNetwork; use super::manage_network::TestManageNetwork; use jsonrpc_core::IoHandler; -use v1::{ - tests::helpers::{TestMinerService, TestUpdater}, - ParitySet, ParitySetClient, -}; +use v1::{tests::helpers::TestMinerService, ParitySet, ParitySetClient}; use fake_fetch::FakeFetch; @@ -42,75 +39,30 @@ fn network_service() -> Arc { Arc::new(TestManageNetwork) } -fn updater_service() -> Arc { - Arc::new(TestUpdater::default()) -} - pub type TestParitySetClient = - ParitySetClient>; + ParitySetClient>; fn parity_set_client( client: &Arc, miner: &Arc, - updater: &Arc, net: &Arc, ) -> TestParitySetClient { ParitySetClient::new( client, miner, - updater, &(net.clone() as Arc), FakeFetch::new(Some(1)), ) } -#[test] -fn rpc_parity_execute_upgrade() { - let miner = miner_service(); - let client = client_service(); - let network = network_service(); - let updater = updater_service(); - let mut io = IoHandler::new(); - io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate()); - - let request = r#"{"jsonrpc": "2.0", "method": "parity_executeUpgrade", "params": [], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; - assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); - - let request = r#"{"jsonrpc": "2.0", "method": "parity_executeUpgrade", "params": [], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":false,"id":1}"#; - assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); -} - -#[test] -fn rpc_parity_upgrade_ready() { - let miner = miner_service(); - let client = client_service(); - let network = network_service(); - let updater = updater_service(); - let mut io = IoHandler::new(); - io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate()); - - let request = r#"{"jsonrpc": "2.0", "method": "parity_upgradeReady", "params": [], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":{"binary":"0x00000000000000000000000000000000000000000000000000000000000005e6","fork":15100,"is_critical":true,"version":{"hash":"0x0000000000000000000000000000000000000097","track":"beta","version":{"major":1,"minor":5,"patch":1}}},"id":1}"#; - assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); - - updater.set_updated(true); - - let request = r#"{"jsonrpc": "2.0", "method": "parity_upgradeReady", "params": [], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#; - assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); -} - #[test] fn rpc_parity_set_min_gas_price() { let miner = miner_service(); let client = client_service(); let network = network_service(); - let updater = updater_service(); let mut io = IoHandler::new(); - io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate()); + io.extend_with(parity_set_client(&client, &miner, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "parity_setMinGasPrice", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; @@ -125,10 +77,9 @@ fn rpc_parity_set_min_gas_price_with_automated_calibration_enabled() { let client = client_service(); let network = network_service(); - let updater = updater_service(); let mut io = IoHandler::new(); - io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate()); + io.extend_with(parity_set_client(&client, &miner, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "parity_setMinGasPrice", "params":["0xdeadbeef"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","error":{"code":-32000,"message":"Can't update fixed gas price while automatic gas calibration is enabled."},"id":1}"#; @@ -141,10 +92,9 @@ fn rpc_parity_set_gas_floor_target() { let miner = miner_service(); let client = client_service(); let network = network_service(); - let updater = updater_service(); let mut io = IoHandler::new(); - io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate()); + io.extend_with(parity_set_client(&client, &miner, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "parity_setGasFloorTarget", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; @@ -161,10 +111,9 @@ fn rpc_parity_set_extra_data() { let miner = miner_service(); let client = client_service(); let network = network_service(); - let updater = updater_service(); let mut io = IoHandler::new(); - io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate()); + io.extend_with(parity_set_client(&client, &miner, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "parity_setExtraData", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; @@ -183,9 +132,9 @@ fn rpc_parity_set_author() { let miner = miner_service(); let client = client_service(); let network = network_service(); - let updater = updater_service(); + let mut io = IoHandler::new(); - io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate()); + io.extend_with(parity_set_client(&client, &miner, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "parity_setAuthor", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; @@ -202,9 +151,9 @@ fn rpc_parity_set_transactions_limit() { let miner = miner_service(); let client = client_service(); let network = network_service(); - let updater = updater_service(); + let mut io = IoHandler::new(); - io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate()); + io.extend_with(parity_set_client(&client, &miner, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "parity_setTransactionsLimit", "params":[10240240], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":false,"id":1}"#; @@ -217,9 +166,9 @@ fn rpc_parity_set_hash_content() { let miner = miner_service(); let client = client_service(); let network = network_service(); - let updater = updater_service(); + let mut io = IoHandler::new(); - io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate()); + io.extend_with(parity_set_client(&client, &miner, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "parity_hashContent", "params":["https://parity.io/assets/images/ethcore-black-horizontal.png"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"0x2be00befcf008bc0e7d9cdefc194db9c75352e8632f48498b5a6bfce9f02c88e","id":1}"#; @@ -234,9 +183,9 @@ fn rpc_parity_remove_transaction() { let miner = miner_service(); let client = client_service(); let network = network_service(); - let updater = updater_service(); + let mut io = IoHandler::new(); - io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate()); + io.extend_with(parity_set_client(&client, &miner, &network).to_delegate()); let tx = Transaction { nonce: 1.into(), diff --git a/rpc/src/v1/traits/parity.rs b/rpc/src/v1/traits/parity.rs index ca06f0029..65bc8568a 100644 --- a/rpc/src/v1/traits/parity.rs +++ b/rpc/src/v1/traits/parity.rs @@ -22,9 +22,8 @@ use ethereum_types::{H160, H256, H512, H64, U256, U64}; use jsonrpc_core::{BoxFuture, Result}; use jsonrpc_derive::rpc; use v1::types::{ - BlockNumber, Bytes, CallRequest, ChainStatus, ConsensusCapability, Histogram, - LocalTransactionStatus, OperationsInfo, Peers, Receipt, RecoveredAccount, RichHeader, - RpcSettings, Transaction, TransactionStats, VersionInfo, + BlockNumber, Bytes, CallRequest, ChainStatus, Histogram, LocalTransactionStatus, Peers, + Receipt, RecoveredAccount, RichHeader, RpcSettings, Transaction, TransactionStats, }; /// Parity-specific rpc interface. @@ -177,18 +176,6 @@ pub trait Parity { #[rpc(name = "parity_enode")] fn enode(&self) -> Result; - /// Returns information on current consensus capability. - #[rpc(name = "parity_consensusCapability")] - fn consensus_capability(&self) -> Result; - - /// Get our version information in a nice object. - #[rpc(name = "parity_versionInfo")] - fn version_info(&self) -> Result; - - /// Get information concerning the latest releases if available. - #[rpc(name = "parity_releasesInfo")] - fn releases_info(&self) -> Result>; - /// Get the current chain status. #[rpc(name = "parity_chainStatus")] fn chain_status(&self) -> Result; diff --git a/rpc/src/v1/traits/parity_set.rs b/rpc/src/v1/traits/parity_set.rs index ce4dc19cf..d6ffb8a98 100644 --- a/rpc/src/v1/traits/parity_set.rs +++ b/rpc/src/v1/traits/parity_set.rs @@ -20,7 +20,7 @@ use ethereum_types::{H160, H256, U256}; use jsonrpc_core::{BoxFuture, Result}; use jsonrpc_derive::rpc; -use v1::types::{Bytes, ReleaseInfo, Transaction}; +use v1::types::{Bytes, Transaction}; /// Parity-specific rpc interface for operations altering the account-related settings. #[rpc(server)] @@ -105,14 +105,6 @@ pub trait ParitySet { #[rpc(name = "parity_hashContent")] fn hash_content(&self, _: String) -> BoxFuture; - /// Is there a release ready for install? - #[rpc(name = "parity_upgradeReady")] - fn upgrade_ready(&self) -> Result>; - - /// Execute a release which is ready according to upgrade_ready(). - #[rpc(name = "parity_executeUpgrade")] - fn execute_upgrade(&self) -> Result; - /// Removes transaction from transaction queue. /// Makes sense only for transactions that were not propagated to other peers yet /// like scheduled transactions or transactions in future. diff --git a/rpc/src/v1/types/consensus_status.rs b/rpc/src/v1/types/consensus_status.rs deleted file mode 100644 index be6fbacad..000000000 --- a/rpc/src/v1/types/consensus_status.rs +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . - -use ethereum_types::{H160, H256}; -use semver; -use updater::{self, CapState}; - -/// Capability info -#[derive(Debug, PartialEq, Serialize)] -#[serde(rename_all = "camelCase")] -pub enum ConsensusCapability { - /// Unknown. - Unknown, - /// Capable of consensus indefinitely. - Capable, - /// Capable of consensus up until a definite block. - CapableUntil(u64), - /// Incapable of consensus since a particular block. - IncapableSince(u64), -} - -impl Into for CapState { - fn into(self) -> ConsensusCapability { - match self { - CapState::Unknown => ConsensusCapability::Unknown, - CapState::Capable => ConsensusCapability::Capable, - CapState::CapableUntil(n) => ConsensusCapability::CapableUntil(n), - CapState::IncapableSince(n) => ConsensusCapability::IncapableSince(n), - } - } -} - -/// A release's track. -#[derive(Debug, PartialEq, Serialize)] -#[serde(rename_all = "camelCase")] -pub enum ReleaseTrack { - /// Stable track. - Stable, - /// Beta track. - Beta, - /// Nightly track. - Nightly, - /// Testing track. - Testing, - /// No known track. - #[serde(rename = "null")] - Unknown, -} - -impl Into for updater::ReleaseTrack { - fn into(self) -> ReleaseTrack { - match self { - updater::ReleaseTrack::Stable => ReleaseTrack::Stable, - updater::ReleaseTrack::Beta => ReleaseTrack::Beta, - updater::ReleaseTrack::Nightly => ReleaseTrack::Nightly, - updater::ReleaseTrack::Testing => ReleaseTrack::Testing, - updater::ReleaseTrack::Unknown => ReleaseTrack::Unknown, - } - } -} - -/// Semantic version. -#[derive(Debug, PartialEq, Serialize)] -pub struct Version { - /// Major part. - major: u64, - /// Minor part. - minor: u64, - /// Patch part. - patch: u64, -} - -impl Into for semver::Version { - fn into(self) -> Version { - Version { - major: self.major, - minor: self.minor, - patch: self.patch, - } - } -} - -/// Version information of a particular release. -#[derive(Debug, PartialEq, Serialize)] -pub struct VersionInfo { - /// The track on which it was released. - pub track: ReleaseTrack, - /// The version. - pub version: Version, - /// The (SHA1?) 160-bit hash of this build's code base. - pub hash: H160, -} - -impl Into for updater::VersionInfo { - fn into(self) -> VersionInfo { - VersionInfo { - track: self.track.into(), - version: self.version.into(), - hash: self.hash, - } - } -} - -/// Information regarding a particular release of Parity -#[derive(Debug, PartialEq, Serialize)] -pub struct ReleaseInfo { - /// Information on the version. - pub version: VersionInfo, - /// Does this release contain critical security updates? - pub is_critical: bool, - /// The latest fork that this release can handle. - pub fork: u64, - /// Our platform's binary, if known. - pub binary: Option, -} - -impl Into for updater::ReleaseInfo { - fn into(self) -> ReleaseInfo { - ReleaseInfo { - version: self.version.into(), - is_critical: self.is_critical, - fork: self.fork, - binary: self.binary.map(Into::into), - } - } -} - -/// Information on our operations environment. -#[derive(Debug, PartialEq, Serialize)] -pub struct OperationsInfo { - /// Our blockchain's latest fork. - pub fork: u64, - /// Last fork our client supports, if known. - pub this_fork: Option, - /// Information on our track's latest release. - pub track: ReleaseInfo, - /// Information on our minor version's latest release. - pub minor: Option, -} - -impl Into for updater::OperationsInfo { - fn into(self) -> OperationsInfo { - OperationsInfo { - fork: self.fork, - this_fork: self.this_fork, - track: self.track.into(), - minor: self.minor.map(Into::into), - } - } -} diff --git a/rpc/src/v1/types/mod.rs b/rpc/src/v1/types/mod.rs index 55cb8d270..dd95d0388 100644 --- a/rpc/src/v1/types/mod.rs +++ b/rpc/src/v1/types/mod.rs @@ -25,7 +25,6 @@ mod block_number; mod bytes; mod call_request; mod confirmations; -mod consensus_status; mod derivation; mod eip191; mod filter; @@ -59,7 +58,6 @@ pub use self::{ ConfirmationResponseWithToken, DecryptRequest, EIP191SignRequest, Either, EthSignRequest, TransactionModification, }, - consensus_status::*, derivation::{Derive, DeriveHash, DeriveHierarchical}, eip191::{EIP191Version, PresignedTransaction}, filter::{Filter, FilterChanges}, diff --git a/updater/Cargo.toml b/updater/Cargo.toml deleted file mode 100644 index dd3417f88..000000000 --- a/updater/Cargo.toml +++ /dev/null @@ -1,37 +0,0 @@ -[package] -description = "Parity Updater Service." -name = "parity-updater" -version = "1.12.0" -license = "GPL-3.0" -authors = ["Parity Technologies "] - -[dependencies] -common-types = { path = "../ethcore/types" } -ethabi = "6.0" -ethabi-contract = "6.0" -ethabi-derive = "6.0" -ethcore = { path = "../ethcore" } -ethcore-sync = { path = "../ethcore/sync" } -ethereum-types = "0.4" -keccak-hash = "0.1" -lazy_static = "1.0" -log = "0.4" -parity-bytes = "0.1" -parity-hash-fetch = { path = "hash-fetch" } -parity-path = "0.1" -parity-version = { path = "../util/version" } -parking_lot = "0.7" -rand = "0.4" -semver = "0.9" -target_info = "0.1" - -[dev-dependencies] -ethcore = { path = "../ethcore", features = ["test-helpers"] } -tempdir = "0.3" -matches = "0.1" - -[features] -# hardcode version number 1.3.7 of parity to force an update -# in order to manually test that parity fall-over to the local version -# in case of invalid or deprecated command line arguments are entered -test-updater = [] diff --git a/updater/hash-fetch/Cargo.toml b/updater/hash-fetch/Cargo.toml deleted file mode 100644 index 1c5477c06..000000000 --- a/updater/hash-fetch/Cargo.toml +++ /dev/null @@ -1,29 +0,0 @@ -[package] -description = "Fetching hash-addressed content." -homepage = "http://parity.io" -license = "GPL-3.0" -name = "parity-hash-fetch" -version = "1.12.0" -authors = ["Parity Technologies "] - -[dependencies] -futures = "0.1" -log = "0.4" -mime = "0.3" -mime_guess = "2.0.0-alpha.2" -rand = "0.4" -rustc-hex = "1.0" -fetch = { path = "../../util/fetch" } -parity-bytes = "0.1" -ethereum-types = "0.4" -parity-runtime = { path = "../../util/runtime" } -keccak-hash = "0.1" -registrar = { path = "../../util/registrar" } - -ethabi = "6.0" -ethabi-derive = "6.0" -ethabi-contract = "6.0" - -[dev-dependencies] -parking_lot = "0.7" -fake-fetch = { path = "../../util/fake-fetch" } diff --git a/updater/hash-fetch/res/urlhint.json b/updater/hash-fetch/res/urlhint.json deleted file mode 100644 index 629f166bb..000000000 --- a/updater/hash-fetch/res/urlhint.json +++ /dev/null @@ -1,6 +0,0 @@ -[ - {"constant":false,"inputs":[{"name":"_content","type":"bytes32"},{"name":"_url","type":"string"}],"name":"hintURL","outputs":[],"type":"function"}, - {"constant":false,"inputs":[{"name":"_content","type":"bytes32"},{"name":"_accountSlashRepo","type":"string"},{"name":"_commit","type":"bytes20"}],"name":"hint","outputs":[],"type":"function"}, - {"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"entries","outputs":[{"name":"accountSlashRepo","type":"string"},{"name":"commit","type":"bytes20"},{"name":"owner","type":"address"}],"type":"function"}, - {"constant":false,"inputs":[{"name":"_content","type":"bytes32"}],"name":"unhint","outputs":[],"type":"function"} -] diff --git a/updater/hash-fetch/src/client.rs b/updater/hash-fetch/src/client.rs deleted file mode 100644 index 87ee75b21..000000000 --- a/updater/hash-fetch/src/client.rs +++ /dev/null @@ -1,327 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . - -//! Hash-addressed content resolver & fetcher. - -use std::{fs, io, io::Write, path::PathBuf, sync::Arc}; - -use ethereum_types::H256; -use fetch::{self, Fetch}; -use futures::{Future, IntoFuture}; -use hash::keccak_buffer; -use parity_runtime::Executor; -use registrar::{Asynchronous, RegistrarClient}; -use urlhint::{URLHint, URLHintContract, URLHintResult}; - -/// API for fetching by hash. -pub trait HashFetch: Send + Sync + 'static { - /// Fetch hash-addressed content. - /// Parameters: - /// 1. `hash` - content hash - /// 2. `on_done` - callback function invoked when the content is ready (or there was error during fetch) - /// - /// This function may fail immediately when fetch cannot be initialized or content cannot be resolved. - fn fetch( - &self, - hash: H256, - abort: fetch::Abort, - on_done: Box) + Send>, - ); -} - -/// Hash-fetching error. -#[derive(Debug)] -pub enum Error { - /// Hash could not be resolved to a valid content address. - NoResolution, - /// Downloaded content hash does not match. - HashMismatch { - /// Expected hash - expected: H256, - /// Computed hash - got: H256, - }, - /// Server didn't respond with OK status. - InvalidStatus, - /// IO Error while validating hash. - IO(io::Error), - /// Error during fetch. - Fetch(fetch::Error), -} - -#[cfg(test)] -impl PartialEq for Error { - fn eq(&self, other: &Self) -> bool { - use Error::*; - match (self, other) { - ( - &HashMismatch { expected, got }, - &HashMismatch { - expected: e, - got: g, - }, - ) => expected == e && got == g, - (&NoResolution, &NoResolution) => true, - (&InvalidStatus, &InvalidStatus) => true, - (&IO(_), &IO(_)) => true, - (&Fetch(_), &Fetch(_)) => true, - _ => false, - } - } -} - -impl From for Error { - fn from(error: fetch::Error) -> Self { - Error::Fetch(error) - } -} - -impl From for Error { - fn from(error: io::Error) -> Self { - Error::IO(error) - } -} - -fn validate_hash(path: PathBuf, hash: H256, body: fetch::BodyReader) -> Result { - // Read the response - let mut reader = io::BufReader::new(body); - let mut writer = io::BufWriter::new(fs::File::create(&path)?); - io::copy(&mut reader, &mut writer)?; - writer.flush()?; - - // And validate the hash - let mut file_reader = io::BufReader::new(fs::File::open(&path)?); - let content_hash = keccak_buffer(&mut file_reader)?; - if content_hash != hash { - Err(Error::HashMismatch { - got: content_hash, - expected: hash, - }) - } else { - Ok(path) - } -} - -/// Default Hash-fetching client using on-chain contract to resolve hashes to URLs. -pub struct Client { - contract: URLHintContract, - fetch: F, - executor: Executor, - random_path: Arc PathBuf + Sync + Send>, -} - -impl Client { - /// Creates new instance of the `Client` given on-chain contract client, fetch service and task runner. - pub fn with_fetch( - contract: Arc>, - fetch: F, - executor: Executor, - ) -> Self { - Client { - contract: URLHintContract::new(contract), - fetch: fetch, - executor: executor, - random_path: Arc::new(random_temp_path), - } - } -} - -impl HashFetch for Client { - fn fetch( - &self, - hash: H256, - abort: fetch::Abort, - on_done: Box) + Send>, - ) { - debug!(target: "fetch", "Fetching: {:?}", hash); - - let random_path = self.random_path.clone(); - let remote_fetch = self.fetch.clone(); - let future = self - .contract - .resolve(hash) - .map_err(|e| { - warn!("Error resolving URL: {}", e); - Error::NoResolution - }) - .and_then(|maybe_url| maybe_url.ok_or(Error::NoResolution)) - .map(|content| match content { - URLHintResult::Dapp(dapp) => dapp.url(), - URLHintResult::GithubDapp(content) => content.url, - URLHintResult::Content(content) => content.url, - }) - .into_future() - .and_then(move |url| { - debug!(target: "fetch", "Resolved {:?} to {:?}. Fetching...", hash, url); - remote_fetch.get(&url, abort).from_err() - }) - .and_then(move |response| { - if !response.is_success() { - Err(Error::InvalidStatus) - } else { - Ok(response) - } - }) - .and_then(move |response| { - debug!(target: "fetch", "Content fetched, validating hash ({:?})", hash); - let path = random_path(); - let res = validate_hash(path.clone(), hash, fetch::BodyReader::new(response)); - if let Err(ref err) = res { - trace!(target: "fetch", "Error: {:?}", err); - // Remove temporary file in case of error - let _ = fs::remove_file(&path); - } - res - }) - .then(move |res| { - on_done(res); - Ok(()) as Result<(), ()> - }); - - self.executor.spawn(future); - } -} - -fn random_temp_path() -> PathBuf { - use rand::Rng; - use std::env; - - let mut rng = ::rand::OsRng::new().expect("Reliable random source is required to work."); - let file: String = rng.gen_ascii_chars().take(12).collect(); - - let mut path = env::temp_dir(); - path.push(file); - path -} - -#[cfg(test)] -mod tests { - use super::{random_temp_path, Client, Error, HashFetch}; - use fake_fetch::FakeFetch; - use parity_runtime::Executor; - use parking_lot::Mutex; - use rustc_hex::FromHex; - use std::sync::{mpsc, Arc}; - use urlhint::tests::{FakeRegistrar, URLHINT}; - - fn registrar() -> FakeRegistrar { - let mut registrar = FakeRegistrar::new(); - registrar.responses = Mutex::new(vec![ - Ok(format!("000000000000000000000000{}", URLHINT).from_hex().unwrap()), - Ok("00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000deadcafebeefbeefcafedeaddeedfeedffffffff000000000000000000000000000000000000000000000000000000000000003c68747470733a2f2f7061726974792e696f2f6173736574732f696d616765732f657468636f72652d626c61636b2d686f72697a6f6e74616c2e706e6700000000".from_hex().unwrap()), - ]); - registrar - } - - #[test] - fn should_return_error_if_hash_not_found() { - // given - let contract = Arc::new(FakeRegistrar::new()); - let fetch = FakeFetch::new(None::); - let client = Client::with_fetch(contract.clone(), fetch, Executor::new_sync()); - - // when - let (tx, rx) = mpsc::channel(); - client.fetch( - 2.into(), - Default::default(), - Box::new(move |result| { - tx.send(result).unwrap(); - }), - ); - - // then - let result = rx.recv().unwrap(); - assert_eq!(result.unwrap_err(), Error::NoResolution); - } - - #[test] - fn should_return_error_if_response_is_not_successful() { - // given - let registrar = Arc::new(registrar()); - let fetch = FakeFetch::new(None::); - let client = Client::with_fetch(registrar.clone(), fetch, Executor::new_sync()); - - // when - let (tx, rx) = mpsc::channel(); - client.fetch( - 2.into(), - Default::default(), - Box::new(move |result| { - tx.send(result).unwrap(); - }), - ); - - // then - let result = rx.recv().unwrap(); - assert_eq!(result.unwrap_err(), Error::InvalidStatus); - } - - #[test] - fn should_return_hash_mismatch() { - // given - let registrar = Arc::new(registrar()); - let fetch = FakeFetch::new(Some(1)); - let mut client = Client::with_fetch(registrar.clone(), fetch, Executor::new_sync()); - let path = random_temp_path(); - let path2 = path.clone(); - client.random_path = Arc::new(move || path2.clone()); - - // when - let (tx, rx) = mpsc::channel(); - client.fetch( - 2.into(), - Default::default(), - Box::new(move |result| { - tx.send(result).unwrap(); - }), - ); - - // then - let result = rx.recv().unwrap(); - let hash = "0x2be00befcf008bc0e7d9cdefc194db9c75352e8632f48498b5a6bfce9f02c88e".into(); - assert_eq!( - result.unwrap_err(), - Error::HashMismatch { - expected: 2.into(), - got: hash - } - ); - assert!(!path.exists(), "Temporary file should be removed."); - } - - #[test] - fn should_return_path_if_hash_matches() { - // given - let registrar = Arc::new(registrar()); - let fetch = FakeFetch::new(Some(1)); - let client = Client::with_fetch(registrar.clone(), fetch, Executor::new_sync()); - - // when - let (tx, rx) = mpsc::channel(); - client.fetch( - "0x2be00befcf008bc0e7d9cdefc194db9c75352e8632f48498b5a6bfce9f02c88e".into(), - Default::default(), - Box::new(move |result| { - tx.send(result).unwrap(); - }), - ); - - // then - let result = rx.recv().unwrap(); - assert!(result.is_ok(), "Should return path, got: {:?}", result); - } -} diff --git a/updater/hash-fetch/src/lib.rs b/updater/hash-fetch/src/lib.rs deleted file mode 100644 index b502ea523..000000000 --- a/updater/hash-fetch/src/lib.rs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . - -//! Hash-addressed content resolver & fetcher. - -#![warn(missing_docs)] - -#[macro_use] -extern crate log; - -extern crate ethabi; -extern crate ethereum_types; -extern crate futures; -extern crate keccak_hash as hash; -extern crate mime; -extern crate mime_guess; -extern crate parity_bytes as bytes; -extern crate parity_runtime; -extern crate rand; -extern crate registrar; -extern crate rustc_hex; - -pub extern crate fetch; - -#[macro_use] -extern crate ethabi_derive; -#[macro_use] -extern crate ethabi_contract; -#[cfg(test)] -extern crate fake_fetch; -#[cfg(test)] -extern crate parking_lot; - -mod client; - -pub mod urlhint; - -pub use client::{Client, Error, HashFetch}; -pub use fetch::Abort; diff --git a/updater/hash-fetch/src/urlhint.rs b/updater/hash-fetch/src/urlhint.rs deleted file mode 100644 index 5dcd446b3..000000000 --- a/updater/hash-fetch/src/urlhint.rs +++ /dev/null @@ -1,395 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . - -//! URLHint Contract - -use mime::{self, Mime}; -use mime_guess; -use rustc_hex::ToHex; -use std::sync::Arc; - -use ethereum_types::{Address, H256}; -use futures::{future, future::Either, Future}; -use registrar::{Asynchronous, Registrar, RegistrarClient}; - -use_contract!(urlhint, "res/urlhint.json"); - -const COMMIT_LEN: usize = 20; -const GITHUB_HINT: &'static str = "githubhint"; -/// GithubHint entries with commit set as `0x0..01` should be treated -/// as Github Dapp, downloadable zip files, than can be extracted, containing -/// the manifest.json file along with the dapp -static GITHUB_DAPP_COMMIT: &[u8; COMMIT_LEN] = - &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]; - -/// Github-hosted dapp. -#[derive(Debug, PartialEq)] -pub struct GithubApp { - /// Github Account - pub account: String, - /// Github Repository - pub repo: String, - /// Commit on Github - pub commit: [u8; COMMIT_LEN], - /// Dapp owner address - pub owner: Address, -} - -impl GithubApp { - /// Returns URL of this Github-hosted dapp package. - pub fn url(&self) -> String { - // Since https fetcher doesn't support redirections we use direct link - // format!("https://github.com/{}/{}/archive/{}.zip", self.account, self.repo, self.commit.to_hex()) - format!( - "https://codeload.github.com/{}/{}/zip/{}", - self.account, - self.repo, - self.commit.to_hex() - ) - } - - fn commit(bytes: &[u8]) -> Option<[u8; COMMIT_LEN]> { - if bytes.len() < COMMIT_LEN { - return None; - } - - let mut commit = [0; COMMIT_LEN]; - for i in 0..COMMIT_LEN { - commit[i] = bytes[i]; - } - - Some(commit) - } -} - -/// Hash-Addressed Content -#[derive(Debug, PartialEq)] -pub struct Content { - /// URL of the content - pub url: String, - /// MIME type of the content - pub mime: Mime, - /// Content owner address - pub owner: Address, -} - -/// Result of resolving id to URL -#[derive(Debug, PartialEq)] -pub enum URLHintResult { - /// Dapp - Dapp(GithubApp), - /// GithubDapp - GithubDapp(Content), - /// Content - Content(Content), -} - -/// URLHint Contract interface -pub trait URLHint: Send + Sync { - /// Resolves given id to registrar entry. - fn resolve( - &self, - id: H256, - ) -> Box, Error = String> + Send>; -} - -/// `URLHintContract` API -pub struct URLHintContract { - registrar: Registrar, - client: Arc>, -} - -impl URLHintContract { - /// Creates new `URLHintContract` - pub fn new(client: Arc>) -> Self { - URLHintContract { - registrar: Registrar::new(client.clone()), - client: client, - } - } -} - -fn get_urlhint_content(account_slash_repo: String, owner: Address) -> Content { - let mime = guess_mime_type(&account_slash_repo).unwrap_or(mime::APPLICATION_JSON); - Content { - url: account_slash_repo, - mime, - owner, - } -} - -fn decode_urlhint_output(output: (String, [u8; 20], Address)) -> Option { - let (account_slash_repo, commit, owner) = output; - - if owner == Address::default() { - return None; - } - - let commit = GithubApp::commit(&commit); - - if commit == Some(Default::default()) { - let content = get_urlhint_content(account_slash_repo, owner); - return Some(URLHintResult::Content(content)); - } - - if commit == Some(*GITHUB_DAPP_COMMIT) { - let content = get_urlhint_content(account_slash_repo, owner); - return Some(URLHintResult::GithubDapp(content)); - } - - let (account, repo) = { - let mut it = account_slash_repo.split('/'); - match (it.next(), it.next()) { - (Some(account), Some(repo)) => (account.into(), repo.into()), - _ => return None, - } - }; - - commit.map(|commit| { - URLHintResult::Dapp(GithubApp { - account: account, - repo: repo, - commit: commit, - owner: owner, - }) - }) -} - -impl URLHint for URLHintContract { - fn resolve( - &self, - id: H256, - ) -> Box, Error = String> + Send> { - let client = self.client.clone(); - - let future = self - .registrar - .get_address(GITHUB_HINT) - .and_then(move |addr| { - if !addr.is_zero() { - let data = urlhint::functions::entries::encode_input(id); - let result = client - .call_contract(addr, data) - .and_then(move |output| { - urlhint::functions::entries::decode_output(&output) - .map_err(|e| e.to_string()) - }) - .map(decode_urlhint_output); - Either::B(result) - } else { - Either::A(future::ok(None)) - } - }); - Box::new(future) - } -} - -fn guess_mime_type(url: &str) -> Option { - const CONTENT_TYPE: &'static str = "content-type="; - - let mut it = url.split('#'); - // skip url - let url = it.next(); - // get meta headers - let metas = it.next(); - if let Some(metas) = metas { - for meta in metas.split('&') { - let meta = meta.to_lowercase(); - if meta.starts_with(CONTENT_TYPE) { - return meta[CONTENT_TYPE.len()..].parse().ok(); - } - } - } - url.and_then(|url| url.split('.').last()) - .and_then(|extension| mime_guess::from_ext(extension).first()) -} - -#[cfg(test)] -pub mod tests { - use rustc_hex::FromHex; - use std::{str::FromStr, sync::Arc}; - - use futures::{Future, IntoFuture}; - - use super::{guess_mime_type, *}; - use bytes::{Bytes, ToPretty}; - use ethereum_types::Address; - use parking_lot::Mutex; - - pub struct FakeRegistrar { - pub calls: Arc>>, - pub responses: Mutex>>, - } - - pub const REGISTRAR: &'static str = "8e4e9b13d4b45cb0befc93c3061b1408f67316b2"; - pub const URLHINT: &'static str = "deadbeefcafe0000000000000000000000000000"; - - impl FakeRegistrar { - pub fn new() -> Self { - FakeRegistrar { - calls: Arc::new(Mutex::new(Vec::new())), - responses: Mutex::new(vec![ - Ok(format!("000000000000000000000000{}", URLHINT) - .from_hex() - .unwrap()), - Ok(Vec::new()), - ]), - } - } - } - - impl RegistrarClient for FakeRegistrar { - type Call = Asynchronous; - - fn registrar_address(&self) -> Result { - Ok(REGISTRAR.parse().unwrap()) - } - - fn call_contract(&self, address: Address, data: Bytes) -> Self::Call { - self.calls.lock().push((address.to_hex(), data.to_hex())); - let res = self.responses.lock().remove(0); - Box::new(res.into_future()) - } - } - - #[test] - fn should_call_registrar_and_urlhint_contracts() { - // given - let registrar = FakeRegistrar::new(); - let resolve_result = { - use ethabi::{encode, Token}; - encode(&[ - Token::String(String::new()), - Token::FixedBytes(vec![0; 20]), - Token::Address([0; 20].into()), - ]) - }; - registrar.responses.lock()[1] = Ok(resolve_result); - - let calls = registrar.calls.clone(); - let urlhint = URLHintContract::new(Arc::new(registrar)); - - // when - let res = urlhint.resolve("test".as_bytes().into()).wait().unwrap(); - let calls = calls.lock(); - let call0 = calls.get(0).expect("Registrar resolve called"); - let call1 = calls.get(1).expect("URLHint Resolve called"); - - // then - assert!(res.is_none()); - assert_eq!(call0.0, REGISTRAR); - assert_eq!(call0.1, - "6795dbcd058740ee9a5a3fb9f1cfa10752baec87e09cc45cd7027fd54708271aca300c75000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000014100000000000000000000000000000000000000000000000000000000000000".to_owned() - ); - assert_eq!(call1.0, URLHINT); - assert_eq!( - call1.1, - "267b69227465737400000000000000000000000000000000000000000000000000000000".to_owned() - ); - } - - #[test] - fn should_decode_urlhint_output() { - // given - let mut registrar = FakeRegistrar::new(); - registrar.responses = Mutex::new(vec![ - Ok(format!("000000000000000000000000{}", URLHINT).from_hex().unwrap()), - Ok("0000000000000000000000000000000000000000000000000000000000000060ec4c1fe06c808fe3739858c347109b1f5f1ed4b5000000000000000000000000000000000000000000000000deadcafebeefbeefcafedeaddeedfeedffffffff0000000000000000000000000000000000000000000000000000000000000011657468636f72652f64616f2e636c61696d000000000000000000000000000000".from_hex().unwrap()), - ]); - let urlhint = URLHintContract::new(Arc::new(registrar)); - - // when - let res = urlhint.resolve("test".as_bytes().into()).wait().unwrap(); - - // then - assert_eq!( - res, - Some(URLHintResult::Dapp(GithubApp { - account: "ethcore".into(), - repo: "dao.claim".into(), - commit: GithubApp::commit( - &"ec4c1fe06c808fe3739858c347109b1f5f1ed4b5" - .from_hex() - .unwrap() - ) - .unwrap(), - owner: Address::from_str("deadcafebeefbeefcafedeaddeedfeedffffffff").unwrap(), - })) - ) - } - - #[test] - fn should_decode_urlhint_content_output() { - // given - let mut registrar = FakeRegistrar::new(); - registrar.responses = Mutex::new(vec![ - Ok(format!("000000000000000000000000{}", URLHINT).from_hex().unwrap()), - Ok("00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000deadcafebeefbeefcafedeaddeedfeedffffffff000000000000000000000000000000000000000000000000000000000000003c68747470733a2f2f7061726974792e696f2f6173736574732f696d616765732f657468636f72652d626c61636b2d686f72697a6f6e74616c2e706e6700000000".from_hex().unwrap()), - ]); - let urlhint = URLHintContract::new(Arc::new(registrar)); - - // when - let res = urlhint.resolve("test".as_bytes().into()).wait().unwrap(); - - // then - assert_eq!( - res, - Some(URLHintResult::Content(Content { - url: "https://parity.io/assets/images/ethcore-black-horizontal.png".into(), - mime: mime::IMAGE_PNG, - owner: Address::from_str("deadcafebeefbeefcafedeaddeedfeedffffffff").unwrap(), - })) - ) - } - - #[test] - fn should_return_valid_url() { - // given - let app = GithubApp { - account: "test".into(), - repo: "xyz".into(), - commit: [ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - ], - owner: Address::default(), - }; - - // when - let url = app.url(); - - // then - assert_eq!( - url, - "https://codeload.github.com/test/xyz/zip/000102030405060708090a0b0c0d0e0f10111213" - .to_owned() - ); - } - - #[test] - fn should_guess_mime_type_from_url() { - let url1 = "https://parity.io/parity"; - let url2 = "https://parity.io/parity#content-type=image/png"; - let url3 = "https://parity.io/parity#something&content-type=image/png"; - let url4 = "https://parity.io/parity.png#content-type=image/jpeg"; - let url5 = "https://parity.io/parity.png"; - - assert_eq!(guess_mime_type(url1), None); - assert_eq!(guess_mime_type(url2), Some(mime::IMAGE_PNG)); - assert_eq!(guess_mime_type(url3), Some(mime::IMAGE_PNG)); - assert_eq!(guess_mime_type(url4), Some(mime::IMAGE_JPEG)); - assert_eq!(guess_mime_type(url5), Some(mime::IMAGE_PNG)); - } -} diff --git a/updater/res/operations.json b/updater/res/operations.json deleted file mode 100644 index b675269f1..000000000 --- a/updater/res/operations.json +++ /dev/null @@ -1,597 +0,0 @@ -[ - { - "constant": false, - "inputs": [ - { - "name": "_client", - "type": "bytes32" - }, - { - "name": "_newOwner", - "type": "address" - } - ], - "name": "resetClientOwner", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_client", - "type": "bytes32" - }, - { - "name": "_release", - "type": "bytes32" - } - ], - "name": "isLatest", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_txid", - "type": "bytes32" - } - ], - "name": "rejectTransaction", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_newOwner", - "type": "address" - } - ], - "name": "setOwner", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_number", - "type": "uint32" - }, - { - "name": "_name", - "type": "bytes32" - }, - { - "name": "_hard", - "type": "bool" - }, - { - "name": "_spec", - "type": "bytes32" - } - ], - "name": "proposeFork", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_client", - "type": "bytes32" - } - ], - "name": "removeClient", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_client", - "type": "bytes32" - }, - { - "name": "_release", - "type": "bytes32" - } - ], - "name": "release", - "outputs": [ - { - "name": "o_forkBlock", - "type": "uint32" - }, - { - "name": "o_track", - "type": "uint8" - }, - { - "name": "o_semver", - "type": "uint24" - }, - { - "name": "o_critical", - "type": "bool" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_client", - "type": "bytes32" - }, - { - "name": "_checksum", - "type": "bytes32" - } - ], - "name": "build", - "outputs": [ - { - "name": "o_release", - "type": "bytes32" - }, - { - "name": "o_platform", - "type": "bytes32" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "rejectFork", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "bytes32" - } - ], - "name": "client", - "outputs": [ - { - "name": "owner", - "type": "address" - }, - { - "name": "required", - "type": "bool" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_newOwner", - "type": "address" - } - ], - "name": "setClientOwner", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "uint32" - } - ], - "name": "fork", - "outputs": [ - { - "name": "name", - "type": "bytes32" - }, - { - "name": "spec", - "type": "bytes32" - }, - { - "name": "hard", - "type": "bool" - }, - { - "name": "ratified", - "type": "bool" - }, - { - "name": "requiredCount", - "type": "uint256" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_release", - "type": "bytes32" - }, - { - "name": "_platform", - "type": "bytes32" - }, - { - "name": "_checksum", - "type": "bytes32" - } - ], - "name": "addChecksum", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_txid", - "type": "bytes32" - } - ], - "name": "confirmTransaction", - "outputs": [ - { - "name": "txSuccess", - "type": "uint256" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "bytes32" - } - ], - "name": "proxy", - "outputs": [ - { - "name": "requiredCount", - "type": "uint256" - }, - { - "name": "to", - "type": "address" - }, - { - "name": "data", - "type": "bytes" - }, - { - "name": "value", - "type": "uint256" - }, - { - "name": "gas", - "type": "uint256" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_client", - "type": "bytes32" - }, - { - "name": "_owner", - "type": "address" - } - ], - "name": "addClient", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "address" - } - ], - "name": "clientOwner", - "outputs": [ - { - "name": "", - "type": "bytes32" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_txid", - "type": "bytes32" - }, - { - "name": "_to", - "type": "address" - }, - { - "name": "_data", - "type": "bytes" - }, - { - "name": "_value", - "type": "uint256" - }, - { - "name": "_gas", - "type": "uint256" - } - ], - "name": "proposeTransaction", - "outputs": [ - { - "name": "txSuccess", - "type": "uint256" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "grandOwner", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_release", - "type": "bytes32" - }, - { - "name": "_forkBlock", - "type": "uint32" - }, - { - "name": "_track", - "type": "uint8" - }, - { - "name": "_semver", - "type": "uint24" - }, - { - "name": "_critical", - "type": "bool" - } - ], - "name": "addRelease", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "acceptFork", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "clientsRequired", - "outputs": [ - { - "name": "", - "type": "uint32" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_client", - "type": "bytes32" - }, - { - "name": "_release", - "type": "bytes32" - } - ], - "name": "track", - "outputs": [ - { - "name": "", - "type": "uint8" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_client", - "type": "bytes32" - }, - { - "name": "_r", - "type": "bool" - } - ], - "name": "setClientRequired", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "latestFork", - "outputs": [ - { - "name": "", - "type": "uint32" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_client", - "type": "bytes32" - }, - { - "name": "_track", - "type": "uint8" - } - ], - "name": "latestInTrack", - "outputs": [ - { - "name": "", - "type": "bytes32" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_client", - "type": "bytes32" - }, - { - "name": "_release", - "type": "bytes32" - }, - { - "name": "_platform", - "type": "bytes32" - } - ], - "name": "checksum", - "outputs": [ - { - "name": "", - "type": "bytes32" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "proposedFork", - "outputs": [ - { - "name": "", - "type": "uint32" - } - ], - "payable": false, - "type": "function" - }, - { - "name": "ReleaseAdded", - "type": "event", - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "client", - "type": "bytes32" - }, - { - "indexed": true, - "name": "forkBlock", - "type": "uint32" - }, - { - "indexed": false, - "name": "release", - "type": "bytes32" - }, - { - "indexed": false, - "name": "track", - "type": "uint8" - }, - { - "indexed": false, - "name": "semver", - "type": "uint24" - }, - { - "indexed": true, - "name": "critical", - "type": "bool" - } - ] - } -] diff --git a/updater/src/lib.rs b/updater/src/lib.rs deleted file mode 100644 index 628737d85..000000000 --- a/updater/src/lib.rs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . - -//! Updater for Parity executables - -#![warn(missing_docs)] - -extern crate common_types; -extern crate ethabi; -extern crate ethcore; -extern crate ethcore_sync as sync; -extern crate ethereum_types; -extern crate keccak_hash as hash; -extern crate parity_bytes as bytes; -extern crate parity_hash_fetch as hash_fetch; -extern crate parity_path; -extern crate parity_version as version; -extern crate parking_lot; -extern crate rand; -extern crate semver; -extern crate target_info; - -#[macro_use] -extern crate ethabi_contract; -#[macro_use] -extern crate ethabi_derive; -#[macro_use] -extern crate lazy_static; -#[macro_use] -extern crate log; - -#[cfg(test)] -extern crate tempdir; - -#[cfg(test)] -#[macro_use] -extern crate matches; - -mod service; -mod types; -mod updater; - -pub use service::Service; -pub use types::{CapState, OperationsInfo, ReleaseInfo, ReleaseTrack, VersionInfo}; -pub use updater::{UpdateFilter, UpdatePolicy, Updater}; diff --git a/updater/src/service.rs b/updater/src/service.rs deleted file mode 100644 index 03ece5e44..000000000 --- a/updater/src/service.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . - -use types::{CapState, OperationsInfo, ReleaseInfo, VersionInfo}; - -/// Parity updater service trait -pub trait Service: Send + Sync { - /// Is the currently running client capable of supporting the current chain? - /// We default to true if there's no clear information. - fn capability(&self) -> CapState; - - /// The release which is ready to be upgraded to, if any. If this returns `Some`, then - /// `execute_upgrade` may be called. - fn upgrade_ready(&self) -> Option; - - /// Actually upgrades the client. Assumes that the binary has been downloaded. - /// @returns `true` on success. - fn execute_upgrade(&self) -> bool; - - /// Our version info. - fn version_info(&self) -> VersionInfo; - - /// Information gathered concerning the release. - fn info(&self) -> Option; -} diff --git a/updater/src/types/all.rs b/updater/src/types/all.rs deleted file mode 100644 index af32411cb..000000000 --- a/updater/src/types/all.rs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . - -//! Types used in the public API - -use ethereum_types::H256; -use types::VersionInfo; - -/// Information regarding a particular release of Parity -#[derive(Debug, Clone, PartialEq)] -pub struct ReleaseInfo { - /// Information on the version. - pub version: VersionInfo, - /// Does this release contain critical security updates? - pub is_critical: bool, - /// The latest fork that this release can handle. - pub fork: u64, - /// Our platform's binary, if known. - pub binary: Option, -} - -/// Information on our operations environment. -#[derive(Debug, Clone, PartialEq)] -pub struct OperationsInfo { - /// Our blockchain's latest fork. - pub fork: u64, - - /// Last fork our client supports, if known. - pub this_fork: Option, - - /// Information on our track's latest release. - pub track: ReleaseInfo, - /// Information on our minor version's latest release. - pub minor: Option, -} - -/// Information on the current version's consensus capabililty. -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum CapState { - /// Unknown. - Unknown, - /// Capable of consensus indefinitely. - Capable, - /// Capable of consensus up until a definite block. - CapableUntil(u64), - /// Incapable of consensus since a particular block. - IncapableSince(u64), -} - -impl Default for CapState { - fn default() -> Self { - CapState::Unknown - } -} diff --git a/updater/src/types/mod.rs b/updater/src/types/mod.rs deleted file mode 100644 index 7dac9e63b..000000000 --- a/updater/src/types/mod.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . - -//! Types used in the public api - -mod all; -mod release_track; -mod version_info; - -pub use self::{ - all::{CapState, OperationsInfo, ReleaseInfo}, - release_track::ReleaseTrack, - version_info::VersionInfo, -}; diff --git a/updater/src/types/release_track.rs b/updater/src/types/release_track.rs deleted file mode 100644 index 33f8777f3..000000000 --- a/updater/src/types/release_track.rs +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . - -//! Types used in the public API - -use std::fmt; - -/// A release's track. -#[repr(u8)] -#[derive(PartialEq, Eq, Clone, Copy, Debug)] -pub enum ReleaseTrack { - /// Stable track. - Stable = 1, - /// Beta track. - Beta = 2, - /// Nightly track. - Nightly = 3, - /// Testing track. - Testing = 4, - /// No known track, also "current executable's track" when it's not yet known. - Unknown = 0, -} - -impl fmt::Display for ReleaseTrack { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "{}", - match *self { - ReleaseTrack::Stable => "stable", - ReleaseTrack::Beta => "beta", - ReleaseTrack::Nightly => "nightly", - ReleaseTrack::Testing => "testing", - ReleaseTrack::Unknown => "unknown", - } - ) - } -} - -impl<'a> From<&'a str> for ReleaseTrack { - fn from(s: &'a str) -> Self { - match s { - "stable" => ReleaseTrack::Stable, - "beta" => ReleaseTrack::Beta, - "nightly" => ReleaseTrack::Nightly, - "testing" => ReleaseTrack::Testing, - _ => ReleaseTrack::Unknown, - } - } -} - -impl From for ReleaseTrack { - fn from(i: u8) -> Self { - match i { - 1 => ReleaseTrack::Stable, - 2 => ReleaseTrack::Beta, - 3 => ReleaseTrack::Nightly, - 4 => ReleaseTrack::Testing, - _ => ReleaseTrack::Unknown, - } - } -} - -impl From for u8 { - fn from(rt: ReleaseTrack) -> Self { - rt as u8 - } -} - -#[cfg(test)] -mod tests { - use super::ReleaseTrack; - - #[test] - fn test_release_track_from() { - assert_eq!(ReleaseTrack::Stable, 1u8.into()); - assert_eq!(ReleaseTrack::Beta, 2u8.into()); - assert_eq!(ReleaseTrack::Nightly, 3u8.into()); - assert_eq!(ReleaseTrack::Testing, 4u8.into()); - assert_eq!(ReleaseTrack::Unknown, 0u8.into()); - } - - #[test] - fn test_release_track_into() { - assert_eq!(1u8, u8::from(ReleaseTrack::Stable)); - assert_eq!(2u8, u8::from(ReleaseTrack::Beta)); - assert_eq!(3u8, u8::from(ReleaseTrack::Nightly)); - assert_eq!(4u8, u8::from(ReleaseTrack::Testing)); - assert_eq!(0u8, u8::from(ReleaseTrack::Unknown)); - } - - #[test] - fn test_release_track_from_str() { - assert_eq!(ReleaseTrack::Stable, "stable".into()); - assert_eq!(ReleaseTrack::Beta, "beta".into()); - assert_eq!(ReleaseTrack::Nightly, "nightly".into()); - assert_eq!(ReleaseTrack::Testing, "testing".into()); - assert_eq!(ReleaseTrack::Unknown, "unknown".into()); - } - - #[test] - fn test_release_track_into_str() { - assert_eq!("stable", ReleaseTrack::Stable.to_string()); - assert_eq!("beta", ReleaseTrack::Beta.to_string()); - assert_eq!("nightly", ReleaseTrack::Nightly.to_string()); - assert_eq!("testing", ReleaseTrack::Testing.to_string()); - assert_eq!("unknown", ReleaseTrack::Unknown.to_string()); - } -} diff --git a/updater/src/types/version_info.rs b/updater/src/types/version_info.rs deleted file mode 100644 index 6eef189a8..000000000 --- a/updater/src/types/version_info.rs +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . - -//! Types used in the public API - -use ethereum_types::H160; -use semver::Version; -use std::fmt; -use types::ReleaseTrack; -use version::raw_package_info; - -/// Version information of a particular release. -#[derive(Debug, Clone, PartialEq)] -pub struct VersionInfo { - /// The track on which it was released. - pub track: ReleaseTrack, - /// The version. - pub version: Version, - /// The (SHA1?) 160-bit hash of this build's code base. - pub hash: H160, -} - -impl fmt::Display for VersionInfo { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!( - f, - "{}.{}.{}-{}-{}", - self.version.major, self.version.minor, self.version.patch, self.track, self.hash - ) - } -} - -impl VersionInfo { - /// Get information for this (currently running) binary. - pub fn this() -> Self { - let raw = raw_package_info(); - VersionInfo { - track: raw.0.into(), - version: { - let mut v = Version::parse(raw.1) - .expect("Environment variables are known to be valid; qed"); - v.build = vec![]; - v.pre = vec![]; - v - }, - hash: raw.2.parse::().unwrap_or_else(|_| H160::zero()), - } - } - - /// Compose the information from the provided raw fields. - pub fn from_raw(semver: u32, track: u8, hash: H160) -> Self { - let t = track.into(); - VersionInfo { - version: Version { - major: u64::from(semver >> 16), - minor: u64::from((semver >> 8) & 0xff), - patch: u64::from(semver & 0xff), - build: vec![], - pre: vec![], - }, - track: t, - hash, - } - } -} diff --git a/updater/src/updater.rs b/updater/src/updater.rs deleted file mode 100644 index 0bd9e8b80..000000000 --- a/updater/src/updater.rs +++ /dev/null @@ -1,1462 +0,0 @@ -// Copyright 2015-2019 Parity Technologies (UK) Ltd. -// This file is part of Parity Ethereum. - -// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see . - -use std::{ - cmp, fs, - io::Write, - path::{Path, PathBuf}, - sync::{Arc, Weak}, - time::{Duration, Instant}, -}; - -use parking_lot::{Mutex, MutexGuard}; -use rand::{self, Rng}; -use target_info::Target; - -use common_types::{filter::Filter, BlockNumber}; -use ethabi::FunctionOutputDecoder; -use ethcore::client::{BlockChainClient, BlockId, ChainNotify, NewBlocks}; -use ethereum_types::H256; -use hash_fetch::{self as fetch, HashFetch}; -use parity_path::restrict_permissions_owner; -use semver::Version; -use service::Service; -use sync::SyncProvider; -use types::{CapState, OperationsInfo, ReleaseInfo, ReleaseTrack, VersionInfo}; -use version; - -use_contract!(operations, "res/operations.json"); - -/// Filter for releases. -#[derive(Debug, Eq, PartialEq, Clone)] -pub enum UpdateFilter { - /// All releases following the same track. - All, - /// As with `All`, but only those which are known to be critical. - Critical, - /// None. - None, -} - -/// The policy for auto-updating. -#[derive(Debug, Eq, PartialEq, Clone)] -pub struct UpdatePolicy { - /// Download potential updates. - pub enable_downloading: bool, - /// Disable client if we know we're incapable of syncing. - pub require_consensus: bool, - /// Which of those downloaded should be automatically installed. - pub filter: UpdateFilter, - /// Which track we should be following. - pub track: ReleaseTrack, - /// Path for the updates to go. - pub path: PathBuf, - /// Maximum download size. - pub max_size: usize, - /// Random update delay range in blocks. - pub max_delay: u64, - /// Number of blocks between each check for updates. - pub frequency: u64, -} - -impl Default for UpdatePolicy { - fn default() -> Self { - UpdatePolicy { - enable_downloading: false, - require_consensus: true, - filter: UpdateFilter::None, - track: ReleaseTrack::Unknown, - path: Default::default(), - max_size: 128 * 1024 * 1024, - max_delay: 100, - frequency: 20, - } - } -} - -/// The current updater status -#[derive(Clone, Debug, PartialEq)] -enum UpdaterStatus { - /// Updater is currently disabled. - Disabled, - /// Updater is currently idle. - Idle, - /// Updater is waiting for block number to fetch a new release. - Waiting { - release: ReleaseInfo, - binary: H256, - block_number: BlockNumber, - }, - /// Updater is fetching a new release. - Fetching { - release: ReleaseInfo, - binary: H256, - retries: u32, - }, - /// Updater failed fetching a new release and it is now backing off until the next retry. - FetchBackoff { - release: ReleaseInfo, - binary: H256, - backoff: (u32, Instant), - }, - /// Updater is ready to update to a new release. - Ready { release: ReleaseInfo }, - /// Updater has installed a new release and can be manually restarted. - Installed { release: ReleaseInfo }, -} - -impl Default for UpdaterStatus { - fn default() -> Self { - UpdaterStatus::Idle - } -} - -#[derive(Debug, Default)] -struct UpdaterState { - latest: Option, - capability: CapState, - status: UpdaterStatus, -} - -/// Service for checking for updates and determining whether we can achieve consensus. -pub struct Updater< - O = OperationsContractClient, - F = fetch::Client, - T = StdTimeProvider, - R = ThreadRngGenRange, -> { - // Useful environmental stuff. - update_policy: UpdatePolicy, - weak_self: Mutex>>, - client: Weak, - sync: Option>, - fetcher: F, - operations_client: O, - exit_handler: Mutex>>, - - time_provider: T, - rng: R, - - // Our version info (static) - this: VersionInfo, - - // All the other info - this changes so leave it behind a Mutex. - state: Mutex, -} - -const CLIENT_ID: &str = "parity"; - -lazy_static! { - static ref CLIENT_ID_HASH: H256 = CLIENT_ID.as_bytes().into(); -} - -lazy_static! { - static ref PLATFORM: String = { - if cfg!(target_os = "macos") { - "x86_64-apple-darwin".into() - } else if cfg!(windows) { - "x86_64-pc-windows-msvc".into() - } else if cfg!(target_os = "linux") { - format!("{}-unknown-linux-gnu", Target::arch()) - } else { - version::platform() - } - }; -} - -lazy_static! { - static ref PLATFORM_ID_HASH: H256 = PLATFORM.as_bytes().into(); -} - -/// Client trait for getting latest release information from operations contract. -/// Useful for mocking in tests. -pub trait OperationsClient: Send + Sync + 'static { - /// Get the latest release operations info for the given track. - fn latest(&self, this: &VersionInfo, track: ReleaseTrack) -> Result; - - /// Fetches the block number when the given release was added, checking the interval [from; latest_block]. - fn release_block_number(&self, from: BlockNumber, release: &ReleaseInfo) - -> Option; -} - -/// `OperationsClient` that delegates calls to the operations contract. -pub struct OperationsContractClient { - client: Weak, -} - -impl OperationsContractClient { - fn new(client: Weak) -> Self { - OperationsContractClient { client } - } - - /// Get the hash of the latest release for the given track - fn latest_hash(&self, track: ReleaseTrack, do_call: &F) -> Result - where - F: Fn(Vec) -> Result, String>, - { - let (data, decoder) = - operations::functions::latest_in_track::call(*CLIENT_ID_HASH, u8::from(track)); - let value = do_call(data)?; - decoder.decode(&value).map_err(|e| e.to_string()) - } - - /// Get release info for the given release - fn release_info(&self, release_id: H256, do_call: &F) -> Result - where - F: Fn(Vec) -> Result, String>, - { - let (data, decoder) = operations::functions::release::call(*CLIENT_ID_HASH, release_id); - - let (fork, track, semver, is_critical) = - decoder.decode(&do_call(data)?).map_err(|e| e.to_string())?; - - let (fork, track, semver) = (fork.low_u64(), track.low_u32(), semver.low_u32()); - - let (data, decoder) = - operations::functions::checksum::call(*CLIENT_ID_HASH, release_id, *PLATFORM_ID_HASH); - let latest_binary = decoder.decode(&do_call(data)?).map_err(|e| e.to_string())?; - - Ok(ReleaseInfo { - version: VersionInfo::from_raw(semver, track as u8, release_id.into()), - is_critical, - fork, - binary: if latest_binary.is_zero() { - None - } else { - Some(latest_binary) - }, - }) - } -} - -impl OperationsClient for OperationsContractClient { - fn latest(&self, this: &VersionInfo, track: ReleaseTrack) -> Result { - if track == ReleaseTrack::Unknown { - return Err(format!("Current executable ({}) is unreleased.", this.hash)); - } - - let client = self - .client - .upgrade() - .ok_or_else(|| "Cannot obtain client")?; - let address = client - .registry_address("operations".into(), BlockId::Latest) - .ok_or_else(|| "Cannot get operations contract address")?; - let do_call = |data| { - client - .call_contract(BlockId::Latest, address, data) - .map_err(|e| format!("{:?}", e)) - }; - - trace!(target: "updater", "Looking up this_fork for our release: {}/{:?}", CLIENT_ID, this.hash); - - // get the fork number of this release - let (data, decoder) = operations::functions::release::call(*CLIENT_ID_HASH, this.hash); - let this_fork = do_call(data) - .and_then(|value| decoder.decode(&value).map_err(|e| e.to_string())) - .ok() - .and_then(|(fork, track, _, _)| { - let this_track: ReleaseTrack = (track.low_u64() as u8).into(); - match this_track { - ReleaseTrack::Unknown => None, - _ => Some(fork.low_u64()), - } - }); - - // get the hash of the latest release in our track - let latest_in_track = self.latest_hash(track, &do_call)?; - - // get the release info for the latest version in track - let in_track = self.release_info(latest_in_track, &do_call)?; - let mut in_minor = Some(in_track.clone()); - const PROOF: &str = - "in_minor initialized and assigned with Some; loop breaks if None assigned; qed"; - - // if the minor version has changed, let's check the minor version on a different track - while in_minor.as_ref().expect(PROOF).version.version.minor != this.version.minor { - let track = match in_minor.as_ref().expect(PROOF).version.track { - ReleaseTrack::Beta => ReleaseTrack::Stable, - ReleaseTrack::Nightly => ReleaseTrack::Beta, - _ => { - in_minor = None; - break; - } - }; - - let latest_in_track = self.latest_hash(track, &do_call)?; - in_minor = Some(self.release_info(latest_in_track, &do_call)?); - } - - let (data, decoder) = operations::functions::latest_fork::call(); - let fork = do_call(data) - .and_then(|value| decoder.decode(&value).map_err(|e| e.to_string()))? - .low_u64(); - - Ok(OperationsInfo { - fork, - this_fork, - track: in_track, - minor: in_minor, - }) - } - - fn release_block_number( - &self, - from: BlockNumber, - release: &ReleaseInfo, - ) -> Option { - let client = self.client.upgrade()?; - let address = client.registry_address("operations".into(), BlockId::Latest)?; - - let topics = operations::events::release_added::filter( - Some(*CLIENT_ID_HASH), - Some(release.fork.into()), - Some(release.is_critical), - ); - let topics = vec![topics.topic0, topics.topic1, topics.topic2, topics.topic3]; - let topics = topics.into_iter().map(Into::into).map(Some).collect(); - - let filter = Filter { - from_block: BlockId::Number(from), - to_block: BlockId::Latest, - address: Some(vec![address]), - topics, - limit: None, - }; - - client - .logs(filter) - .unwrap_or_default() - .iter() - .filter_map(|log| { - let event = operations::events::release_added::parse_log( - (log.topics.clone(), log.data.clone()).into(), - ) - .ok()?; - let version_info = VersionInfo::from_raw( - event.semver.low_u32(), - event.track.low_u32() as u8, - event.release.into(), - ); - if version_info == release.version { - Some(log.block_number) - } else { - None - } - }) - .last() - } -} - -/// Trait to provide current time. Useful for mocking in tests. -pub trait TimeProvider: Send + Sync + 'static { - /// Returns an instant corresponding to "now". - fn now(&self) -> Instant; -} - -/// `TimeProvider` implementation that delegates calls to `std::time`. -pub struct StdTimeProvider; - -impl TimeProvider for StdTimeProvider { - fn now(&self) -> Instant { - Instant::now() - } -} - -/// Trait to generate a random number within a given range. -/// Useful for mocking in tests. -pub trait GenRange: Send + Sync + 'static { - /// Generate a random value in the range [low, high), i.e. inclusive of low and exclusive of high. - fn gen_range(&self, low: u64, high: u64) -> u64; -} - -/// `GenRange` implementation that uses a `rand::thread_rng` for randomness. -pub struct ThreadRngGenRange; - -impl GenRange for ThreadRngGenRange { - fn gen_range(&self, low: u64, high: u64) -> u64 { - rand::thread_rng().gen_range(low, high) - } -} - -impl Updater { - /// `Updater` constructor - pub fn new( - client: &Weak, - sync: &Weak, - update_policy: UpdatePolicy, - fetcher: fetch::Client, - ) -> Arc { - let r = Arc::new(Updater { - update_policy, - weak_self: Mutex::new(Default::default()), - client: client.clone(), - sync: Some(sync.clone()), - fetcher, - operations_client: OperationsContractClient::new(client.clone()), - exit_handler: Mutex::new(None), - this: if cfg!(feature = "test-updater") { - VersionInfo { - track: ReleaseTrack::Stable, - version: Version::new(1, 3, 7), - hash: 0.into(), - } - } else { - VersionInfo::this() - }, - time_provider: StdTimeProvider, - rng: ThreadRngGenRange, - state: Mutex::new(Default::default()), - }); - *r.weak_self.lock() = Arc::downgrade(&r); - - r.poll(); - r - } - - fn update_file_name(v: &VersionInfo) -> String { - format!( - "parity-{}.{}.{}-{:x}", - v.version.major, v.version.minor, v.version.patch, v.hash - ) - } -} - -impl Updater { - /// Set a closure to call when we want to restart the client - pub fn set_exit_handler(&self, g: G) - where - G: Fn() + 'static + Send, - { - *self.exit_handler.lock() = Some(Box::new(g)); - } - - /// Returns release track of the parity node. - /// `update_policy.track` is the track specified from the command line, whereas `this.track` - /// is the track of the software which is currently run - fn track(&self) -> ReleaseTrack { - match self.update_policy.track { - ReleaseTrack::Unknown => self.this.track, - x => x, - } - } - - fn updates_path(&self, name: &str) -> PathBuf { - self.update_policy.path.join(name) - } - - fn on_fetch(&self, latest: &OperationsInfo, res: Result) { - let mut state = self.state.lock(); - - // Bail out if the latest release has changed in the meantime - if state.latest.as_ref() != Some(&latest) { - return; - } - - // The updated status should be set to fetching - if let UpdaterStatus::Fetching { - ref release, - binary, - retries, - } = state.status.clone() - { - match res { - // We've successfully fetched the binary - Ok(path) => { - let setup = |path: &Path| -> Result<(), String> { - let dest = self.updates_path(&Updater::update_file_name(&release.version)); - if !dest.exists() { - info!(target: "updater", "Fetched latest version ({}) OK to {}", release.version, path.display()); - fs::create_dir_all( - dest.parent().expect("at least one thing pushed; qed"), - ) - .map_err(|e| format!("Unable to create updates path: {:?}", e))?; - fs::copy(path, &dest) - .map_err(|e| format!("Unable to copy update: {:?}", e))?; - restrict_permissions_owner(&dest, false, true) - .map_err(|e| format!("Unable to update permissions: {}", e))?; - info!(target: "updater", "Copied updated binary to {}", dest.display()); - } - - Ok(()) - }; - - // There was a fatal error setting up the update, disable the updater - if let Err(err) = setup(&path) { - state.status = UpdaterStatus::Disabled; - warn!("{}", err); - } else { - state.status = UpdaterStatus::Ready { - release: release.clone(), - }; - self.updater_step(state); - } - } - // There was an error fetching the update, apply a backoff delay before retrying - Err(err) => { - let delay = 2_usize.pow(retries) as u64; - // cap maximum backoff to 1 day - let delay = cmp::min(delay, 24 * 60 * 60); - let backoff = ( - retries, - self.time_provider.now() + Duration::from_secs(delay), - ); - - state.status = UpdaterStatus::FetchBackoff { - release: release.clone(), - backoff, - binary, - }; - - warn!( - "Unable to fetch update ({}): {:?}, retrying in {} seconds.", - release.version, err, delay - ); - } - } - } - } - - fn execute_upgrade(&self, mut state: MutexGuard) -> bool { - if let UpdaterStatus::Ready { ref release } = state.status.clone() { - let file = Updater::update_file_name(&release.version); - let path = self.updates_path("latest"); - - // TODO: creating then writing is a bit fragile. would be nice to make it atomic. - if let Err(err) = fs::File::create(&path).and_then(|mut f| f.write_all(file.as_bytes())) - { - state.status = UpdaterStatus::Disabled; - - warn!(target: "updater", "Unable to create soft-link for update {:?}", err); - return false; - } - - info!(target: "updater", "Completed upgrade to {}", &release.version); - state.status = UpdaterStatus::Installed { - release: release.clone(), - }; - - match *self.exit_handler.lock() { - Some(ref h) => (*h)(), - None => info!(target: "updater", "Update installed, ready for restart."), - } - - return true; - }; - - warn!(target: "updater", "Execute upgrade called when no upgrade ready."); - false - } - - fn updater_step(&self, mut state: MutexGuard) { - let current_block_number = self - .client - .upgrade() - .map_or(0, |c| c.block_number(BlockId::Latest).unwrap_or(0)); - - if let Some(latest) = state.latest.clone() { - let fetch = |latest, binary| { - info!(target: "updater", "Attempting to get parity binary {}", binary); - let weak_self = self.weak_self.lock().clone(); - let f = move |res: Result| { - if let Some(this) = weak_self.upgrade() { - this.on_fetch(&latest, res) - } - }; - - self.fetcher.fetch( - binary, - fetch::Abort::default().with_max_size(self.update_policy.max_size), - Box::new(f), - ); - }; - - match state.status.clone() { - // updater is disabled - UpdaterStatus::Disabled => {} - // the update has already been installed - UpdaterStatus::Installed { ref release, .. } if *release == latest.track => {} - // we're currently fetching this update - UpdaterStatus::Fetching { ref release, .. } if *release == latest.track => {} - // the fetch has failed and we're backing off the next retry - UpdaterStatus::FetchBackoff { - ref release, - backoff, - .. - } if *release == latest.track && self.time_provider.now() < backoff.1 => {} - // we're delaying the update until the given block number - UpdaterStatus::Waiting { - ref release, - block_number, - .. - } if *release == latest.track && current_block_number < block_number => {} - // we're at (or past) the block that triggers the update, let's fetch the binary - UpdaterStatus::Waiting { - ref release, - block_number, - binary, - } if *release == latest.track && current_block_number >= block_number => { - info!(target: "updater", "Update for binary {} triggered", binary); - - state.status = UpdaterStatus::Fetching { - release: release.clone(), - binary, - retries: 1, - }; - fetch(latest, binary); - } - // we're ready to retry the fetch after we applied a backoff for the previous failure - UpdaterStatus::FetchBackoff { - ref release, - backoff, - binary, - } if *release == latest.track && self.time_provider.now() >= backoff.1 => { - state.status = UpdaterStatus::Fetching { - release: release.clone(), - binary, - retries: backoff.0 + 1, - }; - fetch(latest, binary); - } - // the update is ready to be installed - UpdaterStatus::Ready { ref release } if *release == latest.track => { - let auto = match self.update_policy.filter { - UpdateFilter::All => true, - UpdateFilter::Critical if release.is_critical /* TODO: or is on a bad fork */ => true, - _ => false, - }; - - if auto { - self.execute_upgrade(state); - } - } - // this is the default case that does the initial triggering to update. we can reach this case by being - // `Idle` but also if the latest release is updated, regardless of the state we're in (except if the - // updater is in the `Disabled` state). if we push a bad update (e.g. wrong hashes or download url) - // clients might eventually be on a really long backoff state for that release, but as soon a new - // release is pushed we'll fall through to the default case. - _ => { - if let Some(binary) = latest.track.binary { - let running_later = - latest.track.version.version < self.version_info().version; - let running_latest = latest.track.version.hash == self.version_info().hash; - - // Bail out if we're already running the latest version or a later one - if running_later || running_latest { - return; - } - - let path = - self.updates_path(&Updater::update_file_name(&latest.track.version)); - if path.exists() { - info!(target: "updater", "Already fetched binary."); - state.status = UpdaterStatus::Ready { - release: latest.track.clone(), - }; - self.updater_step(state); - } else if self.update_policy.enable_downloading { - let update_block_number = { - let max_delay = if latest.fork >= current_block_number { - cmp::min( - latest.fork - current_block_number, - self.update_policy.max_delay, - ) - } else { - self.update_policy.max_delay - }; - - let from = current_block_number.saturating_sub(max_delay); - match self - .operations_client - .release_block_number(from, &latest.track) - { - Some(block_number) => { - let delay = self.rng.gen_range(0, max_delay); - block_number.saturating_add(delay) - } - None => current_block_number, - } - }; - - state.status = UpdaterStatus::Waiting { - release: latest.track.clone(), - binary, - block_number: update_block_number, - }; - - if update_block_number > current_block_number { - info!(target: "updater", "Update for binary {} will be triggered at block {}", binary, update_block_number); - } else { - self.updater_step(state); - } - } - } - } - } - } - } - - fn poll(&self) { - trace!(target: "updater", "Current release is {} ({:?})", self.this, self.this.hash); - - // We rely on a secure state. Bail if we're unsure about it. - if !cfg!(feature = "test-updater") { - if self - .client - .upgrade() - .map_or(true, |c| !c.chain_info().security_level().is_full()) - { - return; - } - } - - // Only check for updates every n blocks - let current_block_number = self - .client - .upgrade() - .map_or(0, |c| c.block_number(BlockId::Latest).unwrap_or(0)); - - if !cfg!(feature = "test-updater") { - if current_block_number % cmp::max(self.update_policy.frequency, 1) != 0 { - return; - } - } - - let mut state = self.state.lock(); - - // Get the latest available release - let latest = self.operations_client.latest(&self.this, self.track()).ok(); - - if let Some(latest) = latest { - // Update current capability - state.capability = match latest.this_fork { - // We're behind the latest fork. Now is the time to be upgrading, perhaps we're too late... - Some(this_fork) if this_fork < latest.fork => { - if current_block_number >= latest.fork - 1 { - // We're at (or past) the last block we can import. Disable the client. - if self.update_policy.require_consensus { - if let Some(c) = self.client.upgrade() { - c.disable(); - } - } - - CapState::IncapableSince(latest.fork) - } else { - CapState::CapableUntil(latest.fork) - } - } - Some(_) => CapState::Capable, - None => CapState::Unknown, - }; - - // There's a new release available - if state.latest.as_ref() != Some(&latest) { - trace!(target: "updater", "Latest release in our track is v{} it is {}critical ({} binary is {})", - latest.track.version, - if latest.track.is_critical {""} else {"non-"}, - *PLATFORM, - latest.track.binary.map_or_else(|| "unreleased".into(), |b| format!("{}", b))); - - trace!(target: "updater", "Fork: this/current/latest/latest-known: {}/#{}/#{}/#{}", - latest.this_fork.map_or_else(|| "unknown".into(), |f| format!("#{}", f)), - current_block_number, - latest.track.fork, - latest.fork); - - // Update latest release - state.latest = Some(latest); - } - } - - self.updater_step(state); - } -} - -impl ChainNotify for Updater { - fn new_blocks(&self, new_blocks: NewBlocks) { - if new_blocks.has_more_blocks_to_import { - return; - } - match ( - self.client.upgrade(), - self.sync.as_ref().and_then(Weak::upgrade), - ) { - (Some(ref c), Some(ref s)) if !s.status().is_syncing(c.queue_info()) => self.poll(), - _ => {} - } - } -} - -impl Service - for Updater -{ - fn capability(&self) -> CapState { - self.state.lock().capability - } - - fn upgrade_ready(&self) -> Option { - match self.state.lock().status { - UpdaterStatus::Ready { ref release, .. } => Some(release.clone()), - _ => None, - } - } - - fn execute_upgrade(&self) -> bool { - let state = self.state.lock(); - self.execute_upgrade(state) - } - - fn version_info(&self) -> VersionInfo { - self.this.clone() - } - - fn info(&self) -> Option { - self.state.lock().latest.clone() - } -} - -#[cfg(test)] -pub mod tests { - use self::fetch::Error; - use super::*; - use ethcore::client::{EachBlockWith, TestBlockChainClient}; - use semver::Version; - use std::{fs::File, io::Read, sync::Arc}; - use tempdir::TempDir; - - #[derive(Clone)] - struct FakeOperationsClient { - result: Arc, Option)>>, - } - - impl FakeOperationsClient { - fn new() -> FakeOperationsClient { - FakeOperationsClient { - result: Arc::new(Mutex::new((None, None))), - } - } - - fn set_result( - &self, - operations_info: Option, - release_block_number: Option, - ) { - let mut result = self.result.lock(); - result.0 = operations_info; - result.1 = release_block_number; - } - } - - impl OperationsClient for FakeOperationsClient { - fn latest( - &self, - _this: &VersionInfo, - _track: ReleaseTrack, - ) -> Result { - self.result.lock().0.clone().ok_or("unavailable".into()) - } - - fn release_block_number( - &self, - _from: BlockNumber, - _release: &ReleaseInfo, - ) -> Option { - self.result.lock().1.clone() - } - } - - #[derive(Clone)] - struct FakeFetch { - on_done: Arc) + Send>>>>, - } - - impl FakeFetch { - fn new() -> FakeFetch { - FakeFetch { - on_done: Arc::new(Mutex::new(None)), - } - } - - fn trigger(&self, result: Option) { - if let Some(ref on_done) = *self.on_done.lock() { - on_done(result.ok_or(Error::NoResolution)) - } - } - } - - impl HashFetch for FakeFetch { - fn fetch( - &self, - _hash: H256, - _abort: fetch::Abort, - on_done: Box) + Send>, - ) { - *self.on_done.lock() = Some(on_done); - } - } - - #[derive(Clone)] - struct FakeTimeProvider { - result: Arc>, - } - - impl FakeTimeProvider { - fn new() -> FakeTimeProvider { - FakeTimeProvider { - result: Arc::new(Mutex::new(Instant::now())), - } - } - - fn set_result(&self, result: Instant) { - *self.result.lock() = result; - } - } - - impl TimeProvider for FakeTimeProvider { - fn now(&self) -> Instant { - *self.result.lock() - } - } - - #[derive(Clone)] - struct FakeGenRange { - result: Arc>, - } - - impl FakeGenRange { - fn new() -> FakeGenRange { - FakeGenRange { - result: Arc::new(Mutex::new(0)), - } - } - - fn set_result(&self, result: u64) { - *self.result.lock() = result; - } - } - - impl GenRange for FakeGenRange { - fn gen_range(&self, _low: u64, _high: u64) -> u64 { - *self.result.lock() - } - } - - type TestUpdater = Updater; - - fn setup( - update_policy: UpdatePolicy, - ) -> ( - Arc, - Arc, - FakeOperationsClient, - FakeFetch, - FakeTimeProvider, - FakeGenRange, - ) { - let client = Arc::new(TestBlockChainClient::new()); - let weak_client = Arc::downgrade(&client); - - let operations_client = FakeOperationsClient::new(); - let fetcher = FakeFetch::new(); - let time_provider = FakeTimeProvider::new(); - let rng = FakeGenRange::new(); - - let this = VersionInfo { - track: ReleaseTrack::Beta, - version: Version::parse("1.0.0").unwrap(), - hash: 0.into(), - }; - - let updater = Arc::new(Updater { - update_policy: update_policy, - weak_self: Mutex::new(Default::default()), - client: weak_client, - sync: None, - fetcher: fetcher.clone(), - operations_client: operations_client.clone(), - exit_handler: Mutex::new(None), - this: this, - time_provider: time_provider.clone(), - rng: rng.clone(), - state: Mutex::new(Default::default()), - }); - - *updater.weak_self.lock() = Arc::downgrade(&updater); - - ( - client, - updater, - operations_client, - fetcher, - time_provider, - rng, - ) - } - - fn update_policy() -> (UpdatePolicy, TempDir) { - let tempdir = TempDir::new("").unwrap(); - - let update_policy = UpdatePolicy { - path: tempdir.path().into(), - enable_downloading: true, - max_delay: 10, - frequency: 1, - ..Default::default() - }; - - (update_policy, tempdir) - } - - fn new_upgrade(version: &str) -> (VersionInfo, ReleaseInfo, OperationsInfo) { - let latest_version = VersionInfo { - track: ReleaseTrack::Beta, - version: Version::parse(version).unwrap(), - hash: 1.into(), - }; - - let latest_release = ReleaseInfo { - version: latest_version.clone(), - is_critical: false, - fork: 0, - binary: Some(0.into()), - }; - - let latest = OperationsInfo { - fork: 0, - this_fork: Some(0), - track: latest_release.clone(), - minor: None, - }; - - (latest_version, latest_release, latest) - } - - #[test] - fn should_stay_idle_when_no_release() { - let (update_policy, _) = update_policy(); - let (_client, updater, _, _, ..) = setup(update_policy); - - assert_eq!(updater.state.lock().status, UpdaterStatus::Idle); - updater.poll(); - assert_eq!(updater.state.lock().status, UpdaterStatus::Idle); - } - - #[test] - fn should_update_on_new_release() { - let (update_policy, tempdir) = update_policy(); - let (_client, updater, operations_client, fetcher, ..) = setup(update_policy); - let (latest_version, latest_release, latest) = new_upgrade("1.0.1"); - - // mock operations contract with a new version - operations_client.set_result(Some(latest.clone()), None); - - // we start in idle state and with no information regarding the latest release - assert_eq!(updater.state.lock().latest, None); - assert_eq!(updater.state.lock().status, UpdaterStatus::Idle); - - updater.poll(); - - // after the first poll the latest release should be set to the one we're mocking and the updater should be - // fetching it - assert_eq!(updater.state.lock().latest, Some(latest)); - assert_matches!( - updater.state.lock().status, - UpdaterStatus::Fetching { ref release, retries, .. } if *release == latest_release && retries == 1); - - // mock fetcher with update binary and trigger the fetch - let update_file = tempdir.path().join("parity"); - File::create(update_file.clone()).unwrap(); - fetcher.trigger(Some(update_file)); - - // after the fetch finishes the upgrade should be ready to install - assert_eq!( - updater.state.lock().status, - UpdaterStatus::Ready { - release: latest_release.clone() - } - ); - assert_eq!(updater.upgrade_ready(), Some(latest_release.clone())); - - // the current update_policy doesn't allow updating automatically, but we can trigger the update manually - ::execute_upgrade(&*updater); - - assert_eq!( - updater.state.lock().status, - UpdaterStatus::Installed { - release: latest_release - } - ); - - // the final binary should exist in the updates folder and the 'latest' file should be updated to point to it - let updated_binary = tempdir - .path() - .join(Updater::update_file_name(&latest_version)); - let latest_file = tempdir.path().join("latest"); - - assert!(updated_binary.exists()); - assert!(latest_file.exists()); - - let mut latest_file_content = String::new(); - File::open(latest_file) - .unwrap() - .read_to_string(&mut latest_file_content) - .unwrap(); - - assert_eq!( - latest_file_content, - updated_binary.file_name().and_then(|n| n.to_str()).unwrap() - ); - } - - #[test] - fn should_randomly_delay_new_updates() { - let (update_policy, _) = update_policy(); - let (client, updater, operations_client, _, _, rng) = setup(update_policy); - - let (_, latest_release, latest) = new_upgrade("1.0.1"); - operations_client.set_result(Some(latest.clone()), Some(0)); - - rng.set_result(5); - - updater.poll(); - - // the update should be delayed for 5 blocks - assert_matches!( - updater.state.lock().status, - UpdaterStatus::Waiting { ref release, block_number, .. } if *release == latest_release && block_number == 5); - - client.add_blocks(1, EachBlockWith::Nothing); - updater.poll(); - - // we should still be in the waiting state after we push one block - assert_matches!( - updater.state.lock().status, - UpdaterStatus::Waiting { ref release, block_number, .. } if *release == latest_release && block_number == 5); - - client.add_blocks(5, EachBlockWith::Nothing); - updater.poll(); - - // after we're past the delay the status should switch to fetching - assert_matches!( - updater.state.lock().status, - UpdaterStatus::Fetching { ref release, .. } if *release == latest_release); - } - - #[test] - fn should_not_delay_old_updates() { - let (update_policy, _) = update_policy(); - let (client, updater, operations_client, ..) = setup(update_policy); - client.add_blocks(100, EachBlockWith::Nothing); - - let (_, latest_release, latest) = new_upgrade("1.0.1"); - operations_client.set_result(Some(latest.clone()), Some(0)); - - updater.poll(); - - // the update should not be delayed since it's older than the maximum delay - // the update was at block 0 (100 blocks ago), and the maximum delay is 10 blocks - assert_matches!( - updater.state.lock().status, - UpdaterStatus::Fetching { ref release, .. } if *release == latest_release); - } - - #[test] - fn should_check_for_updates_with_configured_frequency() { - let (mut update_policy, _) = update_policy(); - update_policy.frequency = 2; - - let (client, updater, operations_client, _, _, rng) = setup(update_policy); - let (_, latest_release, latest) = new_upgrade("1.0.1"); - operations_client.set_result(Some(latest.clone()), Some(0)); - rng.set_result(5); - - client.add_blocks(1, EachBlockWith::Nothing); - updater.poll(); - - // the updater should stay idle since we only check for updates every other block (odd blocks in this case) - assert_eq!(updater.state.lock().status, UpdaterStatus::Idle); - - client.add_blocks(1, EachBlockWith::Nothing); - updater.poll(); - - // after adding a block we check for a new update and trigger the random delay (of 5 blocks) - assert_matches!( - updater.state.lock().status, - UpdaterStatus::Waiting { ref release, block_number, .. } if *release == latest_release && block_number == 5); - } - - #[test] - fn should_backoff_retry_when_update_fails() { - let (update_policy, tempdir) = update_policy(); - let (_client, updater, operations_client, fetcher, time_provider, ..) = - setup(update_policy); - let (_, latest_release, latest) = new_upgrade("1.0.1"); - - // mock operations contract with a new version - operations_client.set_result(Some(latest.clone()), None); - - let mut now = Instant::now(); - time_provider.set_result(now); - - updater.poll(); - fetcher.trigger(None); - - // we triggered the fetcher with an error result so the updater should backoff any retry - assert_matches!( - updater.state.lock().status, - UpdaterStatus::FetchBackoff { ref release, ref backoff, .. } if *release == latest_release && backoff.0 == 1); - - now += Duration::from_secs(1); - time_provider.set_result(now); - updater.poll(); - - // if we don't wait for the elapsed time the updater status should stay the same - assert_matches!( - updater.state.lock().status, - UpdaterStatus::FetchBackoff { ref release, ref backoff, .. } if *release == latest_release && backoff.0 == 1); - - now += Duration::from_secs(1); - time_provider.set_result(now); - updater.poll(); - fetcher.trigger(None); - - // the backoff time has elapsed so we retried again (and failed) - assert_matches!( - updater.state.lock().status, - UpdaterStatus::FetchBackoff { ref release, ref backoff, .. } if *release == latest_release && backoff.0 == 2); - - now += Duration::from_secs(4); - time_provider.set_result(now); - updater.poll(); - - let update_file = tempdir.path().join("parity"); - File::create(update_file.clone()).unwrap(); - fetcher.trigger(Some(update_file)); - - // after setting up the mocked fetch and waiting for the backoff period the update should succeed - assert_eq!( - updater.state.lock().status, - UpdaterStatus::Ready { - release: latest_release - } - ); - } - - #[test] - fn should_quit_backoff_on_new_release() { - let (update_policy, tempdir) = update_policy(); - let (_client, updater, operations_client, fetcher, ..) = setup(update_policy); - let (_, latest_release, latest) = new_upgrade("1.0.1"); - - // mock operations contract with a new version - operations_client.set_result(Some(latest.clone()), None); - - updater.poll(); - fetcher.trigger(None); - - // we triggered the fetcher with an error result so the updater should backoff any retry - assert_matches!( - updater.state.lock().status, - UpdaterStatus::FetchBackoff { ref release, ref backoff, .. } if *release == latest_release && backoff.0 == 1); - - // mock new working release and trigger the fetch afterwards - let (_, latest_release, latest) = new_upgrade("1.0.2"); - operations_client.set_result(Some(latest.clone()), None); - let update_file = tempdir.path().join("parity"); - File::create(update_file.clone()).unwrap(); - - updater.poll(); - fetcher.trigger(Some(update_file)); - - // a new release should short-circuit the backoff - assert_eq!( - updater.state.lock().status, - UpdaterStatus::Ready { - release: latest_release - } - ); - } - - #[test] - fn should_detect_already_downloaded_releases() { - let (update_policy, tempdir) = update_policy(); - let (_client, updater, operations_client, ..) = setup(update_policy); - let (latest_version, latest_release, latest) = new_upgrade("1.0.1"); - - // mock operations contract with a new version - operations_client.set_result(Some(latest.clone()), None); - - // mock final update file - let update_file = tempdir - .path() - .join(Updater::update_file_name(&latest_version)); - File::create(update_file.clone()).unwrap(); - - updater.poll(); - - // after checking for a new update we immediately declare it as ready since it already exists on disk - // there was no need to trigger the fetch - assert_eq!( - updater.state.lock().status, - UpdaterStatus::Ready { - release: latest_release - } - ); - } - - #[test] - fn should_stay_disabled_after_fatal_error() { - let (update_policy, tempdir) = update_policy(); - let (client, updater, operations_client, fetcher, ..) = setup(update_policy); - let (_, _, latest) = new_upgrade("1.0.1"); - - // mock operations contract with a new version - operations_client.set_result(Some(latest.clone()), None); - - updater.poll(); - // trigger the fetch but don't create the file on-disk. this should lead to a fatal error that disables the updater - let update_file = tempdir.path().join("parity"); - fetcher.trigger(Some(update_file)); - - assert_eq!(updater.state.lock().status, UpdaterStatus::Disabled); - - client.add_blocks(100, EachBlockWith::Nothing); - updater.poll(); - - // the updater should stay disabled after new blocks are pushed - assert_eq!(updater.state.lock().status, UpdaterStatus::Disabled); - - let (_, _, latest) = new_upgrade("1.0.2"); - operations_client.set_result(Some(latest.clone()), None); - - updater.poll(); - - // the updater should stay disabled after a new release is pushed - assert_eq!(updater.state.lock().status, UpdaterStatus::Disabled); - } - - #[test] - fn should_ignore_current_fetch_on_new_release() { - let (update_policy, _) = update_policy(); - let (_client, updater, operations_client, fetcher, ..) = setup(update_policy); - let (_, latest_release, latest) = new_upgrade("1.0.1"); - - // mock operations contract with a new version - operations_client.set_result(Some(latest.clone()), None); - - updater.poll(); - - assert_matches!( - updater.state.lock().status, - UpdaterStatus::Fetching { ref release, .. } if *release == latest_release); - - let (_, latest_release, latest) = new_upgrade("1.0.2"); - operations_client.set_result(Some(latest.clone()), None); - fetcher.trigger(None); - updater.poll(); - - // even though we triggered the previous fetch with an error, the current state was updated to fetch the new - // release, and the previous fetch is ignored - assert_matches!( - updater.state.lock().status, - UpdaterStatus::Fetching { ref release, .. } if *release == latest_release); - } - - #[test] - fn should_auto_install_updates_if_update_policy_allows() { - let (mut update_policy, tempdir) = update_policy(); - update_policy.filter = UpdateFilter::All; - let (_client, updater, operations_client, fetcher, ..) = setup(update_policy); - let (latest_version, latest_release, latest) = new_upgrade("1.0.1"); - - // mock operations contract with a new version - operations_client.set_result(Some(latest.clone()), None); - - // we start in idle state and with no information regarding the latest release - assert_eq!(updater.state.lock().latest, None); - assert_eq!(updater.state.lock().status, UpdaterStatus::Idle); - - updater.poll(); - - // mock fetcher with update binary and trigger the fetch - let update_file = tempdir.path().join("parity"); - File::create(update_file.clone()).unwrap(); - fetcher.trigger(Some(update_file)); - - // the update is auto installed since the update policy allows it - assert_eq!( - updater.state.lock().status, - UpdaterStatus::Installed { - release: latest_release - } - ); - - // the final binary should exist in the updates folder and the 'latest' file should be updated to point to it - let updated_binary = tempdir - .path() - .join(Updater::update_file_name(&latest_version)); - let latest_file = tempdir.path().join("latest"); - - assert!(updated_binary.exists()); - assert!(latest_file.exists()); - - let mut latest_file_content = String::new(); - File::open(latest_file) - .unwrap() - .read_to_string(&mut latest_file_content) - .unwrap(); - - assert_eq!( - latest_file_content, - updated_binary.file_name().and_then(|n| n.to_str()).unwrap() - ); - } - - #[test] - fn should_update_capability() { - let (update_policy, _tempdir) = update_policy(); - let (client, updater, operations_client, _, ..) = setup(update_policy); - let (_, _, mut latest) = new_upgrade("1.0.1"); - - // mock operations contract with a new version - operations_client.set_result(Some(latest.clone()), None); - - // we start with no information regarding our node's capabilities - assert_eq!(updater.state.lock().capability, CapState::Unknown); - - updater.poll(); - - // our node supports the current fork - assert_eq!(updater.state.lock().capability, CapState::Capable); - - // lets announce a new fork which our node doesn't support - latest.fork = 2; - operations_client.set_result(Some(latest.clone()), None); - updater.poll(); - - // our node is only capable of operating until block #2 when the fork triggers - assert_eq!(updater.state.lock().capability, CapState::CapableUntil(2)); - - client.add_blocks(3, EachBlockWith::Nothing); - updater.poll(); - - // after we move past the fork the capability should be updated to incapable - assert_eq!(updater.state.lock().capability, CapState::IncapableSince(2)); - - // and since our update policy requires consensus, the client should be disabled - assert!(client.is_disabled()); - } -} diff --git a/util/dir/src/lib.rs b/util/dir/src/lib.rs index 36b33b40e..50e099e12 100644 --- a/util/dir/src/lib.rs +++ b/util/dir/src/lib.rs @@ -268,16 +268,6 @@ pub fn default_local_path() -> String { .unwrap_or_else(|_| "$HOME/.parity".to_owned()) } -/// Default hypervisor path -pub fn default_hypervisor_path() -> PathBuf { - let app_info = AppInfo { - name: PRODUCT_HYPERVISOR, - author: AUTHOR, - }; - get_app_root(AppDataType::UserData, &app_info) - .unwrap_or_else(|_| "$HOME/.parity-hypervisor".into()) -} - /// Get home directory. fn home() -> PathBuf { home_dir().expect("Failed to get home dir") @@ -295,7 +285,6 @@ mod platform { use std::path::PathBuf; pub const AUTHOR: &str = "Parity"; pub const PRODUCT: &str = "io.parity.ethereum"; - pub const PRODUCT_HYPERVISOR: &str = "io.parity.ethereum-updates"; pub fn parity_base() -> PathBuf { let mut home = super::home(); @@ -312,7 +301,6 @@ mod platform { use std::path::PathBuf; pub const AUTHOR: &str = "Parity"; pub const PRODUCT: &str = "Ethereum"; - pub const PRODUCT_HYPERVISOR: &str = "EthereumUpdates"; pub fn parity_base() -> PathBuf { let mut home = super::home(); @@ -330,7 +318,6 @@ mod platform { use std::path::PathBuf; pub const AUTHOR: &str = "parity"; pub const PRODUCT: &str = "io.parity.ethereum"; - pub const PRODUCT_HYPERVISOR: &str = "io.parity.ethereum-updates"; pub fn parity_base() -> PathBuf { let mut home = super::home(); diff --git a/util/version/Cargo.toml b/util/version/Cargo.toml index 7c607d288..a91906050 100644 --- a/util/version/Cargo.toml +++ b/util/version/Cargo.toml @@ -1,5 +1,3 @@ -# NOTE This file is used by the auto-updater service. -# Make sure to update the service if it's moved or the structure is changed. [package] name = "parity-version" # NOTE: this value is used for Parity Ethereum version string (via env CARGO_PKG_VERSION) @@ -8,18 +6,6 @@ authors = ["Parity Technologies "] build = "build.rs" [package.metadata] -# This versions track. Should be changed to `stable` or `beta` when on respective branches. -# Used by auto-updater and for Parity version string. -track = "stable" - -# Network specific settings, used ONLY by auto-updater. -# Latest supported fork blocks. -# Indicates a critical release in this track (i.e. consensus issue). -[package.metadata.networks] -foundation = { forkBlock = 7280000, critical = false } -ropsten = { forkBlock = 4939394, critical = false } -kovan = { forkBlock = 10255201, critical = false } -goerli = { forkBlock = 0, critical = false } [dependencies] parity-bytes = "0.1" diff --git a/util/version/build.rs b/util/version/build.rs index 1b7d103d1..164dcb9f1 100644 --- a/util/version/build.rs +++ b/util/version/build.rs @@ -28,25 +28,15 @@ fn main() { let version = rustc_version::version().expect(ERROR_MSG); - let cargo: toml::Value = toml::from_str(include_str!("./Cargo.toml")).expect(ERROR_MSG); - let track = cargo["package"]["metadata"]["track"] - .as_str() - .expect("'track' has to be a string!"); - create_file( "meta.rs", format!( " - /// This versions track. - #[allow(unused)] - pub const TRACK: &str = {track:?}; - /// Returns compiler version. pub fn rustc_version() -> &'static str {{ \"{version}\" }} ", - track = track, version = version, ), ); diff --git a/util/version/src/lib.rs b/util/version/src/lib.rs index c2dc6908c..1f9eb9ee9 100644 --- a/util/version/src/lib.rs +++ b/util/version/src/lib.rs @@ -34,8 +34,8 @@ mod generated { } #[cfg(feature = "final")] -const THIS_TRACK: &'static str = generated::TRACK; -// ^^^ should be reset in Cargo.toml to "stable" or "beta" according to the release branch. +const THIS_TRACK: &'static str = "stable"; +// ^^^ should be reset in Cargo.toml to "stable" #[cfg(not(feature = "final"))] const THIS_TRACK: &'static str = "unstable";