openethereum/parity/main.rs

329 lines
8.9 KiB
Rust
Raw Normal View History

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/>.
//! 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;
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;
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;
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;
#[macro_use]
extern crate hyper; // for price_info.rs
extern crate json_ipc_server as jsonipc;
2016-03-28 00:49:35 +02: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")]
extern crate ethcore_webapp;
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;
mod webapp;
mod informant;
mod io_handler;
2016-04-21 15:41:25 +02:00
mod cli;
mod configuration;
use ctrlc::CtrlC;
use util::*;
use util::panics::{MayPanic, ForwardPanic, PanicHandler};
2016-05-23 09:51:36 +02:00
use ethcore::client::{BlockID, BlockChainClient};
use ethcore::service::ClientService;
use ethsync::EthSync;
2016-04-21 17:32:53 +02:00
use ethminer::{Miner, MinerService, ExternalMiner};
use daemonize::Daemonize;
2016-03-28 00:49:35 +02:00
2016-04-21 13:12:43 +02:00
use die::*;
use cli::print_version;
2016-04-21 13:12:43 +02:00
use rpc::RpcServer;
use webapp::WebappServer;
use io_handler::ClientIoHandler;
use configuration::Configuration;
2016-04-21 15:41:25 +02:00
fn main() {
let conf = Configuration::parse();
execute(conf);
}
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-04-21 15:41:25 +02:00
if conf.args.cmd_account {
execute_account_cli(conf);
return;
}
2016-05-23 09:51:36 +02:00
if conf.args.cmd_export {
execute_export(conf);
return;
}
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(
2016-05-17 10:32:05 +02:00
client_config, spec, net_settings, Path::new(&conf.path())
).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-16 18:16:56 +02:00
let miner = Miner::with_accounts(conf.args.flag_force_sealing, conf.spec(), 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());
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
});
// 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
let _ipc_server = rpc::new_ipc(conf.ipc_settings(), &dependencies);
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 {
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-05-23 09:51:36 +02:00
fn execute_export(conf: Configuration) {
println!("Exporting to {:?} from {}, to {}", conf.args.arg_file, conf.args.flag_from, conf.args.flag_to);
// Setup panic handler
let panic_handler = PanicHandler::new_in_arc();
// Raise fdlimit
unsafe { ::fdlimit::raise_fd_limit(); }
let spec = conf.spec();
let net_settings = NetworkConfiguration {
config_path: None,
listen_address: None,
public_address: None,
udp_port: None,
nat_enabled: false,
discovery_enabled: false,
pin: true,
boot_nodes: Vec::new(),
use_secret: None,
ideal_peers: 0,
};
let client_config = conf.client_config(&spec);
// Build client
let service = ClientService::start(
client_config, spec, net_settings, Path::new(&conf.path())
).unwrap_or_else(|e| die_with_error("Client", e));
panic_handler.forward_from(&service);
let client = service.client();
// we have a client!
let parse_block_id = |s: &str| -> u64 {
if s == "latest" {
client.chain_info().best_block_number
} else if let Ok(n) = s.parse::<u64>() {
n
} else if let Ok(h) = H256::from_str(s) {
client.block_number(BlockID::Hash(h)).unwrap_or_else(|| {
die!("Unknown block hash passed to --to parameter: {:?}", s);
})
} else {
die!("Invalid --to parameter given: {:?}", s);
}
};
let from = parse_block_id(&conf.args.flag_from);
let to = parse_block_id(&conf.args.flag_to);
for i in from..to {
println!("{}", client.deref().block(BlockID::Number(i)).unwrap().pretty());
}
}
2016-04-21 15:41:25 +02:00
fn execute_account_cli(conf: Configuration) {
use util::keys::store::SecretStore;
use rpassword::read_password;
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
}
/// Parity needs at least 1 test to generate coverage reports correctly.
#[test]
fn if_works() {
}