Expose health status over RPC (#6274)
* Node-health to a separate crate. * Initialize node_health outside of dapps. * Expose health over RPC. * Bring back 412 and fix JS. * Add health to workspace and tests. * Fix compilation without default features. * Fix borked merge. * Revert to generics to avoid virtual calls. * Fix node-health tests. * Add missing trailing comma.
This commit is contained in:
parent
622632616c
commit
3226e1ca33
20
Cargo.lock
generated
20
Cargo.lock
generated
@ -1613,6 +1613,21 @@ dependencies = [
|
|||||||
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "node-health"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"futures-cpupool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"ntp 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"parity-reactor 0.1.0",
|
||||||
|
"parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nodrop"
|
name = "nodrop"
|
||||||
version = "0.1.9"
|
version = "0.1.9"
|
||||||
@ -1821,6 +1836,7 @@ dependencies = [
|
|||||||
"isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
|
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
|
||||||
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"node-health 0.1.0",
|
||||||
"num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"panic_hook 0.1.0",
|
"panic_hook 0.1.0",
|
||||||
@ -1862,7 +1878,6 @@ dependencies = [
|
|||||||
"ethcore-util 1.8.0",
|
"ethcore-util 1.8.0",
|
||||||
"fetch 0.1.0",
|
"fetch 0.1.0",
|
||||||
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures-cpupool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
|
"jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
|
||||||
"jsonrpc-http-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
|
"jsonrpc-http-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
|
||||||
@ -1870,7 +1885,7 @@ dependencies = [
|
|||||||
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ntp 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"node-health 0.1.0",
|
||||||
"parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parity-hash-fetch 1.8.0",
|
"parity-hash-fetch 1.8.0",
|
||||||
"parity-reactor 0.1.0",
|
"parity-reactor 0.1.0",
|
||||||
@ -1985,6 +2000,7 @@ dependencies = [
|
|||||||
"jsonrpc-ws-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
|
"jsonrpc-ws-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
|
||||||
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"multihash 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"multihash 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"node-health 0.1.0",
|
||||||
"order-stat 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"order-stat 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parity-reactor 0.1.0",
|
"parity-reactor 0.1.0",
|
||||||
"parity-updater 1.8.0",
|
"parity-updater 1.8.0",
|
||||||
|
@ -43,6 +43,7 @@ ethcore-logger = { path = "logger" }
|
|||||||
ethcore-stratum = { path = "stratum" }
|
ethcore-stratum = { path = "stratum" }
|
||||||
ethcore-network = { path = "util/network" }
|
ethcore-network = { path = "util/network" }
|
||||||
ethkey = { path = "ethkey" }
|
ethkey = { path = "ethkey" }
|
||||||
|
node-health = { path = "dapps/node-health" }
|
||||||
rlp = { path = "util/rlp" }
|
rlp = { path = "util/rlp" }
|
||||||
rpc-cli = { path = "rpc_cli" }
|
rpc-cli = { path = "rpc_cli" }
|
||||||
parity-hash-fetch = { path = "hash-fetch" }
|
parity-hash-fetch = { path = "hash-fetch" }
|
||||||
@ -110,4 +111,4 @@ lto = false
|
|||||||
panic = "abort"
|
panic = "abort"
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = ["ethstore/cli", "ethkey/cli", "evmbin", "whisper", "chainspec"]
|
members = ["ethstore/cli", "ethkey/cli", "evmbin", "whisper", "chainspec", "dapps/node-health"]
|
||||||
|
@ -9,15 +9,12 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
base32 = "0.3"
|
base32 = "0.3"
|
||||||
env_logger = "0.4"
|
|
||||||
futures = "0.1"
|
futures = "0.1"
|
||||||
futures-cpupool = "0.1"
|
|
||||||
linked-hash-map = "0.3"
|
linked-hash-map = "0.3"
|
||||||
log = "0.3"
|
log = "0.3"
|
||||||
parity-dapps-glue = "1.7"
|
parity-dapps-glue = "1.7"
|
||||||
mime = "0.2"
|
mime = "0.2"
|
||||||
mime_guess = "1.6.1"
|
mime_guess = "1.6.1"
|
||||||
ntp = "0.2.0"
|
|
||||||
rand = "0.3"
|
rand = "0.3"
|
||||||
rustc-hex = "1.0"
|
rustc-hex = "1.0"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
@ -32,15 +29,19 @@ itertools = "0.5"
|
|||||||
jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.7" }
|
jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.7" }
|
||||||
jsonrpc-http-server = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.7" }
|
jsonrpc-http-server = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.7" }
|
||||||
|
|
||||||
ethcore-devtools = { path = "../devtools" }
|
|
||||||
ethcore-util = { path = "../util" }
|
ethcore-util = { path = "../util" }
|
||||||
fetch = { path = "../util/fetch" }
|
fetch = { path = "../util/fetch" }
|
||||||
|
node-health = { path = "./node-health" }
|
||||||
parity-hash-fetch = { path = "../hash-fetch" }
|
parity-hash-fetch = { path = "../hash-fetch" }
|
||||||
parity-reactor = { path = "../util/reactor" }
|
parity-reactor = { path = "../util/reactor" }
|
||||||
parity-ui = { path = "./ui" }
|
parity-ui = { path = "./ui" }
|
||||||
|
|
||||||
clippy = { version = "0.0.103", optional = true}
|
clippy = { version = "0.0.103", optional = true}
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
env_logger = "0.4"
|
||||||
|
ethcore-devtools = { path = "../devtools" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
dev = ["clippy", "ethcore-util/dev"]
|
dev = ["clippy", "ethcore-util/dev"]
|
||||||
|
|
||||||
|
18
dapps/node-health/Cargo.toml
Normal file
18
dapps/node-health/Cargo.toml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
[package]
|
||||||
|
name = "node-health"
|
||||||
|
description = "Node's health status"
|
||||||
|
version = "0.1.0"
|
||||||
|
license = "GPL-3.0"
|
||||||
|
authors = ["Parity Technologies <admin@parity.io>"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
futures = "0.1"
|
||||||
|
futures-cpupool = "0.1"
|
||||||
|
log = "0.3"
|
||||||
|
ntp = "0.2.0"
|
||||||
|
parking_lot = "0.4"
|
||||||
|
serde = "1.0"
|
||||||
|
serde_derive = "1.0"
|
||||||
|
time = "0.1.35"
|
||||||
|
|
||||||
|
parity-reactor = { path = "../../util/reactor" }
|
122
dapps/node-health/src/health.rs
Normal file
122
dapps/node-health/src/health.rs
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! Reporting node's health.
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::time;
|
||||||
|
use futures::{Future, BoxFuture};
|
||||||
|
use futures::sync::oneshot;
|
||||||
|
use types::{HealthInfo, HealthStatus, Health};
|
||||||
|
use time::{TimeChecker, MAX_DRIFT};
|
||||||
|
use parity_reactor::Remote;
|
||||||
|
use parking_lot::Mutex;
|
||||||
|
use {SyncStatus};
|
||||||
|
|
||||||
|
const TIMEOUT_SECS: u64 = 5;
|
||||||
|
const PROOF: &str = "Only one closure is invoked.";
|
||||||
|
|
||||||
|
/// A struct enabling you to query for node's health.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct NodeHealth {
|
||||||
|
sync_status: Arc<SyncStatus>,
|
||||||
|
time: TimeChecker,
|
||||||
|
remote: Remote,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NodeHealth {
|
||||||
|
/// Creates new `NodeHealth`.
|
||||||
|
pub fn new(sync_status: Arc<SyncStatus>, time: TimeChecker, remote: Remote) -> Self {
|
||||||
|
NodeHealth { sync_status, time, remote, }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Query latest health report.
|
||||||
|
pub fn health(&self) -> BoxFuture<Health, ()> {
|
||||||
|
trace!(target: "dapps", "Checking node health.");
|
||||||
|
// Check timediff
|
||||||
|
let sync_status = self.sync_status.clone();
|
||||||
|
let time = self.time.time_drift();
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
let tx = Arc::new(Mutex::new(Some(tx)));
|
||||||
|
let tx2 = tx.clone();
|
||||||
|
self.remote.spawn_with_timeout(
|
||||||
|
move || time.then(move |result| {
|
||||||
|
let _ = tx.lock().take().expect(PROOF).send(Ok(result));
|
||||||
|
Ok(())
|
||||||
|
}),
|
||||||
|
time::Duration::from_secs(TIMEOUT_SECS),
|
||||||
|
move || {
|
||||||
|
let _ = tx2.lock().take().expect(PROOF).send(Err(()));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
rx.map_err(|err| {
|
||||||
|
warn!(target: "dapps", "Health request cancelled: {:?}", err);
|
||||||
|
}).and_then(move |time| {
|
||||||
|
// Check peers
|
||||||
|
let peers = {
|
||||||
|
let (connected, max) = sync_status.peers();
|
||||||
|
let (status, message) = match connected {
|
||||||
|
0 => {
|
||||||
|
(HealthStatus::Bad, "You are not connected to any peers. There is most likely some network issue. Fix connectivity.".into())
|
||||||
|
},
|
||||||
|
1 => (HealthStatus::NeedsAttention, "You are connected to only one peer. Your node might not be reliable. Check your network connection.".into()),
|
||||||
|
_ => (HealthStatus::Ok, "".into()),
|
||||||
|
};
|
||||||
|
HealthInfo { status, message, details: (connected, max) }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check sync
|
||||||
|
let sync = {
|
||||||
|
let is_syncing = sync_status.is_major_importing();
|
||||||
|
let (status, message) = if is_syncing {
|
||||||
|
(HealthStatus::NeedsAttention, "Your node is still syncing, the values you see might be outdated. Wait until it's fully synced.".into())
|
||||||
|
} else {
|
||||||
|
(HealthStatus::Ok, "".into())
|
||||||
|
};
|
||||||
|
HealthInfo { status, message, details: is_syncing }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check time
|
||||||
|
let time = {
|
||||||
|
let (status, message, details) = match time {
|
||||||
|
Ok(Ok(diff)) if diff < MAX_DRIFT && diff > -MAX_DRIFT => {
|
||||||
|
(HealthStatus::Ok, "".into(), diff)
|
||||||
|
},
|
||||||
|
Ok(Ok(diff)) => {
|
||||||
|
(HealthStatus::Bad, format!(
|
||||||
|
"Your clock is not in sync. Detected difference is too big for the protocol to work: {}ms. Synchronize your clock.",
|
||||||
|
diff,
|
||||||
|
), diff)
|
||||||
|
},
|
||||||
|
Ok(Err(err)) => {
|
||||||
|
(HealthStatus::NeedsAttention, format!(
|
||||||
|
"Unable to reach time API: {}. Make sure that your clock is synchronized.",
|
||||||
|
err,
|
||||||
|
), 0)
|
||||||
|
},
|
||||||
|
Err(_) => {
|
||||||
|
(HealthStatus::NeedsAttention, "Time API request timed out. Make sure that the clock is synchronized.".into(), 0)
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
HealthInfo { status, message, details, }
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Health { peers, sync, time})
|
||||||
|
}).boxed()
|
||||||
|
}
|
||||||
|
}
|
49
dapps/node-health/src/lib.rs
Normal file
49
dapps/node-health/src/lib.rs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! Node Health status reporting.
|
||||||
|
|
||||||
|
#![warn(missing_docs)]
|
||||||
|
|
||||||
|
extern crate futures;
|
||||||
|
extern crate futures_cpupool;
|
||||||
|
extern crate ntp;
|
||||||
|
extern crate time as time_crate;
|
||||||
|
extern crate parity_reactor;
|
||||||
|
extern crate parking_lot;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate log;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate serde_derive;
|
||||||
|
|
||||||
|
mod health;
|
||||||
|
mod time;
|
||||||
|
mod types;
|
||||||
|
|
||||||
|
pub use futures_cpupool::CpuPool;
|
||||||
|
pub use health::NodeHealth;
|
||||||
|
pub use types::{Health, HealthInfo, HealthStatus};
|
||||||
|
pub use time::{TimeChecker, Error};
|
||||||
|
|
||||||
|
/// Indicates sync status
|
||||||
|
pub trait SyncStatus: ::std::fmt::Debug + Send + Sync {
|
||||||
|
/// Returns true if there is a major sync happening.
|
||||||
|
fn is_major_importing(&self) -> bool;
|
||||||
|
|
||||||
|
/// Returns number of connected and ideal peers.
|
||||||
|
fn peers(&self) -> (usize, usize);
|
||||||
|
}
|
@ -41,8 +41,8 @@ use futures::{self, Future, BoxFuture};
|
|||||||
use futures::future::{self, IntoFuture};
|
use futures::future::{self, IntoFuture};
|
||||||
use futures_cpupool::{CpuPool, CpuFuture};
|
use futures_cpupool::{CpuPool, CpuFuture};
|
||||||
use ntp;
|
use ntp;
|
||||||
use time::{Duration, Timespec};
|
use parking_lot::RwLock;
|
||||||
use util::RwLock;
|
use time_crate::{Duration, Timespec};
|
||||||
|
|
||||||
/// Time checker error.
|
/// Time checker error.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
@ -164,7 +164,7 @@ impl Ntp for SimpleNtp {
|
|||||||
|
|
||||||
match ntp::request(&server.address) {
|
match ntp::request(&server.address) {
|
||||||
Ok(packet) => {
|
Ok(packet) => {
|
||||||
let dest_time = ::time::now_utc().to_timespec();
|
let dest_time = ::time_crate::now_utc().to_timespec();
|
||||||
let orig_time = Timespec::from(packet.orig_time);
|
let orig_time = Timespec::from(packet.orig_time);
|
||||||
let recv_time = Timespec::from(packet.recv_time);
|
let recv_time = Timespec::from(packet.recv_time);
|
||||||
let transmit_time = Timespec::from(packet.transmit_time);
|
let transmit_time = Timespec::from(packet.transmit_time);
|
||||||
@ -293,7 +293,7 @@ mod tests {
|
|||||||
use time::Duration;
|
use time::Duration;
|
||||||
use futures::{future, Future};
|
use futures::{future, Future};
|
||||||
use super::{Ntp, TimeChecker, Error};
|
use super::{Ntp, TimeChecker, Error};
|
||||||
use util::RwLock;
|
use parking_lot::RwLock;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct FakeNtp(RefCell<Vec<Duration>>, Cell<u64>);
|
struct FakeNtp(RefCell<Vec<Duration>>, Cell<u64>);
|
57
dapps/node-health/src/types.rs
Normal file
57
dapps/node-health/src/types.rs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! Base health types.
|
||||||
|
|
||||||
|
/// Health API endpoint status.
|
||||||
|
#[derive(Debug, PartialEq, Serialize)]
|
||||||
|
pub enum HealthStatus {
|
||||||
|
/// Everything's OK.
|
||||||
|
#[serde(rename = "ok")]
|
||||||
|
Ok,
|
||||||
|
/// Node health need attention
|
||||||
|
/// (the issue is not critical, but may need investigation)
|
||||||
|
#[serde(rename = "needsAttention")]
|
||||||
|
NeedsAttention,
|
||||||
|
/// There is something bad detected with the node.
|
||||||
|
#[serde(rename = "bad")]
|
||||||
|
Bad,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Represents a single check in node health.
|
||||||
|
/// Cointains the status of that check and apropriate message and details.
|
||||||
|
#[derive(Debug, PartialEq, Serialize)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
pub struct HealthInfo<T> {
|
||||||
|
/// Check status.
|
||||||
|
pub status: HealthStatus,
|
||||||
|
/// Human-readable message.
|
||||||
|
pub message: String,
|
||||||
|
/// Technical details of the check.
|
||||||
|
pub details: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Node Health status.
|
||||||
|
#[derive(Debug, PartialEq, Serialize)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
pub struct Health {
|
||||||
|
/// Status of peers.
|
||||||
|
pub peers: HealthInfo<(usize, usize)>,
|
||||||
|
/// Sync status.
|
||||||
|
pub sync: HealthInfo<bool>,
|
||||||
|
/// Time diff info.
|
||||||
|
pub time: HealthInfo<i64>,
|
||||||
|
}
|
@ -21,32 +21,28 @@ use hyper::method::Method;
|
|||||||
use hyper::status::StatusCode;
|
use hyper::status::StatusCode;
|
||||||
|
|
||||||
use api::{response, types};
|
use api::{response, types};
|
||||||
use api::time::{TimeChecker, MAX_DRIFT};
|
|
||||||
use apps::fetcher::Fetcher;
|
use apps::fetcher::Fetcher;
|
||||||
use handlers::{self, extract_url};
|
use handlers::{self, extract_url};
|
||||||
use endpoint::{Endpoint, Handler, EndpointPath};
|
use endpoint::{Endpoint, Handler, EndpointPath};
|
||||||
|
use node_health::{NodeHealth, HealthStatus, Health};
|
||||||
use parity_reactor::Remote;
|
use parity_reactor::Remote;
|
||||||
use {SyncStatus};
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct RestApi {
|
pub struct RestApi {
|
||||||
fetcher: Arc<Fetcher>,
|
fetcher: Arc<Fetcher>,
|
||||||
sync_status: Arc<SyncStatus>,
|
health: NodeHealth,
|
||||||
time: TimeChecker,
|
|
||||||
remote: Remote,
|
remote: Remote,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RestApi {
|
impl RestApi {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
fetcher: Arc<Fetcher>,
|
fetcher: Arc<Fetcher>,
|
||||||
sync_status: Arc<SyncStatus>,
|
health: NodeHealth,
|
||||||
time: TimeChecker,
|
|
||||||
remote: Remote,
|
remote: Remote,
|
||||||
) -> Box<Endpoint> {
|
) -> Box<Endpoint> {
|
||||||
Box::new(RestApi {
|
Box::new(RestApi {
|
||||||
fetcher,
|
fetcher,
|
||||||
sync_status,
|
health,
|
||||||
time,
|
|
||||||
remote,
|
remote,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -90,68 +86,23 @@ impl RestApiRouter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn health(&self, control: Control) -> Box<Handler> {
|
fn health(&self, control: Control) -> Box<Handler> {
|
||||||
use self::types::{HealthInfo, HealthStatus, Health};
|
let map = move |health: Result<Result<Health, ()>, ()>| {
|
||||||
|
let status = match health {
|
||||||
trace!(target: "dapps", "Checking node health.");
|
Ok(Ok(ref health)) => {
|
||||||
// Check timediff
|
if [&health.peers.status, &health.sync.status].iter().any(|x| *x != &HealthStatus::Ok) {
|
||||||
let sync_status = self.api.sync_status.clone();
|
StatusCode::PreconditionFailed // HTTP 412
|
||||||
let map = move |time| {
|
|
||||||
// Check peers
|
|
||||||
let peers = {
|
|
||||||
let (connected, max) = sync_status.peers();
|
|
||||||
let (status, message) = match connected {
|
|
||||||
0 => {
|
|
||||||
(HealthStatus::Bad, "You are not connected to any peers. There is most likely some network issue. Fix connectivity.".into())
|
|
||||||
},
|
|
||||||
1 => (HealthStatus::NeedsAttention, "You are connected to only one peer. Your node might not be reliable. Check your network connection.".into()),
|
|
||||||
_ => (HealthStatus::Ok, "".into()),
|
|
||||||
};
|
|
||||||
HealthInfo { status, message, details: (connected, max) }
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check sync
|
|
||||||
let sync = {
|
|
||||||
let is_syncing = sync_status.is_major_importing();
|
|
||||||
let (status, message) = if is_syncing {
|
|
||||||
(HealthStatus::NeedsAttention, "Your node is still syncing, the values you see might be outdated. Wait until it's fully synced.".into())
|
|
||||||
} else {
|
} else {
|
||||||
(HealthStatus::Ok, "".into())
|
StatusCode::Ok // HTTP 200
|
||||||
};
|
}
|
||||||
HealthInfo { status, message, details: is_syncing }
|
},
|
||||||
|
_ => StatusCode::ServiceUnavailable, // HTTP 503
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check time
|
response::as_json(status, &health)
|
||||||
let time = {
|
|
||||||
let (status, message, details) = match time {
|
|
||||||
Ok(Ok(diff)) if diff < MAX_DRIFT && diff > -MAX_DRIFT => {
|
|
||||||
(HealthStatus::Ok, "".into(), diff)
|
|
||||||
},
|
|
||||||
Ok(Ok(diff)) => {
|
|
||||||
(HealthStatus::Bad, format!(
|
|
||||||
"Your clock is not in sync. Detected difference is too big for the protocol to work: {}ms. Synchronize your clock.",
|
|
||||||
diff,
|
|
||||||
), diff)
|
|
||||||
},
|
|
||||||
Ok(Err(err)) => {
|
|
||||||
(HealthStatus::NeedsAttention, format!(
|
|
||||||
"Unable to reach time API: {}. Make sure that your clock is synchronized.",
|
|
||||||
err,
|
|
||||||
), 0)
|
|
||||||
},
|
|
||||||
Err(_) => {
|
|
||||||
(HealthStatus::NeedsAttention, "Time API request timed out. Make sure that the clock is synchronized.".into(), 0)
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
let health = self.api.health.health();
|
||||||
HealthInfo { status, message, details, }
|
|
||||||
};
|
|
||||||
|
|
||||||
response::as_json(StatusCode::Ok, &Health { peers, sync, time })
|
|
||||||
};
|
|
||||||
|
|
||||||
let time = self.api.time.time_drift();
|
|
||||||
let remote = self.api.remote.clone();
|
let remote = self.api.remote.clone();
|
||||||
Box::new(handlers::AsyncHandler::new(time, map, remote, control))
|
Box::new(handlers::AsyncHandler::new(health, map, remote, control))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,8 +18,6 @@
|
|||||||
|
|
||||||
mod api;
|
mod api;
|
||||||
mod response;
|
mod response;
|
||||||
mod time;
|
|
||||||
mod types;
|
mod types;
|
||||||
|
|
||||||
pub use self::api::RestApi;
|
pub use self::api::RestApi;
|
||||||
pub use self::time::TimeChecker;
|
|
||||||
|
@ -25,43 +25,3 @@ pub struct ApiError {
|
|||||||
/// More technical error details.
|
/// More technical error details.
|
||||||
pub detail: String,
|
pub detail: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Health API endpoint status.
|
|
||||||
#[derive(Debug, PartialEq, Serialize)]
|
|
||||||
pub enum HealthStatus {
|
|
||||||
/// Everything's OK.
|
|
||||||
#[serde(rename = "ok")]
|
|
||||||
Ok,
|
|
||||||
/// Node health need attention
|
|
||||||
/// (the issue is not critical, but may need investigation)
|
|
||||||
#[serde(rename = "needsAttention")]
|
|
||||||
NeedsAttention,
|
|
||||||
/// There is something bad detected with the node.
|
|
||||||
#[serde(rename = "bad")]
|
|
||||||
Bad
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Represents a single check in node health.
|
|
||||||
/// Cointains the status of that check and apropriate message and details.
|
|
||||||
#[derive(Debug, PartialEq, Serialize)]
|
|
||||||
#[serde(deny_unknown_fields)]
|
|
||||||
pub struct HealthInfo<T> {
|
|
||||||
/// Check status.
|
|
||||||
pub status: HealthStatus,
|
|
||||||
/// Human-readable message.
|
|
||||||
pub message: String,
|
|
||||||
/// Technical details of the check.
|
|
||||||
pub details: T,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Node Health status.
|
|
||||||
#[derive(Debug, PartialEq, Serialize)]
|
|
||||||
#[serde(deny_unknown_fields)]
|
|
||||||
pub struct Health {
|
|
||||||
/// Status of peers.
|
|
||||||
pub peers: HealthInfo<(usize, usize)>,
|
|
||||||
/// Sync status.
|
|
||||||
pub sync: HealthInfo<bool>,
|
|
||||||
/// Time diff info.
|
|
||||||
pub time: HealthInfo<i64>,
|
|
||||||
}
|
|
||||||
|
@ -281,6 +281,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
struct FakeSync(bool);
|
struct FakeSync(bool);
|
||||||
impl SyncStatus for FakeSync {
|
impl SyncStatus for FakeSync {
|
||||||
fn is_major_importing(&self) -> bool { self.0 }
|
fn is_major_importing(&self) -> bool { self.0 }
|
||||||
|
@ -21,11 +21,9 @@
|
|||||||
|
|
||||||
extern crate base32;
|
extern crate base32;
|
||||||
extern crate futures;
|
extern crate futures;
|
||||||
extern crate futures_cpupool;
|
|
||||||
extern crate itertools;
|
extern crate itertools;
|
||||||
extern crate linked_hash_map;
|
extern crate linked_hash_map;
|
||||||
extern crate mime_guess;
|
extern crate mime_guess;
|
||||||
extern crate ntp;
|
|
||||||
extern crate rand;
|
extern crate rand;
|
||||||
extern crate rustc_hex;
|
extern crate rustc_hex;
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
@ -40,6 +38,7 @@ extern crate jsonrpc_http_server;
|
|||||||
|
|
||||||
extern crate ethcore_util as util;
|
extern crate ethcore_util as util;
|
||||||
extern crate fetch;
|
extern crate fetch;
|
||||||
|
extern crate node_health;
|
||||||
extern crate parity_dapps_glue as parity_dapps;
|
extern crate parity_dapps_glue as parity_dapps;
|
||||||
extern crate parity_hash_fetch as hash_fetch;
|
extern crate parity_hash_fetch as hash_fetch;
|
||||||
extern crate parity_reactor;
|
extern crate parity_reactor;
|
||||||
@ -57,7 +56,6 @@ extern crate ethcore_devtools as devtools;
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
extern crate env_logger;
|
extern crate env_logger;
|
||||||
|
|
||||||
|
|
||||||
mod endpoint;
|
mod endpoint;
|
||||||
mod apps;
|
mod apps;
|
||||||
mod page;
|
mod page;
|
||||||
@ -79,19 +77,12 @@ use util::RwLock;
|
|||||||
use jsonrpc_http_server::{self as http, hyper, Origin};
|
use jsonrpc_http_server::{self as http, hyper, Origin};
|
||||||
|
|
||||||
use fetch::Fetch;
|
use fetch::Fetch;
|
||||||
use futures_cpupool::CpuPool;
|
use node_health::NodeHealth;
|
||||||
use parity_reactor::Remote;
|
use parity_reactor::Remote;
|
||||||
|
|
||||||
pub use hash_fetch::urlhint::ContractClient;
|
pub use hash_fetch::urlhint::ContractClient;
|
||||||
|
pub use node_health::SyncStatus;
|
||||||
|
|
||||||
/// Indicates sync status
|
|
||||||
pub trait SyncStatus: Send + Sync {
|
|
||||||
/// Returns true if there is a major sync happening.
|
|
||||||
fn is_major_importing(&self) -> bool;
|
|
||||||
|
|
||||||
/// Returns number of connected and ideal peers.
|
|
||||||
fn peers(&self) -> (usize, usize);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Validates Web Proxy tokens
|
/// Validates Web Proxy tokens
|
||||||
pub trait WebProxyTokens: Send + Sync {
|
pub trait WebProxyTokens: Send + Sync {
|
||||||
@ -156,8 +147,7 @@ impl Middleware {
|
|||||||
|
|
||||||
/// Creates new middleware for UI server.
|
/// Creates new middleware for UI server.
|
||||||
pub fn ui<F: Fetch>(
|
pub fn ui<F: Fetch>(
|
||||||
ntp_servers: &[String],
|
health: NodeHealth,
|
||||||
pool: CpuPool,
|
|
||||||
remote: Remote,
|
remote: Remote,
|
||||||
dapps_domain: &str,
|
dapps_domain: &str,
|
||||||
registrar: Arc<ContractClient>,
|
registrar: Arc<ContractClient>,
|
||||||
@ -172,11 +162,9 @@ impl Middleware {
|
|||||||
).embeddable_on(None).allow_dapps(false));
|
).embeddable_on(None).allow_dapps(false));
|
||||||
let special = {
|
let special = {
|
||||||
let mut special = special_endpoints(
|
let mut special = special_endpoints(
|
||||||
ntp_servers,
|
health,
|
||||||
pool,
|
|
||||||
content_fetcher.clone(),
|
content_fetcher.clone(),
|
||||||
remote.clone(),
|
remote.clone(),
|
||||||
sync_status.clone(),
|
|
||||||
);
|
);
|
||||||
special.insert(router::SpecialEndpoint::Home, Some(apps::ui()));
|
special.insert(router::SpecialEndpoint::Home, Some(apps::ui()));
|
||||||
special
|
special
|
||||||
@ -197,8 +185,7 @@ impl Middleware {
|
|||||||
|
|
||||||
/// Creates new Dapps server middleware.
|
/// Creates new Dapps server middleware.
|
||||||
pub fn dapps<F: Fetch>(
|
pub fn dapps<F: Fetch>(
|
||||||
ntp_servers: &[String],
|
health: NodeHealth,
|
||||||
pool: CpuPool,
|
|
||||||
remote: Remote,
|
remote: Remote,
|
||||||
ui_address: Option<(String, u16)>,
|
ui_address: Option<(String, u16)>,
|
||||||
extra_embed_on: Vec<(String, u16)>,
|
extra_embed_on: Vec<(String, u16)>,
|
||||||
@ -236,11 +223,9 @@ impl Middleware {
|
|||||||
|
|
||||||
let special = {
|
let special = {
|
||||||
let mut special = special_endpoints(
|
let mut special = special_endpoints(
|
||||||
ntp_servers,
|
health,
|
||||||
pool,
|
|
||||||
content_fetcher.clone(),
|
content_fetcher.clone(),
|
||||||
remote.clone(),
|
remote.clone(),
|
||||||
sync_status,
|
|
||||||
);
|
);
|
||||||
special.insert(
|
special.insert(
|
||||||
router::SpecialEndpoint::Home,
|
router::SpecialEndpoint::Home,
|
||||||
@ -270,20 +255,17 @@ impl http::RequestMiddleware for Middleware {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn special_endpoints<T: AsRef<str>>(
|
fn special_endpoints(
|
||||||
ntp_servers: &[T],
|
health: NodeHealth,
|
||||||
pool: CpuPool,
|
|
||||||
content_fetcher: Arc<apps::fetcher::Fetcher>,
|
content_fetcher: Arc<apps::fetcher::Fetcher>,
|
||||||
remote: Remote,
|
remote: Remote,
|
||||||
sync_status: Arc<SyncStatus>,
|
|
||||||
) -> HashMap<router::SpecialEndpoint, Option<Box<endpoint::Endpoint>>> {
|
) -> HashMap<router::SpecialEndpoint, Option<Box<endpoint::Endpoint>>> {
|
||||||
let mut special = HashMap::new();
|
let mut special = HashMap::new();
|
||||||
special.insert(router::SpecialEndpoint::Rpc, None);
|
special.insert(router::SpecialEndpoint::Rpc, None);
|
||||||
special.insert(router::SpecialEndpoint::Utils, Some(apps::utils()));
|
special.insert(router::SpecialEndpoint::Utils, Some(apps::utils()));
|
||||||
special.insert(router::SpecialEndpoint::Api, Some(api::RestApi::new(
|
special.insert(router::SpecialEndpoint::Api, Some(api::RestApi::new(
|
||||||
content_fetcher,
|
content_fetcher,
|
||||||
sync_status,
|
health,
|
||||||
api::TimeChecker::new(ntp_servers, pool),
|
|
||||||
remote,
|
remote,
|
||||||
)));
|
)));
|
||||||
special
|
special
|
||||||
|
@ -26,7 +26,7 @@ use jsonrpc_http_server::{self as http, Host, DomainsValidation};
|
|||||||
use devtools::http_client;
|
use devtools::http_client;
|
||||||
use hash_fetch::urlhint::ContractClient;
|
use hash_fetch::urlhint::ContractClient;
|
||||||
use fetch::{Fetch, Client as FetchClient};
|
use fetch::{Fetch, Client as FetchClient};
|
||||||
use futures_cpupool::CpuPool;
|
use node_health::{NodeHealth, TimeChecker, CpuPool};
|
||||||
use parity_reactor::Remote;
|
use parity_reactor::Remote;
|
||||||
|
|
||||||
use {Middleware, SyncStatus, WebProxyTokens};
|
use {Middleware, SyncStatus, WebProxyTokens};
|
||||||
@ -39,6 +39,7 @@ use self::fetch::FakeFetch;
|
|||||||
|
|
||||||
const SIGNER_PORT: u16 = 18180;
|
const SIGNER_PORT: u16 = 18180;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
struct FakeSync(bool);
|
struct FakeSync(bool);
|
||||||
impl SyncStatus for FakeSync {
|
impl SyncStatus for FakeSync {
|
||||||
fn is_major_importing(&self) -> bool { self.0 }
|
fn is_major_importing(&self) -> bool { self.0 }
|
||||||
@ -254,9 +255,13 @@ impl Server {
|
|||||||
remote: Remote,
|
remote: Remote,
|
||||||
fetch: F,
|
fetch: F,
|
||||||
) -> Result<Server, http::Error> {
|
) -> Result<Server, http::Error> {
|
||||||
|
let health = NodeHealth::new(
|
||||||
|
sync_status.clone(),
|
||||||
|
TimeChecker::new::<String>(&[], CpuPool::new(1)),
|
||||||
|
remote.clone(),
|
||||||
|
);
|
||||||
let middleware = Middleware::dapps(
|
let middleware = Middleware::dapps(
|
||||||
&["0.pool.ntp.org:123".into(), "1.pool.ntp.org:123".into()],
|
health,
|
||||||
CpuPool::new(4),
|
|
||||||
remote,
|
remote,
|
||||||
signer_address,
|
signer_address,
|
||||||
vec![],
|
vec![],
|
||||||
|
@ -385,6 +385,11 @@ export default class Parity {
|
|||||||
.then(outNumber);
|
.then(outNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nodeHealth () {
|
||||||
|
return this._transport
|
||||||
|
.execute('parity_nodeHealth');
|
||||||
|
}
|
||||||
|
|
||||||
nodeName () {
|
nodeName () {
|
||||||
return this._transport
|
return this._transport
|
||||||
.execute('parity_nodeName');
|
.execute('parity_nodeName');
|
||||||
|
@ -200,7 +200,7 @@ export default class Status {
|
|||||||
const statusPromises = [
|
const statusPromises = [
|
||||||
this._api.eth.syncing(),
|
this._api.eth.syncing(),
|
||||||
this._api.parity.netPeers(),
|
this._api.parity.netPeers(),
|
||||||
this._fetchHealth()
|
this._api.parity.nodeHealth()
|
||||||
];
|
];
|
||||||
|
|
||||||
return Promise
|
return Promise
|
||||||
@ -247,13 +247,6 @@ export default class Status {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
_fetchHealth = () => {
|
|
||||||
// Support Parity-Extension.
|
|
||||||
const uiUrl = this._api.transport.uiUrlWithProtocol || '';
|
|
||||||
|
|
||||||
return fetch(`${uiUrl}/api/health`).then(res => res.json());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The data fetched here should not change
|
* The data fetched here should not change
|
||||||
* unless Parity is restarted. They are thus
|
* unless Parity is restarted. They are thus
|
||||||
|
@ -346,6 +346,7 @@ impl Configuration {
|
|||||||
daemon: daemon,
|
daemon: daemon,
|
||||||
logger_config: logger_config.clone(),
|
logger_config: logger_config.clone(),
|
||||||
miner_options: self.miner_options(self.args.flag_reseal_min_period)?,
|
miner_options: self.miner_options(self.args.flag_reseal_min_period)?,
|
||||||
|
ntp_servers: self.ntp_servers(),
|
||||||
ws_conf: ws_conf,
|
ws_conf: ws_conf,
|
||||||
http_conf: http_conf,
|
http_conf: http_conf,
|
||||||
ipc_conf: ipc_conf,
|
ipc_conf: ipc_conf,
|
||||||
@ -563,7 +564,6 @@ impl Configuration {
|
|||||||
fn ui_config(&self) -> UiConfiguration {
|
fn ui_config(&self) -> UiConfiguration {
|
||||||
UiConfiguration {
|
UiConfiguration {
|
||||||
enabled: self.ui_enabled(),
|
enabled: self.ui_enabled(),
|
||||||
ntp_servers: self.ntp_servers(),
|
|
||||||
interface: self.ui_interface(),
|
interface: self.ui_interface(),
|
||||||
port: self.ui_port(),
|
port: self.ui_port(),
|
||||||
hosts: self.ui_hosts(),
|
hosts: self.ui_hosts(),
|
||||||
@ -576,7 +576,6 @@ impl Configuration {
|
|||||||
|
|
||||||
DappsConfiguration {
|
DappsConfiguration {
|
||||||
enabled: self.dapps_enabled(),
|
enabled: self.dapps_enabled(),
|
||||||
ntp_servers: self.ntp_servers(),
|
|
||||||
dapps_path: PathBuf::from(self.directories().dapps),
|
dapps_path: PathBuf::from(self.directories().dapps),
|
||||||
extra_dapps: if self.args.cmd_dapp {
|
extra_dapps: if self.args.cmd_dapp {
|
||||||
self.args.arg_path.iter().map(|path| PathBuf::from(path)).collect()
|
self.args.arg_path.iter().map(|path| PathBuf::from(path)).collect()
|
||||||
@ -1318,12 +1317,6 @@ mod tests {
|
|||||||
support_token_api: true
|
support_token_api: true
|
||||||
}, UiConfiguration {
|
}, UiConfiguration {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
ntp_servers: vec![
|
|
||||||
"0.parity.pool.ntp.org:123".into(),
|
|
||||||
"1.parity.pool.ntp.org:123".into(),
|
|
||||||
"2.parity.pool.ntp.org:123".into(),
|
|
||||||
"3.parity.pool.ntp.org:123".into(),
|
|
||||||
],
|
|
||||||
interface: "127.0.0.1".into(),
|
interface: "127.0.0.1".into(),
|
||||||
port: 8180,
|
port: 8180,
|
||||||
hosts: Some(vec![]),
|
hosts: Some(vec![]),
|
||||||
@ -1348,6 +1341,12 @@ mod tests {
|
|||||||
daemon: None,
|
daemon: None,
|
||||||
logger_config: Default::default(),
|
logger_config: Default::default(),
|
||||||
miner_options: Default::default(),
|
miner_options: Default::default(),
|
||||||
|
ntp_servers: vec![
|
||||||
|
"0.parity.pool.ntp.org:123".into(),
|
||||||
|
"1.parity.pool.ntp.org:123".into(),
|
||||||
|
"2.parity.pool.ntp.org:123".into(),
|
||||||
|
"3.parity.pool.ntp.org:123".into(),
|
||||||
|
],
|
||||||
ws_conf: Default::default(),
|
ws_conf: Default::default(),
|
||||||
http_conf: Default::default(),
|
http_conf: Default::default(),
|
||||||
ipc_conf: Default::default(),
|
ipc_conf: Default::default(),
|
||||||
@ -1567,16 +1566,9 @@ mod tests {
|
|||||||
let conf3 = parse(&["parity", "--ui-path", "signer", "--ui-interface", "test"]);
|
let conf3 = parse(&["parity", "--ui-path", "signer", "--ui-interface", "test"]);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
let ntp_servers = vec![
|
|
||||||
"0.parity.pool.ntp.org:123".into(),
|
|
||||||
"1.parity.pool.ntp.org:123".into(),
|
|
||||||
"2.parity.pool.ntp.org:123".into(),
|
|
||||||
"3.parity.pool.ntp.org:123".into(),
|
|
||||||
];
|
|
||||||
assert_eq!(conf0.directories().signer, "signer".to_owned());
|
assert_eq!(conf0.directories().signer, "signer".to_owned());
|
||||||
assert_eq!(conf0.ui_config(), UiConfiguration {
|
assert_eq!(conf0.ui_config(), UiConfiguration {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
ntp_servers: ntp_servers.clone(),
|
|
||||||
interface: "127.0.0.1".into(),
|
interface: "127.0.0.1".into(),
|
||||||
port: 8180,
|
port: 8180,
|
||||||
hosts: Some(vec![]),
|
hosts: Some(vec![]),
|
||||||
@ -1585,7 +1577,6 @@ mod tests {
|
|||||||
assert_eq!(conf1.directories().signer, "signer".to_owned());
|
assert_eq!(conf1.directories().signer, "signer".to_owned());
|
||||||
assert_eq!(conf1.ui_config(), UiConfiguration {
|
assert_eq!(conf1.ui_config(), UiConfiguration {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
ntp_servers: ntp_servers.clone(),
|
|
||||||
interface: "127.0.0.1".into(),
|
interface: "127.0.0.1".into(),
|
||||||
port: 8180,
|
port: 8180,
|
||||||
hosts: Some(vec![]),
|
hosts: Some(vec![]),
|
||||||
@ -1595,7 +1586,6 @@ mod tests {
|
|||||||
assert_eq!(conf2.directories().signer, "signer".to_owned());
|
assert_eq!(conf2.directories().signer, "signer".to_owned());
|
||||||
assert_eq!(conf2.ui_config(), UiConfiguration {
|
assert_eq!(conf2.ui_config(), UiConfiguration {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
ntp_servers: ntp_servers.clone(),
|
|
||||||
interface: "127.0.0.1".into(),
|
interface: "127.0.0.1".into(),
|
||||||
port: 3123,
|
port: 3123,
|
||||||
hosts: Some(vec![]),
|
hosts: Some(vec![]),
|
||||||
@ -1604,7 +1594,6 @@ mod tests {
|
|||||||
assert_eq!(conf3.directories().signer, "signer".to_owned());
|
assert_eq!(conf3.directories().signer, "signer".to_owned());
|
||||||
assert_eq!(conf3.ui_config(), UiConfiguration {
|
assert_eq!(conf3.ui_config(), UiConfiguration {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
ntp_servers: ntp_servers.clone(),
|
|
||||||
interface: "test".into(),
|
interface: "test".into(),
|
||||||
port: 8180,
|
port: 8180,
|
||||||
hosts: Some(vec![]),
|
hosts: Some(vec![]),
|
||||||
|
@ -22,12 +22,12 @@ use ethcore::client::{Client, BlockChainClient, BlockId};
|
|||||||
use ethcore::transaction::{Transaction, Action};
|
use ethcore::transaction::{Transaction, Action};
|
||||||
use ethsync::LightSync;
|
use ethsync::LightSync;
|
||||||
use futures::{future, IntoFuture, Future, BoxFuture};
|
use futures::{future, IntoFuture, Future, BoxFuture};
|
||||||
use futures_cpupool::CpuPool;
|
|
||||||
use hash_fetch::fetch::Client as FetchClient;
|
use hash_fetch::fetch::Client as FetchClient;
|
||||||
use hash_fetch::urlhint::ContractClient;
|
use hash_fetch::urlhint::ContractClient;
|
||||||
use helpers::replace_home;
|
use helpers::replace_home;
|
||||||
use light::client::Client as LightClient;
|
use light::client::Client as LightClient;
|
||||||
use light::on_demand::{self, OnDemand};
|
use light::on_demand::{self, OnDemand};
|
||||||
|
use node_health::{SyncStatus, NodeHealth};
|
||||||
use rpc;
|
use rpc;
|
||||||
use rpc_apis::SignerService;
|
use rpc_apis::SignerService;
|
||||||
use parity_reactor;
|
use parity_reactor;
|
||||||
@ -36,7 +36,6 @@ use util::{Bytes, Address};
|
|||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct Configuration {
|
pub struct Configuration {
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
pub ntp_servers: Vec<String>,
|
|
||||||
pub dapps_path: PathBuf,
|
pub dapps_path: PathBuf,
|
||||||
pub extra_dapps: Vec<PathBuf>,
|
pub extra_dapps: Vec<PathBuf>,
|
||||||
pub extra_embed_on: Vec<(String, u16)>,
|
pub extra_embed_on: Vec<(String, u16)>,
|
||||||
@ -48,12 +47,6 @@ impl Default for Configuration {
|
|||||||
let data_dir = default_data_path();
|
let data_dir = default_data_path();
|
||||||
Configuration {
|
Configuration {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
ntp_servers: vec![
|
|
||||||
"0.parity.pool.ntp.org:123".into(),
|
|
||||||
"1.parity.pool.ntp.org:123".into(),
|
|
||||||
"2.parity.pool.ntp.org:123".into(),
|
|
||||||
"3.parity.pool.ntp.org:123".into(),
|
|
||||||
],
|
|
||||||
dapps_path: replace_home(&data_dir, "$BASE/dapps").into(),
|
dapps_path: replace_home(&data_dir, "$BASE/dapps").into(),
|
||||||
extra_dapps: vec![],
|
extra_dapps: vec![],
|
||||||
extra_embed_on: vec![],
|
extra_embed_on: vec![],
|
||||||
@ -149,10 +142,10 @@ impl ContractClient for LightRegistrar {
|
|||||||
// to resolve.
|
// to resolve.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Dependencies {
|
pub struct Dependencies {
|
||||||
|
pub node_health: NodeHealth,
|
||||||
pub sync_status: Arc<SyncStatus>,
|
pub sync_status: Arc<SyncStatus>,
|
||||||
pub contract_client: Arc<ContractClient>,
|
pub contract_client: Arc<ContractClient>,
|
||||||
pub remote: parity_reactor::TokioRemote,
|
pub remote: parity_reactor::TokioRemote,
|
||||||
pub pool: CpuPool,
|
|
||||||
pub fetch: FetchClient,
|
pub fetch: FetchClient,
|
||||||
pub signer: Arc<SignerService>,
|
pub signer: Arc<SignerService>,
|
||||||
pub ui_address: Option<(String, u16)>,
|
pub ui_address: Option<(String, u16)>,
|
||||||
@ -165,7 +158,6 @@ pub fn new(configuration: Configuration, deps: Dependencies) -> Result<Option<Mi
|
|||||||
|
|
||||||
server::dapps_middleware(
|
server::dapps_middleware(
|
||||||
deps,
|
deps,
|
||||||
&configuration.ntp_servers,
|
|
||||||
configuration.dapps_path,
|
configuration.dapps_path,
|
||||||
configuration.extra_dapps,
|
configuration.extra_dapps,
|
||||||
rpc::DAPPS_DOMAIN,
|
rpc::DAPPS_DOMAIN,
|
||||||
@ -174,19 +166,18 @@ pub fn new(configuration: Configuration, deps: Dependencies) -> Result<Option<Mi
|
|||||||
).map(Some)
|
).map(Some)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_ui(enabled: bool, ntp_servers: &[String], deps: Dependencies) -> Result<Option<Middleware>, String> {
|
pub fn new_ui(enabled: bool, deps: Dependencies) -> Result<Option<Middleware>, String> {
|
||||||
if !enabled {
|
if !enabled {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
server::ui_middleware(
|
server::ui_middleware(
|
||||||
deps,
|
deps,
|
||||||
ntp_servers,
|
|
||||||
rpc::DAPPS_DOMAIN,
|
rpc::DAPPS_DOMAIN,
|
||||||
).map(Some)
|
).map(Some)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use self::server::{SyncStatus, Middleware, service};
|
pub use self::server::{Middleware, service};
|
||||||
|
|
||||||
#[cfg(not(feature = "dapps"))]
|
#[cfg(not(feature = "dapps"))]
|
||||||
mod server {
|
mod server {
|
||||||
@ -196,11 +187,6 @@ mod server {
|
|||||||
use parity_rpc::{hyper, RequestMiddleware, RequestMiddlewareAction};
|
use parity_rpc::{hyper, RequestMiddleware, RequestMiddlewareAction};
|
||||||
use rpc_apis;
|
use rpc_apis;
|
||||||
|
|
||||||
pub trait SyncStatus {
|
|
||||||
fn is_major_importing(&self) -> bool;
|
|
||||||
fn peers(&self) -> (usize, usize);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Middleware;
|
pub struct Middleware;
|
||||||
impl RequestMiddleware for Middleware {
|
impl RequestMiddleware for Middleware {
|
||||||
fn on_request(
|
fn on_request(
|
||||||
@ -212,7 +198,6 @@ mod server {
|
|||||||
|
|
||||||
pub fn dapps_middleware(
|
pub fn dapps_middleware(
|
||||||
_deps: Dependencies,
|
_deps: Dependencies,
|
||||||
_ntp_servers: &[String],
|
|
||||||
_dapps_path: PathBuf,
|
_dapps_path: PathBuf,
|
||||||
_extra_dapps: Vec<PathBuf>,
|
_extra_dapps: Vec<PathBuf>,
|
||||||
_dapps_domain: &str,
|
_dapps_domain: &str,
|
||||||
@ -224,7 +209,6 @@ mod server {
|
|||||||
|
|
||||||
pub fn ui_middleware(
|
pub fn ui_middleware(
|
||||||
_deps: Dependencies,
|
_deps: Dependencies,
|
||||||
_ntp_servers: &[String],
|
|
||||||
_dapps_domain: &str,
|
_dapps_domain: &str,
|
||||||
) -> Result<Middleware, String> {
|
) -> Result<Middleware, String> {
|
||||||
Err("Your Parity version has been compiled without UI support.".into())
|
Err("Your Parity version has been compiled without UI support.".into())
|
||||||
@ -246,11 +230,9 @@ mod server {
|
|||||||
use parity_reactor;
|
use parity_reactor;
|
||||||
|
|
||||||
pub use parity_dapps::Middleware;
|
pub use parity_dapps::Middleware;
|
||||||
pub use parity_dapps::SyncStatus;
|
|
||||||
|
|
||||||
pub fn dapps_middleware(
|
pub fn dapps_middleware(
|
||||||
deps: Dependencies,
|
deps: Dependencies,
|
||||||
ntp_servers: &[String],
|
|
||||||
dapps_path: PathBuf,
|
dapps_path: PathBuf,
|
||||||
extra_dapps: Vec<PathBuf>,
|
extra_dapps: Vec<PathBuf>,
|
||||||
dapps_domain: &str,
|
dapps_domain: &str,
|
||||||
@ -262,8 +244,7 @@ mod server {
|
|||||||
let web_proxy_tokens = Arc::new(move |token| signer.web_proxy_access_token_domain(&token));
|
let web_proxy_tokens = Arc::new(move |token| signer.web_proxy_access_token_domain(&token));
|
||||||
|
|
||||||
Ok(parity_dapps::Middleware::dapps(
|
Ok(parity_dapps::Middleware::dapps(
|
||||||
ntp_servers,
|
deps.node_health,
|
||||||
deps.pool,
|
|
||||||
parity_remote,
|
parity_remote,
|
||||||
deps.ui_address,
|
deps.ui_address,
|
||||||
extra_embed_on,
|
extra_embed_on,
|
||||||
@ -280,13 +261,11 @@ mod server {
|
|||||||
|
|
||||||
pub fn ui_middleware(
|
pub fn ui_middleware(
|
||||||
deps: Dependencies,
|
deps: Dependencies,
|
||||||
ntp_servers: &[String],
|
|
||||||
dapps_domain: &str,
|
dapps_domain: &str,
|
||||||
) -> Result<Middleware, String> {
|
) -> Result<Middleware, String> {
|
||||||
let parity_remote = parity_reactor::Remote::new(deps.remote.clone());
|
let parity_remote = parity_reactor::Remote::new(deps.remote.clone());
|
||||||
Ok(parity_dapps::Middleware::ui(
|
Ok(parity_dapps::Middleware::ui(
|
||||||
ntp_servers,
|
deps.node_health,
|
||||||
deps.pool,
|
|
||||||
parity_remote,
|
parity_remote,
|
||||||
dapps_domain,
|
dapps_domain,
|
||||||
deps.contract_client,
|
deps.contract_client,
|
||||||
|
@ -58,6 +58,7 @@ extern crate ethcore_util as util;
|
|||||||
extern crate ethcore_network as network;
|
extern crate ethcore_network as network;
|
||||||
extern crate ethkey;
|
extern crate ethkey;
|
||||||
extern crate ethsync;
|
extern crate ethsync;
|
||||||
|
extern crate node_health;
|
||||||
extern crate panic_hook;
|
extern crate panic_hook;
|
||||||
extern crate parity_hash_fetch as hash_fetch;
|
extern crate parity_hash_fetch as hash_fetch;
|
||||||
extern crate parity_ipfs_api;
|
extern crate parity_ipfs_api;
|
||||||
|
@ -73,7 +73,6 @@ impl Default for HttpConfiguration {
|
|||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct UiConfiguration {
|
pub struct UiConfiguration {
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
pub ntp_servers: Vec<String>,
|
|
||||||
pub interface: String,
|
pub interface: String,
|
||||||
pub port: u16,
|
pub port: u16,
|
||||||
pub hosts: Option<Vec<String>>,
|
pub hosts: Option<Vec<String>>,
|
||||||
@ -107,12 +106,6 @@ impl Default for UiConfiguration {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
UiConfiguration {
|
UiConfiguration {
|
||||||
enabled: true && cfg!(feature = "ui-enabled"),
|
enabled: true && cfg!(feature = "ui-enabled"),
|
||||||
ntp_servers: vec![
|
|
||||||
"0.parity.pool.ntp.org:123".into(),
|
|
||||||
"1.parity.pool.ntp.org:123".into(),
|
|
||||||
"2.parity.pool.ntp.org:123".into(),
|
|
||||||
"3.parity.pool.ntp.org:123".into(),
|
|
||||||
],
|
|
||||||
port: 8180,
|
port: 8180,
|
||||||
interface: "127.0.0.1".into(),
|
interface: "127.0.0.1".into(),
|
||||||
hosts: Some(vec![]),
|
hosts: Some(vec![]),
|
||||||
|
@ -27,17 +27,18 @@ use ethcore::account_provider::AccountProvider;
|
|||||||
use ethcore::client::Client;
|
use ethcore::client::Client;
|
||||||
use ethcore::miner::{Miner, ExternalMiner};
|
use ethcore::miner::{Miner, ExternalMiner};
|
||||||
use ethcore::snapshot::SnapshotService;
|
use ethcore::snapshot::SnapshotService;
|
||||||
use parity_rpc::{Metadata, NetworkSettings};
|
use ethcore_logger::RotatingLogger;
|
||||||
use parity_rpc::informant::{ActivityNotifier, ClientNotifier};
|
|
||||||
use parity_rpc::dispatch::{FullDispatcher, LightDispatcher};
|
|
||||||
use ethsync::{ManageNetwork, SyncProvider, LightSync};
|
use ethsync::{ManageNetwork, SyncProvider, LightSync};
|
||||||
use hash_fetch::fetch::Client as FetchClient;
|
use hash_fetch::fetch::Client as FetchClient;
|
||||||
use jsonrpc_core::{self as core, MetaIoHandler};
|
use jsonrpc_core::{self as core, MetaIoHandler};
|
||||||
use light::{TransactionQueue as LightTransactionQueue, Cache as LightDataCache};
|
use light::{TransactionQueue as LightTransactionQueue, Cache as LightDataCache};
|
||||||
|
use node_health::NodeHealth;
|
||||||
|
use parity_reactor;
|
||||||
|
use parity_rpc::dispatch::{FullDispatcher, LightDispatcher};
|
||||||
|
use parity_rpc::informant::{ActivityNotifier, ClientNotifier};
|
||||||
|
use parity_rpc::{Metadata, NetworkSettings};
|
||||||
use updater::Updater;
|
use updater::Updater;
|
||||||
use util::{Mutex, RwLock};
|
use util::{Mutex, RwLock};
|
||||||
use ethcore_logger::RotatingLogger;
|
|
||||||
use parity_reactor;
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone, Eq, Hash)]
|
#[derive(Debug, PartialEq, Clone, Eq, Hash)]
|
||||||
pub enum Api {
|
pub enum Api {
|
||||||
@ -217,6 +218,7 @@ pub struct FullDependencies {
|
|||||||
pub settings: Arc<NetworkSettings>,
|
pub settings: Arc<NetworkSettings>,
|
||||||
pub net_service: Arc<ManageNetwork>,
|
pub net_service: Arc<ManageNetwork>,
|
||||||
pub updater: Arc<Updater>,
|
pub updater: Arc<Updater>,
|
||||||
|
pub health: NodeHealth,
|
||||||
pub geth_compatibility: bool,
|
pub geth_compatibility: bool,
|
||||||
pub dapps_service: Option<Arc<DappsService>>,
|
pub dapps_service: Option<Arc<DappsService>>,
|
||||||
pub dapps_address: Option<(String, u16)>,
|
pub dapps_address: Option<(String, u16)>,
|
||||||
@ -300,12 +302,13 @@ impl FullDependencies {
|
|||||||
false => None,
|
false => None,
|
||||||
};
|
};
|
||||||
handler.extend_with(ParityClient::new(
|
handler.extend_with(ParityClient::new(
|
||||||
&self.client,
|
self.client.clone(),
|
||||||
&self.miner,
|
self.miner.clone(),
|
||||||
&self.sync,
|
self.sync.clone(),
|
||||||
&self.updater,
|
self.updater.clone(),
|
||||||
&self.net_service,
|
self.net_service.clone(),
|
||||||
&self.secret_store,
|
self.health.clone(),
|
||||||
|
self.secret_store.clone(),
|
||||||
self.logger.clone(),
|
self.logger.clone(),
|
||||||
self.settings.clone(),
|
self.settings.clone(),
|
||||||
signer,
|
signer,
|
||||||
@ -403,6 +406,7 @@ pub struct LightDependencies {
|
|||||||
pub secret_store: Arc<AccountProvider>,
|
pub secret_store: Arc<AccountProvider>,
|
||||||
pub logger: Arc<RotatingLogger>,
|
pub logger: Arc<RotatingLogger>,
|
||||||
pub settings: Arc<NetworkSettings>,
|
pub settings: Arc<NetworkSettings>,
|
||||||
|
pub health: NodeHealth,
|
||||||
pub on_demand: Arc<::light::on_demand::OnDemand>,
|
pub on_demand: Arc<::light::on_demand::OnDemand>,
|
||||||
pub cache: Arc<Mutex<LightDataCache>>,
|
pub cache: Arc<Mutex<LightDataCache>>,
|
||||||
pub transaction_queue: Arc<RwLock<LightTransactionQueue>>,
|
pub transaction_queue: Arc<RwLock<LightTransactionQueue>>,
|
||||||
@ -507,6 +511,7 @@ impl LightDependencies {
|
|||||||
self.secret_store.clone(),
|
self.secret_store.clone(),
|
||||||
self.logger.clone(),
|
self.logger.clone(),
|
||||||
self.settings.clone(),
|
self.settings.clone(),
|
||||||
|
self.health.clone(),
|
||||||
signer,
|
signer,
|
||||||
self.dapps_address.clone(),
|
self.dapps_address.clone(),
|
||||||
self.ws_address.clone(),
|
self.ws_address.clone(),
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::net::{TcpListener};
|
use std::net::{TcpListener};
|
||||||
|
|
||||||
@ -32,6 +33,7 @@ use fdlimit::raise_fd_limit;
|
|||||||
use hash_fetch::fetch::{Fetch, Client as FetchClient};
|
use hash_fetch::fetch::{Fetch, Client as FetchClient};
|
||||||
use informant::{Informant, LightNodeInformantData, FullNodeInformantData};
|
use informant::{Informant, LightNodeInformantData, FullNodeInformantData};
|
||||||
use light::Cache as LightDataCache;
|
use light::Cache as LightDataCache;
|
||||||
|
use node_health;
|
||||||
use parity_reactor::EventLoop;
|
use parity_reactor::EventLoop;
|
||||||
use parity_rpc::{NetworkSettings, informant, is_major_importing};
|
use parity_rpc::{NetworkSettings, informant, is_major_importing};
|
||||||
use updater::{UpdatePolicy, Updater};
|
use updater::{UpdatePolicy, Updater};
|
||||||
@ -80,6 +82,7 @@ pub struct RunCmd {
|
|||||||
pub daemon: Option<String>,
|
pub daemon: Option<String>,
|
||||||
pub logger_config: LogConfig,
|
pub logger_config: LogConfig,
|
||||||
pub miner_options: MinerOptions,
|
pub miner_options: MinerOptions,
|
||||||
|
pub ntp_servers: Vec<String>,
|
||||||
pub ws_conf: rpc::WsConfiguration,
|
pub ws_conf: rpc::WsConfiguration,
|
||||||
pub http_conf: rpc::HttpConfiguration,
|
pub http_conf: rpc::HttpConfiguration,
|
||||||
pub ipc_conf: rpc::IpcConfiguration,
|
pub ipc_conf: rpc::IpcConfiguration,
|
||||||
@ -283,7 +286,7 @@ fn execute_light(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) ->
|
|||||||
|
|
||||||
// the dapps server
|
// the dapps server
|
||||||
let signer_service = Arc::new(signer::new_service(&cmd.ws_conf, &cmd.ui_conf, &cmd.logger_config));
|
let signer_service = Arc::new(signer::new_service(&cmd.ws_conf, &cmd.ui_conf, &cmd.logger_config));
|
||||||
let dapps_deps = {
|
let (node_health, dapps_deps) = {
|
||||||
let contract_client = Arc::new(::dapps::LightRegistrar {
|
let contract_client = Arc::new(::dapps::LightRegistrar {
|
||||||
client: service.client().clone(),
|
client: service.client().clone(),
|
||||||
sync: light_sync.clone(),
|
sync: light_sync.clone(),
|
||||||
@ -291,7 +294,12 @@ fn execute_light(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) ->
|
|||||||
});
|
});
|
||||||
|
|
||||||
struct LightSyncStatus(Arc<LightSync>);
|
struct LightSyncStatus(Arc<LightSync>);
|
||||||
impl dapps::SyncStatus for LightSyncStatus {
|
impl fmt::Debug for LightSyncStatus {
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(fmt, "Light Sync Status")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl node_health::SyncStatus for LightSyncStatus {
|
||||||
fn is_major_importing(&self) -> bool { self.0.is_major_importing() }
|
fn is_major_importing(&self) -> bool { self.0.is_major_importing() }
|
||||||
fn peers(&self) -> (usize, usize) {
|
fn peers(&self) -> (usize, usize) {
|
||||||
let peers = ethsync::LightSyncProvider::peer_numbers(&*self.0);
|
let peers = ethsync::LightSyncProvider::peer_numbers(&*self.0);
|
||||||
@ -299,19 +307,26 @@ fn execute_light(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) ->
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dapps::Dependencies {
|
let sync_status = Arc::new(LightSyncStatus(light_sync.clone()));
|
||||||
sync_status: Arc::new(LightSyncStatus(light_sync.clone())),
|
let node_health = node_health::NodeHealth::new(
|
||||||
pool: fetch.pool(),
|
sync_status.clone(),
|
||||||
|
node_health::TimeChecker::new(&cmd.ntp_servers, fetch.pool()),
|
||||||
|
event_loop.remote(),
|
||||||
|
);
|
||||||
|
|
||||||
|
(node_health.clone(), dapps::Dependencies {
|
||||||
|
sync_status,
|
||||||
|
node_health,
|
||||||
contract_client: contract_client,
|
contract_client: contract_client,
|
||||||
remote: event_loop.raw_remote(),
|
remote: event_loop.raw_remote(),
|
||||||
fetch: fetch.clone(),
|
fetch: fetch.clone(),
|
||||||
signer: signer_service.clone(),
|
signer: signer_service.clone(),
|
||||||
ui_address: cmd.ui_conf.address(),
|
ui_address: cmd.ui_conf.address(),
|
||||||
}
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
let dapps_middleware = dapps::new(cmd.dapps_conf.clone(), dapps_deps.clone())?;
|
let dapps_middleware = dapps::new(cmd.dapps_conf.clone(), dapps_deps.clone())?;
|
||||||
let ui_middleware = dapps::new_ui(cmd.ui_conf.enabled, &cmd.ui_conf.ntp_servers, dapps_deps)?;
|
let ui_middleware = dapps::new_ui(cmd.ui_conf.enabled, dapps_deps)?;
|
||||||
|
|
||||||
// start RPCs
|
// start RPCs
|
||||||
let dapps_service = dapps::service(&dapps_middleware);
|
let dapps_service = dapps::service(&dapps_middleware);
|
||||||
@ -320,6 +335,7 @@ fn execute_light(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) ->
|
|||||||
client: service.client().clone(),
|
client: service.client().clone(),
|
||||||
sync: light_sync.clone(),
|
sync: light_sync.clone(),
|
||||||
net: light_sync.clone(),
|
net: light_sync.clone(),
|
||||||
|
health: node_health,
|
||||||
secret_store: account_provider,
|
secret_store: account_provider,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
settings: Arc::new(cmd.net_settings),
|
settings: Arc::new(cmd.net_settings),
|
||||||
@ -661,12 +677,17 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
|
|||||||
let signer_service = Arc::new(signer::new_service(&cmd.ws_conf, &cmd.ui_conf, &cmd.logger_config));
|
let signer_service = Arc::new(signer::new_service(&cmd.ws_conf, &cmd.ui_conf, &cmd.logger_config));
|
||||||
|
|
||||||
// the dapps server
|
// the dapps server
|
||||||
let dapps_deps = {
|
let (node_health, dapps_deps) = {
|
||||||
let (sync, client) = (sync_provider.clone(), client.clone());
|
let (sync, client) = (sync_provider.clone(), client.clone());
|
||||||
let contract_client = Arc::new(::dapps::FullRegistrar { client: client.clone() });
|
let contract_client = Arc::new(::dapps::FullRegistrar { client: client.clone() });
|
||||||
|
|
||||||
struct SyncStatus(Arc<ethsync::SyncProvider>, Arc<Client>, ethsync::NetworkConfiguration);
|
struct SyncStatus(Arc<ethsync::SyncProvider>, Arc<Client>, ethsync::NetworkConfiguration);
|
||||||
impl dapps::SyncStatus for SyncStatus {
|
impl fmt::Debug for SyncStatus {
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(fmt, "Dapps Sync Status")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl node_health::SyncStatus for SyncStatus {
|
||||||
fn is_major_importing(&self) -> bool {
|
fn is_major_importing(&self) -> bool {
|
||||||
is_major_importing(Some(self.0.status().state), self.1.queue_info())
|
is_major_importing(Some(self.0.status().state), self.1.queue_info())
|
||||||
}
|
}
|
||||||
@ -676,18 +697,24 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dapps::Dependencies {
|
let sync_status = Arc::new(SyncStatus(sync, client, net_conf));
|
||||||
sync_status: Arc::new(SyncStatus(sync, client, net_conf)),
|
let node_health = node_health::NodeHealth::new(
|
||||||
pool: fetch.pool(),
|
sync_status.clone(),
|
||||||
|
node_health::TimeChecker::new(&cmd.ntp_servers, fetch.pool()),
|
||||||
|
event_loop.remote(),
|
||||||
|
);
|
||||||
|
(node_health.clone(), dapps::Dependencies {
|
||||||
|
sync_status,
|
||||||
|
node_health,
|
||||||
contract_client: contract_client,
|
contract_client: contract_client,
|
||||||
remote: event_loop.raw_remote(),
|
remote: event_loop.raw_remote(),
|
||||||
fetch: fetch.clone(),
|
fetch: fetch.clone(),
|
||||||
signer: signer_service.clone(),
|
signer: signer_service.clone(),
|
||||||
ui_address: cmd.ui_conf.address(),
|
ui_address: cmd.ui_conf.address(),
|
||||||
}
|
})
|
||||||
};
|
};
|
||||||
let dapps_middleware = dapps::new(cmd.dapps_conf.clone(), dapps_deps.clone())?;
|
let dapps_middleware = dapps::new(cmd.dapps_conf.clone(), dapps_deps.clone())?;
|
||||||
let ui_middleware = dapps::new_ui(cmd.ui_conf.enabled, &cmd.ui_conf.ntp_servers, dapps_deps)?;
|
let ui_middleware = dapps::new_ui(cmd.ui_conf.enabled, dapps_deps)?;
|
||||||
|
|
||||||
let dapps_service = dapps::service(&dapps_middleware);
|
let dapps_service = dapps::service(&dapps_middleware);
|
||||||
let deps_for_rpc_apis = Arc::new(rpc_apis::FullDependencies {
|
let deps_for_rpc_apis = Arc::new(rpc_apis::FullDependencies {
|
||||||
@ -695,6 +722,7 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
|
|||||||
snapshot: snapshot_service.clone(),
|
snapshot: snapshot_service.clone(),
|
||||||
client: client.clone(),
|
client: client.clone(),
|
||||||
sync: sync_provider.clone(),
|
sync: sync_provider.clone(),
|
||||||
|
health: node_health,
|
||||||
net: manage_network.clone(),
|
net: manage_network.clone(),
|
||||||
secret_store: secret_store,
|
secret_store: secret_store,
|
||||||
miner: miner.clone(),
|
miner: miner.clone(),
|
||||||
|
@ -47,12 +47,13 @@ ethjson = { path = "../json" }
|
|||||||
ethcore-devtools = { path = "../devtools" }
|
ethcore-devtools = { path = "../devtools" }
|
||||||
ethcore-light = { path = "../ethcore/light" }
|
ethcore-light = { path = "../ethcore/light" }
|
||||||
ethcore-logger = { path = "../logger" }
|
ethcore-logger = { path = "../logger" }
|
||||||
vm = { path = "../ethcore/vm" }
|
|
||||||
parity-updater = { path = "../updater" }
|
|
||||||
parity-reactor = { path = "../util/reactor" }
|
|
||||||
rlp = { path = "../util/rlp" }
|
|
||||||
fetch = { path = "../util/fetch" }
|
fetch = { path = "../util/fetch" }
|
||||||
|
node-health = { path = "../dapps/node-health" }
|
||||||
|
parity-reactor = { path = "../util/reactor" }
|
||||||
|
parity-updater = { path = "../updater" }
|
||||||
|
rlp = { path = "../util/rlp" }
|
||||||
stats = { path = "../util/stats" }
|
stats = { path = "../util/stats" }
|
||||||
|
vm = { path = "../ethcore/vm" }
|
||||||
|
|
||||||
clippy = { version = "0.0.103", optional = true}
|
clippy = { version = "0.0.103", optional = true}
|
||||||
pretty_assertions = "0.1"
|
pretty_assertions = "0.1"
|
||||||
|
@ -55,6 +55,7 @@ extern crate ethsync;
|
|||||||
extern crate ethcore_logger;
|
extern crate ethcore_logger;
|
||||||
extern crate vm;
|
extern crate vm;
|
||||||
extern crate fetch;
|
extern crate fetch;
|
||||||
|
extern crate node_health;
|
||||||
extern crate parity_reactor;
|
extern crate parity_reactor;
|
||||||
extern crate parity_updater as updater;
|
extern crate parity_updater as updater;
|
||||||
extern crate rlp;
|
extern crate rlp;
|
||||||
|
@ -584,8 +584,9 @@ fn decrypt(accounts: &AccountProvider, address: Address, msg: Bytes, password: S
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Extract the default gas price from a client and miner.
|
/// Extract the default gas price from a client and miner.
|
||||||
pub fn default_gas_price<C, M>(client: &C, miner: &M) -> U256
|
pub fn default_gas_price<C, M>(client: &C, miner: &M) -> U256 where
|
||||||
where C: MiningBlockChainClient, M: MinerService
|
C: MiningBlockChainClient,
|
||||||
|
M: MinerService,
|
||||||
{
|
{
|
||||||
client.gas_price_corpus(100).median().cloned().unwrap_or_else(|| miner.sensible_gas_price())
|
client.gas_price_corpus(100).median().cloned().unwrap_or_else(|| miner.sensible_gas_price())
|
||||||
}
|
}
|
||||||
|
@ -24,8 +24,8 @@ use jsonrpc_core::Error;
|
|||||||
use v1::helpers::CallRequest;
|
use v1::helpers::CallRequest;
|
||||||
use v1::helpers::dispatch::default_gas_price;
|
use v1::helpers::dispatch::default_gas_price;
|
||||||
|
|
||||||
pub fn sign_call<B: MiningBlockChainClient, M: MinerService>(
|
pub fn sign_call<C: MiningBlockChainClient, M: MinerService> (
|
||||||
client: &Arc<B>,
|
client: &Arc<C>,
|
||||||
miner: &Arc<M>,
|
miner: &Arc<M>,
|
||||||
request: CallRequest,
|
request: CallRequest,
|
||||||
gas_cap: bool,
|
gas_cap: bool,
|
||||||
|
@ -19,15 +19,15 @@ use std::sync::Arc;
|
|||||||
use std::collections::{BTreeMap, HashSet};
|
use std::collections::{BTreeMap, HashSet};
|
||||||
use futures::{future, Future, BoxFuture};
|
use futures::{future, Future, BoxFuture};
|
||||||
|
|
||||||
use ethcore_logger::RotatingLogger;
|
|
||||||
use util::misc::version_data;
|
use util::misc::version_data;
|
||||||
|
|
||||||
use crypto::ecies;
|
use crypto::{ecies, DEFAULT_MAC};
|
||||||
use ethkey::{Brain, Generator};
|
use ethkey::{Brain, Generator};
|
||||||
use ethstore::random_phrase;
|
use ethstore::random_phrase;
|
||||||
use ethsync::LightSyncProvider;
|
use ethsync::LightSyncProvider;
|
||||||
use ethcore::account_provider::AccountProvider;
|
use ethcore::account_provider::AccountProvider;
|
||||||
use crypto::DEFAULT_MAC;
|
use ethcore_logger::RotatingLogger;
|
||||||
|
use node_health::{NodeHealth, Health};
|
||||||
|
|
||||||
use light::client::LightChainClient;
|
use light::client::LightChainClient;
|
||||||
|
|
||||||
@ -53,6 +53,7 @@ pub struct ParityClient {
|
|||||||
accounts: Arc<AccountProvider>,
|
accounts: Arc<AccountProvider>,
|
||||||
logger: Arc<RotatingLogger>,
|
logger: Arc<RotatingLogger>,
|
||||||
settings: Arc<NetworkSettings>,
|
settings: Arc<NetworkSettings>,
|
||||||
|
health: NodeHealth,
|
||||||
signer: Option<Arc<SignerService>>,
|
signer: Option<Arc<SignerService>>,
|
||||||
dapps_address: Option<(String, u16)>,
|
dapps_address: Option<(String, u16)>,
|
||||||
ws_address: Option<(String, u16)>,
|
ws_address: Option<(String, u16)>,
|
||||||
@ -67,18 +68,20 @@ impl ParityClient {
|
|||||||
accounts: Arc<AccountProvider>,
|
accounts: Arc<AccountProvider>,
|
||||||
logger: Arc<RotatingLogger>,
|
logger: Arc<RotatingLogger>,
|
||||||
settings: Arc<NetworkSettings>,
|
settings: Arc<NetworkSettings>,
|
||||||
|
health: NodeHealth,
|
||||||
signer: Option<Arc<SignerService>>,
|
signer: Option<Arc<SignerService>>,
|
||||||
dapps_address: Option<(String, u16)>,
|
dapps_address: Option<(String, u16)>,
|
||||||
ws_address: Option<(String, u16)>,
|
ws_address: Option<(String, u16)>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
ParityClient {
|
ParityClient {
|
||||||
light_dispatch: light_dispatch,
|
light_dispatch,
|
||||||
accounts: accounts,
|
accounts,
|
||||||
logger: logger,
|
logger,
|
||||||
settings: settings,
|
settings,
|
||||||
signer: signer,
|
health,
|
||||||
dapps_address: dapps_address,
|
signer,
|
||||||
ws_address: ws_address,
|
dapps_address,
|
||||||
|
ws_address,
|
||||||
eip86_transition: client.eip86_transition(),
|
eip86_transition: client.eip86_transition(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -393,4 +396,10 @@ impl Parity for ParityClient {
|
|||||||
fn call(&self, _meta: Self::Metadata, _requests: Vec<CallRequest>, _block: Trailing<BlockNumber>) -> BoxFuture<Vec<Bytes>, Error> {
|
fn call(&self, _meta: Self::Metadata, _requests: Vec<CallRequest>, _block: Trailing<BlockNumber>) -> BoxFuture<Vec<Bytes>, Error> {
|
||||||
future::err(errors::light_unimplemented(None)).boxed()
|
future::err(errors::light_unimplemented(None)).boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn node_health(&self) -> BoxFuture<Health, Error> {
|
||||||
|
self.health.health()
|
||||||
|
.map_err(|err| errors::internal("Health API failure.", err))
|
||||||
|
.boxed()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,11 +20,10 @@ use std::str::FromStr;
|
|||||||
use std::collections::{BTreeMap, HashSet};
|
use std::collections::{BTreeMap, HashSet};
|
||||||
use futures::{future, Future, BoxFuture};
|
use futures::{future, Future, BoxFuture};
|
||||||
|
|
||||||
use ethcore_logger::RotatingLogger;
|
|
||||||
use util::Address;
|
use util::Address;
|
||||||
use util::misc::version_data;
|
use util::misc::version_data;
|
||||||
|
|
||||||
use crypto::ecies;
|
use crypto::{DEFAULT_MAC, ecies};
|
||||||
use ethkey::{Brain, Generator};
|
use ethkey::{Brain, Generator};
|
||||||
use ethstore::random_phrase;
|
use ethstore::random_phrase;
|
||||||
use ethsync::{SyncProvider, ManageNetwork};
|
use ethsync::{SyncProvider, ManageNetwork};
|
||||||
@ -34,8 +33,9 @@ use ethcore::ids::BlockId;
|
|||||||
use ethcore::miner::MinerService;
|
use ethcore::miner::MinerService;
|
||||||
use ethcore::mode::Mode;
|
use ethcore::mode::Mode;
|
||||||
use ethcore::transaction::SignedTransaction;
|
use ethcore::transaction::SignedTransaction;
|
||||||
|
use ethcore_logger::RotatingLogger;
|
||||||
|
use node_health::{NodeHealth, Health};
|
||||||
use updater::{Service as UpdateService};
|
use updater::{Service as UpdateService};
|
||||||
use crypto::DEFAULT_MAC;
|
|
||||||
|
|
||||||
use jsonrpc_core::Error;
|
use jsonrpc_core::Error;
|
||||||
use jsonrpc_macros::Trailing;
|
use jsonrpc_macros::Trailing;
|
||||||
@ -53,17 +53,13 @@ use v1::types::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Parity implementation.
|
/// Parity implementation.
|
||||||
pub struct ParityClient<C, M, S: ?Sized, U> where
|
pub struct ParityClient<C, M, U> {
|
||||||
C: MiningBlockChainClient,
|
|
||||||
M: MinerService,
|
|
||||||
S: SyncProvider,
|
|
||||||
U: UpdateService,
|
|
||||||
{
|
|
||||||
client: Arc<C>,
|
client: Arc<C>,
|
||||||
miner: Arc<M>,
|
miner: Arc<M>,
|
||||||
sync: Arc<S>,
|
|
||||||
updater: Arc<U>,
|
updater: Arc<U>,
|
||||||
|
sync: Arc<SyncProvider>,
|
||||||
net: Arc<ManageNetwork>,
|
net: Arc<ManageNetwork>,
|
||||||
|
health: NodeHealth,
|
||||||
accounts: Option<Arc<AccountProvider>>,
|
accounts: Option<Arc<AccountProvider>>,
|
||||||
logger: Arc<RotatingLogger>,
|
logger: Arc<RotatingLogger>,
|
||||||
settings: Arc<NetworkSettings>,
|
settings: Arc<NetworkSettings>,
|
||||||
@ -73,39 +69,39 @@ pub struct ParityClient<C, M, S: ?Sized, U> where
|
|||||||
eip86_transition: u64,
|
eip86_transition: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, M, S: ?Sized, U> ParityClient<C, M, S, U> where
|
impl<C, M, U> ParityClient<C, M, U> where
|
||||||
C: MiningBlockChainClient,
|
C: MiningBlockChainClient,
|
||||||
M: MinerService,
|
|
||||||
S: SyncProvider,
|
|
||||||
U: UpdateService,
|
|
||||||
{
|
{
|
||||||
/// Creates new `ParityClient`.
|
/// Creates new `ParityClient`.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
client: &Arc<C>,
|
client: Arc<C>,
|
||||||
miner: &Arc<M>,
|
miner: Arc<M>,
|
||||||
sync: &Arc<S>,
|
sync: Arc<SyncProvider>,
|
||||||
updater: &Arc<U>,
|
updater: Arc<U>,
|
||||||
net: &Arc<ManageNetwork>,
|
net: Arc<ManageNetwork>,
|
||||||
store: &Option<Arc<AccountProvider>>,
|
health: NodeHealth,
|
||||||
|
accounts: Option<Arc<AccountProvider>>,
|
||||||
logger: Arc<RotatingLogger>,
|
logger: Arc<RotatingLogger>,
|
||||||
settings: Arc<NetworkSettings>,
|
settings: Arc<NetworkSettings>,
|
||||||
signer: Option<Arc<SignerService>>,
|
signer: Option<Arc<SignerService>>,
|
||||||
dapps_address: Option<(String, u16)>,
|
dapps_address: Option<(String, u16)>,
|
||||||
ws_address: Option<(String, u16)>,
|
ws_address: Option<(String, u16)>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
let eip86_transition = client.eip86_transition();
|
||||||
ParityClient {
|
ParityClient {
|
||||||
client: client.clone(),
|
client,
|
||||||
miner: miner.clone(),
|
miner,
|
||||||
sync: sync.clone(),
|
sync,
|
||||||
updater: updater.clone(),
|
updater,
|
||||||
net: net.clone(),
|
net,
|
||||||
accounts: store.clone(),
|
health,
|
||||||
logger: logger,
|
accounts,
|
||||||
settings: settings,
|
logger,
|
||||||
signer: signer,
|
settings,
|
||||||
dapps_address: dapps_address,
|
signer,
|
||||||
ws_address: ws_address,
|
dapps_address,
|
||||||
eip86_transition: client.eip86_transition(),
|
ws_address,
|
||||||
|
eip86_transition,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,10 +112,9 @@ impl<C, M, S: ?Sized, U> ParityClient<C, M, S, U> where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, M, S: ?Sized, U> Parity for ParityClient<C, M, S, U> where
|
impl<C, M, U> Parity for ParityClient<C, M, U> where
|
||||||
M: MinerService + 'static,
|
|
||||||
C: MiningBlockChainClient + 'static,
|
C: MiningBlockChainClient + 'static,
|
||||||
S: SyncProvider + 'static,
|
M: MinerService + 'static,
|
||||||
U: UpdateService + 'static,
|
U: UpdateService + 'static,
|
||||||
{
|
{
|
||||||
type Metadata = Metadata;
|
type Metadata = Metadata;
|
||||||
@ -429,4 +424,10 @@ impl<C, M, S: ?Sized, U> Parity for ParityClient<C, M, S, U> where
|
|||||||
|
|
||||||
future::done(result).boxed()
|
future::done(result).boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn node_health(&self) -> BoxFuture<Health, Error> {
|
||||||
|
self.health.health()
|
||||||
|
.map_err(|err| errors::internal("Health API failure.", err))
|
||||||
|
.boxed()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,13 +15,15 @@
|
|||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use ethcore_logger::RotatingLogger;
|
|
||||||
use util::{Address, U256};
|
|
||||||
use ethsync::ManageNetwork;
|
|
||||||
use ethcore::account_provider::AccountProvider;
|
use ethcore::account_provider::AccountProvider;
|
||||||
use ethcore::client::{TestBlockChainClient, Executed};
|
use ethcore::client::{TestBlockChainClient, Executed};
|
||||||
use ethcore::miner::LocalTransactionStatus;
|
use ethcore::miner::LocalTransactionStatus;
|
||||||
|
use ethcore_logger::RotatingLogger;
|
||||||
use ethstore::ethkey::{Generator, Random};
|
use ethstore::ethkey::{Generator, Random};
|
||||||
|
use ethsync::ManageNetwork;
|
||||||
|
use node_health::{self, NodeHealth};
|
||||||
|
use parity_reactor;
|
||||||
|
use util::Address;
|
||||||
|
|
||||||
use jsonrpc_core::IoHandler;
|
use jsonrpc_core::IoHandler;
|
||||||
use v1::{Parity, ParityClient};
|
use v1::{Parity, ParityClient};
|
||||||
@ -30,13 +32,14 @@ use v1::helpers::{SignerService, NetworkSettings};
|
|||||||
use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService, TestUpdater};
|
use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService, TestUpdater};
|
||||||
use super::manage_network::TestManageNetwork;
|
use super::manage_network::TestManageNetwork;
|
||||||
|
|
||||||
pub type TestParityClient = ParityClient<TestBlockChainClient, TestMinerService, TestSyncProvider, TestUpdater>;
|
pub type TestParityClient = ParityClient<TestBlockChainClient, TestMinerService, TestUpdater>;
|
||||||
|
|
||||||
pub struct Dependencies {
|
pub struct Dependencies {
|
||||||
pub miner: Arc<TestMinerService>,
|
pub miner: Arc<TestMinerService>,
|
||||||
pub client: Arc<TestBlockChainClient>,
|
pub client: Arc<TestBlockChainClient>,
|
||||||
pub sync: Arc<TestSyncProvider>,
|
pub sync: Arc<TestSyncProvider>,
|
||||||
pub updater: Arc<TestUpdater>,
|
pub updater: Arc<TestUpdater>,
|
||||||
|
pub health: NodeHealth,
|
||||||
pub logger: Arc<RotatingLogger>,
|
pub logger: Arc<RotatingLogger>,
|
||||||
pub settings: Arc<NetworkSettings>,
|
pub settings: Arc<NetworkSettings>,
|
||||||
pub network: Arc<ManageNetwork>,
|
pub network: Arc<ManageNetwork>,
|
||||||
@ -54,6 +57,11 @@ impl Dependencies {
|
|||||||
network_id: 3,
|
network_id: 3,
|
||||||
num_peers: 120,
|
num_peers: 120,
|
||||||
})),
|
})),
|
||||||
|
health: NodeHealth::new(
|
||||||
|
Arc::new(FakeSync),
|
||||||
|
node_health::TimeChecker::new::<String>(&[], node_health::CpuPool::new(1)),
|
||||||
|
parity_reactor::Remote::new_sync(),
|
||||||
|
),
|
||||||
updater: Arc::new(TestUpdater::default()),
|
updater: Arc::new(TestUpdater::default()),
|
||||||
logger: Arc::new(RotatingLogger::new("rpc=trace".to_owned())),
|
logger: Arc::new(RotatingLogger::new("rpc=trace".to_owned())),
|
||||||
settings: Arc::new(NetworkSettings {
|
settings: Arc::new(NetworkSettings {
|
||||||
@ -75,12 +83,13 @@ impl Dependencies {
|
|||||||
let opt_accounts = Some(self.accounts.clone());
|
let opt_accounts = Some(self.accounts.clone());
|
||||||
|
|
||||||
ParityClient::new(
|
ParityClient::new(
|
||||||
&self.client,
|
self.client.clone(),
|
||||||
&self.miner,
|
self.miner.clone(),
|
||||||
&self.sync,
|
self.sync.clone(),
|
||||||
&self.updater,
|
self.updater.clone(),
|
||||||
&self.network,
|
self.network.clone(),
|
||||||
&opt_accounts,
|
self.health.clone(),
|
||||||
|
opt_accounts.clone(),
|
||||||
self.logger.clone(),
|
self.logger.clone(),
|
||||||
self.settings.clone(),
|
self.settings.clone(),
|
||||||
signer,
|
signer,
|
||||||
@ -102,6 +111,13 @@ impl Dependencies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct FakeSync;
|
||||||
|
impl node_health::SyncStatus for FakeSync {
|
||||||
|
fn is_major_importing(&self) -> bool { false }
|
||||||
|
fn peers(&self) -> (usize, usize) { (4, 25) }
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rpc_parity_accounts_info() {
|
fn rpc_parity_accounts_info() {
|
||||||
let deps = Dependencies::new();
|
let deps = Dependencies::new();
|
||||||
@ -507,6 +523,8 @@ fn rpc_parity_cid() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rpc_parity_call() {
|
fn rpc_parity_call() {
|
||||||
|
use util::U256;
|
||||||
|
|
||||||
let deps = Dependencies::new();
|
let deps = Dependencies::new();
|
||||||
deps.client.set_execution_result(Ok(Executed {
|
deps.client.set_execution_result(Ok(Executed {
|
||||||
exception: None,
|
exception: None,
|
||||||
@ -541,3 +559,14 @@ fn rpc_parity_call() {
|
|||||||
|
|
||||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rpc_parity_node_health() {
|
||||||
|
let deps = Dependencies::new();
|
||||||
|
let io = deps.default_client();
|
||||||
|
|
||||||
|
let request = r#"{"jsonrpc": "2.0", "method": "parity_nodeHealth", "params":[], "id": 1}"#;
|
||||||
|
let response = r#"{"jsonrpc":"2.0","result":{"peers":{"details":[4,25],"message":"","status":"ok"},"sync":{"details":false,"message":"","status":"ok"},"time":{"details":0,"message":"","status":"ok"}},"id":1}"#;
|
||||||
|
|
||||||
|
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||||
|
}
|
||||||
|
@ -22,6 +22,7 @@ use jsonrpc_core::Error;
|
|||||||
use jsonrpc_macros::Trailing;
|
use jsonrpc_macros::Trailing;
|
||||||
use futures::BoxFuture;
|
use futures::BoxFuture;
|
||||||
|
|
||||||
|
use node_health::Health;
|
||||||
use v1::types::{
|
use v1::types::{
|
||||||
H160, H256, H512, U256, Bytes, CallRequest,
|
H160, H256, H512, U256, Bytes, CallRequest,
|
||||||
Peers, Transaction, RpcSettings, Histogram,
|
Peers, Transaction, RpcSettings, Histogram,
|
||||||
@ -207,5 +208,9 @@ build_rpc_trait! {
|
|||||||
/// Call contract, returning the output data.
|
/// Call contract, returning the output data.
|
||||||
#[rpc(meta, name = "parity_call")]
|
#[rpc(meta, name = "parity_call")]
|
||||||
fn call(&self, Self::Metadata, Vec<CallRequest>, Trailing<BlockNumber>) -> BoxFuture<Vec<Bytes>, Error>;
|
fn call(&self, Self::Metadata, Vec<CallRequest>, Trailing<BlockNumber>) -> BoxFuture<Vec<Bytes>, Error>;
|
||||||
|
|
||||||
|
/// Returns node's health report.
|
||||||
|
#[rpc(async, name = "parity_nodeHealth")]
|
||||||
|
fn node_health(&self) -> BoxFuture<Health, Error>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
extern crate futures;
|
extern crate futures;
|
||||||
extern crate tokio_core;
|
extern crate tokio_core;
|
||||||
|
|
||||||
use std::thread;
|
use std::{fmt, thread};
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use futures::{Future, IntoFuture};
|
use futures::{Future, IntoFuture};
|
||||||
@ -81,7 +81,19 @@ enum Mode {
|
|||||||
ThreadPerFuture,
|
ThreadPerFuture,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
impl fmt::Debug for Mode {
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
use self::Mode::*;
|
||||||
|
|
||||||
|
match *self {
|
||||||
|
Tokio(_) => write!(fmt, "tokio"),
|
||||||
|
Sync => write!(fmt, "synchronous"),
|
||||||
|
ThreadPerFuture => write!(fmt, "thread per future"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub struct Remote {
|
pub struct Remote {
|
||||||
inner: Mode,
|
inner: Mode,
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user