Remove updater
This commit is contained in:
parent
194101ed00
commit
defd24c40e
64
Cargo.lock
generated
64
Cargo.lock
generated
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -1,5 +1,4 @@
|
||||
[parity]
|
||||
no_consensus = true
|
||||
chain = "dev"
|
||||
|
||||
[mining]
|
||||
|
@ -1,6 +1,3 @@
|
||||
[parity]
|
||||
no_consensus = true
|
||||
|
||||
[rpc]
|
||||
interface = "all"
|
||||
apis = ["all"]
|
||||
|
@ -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"
|
||||
|
@ -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()),
|
||||
|
@ -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)
|
||||
}
|
||||
|
346
parity/main.rs
346
parity/main.rs
@ -34,11 +34,7 @@ extern crate ethcore_logger;
|
||||
extern crate winapi;
|
||||
|
||||
use std::{
|
||||
env,
|
||||
ffi::OsString,
|
||||
fs::{create_dir_all, metadata, remove_file, File},
|
||||
io::{Read, Write},
|
||||
path::PathBuf,
|
||||
io::Write,
|
||||
process,
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
@ -48,148 +44,12 @@ use std::{
|
||||
|
||||
use ansi_term::Colour;
|
||||
use ctrlc::CtrlC;
|
||||
use dir::default_hypervisor_path;
|
||||
use ethcore_logger::setup_log;
|
||||
use fdlimit::raise_fd_limit;
|
||||
use parity_daemonize::AsHandle;
|
||||
use parity_ethereum::{start, ExecutionAction};
|
||||
use parking_lot::{Condvar, Mutex};
|
||||
|
||||
const PLEASE_RESTART_EXIT_CODE: i32 = 69;
|
||||
const PARITY_EXECUTABLE_NAME: &str = "parity";
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Error {
|
||||
BinaryNotFound,
|
||||
ExitCode(i32),
|
||||
Restart,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
fn update_path(name: &str) -> PathBuf {
|
||||
let mut dest = default_hypervisor_path();
|
||||
dest.push(name);
|
||||
dest
|
||||
}
|
||||
|
||||
fn latest_exe_path() -> Result<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 || {})
|
||||
};
|
||||
let exec = start(conf, logger);
|
||||
|
||||
let res = match exec {
|
||||
match exec {
|
||||
Ok(result) => match result {
|
||||
ExecutionAction::Instant(Some(s)) => {
|
||||
ExecutionAction::Instant(output) => {
|
||||
if let Some(s) = output {
|
||||
println!("{}", s);
|
||||
0
|
||||
}
|
||||
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
|
||||
}
|
||||
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(())
|
||||
}
|
||||
|
@ -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},
|
||||
|
@ -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(),
|
||||
)
|
||||
|
@ -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,
|
||||
|
@ -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" }
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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,
|
||||
})
|
||||
}
|
||||
}
|
@ -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();
|
||||
|
@ -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(),
|
||||
|
@ -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>;
|
||||
|
@ -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.
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
@ -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},
|
||||
|
@ -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 = []
|
@ -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" }
|
@ -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"}
|
||||
]
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
@ -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));
|
||||
}
|
||||
}
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
@ -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};
|
@ -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>;
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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,
|
||||
};
|
@ -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());
|
||||
}
|
||||
}
|
@ -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
@ -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();
|
||||
|
@ -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"
|
||||
|
@ -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,
|
||||
),
|
||||
);
|
||||
|
@ -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";
|
||||
|
Loading…
Reference in New Issue
Block a user