2016-02-05 13:40:41 +01:00
|
|
|
// Copyright 2015, 2016 Ethcore (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/>.
|
|
|
|
|
2016-01-27 17:18:38 +01:00
|
|
|
//! Ethcore client application.
|
|
|
|
|
|
|
|
#![warn(missing_docs)]
|
2016-03-11 11:16:49 +01:00
|
|
|
#![cfg_attr(feature="dev", feature(plugin))]
|
|
|
|
#![cfg_attr(feature="dev", plugin(clippy))]
|
2016-04-06 10:07:24 +02:00
|
|
|
#![cfg_attr(feature="dev", allow(useless_format))]
|
2016-04-21 13:12:43 +02:00
|
|
|
|
2016-01-23 23:53:20 +01:00
|
|
|
extern crate docopt;
|
2016-03-22 19:12:17 +01:00
|
|
|
extern crate num_cpus;
|
2016-01-23 23:53:20 +01:00
|
|
|
extern crate rustc_serialize;
|
2015-12-22 22:19:50 +01:00
|
|
|
extern crate ethcore_util as util;
|
2016-01-07 16:08:12 +01:00
|
|
|
extern crate ethcore;
|
2016-01-29 15:56:06 +01:00
|
|
|
extern crate ethsync;
|
2016-03-08 15:46:44 +01:00
|
|
|
extern crate ethminer;
|
2016-02-18 12:42:01 +01:00
|
|
|
#[macro_use]
|
2016-01-31 11:08:04 +01:00
|
|
|
extern crate log as rlog;
|
2016-01-09 23:21:57 +01:00
|
|
|
extern crate env_logger;
|
2016-01-22 00:11:19 +01:00
|
|
|
extern crate ctrlc;
|
2016-02-05 13:49:36 +01:00
|
|
|
extern crate fdlimit;
|
2016-02-18 13:10:04 +01:00
|
|
|
extern crate daemonize;
|
2016-02-23 20:14:37 +01:00
|
|
|
extern crate time;
|
2016-02-25 14:09:39 +01:00
|
|
|
extern crate number_prefix;
|
2016-03-09 14:11:15 +01:00
|
|
|
extern crate rpassword;
|
2016-04-10 15:12:20 +02:00
|
|
|
extern crate semver;
|
2016-04-13 18:03:57 +02:00
|
|
|
extern crate ethcore_ipc as ipc;
|
|
|
|
extern crate ethcore_ipc_nano as nanoipc;
|
2016-04-21 16:45:04 +02:00
|
|
|
#[macro_use]
|
|
|
|
extern crate hyper; // for price_info.rs
|
2016-05-04 15:37:09 +02:00
|
|
|
extern crate json_ipc_server as jsonipc;
|
2016-03-28 00:49:35 +02:00
|
|
|
|
2016-01-20 04:19:38 +01:00
|
|
|
#[cfg(feature = "rpc")]
|
2016-04-21 13:12:43 +02:00
|
|
|
extern crate ethcore_rpc;
|
|
|
|
|
2016-04-07 10:49:00 +02:00
|
|
|
#[cfg(feature = "webapp")]
|
2016-04-21 13:57:27 +02:00
|
|
|
extern crate ethcore_webapp;
|
2016-01-20 04:19:38 +01:00
|
|
|
|
2016-04-21 13:12:43 +02:00
|
|
|
#[macro_use]
|
|
|
|
mod die;
|
2016-03-28 00:49:35 +02:00
|
|
|
mod price_info;
|
2016-04-10 15:12:20 +02:00
|
|
|
mod upgrade;
|
2016-04-13 18:03:57 +02:00
|
|
|
mod hypervisor;
|
2016-04-21 13:12:43 +02:00
|
|
|
mod setup_log;
|
|
|
|
mod rpc;
|
2016-04-21 13:57:27 +02:00
|
|
|
mod webapp;
|
|
|
|
mod informant;
|
|
|
|
mod io_handler;
|
2016-04-21 15:41:25 +02:00
|
|
|
mod cli;
|
2016-04-21 16:45:04 +02:00
|
|
|
mod configuration;
|
|
|
|
|
|
|
|
use ctrlc::CtrlC;
|
|
|
|
use util::*;
|
|
|
|
use util::panics::{MayPanic, ForwardPanic, PanicHandler};
|
|
|
|
use ethcore::service::ClientService;
|
|
|
|
use ethsync::EthSync;
|
2016-04-21 17:32:53 +02:00
|
|
|
use ethminer::{Miner, MinerService, ExternalMiner};
|
2016-04-21 16:45:04 +02:00
|
|
|
use daemonize::Daemonize;
|
2016-03-28 00:49:35 +02:00
|
|
|
|
2016-04-21 13:12:43 +02:00
|
|
|
use die::*;
|
2016-04-21 16:45:04 +02:00
|
|
|
use cli::print_version;
|
2016-04-21 13:12:43 +02:00
|
|
|
use rpc::RpcServer;
|
2016-04-21 13:57:27 +02:00
|
|
|
use webapp::WebappServer;
|
|
|
|
use io_handler::ClientIoHandler;
|
2016-04-21 16:45:04 +02:00
|
|
|
use configuration::Configuration;
|
2016-04-21 15:41:25 +02:00
|
|
|
|
|
|
|
fn main() {
|
|
|
|
let conf = Configuration::parse();
|
|
|
|
execute(conf);
|
2016-02-18 14:16:55 +01:00
|
|
|
}
|
2015-12-22 22:19:50 +01:00
|
|
|
|
2016-04-21 15:41:25 +02:00
|
|
|
fn execute(conf: Configuration) {
|
|
|
|
if conf.args.flag_version {
|
|
|
|
print_version();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
execute_upgrades(&conf);
|
|
|
|
|
|
|
|
if conf.args.cmd_daemon {
|
|
|
|
Daemonize::new()
|
|
|
|
.pid_file(conf.args.arg_pid_file.clone())
|
|
|
|
.chown_pid_file(true)
|
|
|
|
.start()
|
|
|
|
.unwrap_or_else(|e| die!("Couldn't daemonize; {}", e));
|
|
|
|
}
|
2016-01-20 04:19:38 +01:00
|
|
|
|
2016-04-21 15:41:25 +02:00
|
|
|
if conf.args.cmd_account {
|
|
|
|
execute_account_cli(conf);
|
|
|
|
return;
|
|
|
|
}
|
2016-02-09 15:51:48 +01:00
|
|
|
|
2016-04-21 15:41:25 +02:00
|
|
|
execute_client(conf);
|
2016-02-10 18:11:10 +01:00
|
|
|
}
|
|
|
|
|
2016-04-21 15:41:25 +02:00
|
|
|
fn execute_upgrades(conf: &Configuration) {
|
|
|
|
match ::upgrade::upgrade(Some(&conf.path())) {
|
|
|
|
Ok(upgrades_applied) if upgrades_applied > 0 => {
|
|
|
|
println!("Executed {} upgrade scripts - ok", upgrades_applied);
|
|
|
|
},
|
|
|
|
Err(e) => {
|
|
|
|
die!("Error upgrading parity data: {:?}", e);
|
|
|
|
},
|
|
|
|
_ => {},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn execute_client(conf: Configuration) {
|
|
|
|
// Setup panic handler
|
|
|
|
let panic_handler = PanicHandler::new_in_arc();
|
|
|
|
|
|
|
|
// Setup logging
|
|
|
|
let logger = setup_log::setup_log(&conf.args.flag_logging);
|
|
|
|
// Raise fdlimit
|
|
|
|
unsafe { ::fdlimit::raise_fd_limit(); }
|
|
|
|
|
|
|
|
let spec = conf.spec();
|
|
|
|
let net_settings = conf.net_settings(&spec);
|
|
|
|
let sync_config = conf.sync_config(&spec);
|
|
|
|
let client_config = conf.client_config(&spec);
|
|
|
|
|
|
|
|
// Secret Store
|
|
|
|
let account_service = Arc::new(conf.account_service());
|
|
|
|
|
|
|
|
// Build client
|
|
|
|
let mut service = ClientService::start(
|
|
|
|
client_config, spec, net_settings, &Path::new(&conf.path())
|
2016-04-28 21:48:00 +02:00
|
|
|
).unwrap_or_else(|e| die_with_error("Client", e));
|
2016-04-21 15:41:25 +02:00
|
|
|
|
|
|
|
panic_handler.forward_from(&service);
|
|
|
|
let client = service.client();
|
|
|
|
|
|
|
|
// Miner
|
2016-05-03 17:23:53 +02:00
|
|
|
let miner = Miner::with_accounts(conf.args.flag_force_sealing, account_service.clone());
|
2016-04-21 15:41:25 +02:00
|
|
|
miner.set_author(conf.author());
|
|
|
|
miner.set_gas_floor_target(conf.gas_floor_target());
|
|
|
|
miner.set_extra_data(conf.extra_data());
|
|
|
|
miner.set_minimal_gas_price(conf.gas_price());
|
|
|
|
miner.set_transactions_limit(conf.args.flag_tx_limit);
|
|
|
|
|
2016-04-21 17:32:53 +02:00
|
|
|
let external_miner = Arc::new(ExternalMiner::default());
|
2016-04-21 19:19:42 +02:00
|
|
|
let network_settings = Arc::new(conf.network_settings());
|
|
|
|
|
2016-04-21 15:41:25 +02:00
|
|
|
// Sync
|
|
|
|
let sync = EthSync::register(service.network(), sync_config, client.clone(), miner.clone());
|
|
|
|
|
2016-05-04 15:37:09 +02:00
|
|
|
let dependencies = Arc::new(rpc::Dependencies {
|
2016-04-23 12:29:12 +02:00
|
|
|
panic_handler: panic_handler.clone(),
|
2016-04-21 15:41:25 +02:00
|
|
|
client: client.clone(),
|
|
|
|
sync: sync.clone(),
|
|
|
|
secret_store: account_service.clone(),
|
|
|
|
miner: miner.clone(),
|
2016-04-21 17:32:53 +02:00
|
|
|
external_miner: external_miner.clone(),
|
2016-04-21 19:19:42 +02:00
|
|
|
logger: logger.clone(),
|
|
|
|
settings: network_settings.clone(),
|
2016-04-21 15:41:25 +02:00
|
|
|
});
|
|
|
|
|
2016-05-04 15:37:09 +02:00
|
|
|
// Setup http rpc
|
|
|
|
let rpc_server = rpc::new_http(rpc::HttpConfiguration {
|
|
|
|
enabled: network_settings.rpc_enabled,
|
|
|
|
interface: network_settings.rpc_interface.clone(),
|
|
|
|
port: network_settings.rpc_port,
|
|
|
|
apis: conf.rpc_apis(),
|
|
|
|
cors: conf.rpc_cors(),
|
|
|
|
}, &dependencies);
|
|
|
|
|
|
|
|
// setup ipc rpc
|
2016-05-04 22:44:42 +02:00
|
|
|
let _ipc_server = rpc::new_ipc(conf.ipc_settings(), &dependencies);
|
2016-05-04 15:37:09 +02:00
|
|
|
|
2016-05-04 22:44:42 +02:00
|
|
|
if conf.args.flag_webapp { println!("WARNING: Flag -w/--webapp is deprecated. Web app server is now on by default. Ignoring."); }
|
2016-04-21 15:41:25 +02:00
|
|
|
let webapp_server = webapp::new(webapp::Configuration {
|
2016-05-04 22:44:42 +02:00
|
|
|
enabled: !conf.args.flag_webapp_off,
|
2016-04-21 15:41:25 +02:00
|
|
|
interface: conf.args.flag_webapp_interface.clone(),
|
|
|
|
port: conf.args.flag_webapp_port,
|
|
|
|
user: conf.args.flag_webapp_user.clone(),
|
|
|
|
pass: conf.args.flag_webapp_pass.clone(),
|
|
|
|
}, webapp::Dependencies {
|
2016-04-23 12:29:12 +02:00
|
|
|
panic_handler: panic_handler.clone(),
|
2016-04-21 15:41:25 +02:00
|
|
|
client: client.clone(),
|
|
|
|
sync: sync.clone(),
|
|
|
|
secret_store: account_service.clone(),
|
|
|
|
miner: miner.clone(),
|
2016-04-21 17:32:53 +02:00
|
|
|
external_miner: external_miner.clone(),
|
2016-04-21 19:19:42 +02:00
|
|
|
logger: logger.clone(),
|
|
|
|
settings: network_settings.clone(),
|
2016-04-21 15:41:25 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
// Register IO handler
|
|
|
|
let io_handler = Arc::new(ClientIoHandler {
|
|
|
|
client: service.client(),
|
|
|
|
info: Default::default(),
|
|
|
|
sync: sync.clone(),
|
|
|
|
accounts: account_service.clone(),
|
|
|
|
});
|
|
|
|
service.io().register_handler(io_handler).expect("Error registering IO handler");
|
|
|
|
|
|
|
|
// Handle exit
|
|
|
|
wait_for_exit(panic_handler, rpc_server, webapp_server);
|
|
|
|
}
|
|
|
|
|
2016-05-02 15:29:50 +02:00
|
|
|
fn flush_stdout() {
|
2016-05-04 15:22:22 +02:00
|
|
|
::std::io::stdout().flush().expect("stdout is flushable; qed");
|
2016-05-02 15:29:50 +02:00
|
|
|
}
|
|
|
|
|
2016-04-21 15:41:25 +02:00
|
|
|
fn execute_account_cli(conf: Configuration) {
|
|
|
|
use util::keys::store::SecretStore;
|
|
|
|
use rpassword::read_password;
|
2016-05-14 13:30:25 +02:00
|
|
|
let mut secret_store = SecretStore::with_security(Path::new(&conf.keys_path()), conf.keys_iterations());
|
2016-04-21 15:41:25 +02:00
|
|
|
if conf.args.cmd_new {
|
|
|
|
println!("Please note that password is NOT RECOVERABLE.");
|
|
|
|
print!("Type password: ");
|
2016-05-02 15:29:50 +02:00
|
|
|
flush_stdout();
|
2016-04-21 15:41:25 +02:00
|
|
|
let password = read_password().unwrap();
|
|
|
|
print!("Repeat password: ");
|
2016-05-02 15:29:50 +02:00
|
|
|
flush_stdout();
|
2016-04-21 15:41:25 +02:00
|
|
|
let password_repeat = read_password().unwrap();
|
|
|
|
if password != password_repeat {
|
|
|
|
println!("Passwords do not match!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
println!("New account address:");
|
|
|
|
let new_address = secret_store.new_account(&password).unwrap();
|
|
|
|
println!("{:?}", new_address);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if conf.args.cmd_list {
|
|
|
|
println!("Known addresses:");
|
|
|
|
for &(addr, _) in &secret_store.accounts().unwrap() {
|
|
|
|
println!("{:?}", addr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn wait_for_exit(panic_handler: Arc<PanicHandler>, _rpc_server: Option<RpcServer>, _webapp_server: Option<WebappServer>) {
|
|
|
|
let exit = Arc::new(Condvar::new());
|
|
|
|
|
|
|
|
// Handle possible exits
|
|
|
|
let e = exit.clone();
|
|
|
|
CtrlC::set_handler(move || { e.notify_all(); });
|
|
|
|
|
|
|
|
// Handle panics
|
|
|
|
let e = exit.clone();
|
|
|
|
panic_handler.on_panic(move |_reason| { e.notify_all(); });
|
|
|
|
|
|
|
|
// Wait for signal
|
|
|
|
let mutex = Mutex::new(());
|
|
|
|
let _ = exit.wait(mutex.lock().unwrap()).unwrap();
|
|
|
|
info!("Finishing work, please wait...");
|
2016-02-10 18:11:10 +01:00
|
|
|
}
|
|
|
|
|
2016-02-02 02:04:03 +01:00
|
|
|
/// Parity needs at least 1 test to generate coverage reports correctly.
|
|
|
|
#[test]
|
|
|
|
fn if_works() {
|
|
|
|
}
|