Remove updater

This commit is contained in:
Artem Vorotnikov 2020-08-14 13:24:16 +03:00
parent 194101ed00
commit defd24c40e
No known key found for this signature in database
GPG Key ID: E0148C3F2FBB7A20
43 changed files with 60 additions and 4502 deletions

64
Cargo.lock generated
View File

@ -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"

View File

@ -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 <parity params>`
# 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"

View File

@ -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<F>(&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

View File

@ -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<String>,
mode_timeout: Option<u64>,
mode_alarm: Option<u64>,
auto_update: Option<String>,
auto_update_delay: Option<u16>,
auto_update_check_frequency: Option<u16>,
release_track: Option<String>,
no_download: Option<bool>,
no_consensus: Option<bool>,
chain: Option<String>,
base_path: Option<String>,
db_path: Option<String>,
@ -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,

View File

@ -1,5 +1,4 @@
[parity]
no_consensus = true
chain = "dev"
[mining]

View File

@ -1,6 +1,3 @@
[parity]
no_consensus = true
[rpc]
interface = "all"
apis = ["all"]

View File

@ -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"

View File

@ -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<UpdatePolicy, String> {
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()),

View File

@ -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<Cr, Rr>(
command: Execute,
logger: Arc<RotatingLogger>,
on_client_rq: Cr,
on_updater_rq: Rr,
) -> Result<ExecutionAction, String>
where
Cr: Fn(String) + 'static + Send,
Rr: Fn() + 'static + Send,
{
fn execute(command: Execute, logger: Arc<RotatingLogger>) -> Result<ExecutionAction, String> {
#[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<Cr, Rr>(
conf: Configuration,
logger: Arc<RotatingLogger>,
on_client_rq: Cr,
on_updater_rq: Rr,
) -> Result<ExecutionAction, String>
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<RotatingLogger>) -> Result<ExecutionAction, String> {
execute(conf.into_command()?, logger)
}

View File

@ -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<PathBuf, Error> {
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<PathBuf>,
latest_binary: &Option<PathBuf>,
) -> 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<String> {
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::<Vec<_>>()),
)
.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<String>,
}
// 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::<Vec<_>>();
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(|| "<unknown>".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(())
}

View File

@ -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},

View File

@ -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<RotatingLogger>,
pub settings: Arc<NetworkSettings>,
pub net_service: Arc<dyn ManageNetwork>,
pub updater: Arc<Updater>,
pub experimental_rpcs: bool,
pub ws_address: Option<Host>,
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(),
)

View File

@ -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<Mode>,
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<Cr, Rr>(
cmd: RunCmd,
logger: Arc<RotatingLogger>,
on_client_rq: Cr,
on_updater_rq: Rr,
) -> Result<RunningClient, String>
where
Cr: Fn(String) + 'static + Send,
Rr: Fn() + 'static + Send,
{
pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<RunningClient, String> {
// 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<Client>,
}
impl RegistrarClient for FullRegistrar {
type Call = Asynchronous;
fn registrar_address(&self) -> Result<Address, String> {
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<dyn BlockChainClient>)),
&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,

View File

@ -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" }

View File

@ -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;

View File

@ -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<C, M, U> {
pub struct ParityClient<C, M> {
client: Arc<C>,
miner: Arc<M>,
updater: Arc<U>,
sync: Arc<dyn SyncProvider>,
net: Arc<dyn ManageNetwork>,
logger: Arc<RotatingLogger>,
@ -66,7 +64,7 @@ pub struct ParityClient<C, M, U> {
snapshot: Option<Arc<dyn SnapshotService>>,
}
impl<C, M, U> ParityClient<C, M, U>
impl<C, M> ParityClient<C, M>
where
C: BlockChainClient,
{
@ -75,7 +73,6 @@ where
client: Arc<C>,
miner: Arc<M>,
sync: Arc<dyn SyncProvider>,
updater: Arc<U>,
net: Arc<dyn ManageNetwork>,
logger: Arc<RotatingLogger>,
settings: Arc<NetworkSettings>,
@ -87,7 +84,6 @@ where
client,
miner,
sync,
updater,
net,
logger,
settings,
@ -98,7 +94,7 @@ where
}
}
impl<C, M, U, S> Parity for ParityClient<C, M, U>
impl<C, M, S> Parity for ParityClient<C, M>
where
S: StateInfo + 'static,
C: miner::BlockChainClient
@ -107,7 +103,6 @@ where
+ Call<State = S>
+ 'static,
M: MinerService<State = S> + '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<ConsensusCapability> {
Ok(self.updater.capability().into())
}
fn version_info(&self) -> Result<VersionInfo> {
Ok(self.updater.version_info().into())
}
fn releases_info(&self) -> Result<Option<OperationsInfo>> {
Ok(self.updater.info().map(Into::into))
}
fn chain_status(&self) -> Result<ChainStatus> {
let chain_info = self.client.chain_info();

View File

@ -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<C, M, U, F = fetch::Client> {
pub struct ParitySetClient<C, M, F = fetch::Client> {
client: Arc<C>,
miner: Arc<M>,
updater: Arc<U>,
net: Arc<dyn ManageNetwork>,
fetch: F,
}
impl<C, M, U, F> ParitySetClient<C, M, U, F>
impl<C, M, F> ParitySetClient<C, M, F>
where
C: BlockChainClient + 'static,
{
/// Creates new `ParitySetClient` with given `Fetch`.
pub fn new(
client: &Arc<C>,
miner: &Arc<M>,
updater: &Arc<U>,
net: &Arc<dyn ManageNetwork>,
fetch: F,
) -> Self {
pub fn new(client: &Arc<C>, miner: &Arc<M>, net: &Arc<dyn ManageNetwork>, fetch: F) -> Self {
ParitySetClient {
client: client.clone(),
miner: miner.clone(),
updater: updater.clone(),
net: net.clone(),
fetch,
}
}
}
impl<C, M, U, F> ParitySet for ParitySetClient<C, M, U, F>
impl<C, M, F> ParitySet for ParitySetClient<C, M, F>
where
C: BlockChainClient + 'static,
M: MinerService + 'static,
U: UpdateService + 'static,
F: Fetch + 'static,
{
fn set_min_gas_price(&self, gas_price: U256) -> Result<bool> {
@ -239,14 +229,6 @@ where
Box::new(future)
}
fn upgrade_ready(&self) -> Result<Option<ReleaseInfo>> {
Ok(self.updater.upgrade_ready().map(Into::into))
}
fn execute_upgrade(&self) -> Result<bool> {
Ok(self.updater.execute_upgrade())
}
fn remove_transaction(&self, hash: H256) -> Result<Option<Transaction>> {
Ok(self
.miner

View File

@ -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,
};

View File

@ -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 <http://www.gnu.org/licenses/>.
//! 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<ReleaseInfo> {
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<OperationsInfo> {
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,
})
}
}

View File

@ -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<TestBlockChainClient, TestMinerService, TestUpdater>;
pub type TestParityClient = ParityClient<TestBlockChainClient, TestMinerService>;
pub struct Dependencies {
pub miner: Arc<TestMinerService>,
pub client: Arc<TestBlockChainClient>,
pub sync: Arc<TestSyncProvider>,
pub updater: Arc<TestUpdater>,
pub logger: Arc<RotatingLogger>,
pub settings: Arc<NetworkSettings>,
pub network: Arc<dyn ManageNetwork>,
@ -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();

View File

@ -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<TestManageNetwork> {
Arc::new(TestManageNetwork)
}
fn updater_service() -> Arc<TestUpdater> {
Arc::new(TestUpdater::default())
}
pub type TestParitySetClient =
ParitySetClient<TestBlockChainClient, TestMinerService, TestUpdater, FakeFetch<usize>>;
ParitySetClient<TestBlockChainClient, TestMinerService, FakeFetch<usize>>;
fn parity_set_client(
client: &Arc<TestBlockChainClient>,
miner: &Arc<TestMinerService>,
updater: &Arc<TestUpdater>,
net: &Arc<TestManageNetwork>,
) -> TestParitySetClient {
ParitySetClient::new(
client,
miner,
updater,
&(net.clone() as Arc<dyn ManageNetwork>),
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(),

View File

@ -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<String>;
/// Returns information on current consensus capability.
#[rpc(name = "parity_consensusCapability")]
fn consensus_capability(&self) -> Result<ConsensusCapability>;
/// Get our version information in a nice object.
#[rpc(name = "parity_versionInfo")]
fn version_info(&self) -> Result<VersionInfo>;
/// Get information concerning the latest releases if available.
#[rpc(name = "parity_releasesInfo")]
fn releases_info(&self) -> Result<Option<OperationsInfo>>;
/// Get the current chain status.
#[rpc(name = "parity_chainStatus")]
fn chain_status(&self) -> Result<ChainStatus>;

View File

@ -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<H256>;
/// Is there a release ready for install?
#[rpc(name = "parity_upgradeReady")]
fn upgrade_ready(&self) -> Result<Option<ReleaseInfo>>;
/// Execute a release which is ready according to upgrade_ready().
#[rpc(name = "parity_executeUpgrade")]
fn execute_upgrade(&self) -> Result<bool>;
/// 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.

View File

@ -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 <http://www.gnu.org/licenses/>.
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<ConsensusCapability> 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<ReleaseTrack> 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<Version> 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<VersionInfo> 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<H256>,
}
impl Into<ReleaseInfo> 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<u64>,
/// Information on our track's latest release.
pub track: ReleaseInfo,
/// Information on our minor version's latest release.
pub minor: Option<ReleaseInfo>,
}
impl Into<OperationsInfo> 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),
}
}
}

View File

@ -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},

View File

@ -1,37 +0,0 @@
[package]
description = "Parity Updater Service."
name = "parity-updater"
version = "1.12.0"
license = "GPL-3.0"
authors = ["Parity Technologies <admin@parity.io>"]
[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 = []

View File

@ -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 <admin@parity.io>"]
[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" }

View File

@ -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"}
]

View File

@ -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 <http://www.gnu.org/licenses/>.
//! 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<dyn Fn(Result<PathBuf, Error>) + 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<fetch::Error> for Error {
fn from(error: fetch::Error) -> Self {
Error::Fetch(error)
}
}
impl From<io::Error> for Error {
fn from(error: io::Error) -> Self {
Error::IO(error)
}
}
fn validate_hash(path: PathBuf, hash: H256, body: fetch::BodyReader) -> Result<PathBuf, Error> {
// 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<F: Fetch + 'static = fetch::Client> {
contract: URLHintContract,
fetch: F,
executor: Executor,
random_path: Arc<dyn Fn() -> PathBuf + Sync + Send>,
}
impl<F: Fetch + 'static> Client<F> {
/// Creates new instance of the `Client` given on-chain contract client, fetch service and task runner.
pub fn with_fetch(
contract: Arc<dyn RegistrarClient<Call = Asynchronous>>,
fetch: F,
executor: Executor,
) -> Self {
Client {
contract: URLHintContract::new(contract),
fetch: fetch,
executor: executor,
random_path: Arc::new(random_temp_path),
}
}
}
impl<F: Fetch + 'static> HashFetch for Client<F> {
fn fetch(
&self,
hash: H256,
abort: fetch::Abort,
on_done: Box<dyn Fn(Result<PathBuf, Error>) + 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::<usize>);
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::<usize>);
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);
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
//! 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;

View File

@ -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 <http://www.gnu.org/licenses/>.
//! 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<dyn Future<Item = Option<URLHintResult>, Error = String> + Send>;
}
/// `URLHintContract` API
pub struct URLHintContract {
registrar: Registrar,
client: Arc<dyn RegistrarClient<Call = Asynchronous>>,
}
impl URLHintContract {
/// Creates new `URLHintContract`
pub fn new(client: Arc<dyn RegistrarClient<Call = Asynchronous>>) -> 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<URLHintResult> {
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<dyn Future<Item = Option<URLHintResult>, 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<Mime> {
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<Mutex<Vec<(String, String)>>>,
pub responses: Mutex<Vec<Result<Bytes, String>>>,
}
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<Address, String> {
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));
}
}

View File

@ -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"
}
]
}
]

View File

@ -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 <http://www.gnu.org/licenses/>.
//! 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};

View File

@ -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 <http://www.gnu.org/licenses/>.
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<ReleaseInfo>;
/// 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<OperationsInfo>;
}

View File

@ -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 <http://www.gnu.org/licenses/>.
//! 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<H256>,
}
/// 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<u64>,
/// Information on our track's latest release.
pub track: ReleaseInfo,
/// Information on our minor version's latest release.
pub minor: Option<ReleaseInfo>,
}
/// 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
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
//! 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,
};

View File

@ -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 <http://www.gnu.org/licenses/>.
//! 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<u8> 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<ReleaseTrack> 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());
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
//! 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::<H160>().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,
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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();

View File

@ -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 <admin@parity.io>"]
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"

View File

@ -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,
),
);

View File

@ -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";