Remove light client
This commit is contained in:
@@ -14,14 +14,7 @@
|
||||
// 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 std::{
|
||||
fs, io,
|
||||
io::{BufRead, BufReader},
|
||||
str::from_utf8,
|
||||
sync::Arc,
|
||||
thread::sleep,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
use std::{fs, io, sync::Arc, time::Instant};
|
||||
|
||||
use ansi_term::Colour;
|
||||
use bytes::ToPretty;
|
||||
@@ -33,7 +26,6 @@ use ethcore::{
|
||||
Balance, BlockChainClient, BlockChainReset, BlockId, DatabaseCompactionProfile,
|
||||
ImportExportBlocks, Mode, Nonce, VMType,
|
||||
},
|
||||
error::{Error as EthcoreError, ErrorKind as EthcoreErrorKind, ImportErrorKind},
|
||||
miner::Miner,
|
||||
verification::queue::VerifierSettings,
|
||||
};
|
||||
@@ -44,8 +36,6 @@ use hash::{keccak, KECCAK_NULL_RLP};
|
||||
use helpers::{execute_upgrades, to_client_config};
|
||||
use informant::{FullNodeInformantData, Informant, MillisecondDuration};
|
||||
use params::{fatdb_switch_to_bool, tracing_switch_to_bool, Pruning, SpecType, Switch};
|
||||
use rlp::PayloadInfo;
|
||||
use rustc_hex::FromHex;
|
||||
use types::data_format::DataFormat;
|
||||
use user_defaults::UserDefaults;
|
||||
|
||||
@@ -96,7 +86,6 @@ pub struct ImportBlockchain {
|
||||
pub check_seal: bool,
|
||||
pub with_color: bool,
|
||||
pub verifier_settings: VerifierSettings,
|
||||
pub light: bool,
|
||||
pub max_round_blocks_to_import: usize,
|
||||
}
|
||||
|
||||
@@ -143,201 +132,13 @@ pub struct ExportState {
|
||||
pub fn execute(cmd: BlockchainCmd) -> Result<(), String> {
|
||||
match cmd {
|
||||
BlockchainCmd::Kill(kill_cmd) => kill_db(kill_cmd),
|
||||
BlockchainCmd::Import(import_cmd) => {
|
||||
if import_cmd.light {
|
||||
execute_import_light(import_cmd)
|
||||
} else {
|
||||
execute_import(import_cmd)
|
||||
}
|
||||
}
|
||||
BlockchainCmd::Import(import_cmd) => execute_import(import_cmd),
|
||||
BlockchainCmd::Export(export_cmd) => execute_export(export_cmd),
|
||||
BlockchainCmd::ExportState(export_cmd) => execute_export_state(export_cmd),
|
||||
BlockchainCmd::Reset(reset_cmd) => execute_reset(reset_cmd),
|
||||
}
|
||||
}
|
||||
|
||||
fn execute_import_light(cmd: ImportBlockchain) -> Result<(), String> {
|
||||
use light::{
|
||||
cache::Cache as LightDataCache,
|
||||
client::{Config as LightClientConfig, Service as LightClientService},
|
||||
};
|
||||
use parking_lot::Mutex;
|
||||
|
||||
let timer = Instant::now();
|
||||
|
||||
// load spec file
|
||||
let spec = cmd.spec.spec(&cmd.dirs.cache)?;
|
||||
|
||||
// load genesis hash
|
||||
let genesis_hash = spec.genesis_header().hash();
|
||||
|
||||
// database paths
|
||||
let db_dirs = cmd.dirs.database(genesis_hash, None, spec.data_dir.clone());
|
||||
|
||||
// user defaults path
|
||||
let user_defaults_path = db_dirs.user_defaults_path();
|
||||
|
||||
// load user defaults
|
||||
let user_defaults = UserDefaults::load(&user_defaults_path)?;
|
||||
|
||||
// select pruning algorithm
|
||||
let algorithm = cmd.pruning.to_algorithm(&user_defaults);
|
||||
|
||||
// prepare client and snapshot paths.
|
||||
let client_path = db_dirs.client_path(algorithm);
|
||||
|
||||
// execute upgrades
|
||||
execute_upgrades(&cmd.dirs.base, &db_dirs, algorithm, &cmd.compaction)?;
|
||||
|
||||
// create dirs used by parity
|
||||
cmd.dirs.create_dirs(false, false)?;
|
||||
|
||||
let cache = Arc::new(Mutex::new(LightDataCache::new(
|
||||
Default::default(),
|
||||
Duration::new(0, 0),
|
||||
)));
|
||||
|
||||
let mut config = LightClientConfig {
|
||||
queue: Default::default(),
|
||||
chain_column: ethcore_db::COL_LIGHT_CHAIN,
|
||||
verify_full: true,
|
||||
check_seal: cmd.check_seal,
|
||||
no_hardcoded_sync: true,
|
||||
};
|
||||
|
||||
config.queue.max_mem_use = cmd.cache_config.queue() as usize * 1024 * 1024;
|
||||
config.queue.verifier_settings = cmd.verifier_settings;
|
||||
|
||||
// initialize database.
|
||||
let db = db::open_db(
|
||||
&client_path
|
||||
.to_str()
|
||||
.expect("DB path could not be converted to string."),
|
||||
&cmd.cache_config,
|
||||
&cmd.compaction,
|
||||
)
|
||||
.map_err(|e| format!("Failed to open database: {:?}", e))?;
|
||||
|
||||
// TODO: could epoch signals be available at the end of the file?
|
||||
let fetch = ::light::client::fetch::unavailable();
|
||||
let service = LightClientService::start(config, &spec, fetch, db, cache)
|
||||
.map_err(|e| format!("Failed to start client: {}", e))?;
|
||||
|
||||
// free up the spec in memory.
|
||||
drop(spec);
|
||||
|
||||
let client = service.client();
|
||||
|
||||
let mut instream: Box<dyn io::Read> = match cmd.file_path {
|
||||
Some(f) => {
|
||||
Box::new(fs::File::open(&f).map_err(|_| format!("Cannot open given file: {}", f))?)
|
||||
}
|
||||
None => Box::new(io::stdin()),
|
||||
};
|
||||
|
||||
const READAHEAD_BYTES: usize = 8;
|
||||
|
||||
let mut first_bytes: Vec<u8> = vec![0; READAHEAD_BYTES];
|
||||
let mut first_read = 0;
|
||||
|
||||
let format = match cmd.format {
|
||||
Some(format) => format,
|
||||
None => {
|
||||
first_read = instream
|
||||
.read(&mut first_bytes)
|
||||
.map_err(|_| "Error reading from the file/stream.")?;
|
||||
match first_bytes[0] {
|
||||
0xf9 => DataFormat::Binary,
|
||||
_ => DataFormat::Hex,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let do_import = |bytes: Vec<u8>| {
|
||||
while client.queue_info().is_full() {
|
||||
sleep(Duration::from_secs(1));
|
||||
}
|
||||
|
||||
let header: ::types::header::Header = ::rlp::Rlp::new(&bytes)
|
||||
.val_at(0)
|
||||
.map_err(|e| format!("Bad block: {}", e))?;
|
||||
|
||||
if client.best_block_header().number() >= header.number() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if header.number() % 10000 == 0 {
|
||||
info!("#{}", header.number());
|
||||
}
|
||||
|
||||
match client.import_header(header) {
|
||||
Err(EthcoreError(EthcoreErrorKind::Import(ImportErrorKind::AlreadyInChain), _)) => {
|
||||
trace!("Skipping block already in chain.");
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(format!("Cannot import block: {:?}", e));
|
||||
}
|
||||
Ok(_) => {}
|
||||
}
|
||||
Ok(())
|
||||
};
|
||||
|
||||
match format {
|
||||
DataFormat::Binary => loop {
|
||||
let mut bytes = if first_read > 0 {
|
||||
first_bytes.clone()
|
||||
} else {
|
||||
vec![0; READAHEAD_BYTES]
|
||||
};
|
||||
let n = if first_read > 0 {
|
||||
first_read
|
||||
} else {
|
||||
instream
|
||||
.read(&mut bytes)
|
||||
.map_err(|_| "Error reading from the file/stream.")?
|
||||
};
|
||||
if n == 0 {
|
||||
break;
|
||||
}
|
||||
first_read = 0;
|
||||
let s = PayloadInfo::from(&bytes)
|
||||
.map_err(|e| format!("Invalid RLP in the file/stream: {:?}", e))?
|
||||
.total();
|
||||
bytes.resize(s, 0);
|
||||
instream
|
||||
.read_exact(&mut bytes[n..])
|
||||
.map_err(|_| "Error reading from the file/stream.")?;
|
||||
do_import(bytes)?;
|
||||
},
|
||||
DataFormat::Hex => {
|
||||
for line in BufReader::new(instream).lines() {
|
||||
let s = line.map_err(|_| "Error reading from the file/stream.")?;
|
||||
let s = if first_read > 0 {
|
||||
from_utf8(&first_bytes).unwrap().to_owned() + &(s[..])
|
||||
} else {
|
||||
s
|
||||
};
|
||||
first_read = 0;
|
||||
let bytes = s.from_hex().map_err(|_| "Invalid hex in file/stream.")?;
|
||||
do_import(bytes)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
client.flush_queue();
|
||||
|
||||
let ms = timer.elapsed().as_milliseconds();
|
||||
let report = client.report();
|
||||
|
||||
info!(
|
||||
"Import completed in {} seconds, {} headers, {} hdr/s",
|
||||
ms / 1000,
|
||||
report.blocks_imported,
|
||||
(report.blocks_imported * 1000) as u64 / ms,
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_import(cmd: ImportBlockchain) -> Result<(), String> {
|
||||
let timer = Instant::now();
|
||||
|
||||
|
||||
@@ -230,11 +230,6 @@ usage! {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CMD cmd_export_hardcoded_sync
|
||||
{
|
||||
"Print the hashed light clients headers of the given --chain (default: mainnet) in a JSON format. To be used as hardcoded headers in a genesis file.",
|
||||
}
|
||||
}
|
||||
{
|
||||
// Global flags and arguments
|
||||
@@ -247,14 +242,6 @@ usage! {
|
||||
"--no-consensus",
|
||||
"Force the binary to run even if there are known issues regarding consensus. Not recommended.",
|
||||
|
||||
FLAG flag_light: (bool) = false, or |c: &Config| c.parity.as_ref()?.light,
|
||||
"--light",
|
||||
"Experimental: run in light client mode. Light clients synchronize a bare minimum of data and fetch necessary data on-demand from the network. Much lower in storage, potentially higher in bandwidth. Has no effect with subcommands.",
|
||||
|
||||
FLAG flag_no_hardcoded_sync: (bool) = false, or |c: &Config| c.parity.as_ref()?.no_hardcoded_sync,
|
||||
"--no-hardcoded-sync",
|
||||
"By default, if there is no existing database the light client will automatically jump to a block hardcoded in the chain's specifications. This disables this feature.",
|
||||
|
||||
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.",
|
||||
@@ -392,10 +379,6 @@ usage! {
|
||||
"--no-ancient-blocks",
|
||||
"Disable downloading old blocks after snapshot restoration or warp sync. Not recommended.",
|
||||
|
||||
FLAG flag_no_serve_light: (bool) = false, or |c: &Config| c.network.as_ref()?.no_serve_light.clone(),
|
||||
"--no-serve-light",
|
||||
"Disable serving of light peers.",
|
||||
|
||||
ARG arg_warp_barrier: (Option<u64>) = None, or |c: &Config| c.network.as_ref()?.warp_barrier.clone(),
|
||||
"--warp-barrier=[NUM]",
|
||||
"When warp enabled never attempt regular sync before warping to block NUM.",
|
||||
@@ -574,27 +557,6 @@ usage! {
|
||||
"--ipfs-api-cors=[URL]",
|
||||
"Specify CORS header for IPFS API responses. Special options: \"all\", \"none\".",
|
||||
|
||||
["Light Client Options"]
|
||||
ARG arg_on_demand_response_time_window: (Option<u64>) = None, or |c: &Config| c.light.as_ref()?.on_demand_response_time_window,
|
||||
"--on-demand-time-window=[S]",
|
||||
"Specify the maximum time to wait for a successful response",
|
||||
|
||||
ARG arg_on_demand_request_backoff_start: (Option<u64>) = None, or |c: &Config| c.light.as_ref()?.on_demand_request_backoff_start,
|
||||
"--on-demand-start-backoff=[S]",
|
||||
"Specify light client initial backoff time for a request",
|
||||
|
||||
ARG arg_on_demand_request_backoff_max: (Option<u64>) = None, or |c: &Config| c.light.as_ref()?.on_demand_request_backoff_max,
|
||||
"--on-demand-end-backoff=[S]",
|
||||
"Specify light client maximum backoff time for a request",
|
||||
|
||||
ARG arg_on_demand_request_backoff_rounds_max: (Option<usize>) = None, or |c: &Config| c.light.as_ref()?.on_demand_request_backoff_rounds_max,
|
||||
"--on-demand-max-backoff-rounds=[TIMES]",
|
||||
"Specify light client maximum number of backoff iterations for a request",
|
||||
|
||||
ARG arg_on_demand_request_consecutive_failures: (Option<usize>) = None, or |c: &Config| c.light.as_ref()?.on_demand_request_consecutive_failures,
|
||||
"--on-demand-consecutive-failures=[TIMES]",
|
||||
"Specify light client the number of failures for a request until it gets exponentially backed off",
|
||||
|
||||
["Secret Store Options"]
|
||||
FLAG flag_no_secretstore: (bool) = false, or |c: &Config| c.secretstore.as_ref()?.disable.clone(),
|
||||
"--no-secretstore",
|
||||
@@ -926,7 +888,6 @@ struct Config {
|
||||
snapshots: Option<Snapshots>,
|
||||
misc: Option<Misc>,
|
||||
stratum: Option<Stratum>,
|
||||
light: Option<Light>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, PartialEq, Deserialize)]
|
||||
@@ -946,9 +907,7 @@ struct Operating {
|
||||
db_path: Option<String>,
|
||||
keys_path: Option<String>,
|
||||
identity: Option<String>,
|
||||
light: Option<bool>,
|
||||
no_persistent_txqueue: Option<bool>,
|
||||
no_hardcoded_sync: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, PartialEq, Deserialize)]
|
||||
@@ -998,7 +957,6 @@ struct Network {
|
||||
node_key: Option<String>,
|
||||
reserved_peers: Option<String>,
|
||||
reserved_only: Option<bool>,
|
||||
no_serve_light: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, PartialEq, Deserialize)]
|
||||
@@ -1154,21 +1112,11 @@ struct Misc {
|
||||
unsafe_expose: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, PartialEq, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
struct Light {
|
||||
on_demand_response_time_window: Option<u64>,
|
||||
on_demand_request_backoff_start: Option<u64>,
|
||||
on_demand_request_backoff_max: Option<u64>,
|
||||
on_demand_request_backoff_rounds_max: Option<usize>,
|
||||
on_demand_request_consecutive_failures: Option<usize>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{
|
||||
Account, Args, ArgsError, Config, Footprint, Ipc, Ipfs, Light, Mining, Misc, Network,
|
||||
Operating, Rpc, SecretStore, Snapshots, Ws,
|
||||
Account, Args, ArgsError, Config, Footprint, Ipc, Ipfs, Mining, Misc, Network, Operating,
|
||||
Rpc, SecretStore, Snapshots, Ws,
|
||||
};
|
||||
use clap::ErrorKind as ClapErrorKind;
|
||||
use toml;
|
||||
@@ -1373,7 +1321,6 @@ mod tests {
|
||||
cmd_db: false,
|
||||
cmd_db_kill: false,
|
||||
cmd_db_reset: false,
|
||||
cmd_export_hardcoded_sync: false,
|
||||
|
||||
// Arguments
|
||||
arg_daemon_pid_file: None,
|
||||
@@ -1408,8 +1355,6 @@ mod tests {
|
||||
arg_db_path: Some("$HOME/.parity/chains".into()),
|
||||
arg_keys_path: "$HOME/.parity/keys".into(),
|
||||
arg_identity: "".into(),
|
||||
flag_light: false,
|
||||
flag_no_hardcoded_sync: false,
|
||||
flag_no_persistent_txqueue: false,
|
||||
flag_force_direct: false,
|
||||
|
||||
@@ -1453,7 +1398,6 @@ mod tests {
|
||||
arg_reserved_peers: Some("./path_to_file".into()),
|
||||
flag_reserved_only: false,
|
||||
flag_no_ancient_blocks: false,
|
||||
flag_no_serve_light: false,
|
||||
arg_warp_barrier: None,
|
||||
|
||||
// -- API and Console Options
|
||||
@@ -1582,13 +1526,6 @@ mod tests {
|
||||
flag_no_periodic_snapshot: false,
|
||||
arg_snapshot_threads: None,
|
||||
|
||||
// -- Light options.
|
||||
arg_on_demand_response_time_window: Some(2),
|
||||
arg_on_demand_request_backoff_start: Some(9),
|
||||
arg_on_demand_request_backoff_max: Some(15),
|
||||
arg_on_demand_request_backoff_rounds_max: Some(100),
|
||||
arg_on_demand_request_consecutive_failures: Some(1),
|
||||
|
||||
// -- Internal Options
|
||||
flag_can_restart: false,
|
||||
|
||||
@@ -1648,8 +1585,6 @@ mod tests {
|
||||
db_path: None,
|
||||
keys_path: None,
|
||||
identity: None,
|
||||
light: None,
|
||||
no_hardcoded_sync: None,
|
||||
no_persistent_txqueue: None,
|
||||
}),
|
||||
account: Some(Account {
|
||||
@@ -1677,7 +1612,6 @@ mod tests {
|
||||
node_key: None,
|
||||
reserved_peers: Some("./path/to/reserved_peers".into()),
|
||||
reserved_only: Some(true),
|
||||
no_serve_light: None,
|
||||
}),
|
||||
websockets: Some(Ws {
|
||||
disable: Some(true),
|
||||
@@ -1787,13 +1721,6 @@ mod tests {
|
||||
scale_verifiers: Some(false),
|
||||
num_verifiers: None,
|
||||
}),
|
||||
light: Some(Light {
|
||||
on_demand_response_time_window: Some(2),
|
||||
on_demand_request_backoff_start: Some(9),
|
||||
on_demand_request_backoff_max: Some(15),
|
||||
on_demand_request_backoff_rounds_max: Some(10),
|
||||
on_demand_request_consecutive_failures: Some(1),
|
||||
}),
|
||||
snapshots: Some(Snapshots {
|
||||
disable_periodic: Some(true),
|
||||
processing_threads: None,
|
||||
|
||||
@@ -15,8 +15,6 @@ base_path = "$HOME/.parity"
|
||||
db_path = "$HOME/.parity/chains"
|
||||
keys_path = "$HOME/.parity/keys"
|
||||
identity = ""
|
||||
light = false
|
||||
no_hardcoded_sync = false
|
||||
|
||||
[account]
|
||||
unlock = ["0xdeadbeefcafe0000000000000000000000000000"]
|
||||
@@ -47,7 +45,6 @@ warp = true
|
||||
allow_ips = "all"
|
||||
snapshot_peers = 0
|
||||
max_pending_peers = 64
|
||||
no_serve_light = false
|
||||
|
||||
reserved_only = false
|
||||
reserved_peers = "./path_to_file"
|
||||
@@ -142,13 +139,6 @@ fat_db = "auto"
|
||||
scale_verifiers = true
|
||||
num_verifiers = 6
|
||||
|
||||
[light]
|
||||
on_demand_response_time_window = 2
|
||||
on_demand_request_backoff_start = 9
|
||||
on_demand_request_backoff_max = 15
|
||||
on_demand_request_backoff_rounds_max = 100
|
||||
on_demand_request_consecutive_failures = 1
|
||||
|
||||
[snapshots]
|
||||
disable_periodic = false
|
||||
|
||||
|
||||
@@ -62,13 +62,6 @@ db_compaction = "ssd"
|
||||
fat_db = "off"
|
||||
scale_verifiers = false
|
||||
|
||||
[light]
|
||||
on_demand_response_time_window = 2
|
||||
on_demand_request_backoff_start = 9
|
||||
on_demand_request_backoff_max = 15
|
||||
on_demand_request_backoff_rounds_max = 10
|
||||
on_demand_request_consecutive_failures = 1
|
||||
|
||||
[snapshots]
|
||||
disable_periodic = true
|
||||
|
||||
|
||||
@@ -53,7 +53,6 @@ use dir::{
|
||||
};
|
||||
use ethcore_logger::Config as LogConfig;
|
||||
use ethcore_private_tx::{EncryptorConfig, ProviderConfig};
|
||||
use export_hardcoded_sync::ExportHsyncCmd;
|
||||
use helpers::{
|
||||
parity_ipc_path, to_address, to_addresses, to_block_id, to_bootnodes, to_duration, to_mode,
|
||||
to_pending_set, to_price, to_queue_penalization, to_queue_strategy, to_u256,
|
||||
@@ -103,7 +102,6 @@ pub enum Cmd {
|
||||
},
|
||||
Snapshot(SnapshotCommand),
|
||||
Hash(Option<String>),
|
||||
ExportHardcodedSync(ExportHsyncCmd),
|
||||
}
|
||||
|
||||
pub struct Execute {
|
||||
@@ -286,7 +284,6 @@ impl Configuration {
|
||||
check_seal: !self.args.flag_no_seal_check,
|
||||
with_color: logger_config.color,
|
||||
verifier_settings: self.verifier_settings(),
|
||||
light: self.args.flag_light,
|
||||
max_round_blocks_to_import: self.args.arg_max_round_blocks_to_import,
|
||||
};
|
||||
Cmd::Blockchain(BlockchainCmd::Import(import_cmd))
|
||||
@@ -376,15 +373,6 @@ impl Configuration {
|
||||
snapshot_conf: snapshot_conf,
|
||||
};
|
||||
Cmd::Snapshot(restore_cmd)
|
||||
} else if self.args.cmd_export_hardcoded_sync {
|
||||
let export_hs_cmd = ExportHsyncCmd {
|
||||
cache_config: cache_config,
|
||||
dirs: dirs,
|
||||
spec: spec,
|
||||
pruning: pruning,
|
||||
compaction: compaction,
|
||||
};
|
||||
Cmd::ExportHardcodedSync(export_hs_cmd)
|
||||
} else {
|
||||
let daemon = if self.args.cmd_daemon {
|
||||
Some(
|
||||
@@ -444,20 +432,8 @@ impl Configuration {
|
||||
check_seal: !self.args.flag_no_seal_check,
|
||||
download_old_blocks: !self.args.flag_no_ancient_blocks,
|
||||
verifier_settings: verifier_settings,
|
||||
serve_light: !self.args.flag_no_serve_light,
|
||||
light: self.args.flag_light,
|
||||
no_persistent_txqueue: self.args.flag_no_persistent_txqueue,
|
||||
no_hardcoded_sync: self.args.flag_no_hardcoded_sync,
|
||||
max_round_blocks_to_import: self.args.arg_max_round_blocks_to_import,
|
||||
on_demand_response_time_window: self.args.arg_on_demand_response_time_window,
|
||||
on_demand_request_backoff_start: self.args.arg_on_demand_request_backoff_start,
|
||||
on_demand_request_backoff_max: self.args.arg_on_demand_request_backoff_max,
|
||||
on_demand_request_backoff_rounds_max: self
|
||||
.args
|
||||
.arg_on_demand_request_backoff_rounds_max,
|
||||
on_demand_request_consecutive_failures: self
|
||||
.args
|
||||
.arg_on_demand_request_consecutive_failures,
|
||||
};
|
||||
Cmd::Run(run_cmd)
|
||||
};
|
||||
@@ -1106,16 +1082,7 @@ impl Configuration {
|
||||
let is_using_base_path = self.args.arg_base_path.is_some();
|
||||
// If base_path is set and db_path is not we default to base path subdir instead of LOCAL.
|
||||
let base_db_path = if is_using_base_path && self.args.arg_db_path.is_none() {
|
||||
if self.args.flag_light {
|
||||
"$BASE/chains_light"
|
||||
} else {
|
||||
"$BASE/chains"
|
||||
}
|
||||
} else if self.args.flag_light {
|
||||
self.args
|
||||
.arg_db_path
|
||||
.as_ref()
|
||||
.map_or(dir::CHAINS_PATH_LIGHT, |s| &s)
|
||||
"$BASE/chains"
|
||||
} else {
|
||||
self.args
|
||||
.arg_db_path
|
||||
@@ -1479,7 +1446,6 @@ mod tests {
|
||||
check_seal: true,
|
||||
with_color: !cfg!(windows),
|
||||
verifier_settings: Default::default(),
|
||||
light: false,
|
||||
max_round_blocks_to_import: 12,
|
||||
}))
|
||||
);
|
||||
@@ -1674,16 +1640,8 @@ mod tests {
|
||||
check_seal: true,
|
||||
download_old_blocks: true,
|
||||
verifier_settings: Default::default(),
|
||||
serve_light: true,
|
||||
light: false,
|
||||
no_hardcoded_sync: false,
|
||||
no_persistent_txqueue: false,
|
||||
max_round_blocks_to_import: 12,
|
||||
on_demand_response_time_window: None,
|
||||
on_demand_request_backoff_start: None,
|
||||
on_demand_request_backoff_max: None,
|
||||
on_demand_request_backoff_rounds_max: None,
|
||||
on_demand_request_consecutive_failures: None,
|
||||
};
|
||||
expected.secretstore_conf.enabled = cfg!(feature = "secretstore");
|
||||
expected.secretstore_conf.http_enabled = cfg!(feature = "secretstore");
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#[path = "rocksdb/mod.rs"]
|
||||
mod impls;
|
||||
|
||||
pub use self::impls::{migrate, open_db, restoration_db_handler};
|
||||
pub use self::impls::{migrate, restoration_db_handler};
|
||||
|
||||
#[cfg(feature = "secretstore")]
|
||||
pub use self::impls::open_secretstore_db;
|
||||
|
||||
@@ -23,13 +23,10 @@ use self::{
|
||||
kvdb_rocksdb::{Database, DatabaseConfig},
|
||||
};
|
||||
use blooms_db;
|
||||
use ethcore::client::{ClientConfig, DatabaseCompactionProfile};
|
||||
use ethcore_db::NUM_COLUMNS;
|
||||
use ethcore::client::ClientConfig;
|
||||
use kvdb::KeyValueDB;
|
||||
use std::{fs, io, path::Path, sync::Arc};
|
||||
|
||||
use cache::CacheConfig;
|
||||
|
||||
mod blooms;
|
||||
mod helpers;
|
||||
mod migration;
|
||||
@@ -93,23 +90,6 @@ pub fn restoration_db_handler(
|
||||
})
|
||||
}
|
||||
|
||||
/// Open a new main DB.
|
||||
pub fn open_db(
|
||||
client_path: &str,
|
||||
cache_config: &CacheConfig,
|
||||
compaction: &DatabaseCompactionProfile,
|
||||
) -> io::Result<Arc<dyn BlockChainDB>> {
|
||||
let path = Path::new(client_path);
|
||||
|
||||
let db_config = DatabaseConfig {
|
||||
memory_budget: Some(cache_config.blockchain() as usize * 1024 * 1024),
|
||||
compaction: helpers::compaction_profile(&compaction, path),
|
||||
..DatabaseConfig::with_columns(NUM_COLUMNS)
|
||||
};
|
||||
|
||||
open_database(client_path, &db_config)
|
||||
}
|
||||
|
||||
pub fn open_database(
|
||||
client_path: &str,
|
||||
config: &DatabaseConfig,
|
||||
|
||||
@@ -1,121 +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 std::{sync::Arc, time::Duration};
|
||||
|
||||
use ethcore::{
|
||||
client::DatabaseCompactionProfile,
|
||||
spec::{OptimizeFor, SpecParams},
|
||||
};
|
||||
use light::{client::fetch::Unavailable as UnavailableDataFetcher, Cache as LightDataCache};
|
||||
|
||||
use cache::CacheConfig;
|
||||
use db;
|
||||
use dir::Directories;
|
||||
use helpers::execute_upgrades;
|
||||
use params::{Pruning, SpecType};
|
||||
use user_defaults::UserDefaults;
|
||||
|
||||
// Number of minutes before a given gas price corpus should expire.
|
||||
// Light client only.
|
||||
const GAS_CORPUS_EXPIRATION_MINUTES: u64 = 60 * 6;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct ExportHsyncCmd {
|
||||
pub cache_config: CacheConfig,
|
||||
pub dirs: Directories,
|
||||
pub spec: SpecType,
|
||||
pub pruning: Pruning,
|
||||
pub compaction: DatabaseCompactionProfile,
|
||||
}
|
||||
|
||||
pub fn execute(cmd: ExportHsyncCmd) -> Result<String, String> {
|
||||
use light::client as light_client;
|
||||
use parking_lot::Mutex;
|
||||
|
||||
// load spec
|
||||
let spec = cmd.spec.spec(SpecParams::new(
|
||||
cmd.dirs.cache.as_ref(),
|
||||
OptimizeFor::Memory,
|
||||
))?;
|
||||
|
||||
// load genesis hash
|
||||
let genesis_hash = spec.genesis_header().hash();
|
||||
|
||||
// database paths
|
||||
let db_dirs = cmd.dirs.database(
|
||||
genesis_hash,
|
||||
cmd.spec.legacy_fork_name(),
|
||||
spec.data_dir.clone(),
|
||||
);
|
||||
|
||||
// user defaults path
|
||||
let user_defaults_path = db_dirs.user_defaults_path();
|
||||
|
||||
// load user defaults
|
||||
let user_defaults = UserDefaults::load(&user_defaults_path)?;
|
||||
|
||||
// select pruning algorithm
|
||||
let algorithm = cmd.pruning.to_algorithm(&user_defaults);
|
||||
|
||||
// execute upgrades
|
||||
execute_upgrades(&cmd.dirs.base, &db_dirs, algorithm, &cmd.compaction)?;
|
||||
|
||||
// create dirs used by parity
|
||||
cmd.dirs.create_dirs(false, false)?;
|
||||
|
||||
// TODO: configurable cache size.
|
||||
let cache = LightDataCache::new(
|
||||
Default::default(),
|
||||
Duration::from_secs(60 * GAS_CORPUS_EXPIRATION_MINUTES),
|
||||
);
|
||||
let cache = Arc::new(Mutex::new(cache));
|
||||
|
||||
// start client and create transaction queue.
|
||||
let mut config = light_client::Config {
|
||||
queue: Default::default(),
|
||||
chain_column: ::ethcore_db::COL_LIGHT_CHAIN,
|
||||
verify_full: true,
|
||||
check_seal: true,
|
||||
no_hardcoded_sync: true,
|
||||
};
|
||||
|
||||
config.queue.max_mem_use = cmd.cache_config.queue() as usize * 1024 * 1024;
|
||||
|
||||
// initialize database.
|
||||
let db = db::open_db(
|
||||
&db_dirs
|
||||
.client_path(algorithm)
|
||||
.to_str()
|
||||
.expect("DB path could not be converted to string."),
|
||||
&cmd.cache_config,
|
||||
&cmd.compaction,
|
||||
)
|
||||
.map_err(|e| format!("Failed to open database {:?}", e))?;
|
||||
|
||||
let service = light_client::Service::start(config, &spec, UnavailableDataFetcher, db, cache)
|
||||
.map_err(|e| format!("Error starting light client: {}", e))?;
|
||||
|
||||
let hs = service
|
||||
.client()
|
||||
.read_hardcoded_sync()
|
||||
.map_err(|e| format!("Error reading hardcoded sync: {}", e))?;
|
||||
if let Some(hs) = hs {
|
||||
Ok(::serde_json::to_string_pretty(&hs.to_json()).expect("generated JSON is always valid"))
|
||||
} else {
|
||||
Err("Error: cannot generate hardcoded sync because the database is empty.".into())
|
||||
}
|
||||
}
|
||||
@@ -37,16 +37,11 @@ use ethcore::{
|
||||
},
|
||||
snapshot::{service::Service as SnapshotService, RestorationStatus, SnapshotService as SS},
|
||||
};
|
||||
use ethereum_types::H256;
|
||||
use io::{IoContext, IoHandler, TimerToken};
|
||||
use light::{
|
||||
client::{LightChainClient, LightChainNotify},
|
||||
Cache as LightDataCache,
|
||||
};
|
||||
use number_prefix::{binary_prefix, Prefixed, Standalone};
|
||||
use parity_rpc::{informant::RpcStats, is_major_importing_or_waiting};
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use sync::{LightSync, LightSyncProvider, ManageNetwork, SyncProvider};
|
||||
use sync::{ManageNetwork, SyncProvider};
|
||||
use types::BlockNumber;
|
||||
|
||||
/// Format byte counts to standard denominations.
|
||||
@@ -189,53 +184,6 @@ impl InformantData for FullNodeInformantData {
|
||||
}
|
||||
}
|
||||
|
||||
/// Informant data for a light node -- note that the network is required.
|
||||
pub struct LightNodeInformantData {
|
||||
pub client: Arc<dyn LightChainClient>,
|
||||
pub sync: Arc<LightSync>,
|
||||
pub cache: Arc<Mutex<LightDataCache>>,
|
||||
}
|
||||
|
||||
impl InformantData for LightNodeInformantData {
|
||||
fn executes_transactions(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn is_major_importing(&self) -> bool {
|
||||
self.sync.is_major_importing()
|
||||
}
|
||||
|
||||
fn report(&self) -> Report {
|
||||
let (client_report, queue_info, chain_info) = (
|
||||
self.client.report(),
|
||||
self.client.queue_info(),
|
||||
self.client.chain_info(),
|
||||
);
|
||||
|
||||
let mut cache_sizes = CacheSizes::default();
|
||||
cache_sizes.insert("queue", queue_info.mem_used);
|
||||
cache_sizes.insert("cache", self.cache.lock().mem_used());
|
||||
|
||||
let peer_numbers = self.sync.peer_numbers();
|
||||
let sync_info = Some(SyncInfo {
|
||||
last_imported_block_number: chain_info.best_block_number,
|
||||
last_imported_old_block_number: None,
|
||||
num_peers: peer_numbers.connected,
|
||||
max_peers: peer_numbers.max as u32,
|
||||
snapshot_sync: false,
|
||||
});
|
||||
|
||||
Report {
|
||||
importing: self.sync.is_major_importing(),
|
||||
chain_info,
|
||||
client_report,
|
||||
queue_info,
|
||||
cache_sizes,
|
||||
sync_info,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Informant<T> {
|
||||
last_tick: RwLock<Instant>,
|
||||
with_color: bool,
|
||||
@@ -449,36 +397,6 @@ impl ChainNotify for Informant<FullNodeInformantData> {
|
||||
}
|
||||
}
|
||||
|
||||
impl LightChainNotify for Informant<LightNodeInformantData> {
|
||||
fn new_headers(&self, good: &[H256]) {
|
||||
let mut last_import = self.last_import.lock();
|
||||
let client = &self.target.client;
|
||||
|
||||
let importing = self.target.is_major_importing();
|
||||
let ripe = Instant::now() > *last_import + Duration::from_secs(1) && !importing;
|
||||
|
||||
if ripe {
|
||||
if let Some(header) = good
|
||||
.last()
|
||||
.and_then(|h| client.block_header(BlockId::Hash(*h)))
|
||||
{
|
||||
info!(target: "import", "Imported {} {} ({} Mgas){}",
|
||||
Colour::White.bold().paint(format!("#{}", header.number())),
|
||||
Colour::White.bold().paint(format!("{}", header.hash())),
|
||||
Colour::Yellow.bold().paint(format!("{:.2}", header.gas_used().low_u64() as f32 / 1000000f32)),
|
||||
if good.len() > 1 {
|
||||
format!(" + another {} header(s)",
|
||||
Colour::Red.bold().paint(format!("{}", good.len() - 1)))
|
||||
} else {
|
||||
String::new()
|
||||
}
|
||||
);
|
||||
*last_import = Instant::now();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const INFO_TIMER: TimerToken = 0;
|
||||
|
||||
impl<T: InformantData> IoHandler<ClientIoMessage> for Informant<T> {
|
||||
|
||||
@@ -46,7 +46,6 @@ extern crate ethcore;
|
||||
extern crate ethcore_call_contract as call_contract;
|
||||
extern crate ethcore_db;
|
||||
extern crate ethcore_io as io;
|
||||
extern crate ethcore_light as light;
|
||||
extern crate ethcore_logger;
|
||||
extern crate ethcore_miner as miner;
|
||||
extern crate ethcore_network as network;
|
||||
@@ -98,11 +97,9 @@ mod cache;
|
||||
mod cli;
|
||||
mod configuration;
|
||||
mod db;
|
||||
mod export_hardcoded_sync;
|
||||
mod helpers;
|
||||
mod informant;
|
||||
mod ipfs;
|
||||
mod light_helpers;
|
||||
mod modules;
|
||||
mod params;
|
||||
mod presale;
|
||||
@@ -235,9 +232,6 @@ where
|
||||
Cmd::Snapshot(snapshot_cmd) => {
|
||||
snapshot::execute(snapshot_cmd).map(|s| ExecutionAction::Instant(Some(s)))
|
||||
}
|
||||
Cmd::ExportHardcodedSync(export_hs_cmd) => {
|
||||
export_hardcoded_sync::execute(export_hs_cmd).map(|s| ExecutionAction::Instant(Some(s)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,100 +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 std::sync::{Arc, Weak};
|
||||
|
||||
use ethcore::{
|
||||
engines::{EthEngine, StateDependentProof},
|
||||
machine::EthereumMachine,
|
||||
};
|
||||
use sync::{LightNetworkDispatcher, LightSync};
|
||||
use types::{encoded, header::Header, receipt::Receipt};
|
||||
|
||||
use futures::{future, future::Either, Future};
|
||||
|
||||
use light::{
|
||||
client::fetch::ChainDataFetcher,
|
||||
on_demand::{request, OnDemand, OnDemandRequester},
|
||||
};
|
||||
|
||||
use ethereum_types::H256;
|
||||
use parking_lot::RwLock;
|
||||
|
||||
const ALL_VALID_BACKREFS: &str = "no back-references, therefore all back-references valid; qed";
|
||||
|
||||
type BoxFuture<T, E> = Box<dyn Future<Item = T, Error = E>>;
|
||||
|
||||
/// Allows on-demand fetch of data useful for the light client.
|
||||
pub struct EpochFetch {
|
||||
/// A handle to the sync service.
|
||||
pub sync: Arc<RwLock<Weak<LightSync>>>,
|
||||
/// The on-demand request service.
|
||||
pub on_demand: Arc<OnDemand>,
|
||||
}
|
||||
|
||||
impl EpochFetch {
|
||||
fn request<T>(&self, req: T) -> BoxFuture<T::Out, &'static str>
|
||||
where
|
||||
T: Send + request::RequestAdapter + 'static,
|
||||
T::Out: Send + 'static,
|
||||
{
|
||||
Box::new(match self.sync.read().upgrade() {
|
||||
Some(sync) => {
|
||||
let on_demand = &self.on_demand;
|
||||
let maybe_future = sync.with_context(move |ctx| {
|
||||
on_demand.request(ctx, req).expect(ALL_VALID_BACKREFS)
|
||||
});
|
||||
|
||||
match maybe_future {
|
||||
Some(x) => Either::A(x.map_err(|_| "Request canceled")),
|
||||
None => Either::B(future::err("Unable to access network.")),
|
||||
}
|
||||
}
|
||||
None => Either::B(future::err("Unable to access network")),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ChainDataFetcher for EpochFetch {
|
||||
type Error = &'static str;
|
||||
|
||||
type Body = BoxFuture<encoded::Block, &'static str>;
|
||||
type Receipts = BoxFuture<Vec<Receipt>, &'static str>;
|
||||
type Transition = BoxFuture<Vec<u8>, &'static str>;
|
||||
|
||||
fn block_body(&self, header: &Header) -> Self::Body {
|
||||
self.request(request::Body(header.encoded().into()))
|
||||
}
|
||||
|
||||
/// Fetch block receipts.
|
||||
fn block_receipts(&self, header: &Header) -> Self::Receipts {
|
||||
self.request(request::BlockReceipts(header.encoded().into()))
|
||||
}
|
||||
|
||||
/// Fetch epoch transition proof at given header.
|
||||
fn epoch_transition(
|
||||
&self,
|
||||
hash: H256,
|
||||
engine: Arc<dyn EthEngine>,
|
||||
checker: Arc<dyn StateDependentProof<EthereumMachine>>,
|
||||
) -> Self::Transition {
|
||||
self.request(request::Signal {
|
||||
hash: hash,
|
||||
engine: engine,
|
||||
proof_check: checker,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,21 +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/>.
|
||||
|
||||
//! Utilities and helpers for the light client.
|
||||
|
||||
mod epoch_fetch;
|
||||
|
||||
pub use self::epoch_fetch::EpochFetch;
|
||||
@@ -17,7 +17,6 @@
|
||||
use std::sync::{mpsc, Arc};
|
||||
|
||||
use ethcore::{client::BlockChainClient, snapshot::SnapshotService};
|
||||
use light::Provider;
|
||||
use sync::{self, ConnectionFilter, NetworkConfiguration, Params, SyncConfig};
|
||||
|
||||
pub use ethcore::client::ChainNotify;
|
||||
@@ -37,7 +36,6 @@ pub fn sync(
|
||||
chain: Arc<dyn BlockChainClient>,
|
||||
snapshot_service: Arc<dyn SnapshotService>,
|
||||
private_tx_handler: Option<Arc<dyn PrivateTxHandler>>,
|
||||
provider: Arc<dyn Provider>,
|
||||
_log_settings: &LogConfig,
|
||||
connection_filter: Option<Arc<dyn ConnectionFilter>>,
|
||||
) -> Result<SyncModules, sync::Error> {
|
||||
@@ -45,7 +43,6 @@ pub fn sync(
|
||||
Params {
|
||||
config,
|
||||
chain,
|
||||
provider,
|
||||
snapshot_service,
|
||||
private_tx_handler,
|
||||
network_config,
|
||||
|
||||
@@ -14,34 +14,25 @@
|
||||
// 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 std::{
|
||||
cmp::PartialEq,
|
||||
collections::HashSet,
|
||||
str::FromStr,
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
use std::{cmp::PartialEq, collections::HashSet, str::FromStr, sync::Arc};
|
||||
|
||||
pub use parity_rpc::signer::SignerService;
|
||||
|
||||
use account_utils::{self, AccountProvider};
|
||||
use ethcore::{client::Client, miner::Miner, snapshot::SnapshotService};
|
||||
use ethcore_logger::RotatingLogger;
|
||||
use ethcore_private_tx::Provider as PrivateTransactionManager;
|
||||
use ethcore_service::PrivateTxService;
|
||||
use hash_fetch::fetch::Client as FetchClient;
|
||||
use jsonrpc_core::{self as core, MetaIoHandler};
|
||||
use light::{
|
||||
client::LightChainClient, Cache as LightDataCache, TransactionQueue as LightTransactionQueue,
|
||||
};
|
||||
use miner::external::ExternalMiner;
|
||||
use parity_rpc::{
|
||||
dispatch::{FullDispatcher, LightDispatcher},
|
||||
dispatch::FullDispatcher,
|
||||
informant::{ActivityNotifier, ClientNotifier},
|
||||
Host, Metadata, NetworkSettings,
|
||||
};
|
||||
use parity_runtime::Executor;
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use sync::{LightSync, ManageNetwork, SyncProvider};
|
||||
use parking_lot::Mutex;
|
||||
use sync::{ManageNetwork, SyncProvider};
|
||||
use updater::Updater;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Eq, Hash)]
|
||||
@@ -426,220 +417,6 @@ impl Dependencies for FullDependencies {
|
||||
}
|
||||
}
|
||||
|
||||
/// Light client notifier. Doesn't do anything yet, but might in the future.
|
||||
pub struct LightClientNotifier;
|
||||
|
||||
impl ActivityNotifier for LightClientNotifier {
|
||||
fn active(&self) {}
|
||||
}
|
||||
|
||||
/// RPC dependencies for a light client.
|
||||
pub struct LightDependencies<T> {
|
||||
pub signer_service: Arc<SignerService>,
|
||||
pub client: Arc<T>,
|
||||
pub sync: Arc<LightSync>,
|
||||
pub net: Arc<dyn ManageNetwork>,
|
||||
pub accounts: Arc<AccountProvider>,
|
||||
pub logger: Arc<RotatingLogger>,
|
||||
pub settings: Arc<NetworkSettings>,
|
||||
pub on_demand: Arc<::light::on_demand::OnDemand>,
|
||||
pub cache: Arc<Mutex<LightDataCache>>,
|
||||
pub transaction_queue: Arc<RwLock<LightTransactionQueue>>,
|
||||
pub ws_address: Option<Host>,
|
||||
pub fetch: FetchClient,
|
||||
pub experimental_rpcs: bool,
|
||||
pub executor: Executor,
|
||||
pub private_tx_service: Option<Arc<PrivateTransactionManager>>,
|
||||
pub gas_price_percentile: usize,
|
||||
pub poll_lifetime: u32,
|
||||
}
|
||||
|
||||
impl<C: LightChainClient + 'static> LightDependencies<C> {
|
||||
fn extend_api<T: core::Middleware<Metadata>>(
|
||||
&self,
|
||||
handler: &mut MetaIoHandler<Metadata, T>,
|
||||
apis: &HashSet<Api>,
|
||||
for_generic_pubsub: bool,
|
||||
) {
|
||||
use parity_rpc::v1::*;
|
||||
|
||||
let dispatcher = LightDispatcher::new(
|
||||
self.sync.clone(),
|
||||
self.client.clone(),
|
||||
self.on_demand.clone(),
|
||||
self.cache.clone(),
|
||||
self.transaction_queue.clone(),
|
||||
Arc::new(Mutex::new(dispatch::Reservations::new(
|
||||
self.executor.clone(),
|
||||
))),
|
||||
self.gas_price_percentile,
|
||||
);
|
||||
let account_signer = Arc::new(dispatch::Signer::new(self.accounts.clone())) as _;
|
||||
let accounts = account_utils::accounts_list(self.accounts.clone());
|
||||
|
||||
for api in apis {
|
||||
match *api {
|
||||
Api::Debug => {
|
||||
warn!(target: "rpc", "Debug API is not available in light client mode.")
|
||||
}
|
||||
Api::Web3 => {
|
||||
handler.extend_with(Web3Client::default().to_delegate());
|
||||
}
|
||||
Api::Net => {
|
||||
handler.extend_with(light::NetClient::new(self.sync.clone()).to_delegate());
|
||||
}
|
||||
Api::Eth => {
|
||||
let client = light::EthClient::new(
|
||||
self.sync.clone(),
|
||||
self.client.clone(),
|
||||
self.on_demand.clone(),
|
||||
self.transaction_queue.clone(),
|
||||
accounts.clone(),
|
||||
self.cache.clone(),
|
||||
self.gas_price_percentile,
|
||||
self.poll_lifetime,
|
||||
);
|
||||
handler.extend_with(Eth::to_delegate(client.clone()));
|
||||
|
||||
if !for_generic_pubsub {
|
||||
handler.extend_with(EthFilter::to_delegate(client));
|
||||
add_signing_methods!(
|
||||
EthSigning,
|
||||
handler,
|
||||
self,
|
||||
(&dispatcher, &account_signer)
|
||||
);
|
||||
}
|
||||
}
|
||||
Api::EthPubSub => {
|
||||
let client = EthPubSubClient::light(
|
||||
self.client.clone(),
|
||||
self.on_demand.clone(),
|
||||
self.sync.clone(),
|
||||
self.cache.clone(),
|
||||
self.executor.clone(),
|
||||
self.gas_price_percentile,
|
||||
);
|
||||
self.client.add_listener(client.handler() as Weak<_>);
|
||||
let h = client.handler();
|
||||
self.transaction_queue
|
||||
.write()
|
||||
.add_listener(Box::new(move |transactions| {
|
||||
if let Some(h) = h.upgrade() {
|
||||
h.notify_new_transactions(transactions);
|
||||
}
|
||||
}));
|
||||
handler.extend_with(EthPubSub::to_delegate(client));
|
||||
}
|
||||
Api::Personal => {
|
||||
#[cfg(feature = "accounts")]
|
||||
handler.extend_with(
|
||||
PersonalClient::new(
|
||||
&self.accounts,
|
||||
dispatcher.clone(),
|
||||
self.experimental_rpcs,
|
||||
)
|
||||
.to_delegate(),
|
||||
);
|
||||
}
|
||||
Api::Signer => {
|
||||
handler.extend_with(
|
||||
SignerClient::new(
|
||||
account_signer.clone(),
|
||||
dispatcher.clone(),
|
||||
&self.signer_service,
|
||||
self.executor.clone(),
|
||||
)
|
||||
.to_delegate(),
|
||||
);
|
||||
}
|
||||
Api::Parity => {
|
||||
let signer = match self.signer_service.is_enabled() {
|
||||
true => Some(self.signer_service.clone()),
|
||||
false => None,
|
||||
};
|
||||
handler.extend_with(
|
||||
light::ParityClient::new(
|
||||
Arc::new(dispatcher.clone()),
|
||||
self.logger.clone(),
|
||||
self.settings.clone(),
|
||||
signer,
|
||||
self.ws_address.clone(),
|
||||
self.gas_price_percentile,
|
||||
)
|
||||
.to_delegate(),
|
||||
);
|
||||
#[cfg(feature = "accounts")]
|
||||
handler.extend_with(ParityAccountsInfo::to_delegate(
|
||||
ParityAccountsClient::new(&self.accounts),
|
||||
));
|
||||
|
||||
if !for_generic_pubsub {
|
||||
add_signing_methods!(
|
||||
ParitySigning,
|
||||
handler,
|
||||
self,
|
||||
(&dispatcher, &account_signer)
|
||||
);
|
||||
}
|
||||
}
|
||||
Api::ParityPubSub => {
|
||||
if !for_generic_pubsub {
|
||||
let mut rpc = MetaIoHandler::default();
|
||||
let apis = ApiSet::List(apis.clone())
|
||||
.retain(ApiSet::PubSub)
|
||||
.list_apis();
|
||||
self.extend_api(&mut rpc, &apis, true);
|
||||
handler.extend_with(
|
||||
PubSubClient::new(rpc, self.executor.clone()).to_delegate(),
|
||||
);
|
||||
}
|
||||
}
|
||||
Api::ParityAccounts => {
|
||||
#[cfg(feature = "accounts")]
|
||||
handler.extend_with(ParityAccounts::to_delegate(ParityAccountsClient::new(
|
||||
&self.accounts,
|
||||
)));
|
||||
}
|
||||
Api::ParitySet => handler.extend_with(
|
||||
light::ParitySetClient::new(
|
||||
self.client.clone(),
|
||||
self.sync.clone(),
|
||||
self.fetch.clone(),
|
||||
)
|
||||
.to_delegate(),
|
||||
),
|
||||
Api::Traces => handler.extend_with(light::TracesClient.to_delegate()),
|
||||
Api::SecretStore => {
|
||||
#[cfg(feature = "accounts")]
|
||||
handler.extend_with(SecretStoreClient::new(&self.accounts).to_delegate());
|
||||
}
|
||||
Api::Private => {
|
||||
if let Some(ref tx_manager) = self.private_tx_service {
|
||||
let private_tx_service = Some(tx_manager.clone());
|
||||
handler.extend_with(PrivateClient::new(private_tx_service).to_delegate());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: LightChainClient + 'static> Dependencies for LightDependencies<T> {
|
||||
type Notifier = LightClientNotifier;
|
||||
|
||||
fn activity_notifier(&self) -> Self::Notifier {
|
||||
LightClientNotifier
|
||||
}
|
||||
|
||||
fn extend_with_set<S>(&self, handler: &mut MetaIoHandler<Metadata, S>, apis: &HashSet<Api>)
|
||||
where
|
||||
S: core::Middleware<Metadata>,
|
||||
{
|
||||
self.extend_api(handler, apis, false)
|
||||
}
|
||||
}
|
||||
|
||||
impl ApiSet {
|
||||
/// Retains only APIs in given set.
|
||||
pub fn retain(self, set: Self) -> Self {
|
||||
|
||||
332
parity/run.rs
332
parity/run.rs
@@ -34,7 +34,6 @@ use ethcore::{
|
||||
},
|
||||
miner::{self, stratum, Miner, MinerOptions, MinerService},
|
||||
snapshot::{self, SnapshotConfiguration},
|
||||
spec::{OptimizeFor, SpecParams},
|
||||
verification::queue::VerifierSettings,
|
||||
};
|
||||
use ethcore_logger::{Config as LogConfig, RotatingLogger};
|
||||
@@ -44,11 +43,10 @@ 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, LightNodeInformantData};
|
||||
use informant::{FullNodeInformantData, Informant};
|
||||
use ipfs;
|
||||
use journaldb::Algorithm;
|
||||
use jsonrpc_core;
|
||||
use light::Cache as LightDataCache;
|
||||
use miner::{external::ExternalMiner, work_notify::WorkPoster};
|
||||
use modules;
|
||||
use node_filter::NodeFilter;
|
||||
@@ -77,16 +75,9 @@ const SNAPSHOT_PERIOD: u64 = 5000;
|
||||
// how many blocks to wait before starting a periodic snapshot.
|
||||
const SNAPSHOT_HISTORY: u64 = 100;
|
||||
|
||||
// Number of minutes before a given gas price corpus should expire.
|
||||
// Light client only.
|
||||
const GAS_CORPUS_EXPIRATION_MINUTES: u64 = 60 * 6;
|
||||
|
||||
// Full client number of DNS threads
|
||||
const FETCH_FULL_NUM_DNS_THREADS: usize = 4;
|
||||
|
||||
// Light client number of DNS threads
|
||||
const FETCH_LIGHT_NUM_DNS_THREADS: usize = 1;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct RunCmd {
|
||||
pub cache_config: CacheConfig,
|
||||
@@ -132,16 +123,8 @@ pub struct RunCmd {
|
||||
pub allow_missing_blocks: bool,
|
||||
pub download_old_blocks: bool,
|
||||
pub verifier_settings: VerifierSettings,
|
||||
pub serve_light: bool,
|
||||
pub light: bool,
|
||||
pub no_persistent_txqueue: bool,
|
||||
pub no_hardcoded_sync: bool,
|
||||
pub max_round_blocks_to_import: usize,
|
||||
pub on_demand_response_time_window: Option<u64>,
|
||||
pub on_demand_request_backoff_start: Option<u64>,
|
||||
pub on_demand_request_backoff_max: Option<u64>,
|
||||
pub on_demand_request_backoff_rounds_max: Option<usize>,
|
||||
pub on_demand_request_consecutive_failures: Option<usize>,
|
||||
}
|
||||
|
||||
// node info fetcher for the local store.
|
||||
@@ -169,252 +152,15 @@ impl ::local_store::NodeInfo for FullNodeInfo {
|
||||
}
|
||||
}
|
||||
|
||||
type LightClient = ::light::client::Client<::light_helpers::EpochFetch>;
|
||||
|
||||
// helper for light execution.
|
||||
fn execute_light_impl<Cr>(
|
||||
cmd: RunCmd,
|
||||
logger: Arc<RotatingLogger>,
|
||||
on_client_rq: Cr,
|
||||
) -> Result<RunningClient, String>
|
||||
where
|
||||
Cr: Fn(String) + 'static + Send,
|
||||
{
|
||||
use light::client as light_client;
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use sync::{LightSync, LightSyncParams, ManageNetwork};
|
||||
|
||||
// load spec
|
||||
let spec = cmd.spec.spec(SpecParams::new(
|
||||
cmd.dirs.cache.as_ref(),
|
||||
OptimizeFor::Memory,
|
||||
))?;
|
||||
|
||||
// load genesis hash
|
||||
let genesis_hash = spec.genesis_header().hash();
|
||||
|
||||
// database paths
|
||||
let db_dirs = cmd.dirs.database(
|
||||
genesis_hash,
|
||||
cmd.spec.legacy_fork_name(),
|
||||
spec.data_dir.clone(),
|
||||
);
|
||||
|
||||
// user defaults path
|
||||
let user_defaults_path = db_dirs.user_defaults_path();
|
||||
|
||||
// load user defaults
|
||||
let user_defaults = UserDefaults::load(&user_defaults_path)?;
|
||||
|
||||
// select pruning algorithm
|
||||
let algorithm = cmd.pruning.to_algorithm(&user_defaults);
|
||||
|
||||
// execute upgrades
|
||||
execute_upgrades(&cmd.dirs.base, &db_dirs, algorithm, &cmd.compaction)?;
|
||||
|
||||
// create dirs used by parity
|
||||
cmd.dirs.create_dirs(
|
||||
cmd.acc_conf.unlocked_accounts.len() == 0,
|
||||
cmd.secretstore_conf.enabled,
|
||||
)?;
|
||||
|
||||
//print out running parity environment
|
||||
print_running_environment(&spec.data_dir, &cmd.dirs, &db_dirs);
|
||||
|
||||
info!(
|
||||
"Running in experimental {} mode.",
|
||||
Colour::Blue.bold().paint("Light Client")
|
||||
);
|
||||
|
||||
// TODO: configurable cache size.
|
||||
let cache = LightDataCache::new(
|
||||
Default::default(),
|
||||
Duration::from_secs(60 * GAS_CORPUS_EXPIRATION_MINUTES),
|
||||
);
|
||||
let cache = Arc::new(Mutex::new(cache));
|
||||
|
||||
// start client and create transaction queue.
|
||||
let mut config = light_client::Config {
|
||||
queue: Default::default(),
|
||||
chain_column: ::ethcore_db::COL_LIGHT_CHAIN,
|
||||
verify_full: true,
|
||||
check_seal: cmd.check_seal,
|
||||
no_hardcoded_sync: cmd.no_hardcoded_sync,
|
||||
};
|
||||
|
||||
config.queue.max_mem_use = cmd.cache_config.queue() as usize * 1024 * 1024;
|
||||
config.queue.verifier_settings = cmd.verifier_settings;
|
||||
|
||||
// start on_demand service.
|
||||
|
||||
let response_time_window = cmd
|
||||
.on_demand_response_time_window
|
||||
.map_or(::light::on_demand::DEFAULT_RESPONSE_TIME_TO_LIVE, |s| {
|
||||
Duration::from_secs(s)
|
||||
});
|
||||
|
||||
let request_backoff_start = cmd.on_demand_request_backoff_start.map_or(
|
||||
::light::on_demand::DEFAULT_REQUEST_MIN_BACKOFF_DURATION,
|
||||
|s| Duration::from_secs(s),
|
||||
);
|
||||
|
||||
let request_backoff_max = cmd.on_demand_request_backoff_max.map_or(
|
||||
::light::on_demand::DEFAULT_REQUEST_MAX_BACKOFF_DURATION,
|
||||
|s| Duration::from_secs(s),
|
||||
);
|
||||
|
||||
let on_demand = Arc::new({
|
||||
::light::on_demand::OnDemand::new(
|
||||
cache.clone(),
|
||||
response_time_window,
|
||||
request_backoff_start,
|
||||
request_backoff_max,
|
||||
cmd.on_demand_request_backoff_rounds_max
|
||||
.unwrap_or(::light::on_demand::DEFAULT_MAX_REQUEST_BACKOFF_ROUNDS),
|
||||
cmd.on_demand_request_consecutive_failures
|
||||
.unwrap_or(::light::on_demand::DEFAULT_NUM_CONSECUTIVE_FAILED_REQUESTS),
|
||||
)
|
||||
});
|
||||
|
||||
let sync_handle = Arc::new(RwLock::new(Weak::new()));
|
||||
let fetch = ::light_helpers::EpochFetch {
|
||||
on_demand: on_demand.clone(),
|
||||
sync: sync_handle.clone(),
|
||||
};
|
||||
|
||||
// initialize database.
|
||||
let db = db::open_db(
|
||||
&db_dirs
|
||||
.client_path(algorithm)
|
||||
.to_str()
|
||||
.expect("DB path could not be converted to string."),
|
||||
&cmd.cache_config,
|
||||
&cmd.compaction,
|
||||
)
|
||||
.map_err(|e| format!("Failed to open database {:?}", e))?;
|
||||
|
||||
let service = light_client::Service::start(config, &spec, fetch, db, cache.clone())
|
||||
.map_err(|e| format!("Error starting light client: {}", e))?;
|
||||
let client = service.client().clone();
|
||||
let txq = Arc::new(RwLock::new(
|
||||
::light::transaction_queue::TransactionQueue::default(),
|
||||
));
|
||||
let provider = ::light::provider::LightProvider::new(client.clone(), txq.clone());
|
||||
|
||||
// start network.
|
||||
// set up bootnodes
|
||||
let mut net_conf = cmd.net_conf;
|
||||
if !cmd.custom_bootnodes {
|
||||
net_conf.boot_nodes = spec.nodes.clone();
|
||||
}
|
||||
|
||||
// set network path.
|
||||
net_conf.net_config_path = Some(db_dirs.network_path().to_string_lossy().into_owned());
|
||||
let sync_params = LightSyncParams {
|
||||
network_config: net_conf
|
||||
.into_basic()
|
||||
.map_err(|e| format!("Failed to produce network config: {}", e))?,
|
||||
client: Arc::new(provider),
|
||||
network_id: cmd.network_id.unwrap_or(spec.network_id()),
|
||||
subprotocol_name: sync::LIGHT_PROTOCOL,
|
||||
handlers: vec![on_demand.clone()],
|
||||
};
|
||||
let light_sync =
|
||||
LightSync::new(sync_params).map_err(|e| format!("Error starting network: {}", e))?;
|
||||
let light_sync = Arc::new(light_sync);
|
||||
*sync_handle.write() = Arc::downgrade(&light_sync);
|
||||
|
||||
// spin up event loop
|
||||
let runtime = Runtime::with_default_thread_count();
|
||||
|
||||
// start the network.
|
||||
light_sync.start_network();
|
||||
|
||||
// fetch service
|
||||
let fetch = fetch::Client::new(FETCH_LIGHT_NUM_DNS_THREADS)
|
||||
.map_err(|e| format!("Error starting fetch client: {:?}", e))?;
|
||||
let passwords = passwords_from_files(&cmd.acc_conf.password_files)?;
|
||||
|
||||
// prepare account provider
|
||||
let account_provider = Arc::new(account_utils::prepare_account_provider(
|
||||
&cmd.spec,
|
||||
&cmd.dirs,
|
||||
&spec.data_dir,
|
||||
cmd.acc_conf,
|
||||
&passwords,
|
||||
)?);
|
||||
let rpc_stats = Arc::new(informant::RpcStats::default());
|
||||
|
||||
// the dapps server
|
||||
let signer_service = Arc::new(signer::new_service(&cmd.ws_conf, &cmd.logger_config));
|
||||
|
||||
// start RPCs
|
||||
let deps_for_rpc_apis = Arc::new(rpc_apis::LightDependencies {
|
||||
signer_service: signer_service,
|
||||
client: client.clone(),
|
||||
sync: light_sync.clone(),
|
||||
net: light_sync.clone(),
|
||||
accounts: account_provider,
|
||||
logger: logger,
|
||||
settings: Arc::new(cmd.net_settings),
|
||||
on_demand: on_demand,
|
||||
cache: cache.clone(),
|
||||
transaction_queue: txq,
|
||||
ws_address: cmd.ws_conf.address(),
|
||||
fetch: fetch,
|
||||
experimental_rpcs: cmd.experimental_rpcs,
|
||||
executor: runtime.executor(),
|
||||
private_tx_service: None, //TODO: add this to client.
|
||||
gas_price_percentile: cmd.gas_price_percentile,
|
||||
poll_lifetime: cmd.poll_lifetime,
|
||||
});
|
||||
|
||||
let dependencies = rpc::Dependencies {
|
||||
apis: deps_for_rpc_apis.clone(),
|
||||
executor: runtime.executor(),
|
||||
stats: rpc_stats.clone(),
|
||||
};
|
||||
|
||||
// start rpc servers
|
||||
let rpc_direct = rpc::setup_apis(rpc_apis::ApiSet::All, &dependencies);
|
||||
let ws_server = rpc::new_ws(cmd.ws_conf, &dependencies)?;
|
||||
let http_server = rpc::new_http(
|
||||
"HTTP JSON-RPC",
|
||||
"jsonrpc",
|
||||
cmd.http_conf.clone(),
|
||||
&dependencies,
|
||||
)?;
|
||||
let ipc_server = rpc::new_ipc(cmd.ipc_conf, &dependencies)?;
|
||||
|
||||
// the informant
|
||||
let informant = Arc::new(Informant::new(
|
||||
LightNodeInformantData {
|
||||
client: client.clone(),
|
||||
sync: light_sync.clone(),
|
||||
cache: cache,
|
||||
},
|
||||
None,
|
||||
Some(rpc_stats),
|
||||
cmd.logger_config.color,
|
||||
));
|
||||
service.add_notify(informant.clone());
|
||||
service
|
||||
.register_handler(informant.clone())
|
||||
.map_err(|_| "Unable to register informant handler".to_owned())?;
|
||||
|
||||
client.set_exit_handler(on_client_rq);
|
||||
|
||||
Ok(RunningClient {
|
||||
inner: RunningClientInner::Light {
|
||||
rpc: rpc_direct,
|
||||
informant,
|
||||
client,
|
||||
keep_alive: Box::new((service, ws_server, http_server, ipc_server, runtime)),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
fn execute_impl<Cr, Rr>(
|
||||
/// 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,
|
||||
@@ -540,7 +286,6 @@ where
|
||||
_ => sync::WarpSync::Disabled,
|
||||
};
|
||||
sync_config.download_old_blocks = cmd.download_old_blocks;
|
||||
sync_config.serve_light = cmd.serve_light;
|
||||
|
||||
let passwords = passwords_from_files(&cmd.acc_conf.password_files)?;
|
||||
|
||||
@@ -597,11 +342,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
// display warning if using --no-hardcoded-sync
|
||||
if cmd.no_hardcoded_sync {
|
||||
warn!("The --no-hardcoded-sync flag has no effect if you don't use --light");
|
||||
}
|
||||
|
||||
// create client config
|
||||
let mut client_config = to_client_config(
|
||||
&cmd.cache_config,
|
||||
@@ -747,7 +487,6 @@ where
|
||||
client.clone(),
|
||||
snapshot_service.clone(),
|
||||
private_tx_sync,
|
||||
client.clone(),
|
||||
&cmd.logger_config,
|
||||
connection_filter
|
||||
.clone()
|
||||
@@ -965,15 +704,6 @@ pub struct RunningClient {
|
||||
}
|
||||
|
||||
enum RunningClientInner {
|
||||
Light {
|
||||
rpc: jsonrpc_core::MetaIoHandler<
|
||||
Metadata,
|
||||
informant::Middleware<rpc_apis::LightClientNotifier>,
|
||||
>,
|
||||
informant: Arc<Informant<LightNodeInformantData>>,
|
||||
client: Arc<LightClient>,
|
||||
keep_alive: Box<dyn Any>,
|
||||
},
|
||||
Full {
|
||||
rpc:
|
||||
jsonrpc_core::MetaIoHandler<Metadata, informant::Middleware<informant::ClientNotifier>>,
|
||||
@@ -998,7 +728,6 @@ impl RunningClient {
|
||||
};
|
||||
|
||||
match self.inner {
|
||||
RunningClientInner::Light { ref rpc, .. } => rpc.handle_request(request, metadata),
|
||||
RunningClientInner::Full { ref rpc, .. } => rpc.handle_request(request, metadata),
|
||||
}
|
||||
}
|
||||
@@ -1006,22 +735,6 @@ impl RunningClient {
|
||||
/// Shuts down the client.
|
||||
pub fn shutdown(self) {
|
||||
match self.inner {
|
||||
RunningClientInner::Light {
|
||||
rpc,
|
||||
informant,
|
||||
client,
|
||||
keep_alive,
|
||||
} => {
|
||||
// Create a weak reference to the client so that we can wait on shutdown
|
||||
// until it is dropped
|
||||
let weak_client = Arc::downgrade(&client);
|
||||
drop(rpc);
|
||||
drop(keep_alive);
|
||||
informant.shutdown();
|
||||
drop(informant);
|
||||
drop(client);
|
||||
wait_for_drop(weak_client);
|
||||
}
|
||||
RunningClientInner::Full {
|
||||
rpc,
|
||||
informant,
|
||||
@@ -1060,31 +773,6 @@ impl RunningClient {
|
||||
}
|
||||
}
|
||||
|
||||
/// 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,
|
||||
{
|
||||
if cmd.light {
|
||||
execute_light_impl(cmd, logger, on_client_rq)
|
||||
} else {
|
||||
execute_impl(cmd, logger, on_client_rq, on_updater_rq)
|
||||
}
|
||||
}
|
||||
|
||||
fn print_running_environment(data_dir: &str, dirs: &Directories, db_dirs: &DatabaseDirectories) {
|
||||
info!("Starting {}", Colour::White.bold().paint(version()));
|
||||
info!(
|
||||
|
||||
Reference in New Issue
Block a user