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-07-10 13:18:33 +02:00
#![ cfg_attr(feature= " dev " , allow(match_bool)) ]
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-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-06-13 18:55:24 +02:00
#[ cfg(not(windows)) ]
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-07-09 17:18:34 +02:00
extern crate ethcore_ipc_hypervisor as hypervisor ;
2016-04-21 13:12:43 +02:00
extern crate ethcore_rpc ;
2016-07-11 17:11:49 +02:00
extern crate ethcore_signer ;
extern crate ansi_term ;
2016-07-13 09:05:26 +02:00
#[ macro_use ]
extern crate lazy_static ;
extern crate regex ;
2016-07-15 10:11:14 +02:00
extern crate isatty ;
2016-07-11 17:11:49 +02:00
2016-05-26 18:21:15 +02:00
#[ cfg(feature = " dapps " ) ]
extern crate ethcore_dapps ;
2016-01-20 04:19:38 +01:00
2016-04-21 13:12:43 +02:00
#[ macro_use ]
mod die ;
2016-04-10 15:12:20 +02:00
mod upgrade ;
2016-04-21 13:12:43 +02:00
mod setup_log ;
mod rpc ;
2016-05-26 18:21:15 +02:00
mod dapps ;
2016-04-21 13:57:27 +02:00
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 ;
2016-05-26 18:24:51 +02:00
mod migration ;
2016-05-27 13:03:00 +02:00
mod signer ;
2016-06-01 19:37:34 +02:00
mod rpc_apis ;
2016-06-14 16:12:46 +02:00
mod url ;
2016-07-16 14:24:57 +02:00
mod modules ;
2016-04-21 16:45:04 +02:00
2016-05-26 18:24:51 +02:00
use std ::io ::{ Write , Read , BufReader , BufRead } ;
use std ::ops ::Deref ;
2016-07-13 19:59:59 +02:00
use std ::sync ::Arc ;
2016-05-26 18:24:51 +02:00
use std ::path ::Path ;
2016-05-23 18:42:59 +02:00
use std ::fs ::File ;
2016-05-26 18:24:51 +02:00
use std ::str ::{ FromStr , from_utf8 } ;
2016-05-25 09:57:31 +02:00
use std ::thread ::sleep ;
2016-05-26 18:24:51 +02:00
use std ::time ::Duration ;
use rustc_serialize ::hex ::FromHex ;
use ctrlc ::CtrlC ;
2016-07-17 23:00:57 +02:00
use util ::{ H256 , ToPretty , PayloadInfo , Bytes , Colour , version , journaldb , RotatingLogger } ;
2016-04-21 16:45:04 +02:00
use util ::panics ::{ MayPanic , ForwardPanic , PanicHandler } ;
2016-07-20 12:36:20 +02:00
use ethcore ::client ::{ BlockID , BlockChainClient , ClientConfig , get_db_path , BlockImportError , Mode , ChainNotify } ;
2016-07-01 21:40:54 +02:00
use ethcore ::error ::{ ImportError } ;
2016-04-21 16:45:04 +02:00
use ethcore ::service ::ClientService ;
2016-05-26 18:24:51 +02:00
use ethcore ::spec ::Spec ;
2016-07-16 15:51:06 +02:00
use ethsync ::{ NetworkConfiguration } ;
2016-05-31 21:31:42 +02:00
use ethcore ::miner ::{ Miner , MinerService , ExternalMiner } ;
2016-05-26 18:24:51 +02:00
use migration ::migrate ;
2016-05-25 09:57:31 +02:00
use informant ::Informant ;
2016-07-13 19:59:59 +02:00
use util ::{ Mutex , Condvar } ;
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-06-07 17:21:19 +02:00
use signer ::{ SignerServer , new_token } ;
2016-05-26 18:21:15 +02:00
use dapps ::WebappServer ;
2016-04-21 13:57:27 +02:00
use io_handler ::ClientIoHandler ;
2016-07-16 13:02:56 +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 ;
}
2016-06-14 12:23:01 +02:00
if conf . args . cmd_signer {
execute_signer ( conf ) ;
return ;
}
2016-05-26 18:24:51 +02:00
let spec = conf . spec ( ) ;
let client_config = conf . client_config ( & spec ) ;
execute_upgrades ( & conf , & spec , & client_config ) ;
2016-04-21 15:41:25 +02:00
if conf . args . cmd_daemon {
2016-06-13 18:55:24 +02:00
daemonize ( & conf ) ;
2016-04-21 15:41:25 +02:00
}
2016-01-20 04:19:38 +01:00
2016-07-17 23:00:57 +02:00
// Setup panic handler
let panic_handler = PanicHandler ::new_in_arc ( ) ;
// Setup logging
let logger = setup_log ::setup_log ( & conf . args . flag_logging , conf . have_color ( ) , & conf . args . flag_log_file ) ;
// Raise fdlimit
unsafe { ::fdlimit ::raise_fd_limit ( ) ; }
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-06-21 17:50:22 +02:00
if conf . args . cmd_wallet {
execute_wallet_cli ( conf ) ;
return ;
}
2016-05-23 09:51:36 +02:00
if conf . args . cmd_export {
2016-07-17 23:00:57 +02:00
execute_export ( conf , panic_handler ) ;
2016-05-23 09:51:36 +02:00
return ;
}
2016-05-24 20:29:19 +02:00
if conf . args . cmd_import {
2016-07-17 23:00:57 +02:00
execute_import ( conf , panic_handler ) ;
2016-05-24 20:29:19 +02:00
return ;
}
2016-07-17 23:00:57 +02:00
execute_client ( conf , spec , client_config , panic_handler , logger ) ;
2016-02-10 18:11:10 +01:00
}
2016-06-13 18:55:24 +02:00
#[ cfg(not(windows)) ]
fn daemonize ( conf : & Configuration ) {
use daemonize ::Daemonize ;
Daemonize ::new ( )
. pid_file ( conf . args . arg_pid_file . clone ( ) )
. chown_pid_file ( true )
. start ( )
. unwrap_or_else ( | e | die! ( " Couldn't daemonize; {} " , e ) ) ;
}
#[ cfg(windows) ]
fn daemonize ( _conf : & Configuration ) {
}
2016-05-26 18:24:51 +02:00
fn execute_upgrades ( conf : & Configuration , spec : & Spec , client_config : & ClientConfig ) {
2016-04-21 15:41:25 +02:00
match ::upgrade ::upgrade ( Some ( & conf . path ( ) ) ) {
Ok ( upgrades_applied ) if upgrades_applied > 0 = > {
2016-07-17 23:00:57 +02:00
debug! ( " Executed {} upgrade scripts - ok " , upgrades_applied ) ;
2016-04-21 15:41:25 +02:00
} ,
Err ( e ) = > {
die! ( " Error upgrading parity data: {:?} " , e ) ;
} ,
_ = > { } ,
}
2016-05-26 18:24:51 +02:00
let db_path = get_db_path ( Path ::new ( & conf . path ( ) ) , client_config . pruning , spec . genesis_header ( ) . hash ( ) ) ;
2016-07-11 09:46:33 +02:00
let result = migrate ( & db_path , client_config . pruning ) ;
2016-05-26 18:24:51 +02:00
if let Err ( err ) = result {
2016-07-16 10:41:09 +02:00
die_with_message ( & format! ( " {} DB path: {} " , err , db_path . to_string_lossy ( ) ) ) ;
2016-05-26 18:24:51 +02:00
}
2016-04-21 15:41:25 +02:00
}
2016-07-17 23:00:57 +02:00
fn execute_client ( conf : Configuration , spec : Spec , client_config : ClientConfig , panic_handler : Arc < PanicHandler > , logger : Arc < RotatingLogger > ) {
2016-07-15 10:11:14 +02:00
info! ( " Starting {} " , Colour ::White . bold ( ) . paint ( format! ( " {} " , version ( ) ) ) ) ;
info! ( " Using state DB journalling strategy {} " , Colour ::White . bold ( ) . paint ( match client_config . pruning {
2016-07-06 18:28:11 +02:00
journaldb ::Algorithm ::Archive = > " archive " ,
journaldb ::Algorithm ::EarlyMerge = > " light " ,
journaldb ::Algorithm ::OverlayRecent = > " fast " ,
journaldb ::Algorithm ::RefCounted = > " basic " ,
2016-07-15 10:11:14 +02:00
} ) ) ;
2016-07-06 18:28:11 +02:00
// Display warning about using experimental journaldb types
match client_config . pruning {
journaldb ::Algorithm ::EarlyMerge | journaldb ::Algorithm ::RefCounted = > {
2016-07-15 10:11:14 +02:00
warn! ( " Your chosen strategy is {}! You can re-run with --pruning to change. " , Colour ::Red . bold ( ) . paint ( " unstable " ) ) ;
2016-07-06 18:28:11 +02:00
}
_ = > { }
}
2016-04-21 15:41:25 +02:00
2016-06-22 21:32:26 +02:00
// Display warning about using unlock with signer
2016-06-24 14:20:39 +02:00
if conf . signer_enabled ( ) & & conf . args . flag_unlock . is_some ( ) {
2016-06-22 21:32:26 +02:00
warn! ( " Using Trusted Signer and --unlock is not recommended! " ) ;
warn! ( " NOTE that Signer will not ask you to confirm transactions from unlocked account. " ) ;
}
2016-07-06 18:28:11 +02:00
let net_settings = conf . net_settings ( & spec ) ;
let sync_config = conf . sync_config ( & spec ) ;
2016-04-21 15:41:25 +02:00
// Secret Store
let account_service = Arc ::new ( conf . account_service ( ) ) ;
// Miner
2016-07-08 17:26:06 +02:00
let miner = Miner ::new ( conf . miner_options ( ) , conf . gas_pricer ( ) , conf . spec ( ) , Some ( account_service . clone ( ) ) ) ;
2016-06-26 22:48:09 +02:00
miner . set_author ( conf . author ( ) . unwrap_or_default ( ) ) ;
2016-04-21 15:41:25 +02:00
miner . set_gas_floor_target ( conf . gas_floor_target ( ) ) ;
2016-06-23 14:29:16 +02:00
miner . set_gas_ceil_target ( conf . gas_ceil_target ( ) ) ;
2016-04-21 15:41:25 +02:00
miner . set_extra_data ( conf . extra_data ( ) ) ;
2016-06-27 18:27:06 +02:00
miner . set_transactions_limit ( conf . args . flag_tx_queue_size ) ;
2016-04-21 15:41:25 +02:00
2016-05-31 21:38:07 +02:00
// Build client
2016-07-11 17:02:42 +02:00
let service = ClientService ::start (
2016-07-05 17:50:46 +02:00
client_config ,
spec ,
Path ::new ( & conf . path ( ) ) ,
miner . clone ( ) ,
2016-05-31 21:38:07 +02:00
) . unwrap_or_else ( | e | die_with_error ( " Client " , e ) ) ;
panic_handler . forward_from ( & service ) ;
let client = service . client ( ) ;
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
2016-07-16 15:51:06 +02:00
let ( sync_provider , manage_network , chain_notify ) =
modules ::sync ( sync_config , NetworkConfiguration ::from ( net_settings ) , client . clone ( ) )
. unwrap_or_else ( | e | die_with_error ( " Sync " , e ) ) ;
2016-07-20 12:36:20 +02:00
service . add_notify ( & chain_notify ) ;
2016-07-11 17:02:42 +02:00
// if network is active by default
if match conf . mode ( ) { Mode ::Dark ( .. ) = > false , _ = > ! conf . args . flag_no_network } {
2016-07-16 15:51:06 +02:00
chain_notify . start ( ) ;
2016-07-11 17:02:42 +02:00
}
2016-04-21 15:41:25 +02:00
2016-06-01 19:37:34 +02:00
let deps_for_rpc_apis = Arc ::new ( rpc_apis ::Dependencies {
2016-06-10 15:39:34 +02:00
signer_port : conf . signer_port ( ) ,
2016-06-01 19:37:34 +02:00
signer_queue : Arc ::new ( rpc_apis ::ConfirmationsQueue ::default ( ) ) ,
2016-04-21 15:41:25 +02:00
client : client . clone ( ) ,
2016-07-16 15:51:06 +02:00
sync : sync_provider . clone ( ) ,
net : manage_network . clone ( ) ,
2016-04-21 15:41:25 +02:00
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-06-19 14:51:51 +02:00
allow_pending_receipt_query : ! conf . args . flag_geth ,
2016-07-16 15:51:06 +02:00
net_service : manage_network . clone ( ) ,
2016-04-21 15:41:25 +02:00
} ) ;
2016-06-01 19:37:34 +02:00
let dependencies = rpc ::Dependencies {
panic_handler : panic_handler . clone ( ) ,
apis : deps_for_rpc_apis . clone ( ) ,
} ;
2016-05-04 15:37:09 +02:00
// Setup http rpc
let rpc_server = rpc ::new_http ( rpc ::HttpConfiguration {
enabled : network_settings . rpc_enabled ,
2016-06-24 12:10:36 +02:00
interface : conf . rpc_interface ( ) ,
2016-05-04 15:37:09 +02:00
port : network_settings . rpc_port ,
apis : conf . rpc_apis ( ) ,
cors : conf . rpc_cors ( ) ,
2016-07-20 12:34:17 +02:00
hosts : conf . rpc_hosts ( ) ,
2016-05-04 15:37:09 +02:00
} , & dependencies ) ;
// setup ipc rpc
2016-05-04 22:44:42 +02:00
let _ipc_server = rpc ::new_ipc ( conf . ipc_settings ( ) , & dependencies ) ;
2016-06-13 18:55:24 +02:00
debug! ( " IPC: {} " , conf . ipc_settings ( ) ) ;
2016-05-04 15:37:09 +02:00
2016-05-26 18:21:15 +02:00
if conf . args . flag_webapp { println! ( " WARNING: Flag -w/--webapp is deprecated. Dapps server is now on by default. Ignoring. " ) ; }
let dapps_server = dapps ::new ( dapps ::Configuration {
2016-06-24 12:14:46 +02:00
enabled : conf . dapps_enabled ( ) ,
2016-06-24 12:10:36 +02:00
interface : conf . dapps_interface ( ) ,
2016-05-26 18:21:15 +02:00
port : conf . args . flag_dapps_port ,
user : conf . args . flag_dapps_user . clone ( ) ,
pass : conf . args . flag_dapps_pass . clone ( ) ,
2016-06-03 11:51:11 +02:00
dapps_path : conf . directories ( ) . dapps ,
2016-05-26 18:21:15 +02:00
} , dapps ::Dependencies {
2016-04-23 12:29:12 +02:00
panic_handler : panic_handler . clone ( ) ,
2016-06-01 19:37:34 +02:00
apis : deps_for_rpc_apis . clone ( ) ,
2016-04-21 15:41:25 +02:00
} ) ;
2016-05-27 13:03:00 +02:00
// Set up a signer
let signer_server = signer ::start ( signer ::Configuration {
2016-06-24 14:29:15 +02:00
enabled : conf . signer_enabled ( ) ,
2016-05-27 13:03:00 +02:00
port : conf . args . flag_signer_port ,
2016-06-07 17:21:19 +02:00
signer_path : conf . directories ( ) . signer ,
2016-05-27 13:03:00 +02:00
} , signer ::Dependencies {
panic_handler : panic_handler . clone ( ) ,
2016-06-01 19:37:34 +02:00
apis : deps_for_rpc_apis . clone ( ) ,
2016-05-27 13:03:00 +02:00
} ) ;
2016-07-20 12:36:20 +02:00
let informant = Arc ::new ( Informant ::new ( service . client ( ) , Some ( sync_provider . clone ( ) ) , Some ( manage_network . clone ( ) ) , conf . have_color ( ) ) ) ;
let info_notify : Arc < ChainNotify > = informant . clone ( ) ;
service . add_notify ( & info_notify ) ;
2016-04-21 15:41:25 +02:00
// Register IO handler
2016-07-05 17:50:46 +02:00
let io_handler = Arc ::new ( ClientIoHandler {
2016-04-21 15:41:25 +02:00
client : service . client ( ) ,
2016-07-20 12:36:20 +02:00
info : informant ,
2016-07-16 15:51:06 +02:00
sync : sync_provider . clone ( ) ,
net : manage_network . clone ( ) ,
2016-04-21 15:41:25 +02:00
accounts : account_service . clone ( ) ,
} ) ;
2016-06-17 12:58:28 +02:00
service . register_io_handler ( io_handler ) . expect ( " Error registering IO handler " ) ;
2016-04-21 15:41:25 +02:00
2016-06-14 16:12:46 +02:00
if conf . args . cmd_ui {
2016-06-24 12:14:46 +02:00
if ! conf . dapps_enabled ( ) {
2016-06-24 12:10:36 +02:00
die_with_message ( " Cannot use UI command with Dapps turned off. " ) ;
}
url ::open ( & format! ( " http:// {} : {} / " , conf . dapps_interface ( ) , conf . args . flag_dapps_port ) ) ;
2016-06-14 16:12:46 +02:00
}
2016-04-21 15:41:25 +02:00
// Handle exit
2016-05-27 13:03:00 +02:00
wait_for_exit ( panic_handler , rpc_server , dapps_server , signer_server ) ;
2016-04-21 15:41:25 +02:00
}
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 18:42:59 +02:00
enum DataFormat {
Hex ,
Binary ,
}
2016-07-17 23:00:57 +02:00
fn execute_export ( conf : Configuration , panic_handler : Arc < PanicHandler > ) {
2016-05-23 09:51:36 +02:00
let spec = conf . spec ( ) ;
let client_config = conf . client_config ( & spec ) ;
// Build client
let service = ClientService ::start (
2016-07-11 17:02:42 +02:00
client_config , spec , Path ::new ( & conf . path ( ) ) , Arc ::new ( Miner ::with_spec ( conf . spec ( ) ) )
2016-05-23 09:51:36 +02:00
) . unwrap_or_else ( | e | die_with_error ( " Client " , e ) ) ;
panic_handler . forward_from ( & service ) ;
let client = service . client ( ) ;
// we have a client!
2016-05-24 13:31:03 +02:00
let parse_block_id = | s : & str , arg : & str | -> u64 {
2016-05-23 09:51:36 +02:00
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 ( | | {
2016-05-24 13:31:03 +02:00
die! ( " Unknown block hash passed to {} parameter: {:?} " , arg , s ) ;
2016-05-23 09:51:36 +02:00
} )
} else {
2016-05-24 13:31:03 +02:00
die! ( " Invalid {} parameter given: {:?} " , arg , s ) ;
2016-05-23 09:51:36 +02:00
}
} ;
2016-05-24 13:31:03 +02:00
let from = parse_block_id ( & conf . args . flag_from , " --from " ) ;
let to = parse_block_id ( & conf . args . flag_to , " --to " ) ;
2016-05-24 20:29:19 +02:00
let format = match conf . args . flag_format {
Some ( x ) = > match x . deref ( ) {
" binary " | " bin " = > DataFormat ::Binary ,
" hex " = > DataFormat ::Hex ,
x = > die! ( " Invalid --format parameter given: {:?} " , x ) ,
} ,
None if conf . args . arg_file . is_none ( ) = > DataFormat ::Hex ,
None = > DataFormat ::Binary ,
2016-05-23 18:42:59 +02:00
} ;
2016-05-23 09:51:36 +02:00
2016-05-23 18:42:59 +02:00
let mut out : Box < Write > = if let Some ( f ) = conf . args . arg_file {
Box ::new ( File ::create ( & f ) . unwrap_or_else ( | _ | die! ( " Cannot write to file given: {} " , f ) ) )
} else {
Box ::new ( ::std ::io ::stdout ( ) )
} ;
for i in from .. ( to + 1 ) {
let b = client . deref ( ) . block ( BlockID ::Number ( i ) ) . unwrap ( ) ;
match format {
DataFormat ::Binary = > { out . write ( & b ) . expect ( " Couldn't write to stream. " ) ; }
DataFormat ::Hex = > { out . write_fmt ( format_args! ( " {} " , b . pretty ( ) ) ) . expect ( " Couldn't write to stream. " ) ; }
}
2016-05-23 09:51:36 +02:00
}
}
2016-07-17 23:00:57 +02:00
fn execute_import ( conf : Configuration , panic_handler : Arc < PanicHandler > ) {
2016-05-24 20:29:19 +02:00
let spec = conf . spec ( ) ;
let client_config = conf . client_config ( & spec ) ;
// Build client
let service = ClientService ::start (
2016-07-11 17:02:42 +02:00
client_config , spec , Path ::new ( & conf . path ( ) ) , Arc ::new ( Miner ::with_spec ( conf . spec ( ) ) )
2016-05-24 20:29:19 +02:00
) . unwrap_or_else ( | e | die_with_error ( " Client " , e ) ) ;
panic_handler . forward_from ( & service ) ;
let client = service . client ( ) ;
2016-06-13 18:55:24 +02:00
let mut instream : Box < Read > = if let Some ( ref f ) = conf . args . arg_file {
let f = File ::open ( f ) . unwrap_or_else ( | _ | die! ( " Cannot open the file given: {} " , f ) ) ;
2016-05-24 20:29:19 +02:00
Box ::new ( f )
} else {
Box ::new ( ::std ::io ::stdin ( ) )
} ;
2016-06-15 23:12:43 +02:00
const READAHEAD_BYTES : usize = 8 ;
let mut first_bytes : Bytes = vec! [ 0 ; READAHEAD_BYTES ] ;
2016-05-24 20:29:19 +02:00
let mut first_read = 0 ;
let format = match conf . args . flag_format {
2016-06-13 18:55:24 +02:00
Some ( ref x ) = > match x . deref ( ) {
2016-05-24 20:29:19 +02:00
" binary " | " bin " = > DataFormat ::Binary ,
" hex " = > DataFormat ::Hex ,
x = > die! ( " Invalid --format parameter given: {:?} " , x ) ,
} ,
None = > {
// autodetect...
first_read = instream . read ( & mut ( first_bytes [ .. ] ) ) . unwrap_or_else ( | _ | die! ( " Error reading from the file/stream. " ) ) ;
match first_bytes [ 0 ] {
0xf9 = > {
2016-07-17 23:00:57 +02:00
info! ( " Autodetected binary data format. " ) ;
2016-05-24 20:29:19 +02:00
DataFormat ::Binary
}
_ = > {
2016-07-17 23:00:57 +02:00
info! ( " Autodetected hex data format. " ) ;
2016-05-24 20:29:19 +02:00
DataFormat ::Hex
}
}
}
} ;
2016-07-20 12:36:20 +02:00
let informant = Informant ::new ( client . clone ( ) , None , None , conf . have_color ( ) ) ;
2016-05-25 09:57:31 +02:00
2016-05-24 20:29:19 +02:00
let do_import = | bytes | {
2016-05-25 09:57:31 +02:00
while client . queue_info ( ) . is_full ( ) { sleep ( Duration ::from_secs ( 1 ) ) ; }
2016-05-24 20:29:19 +02:00
match client . import_block ( bytes ) {
2016-05-25 09:57:31 +02:00
Ok ( _ ) = > { }
2016-07-01 21:40:54 +02:00
Err ( BlockImportError ::Import ( ImportError ::AlreadyInChain ) ) = > { trace! ( " Skipping block already in chain. " ) ; }
2016-05-24 20:29:19 +02:00
Err ( e ) = > die! ( " Cannot import block: {:?} " , e )
}
2016-07-20 12:36:20 +02:00
informant . tick ( ) ;
2016-05-24 20:29:19 +02:00
} ;
match format {
DataFormat ::Binary = > {
loop {
2016-06-15 23:12:43 +02:00
let mut bytes : Bytes = if first_read > 0 { first_bytes . clone ( ) } else { vec! [ 0 ; READAHEAD_BYTES ] } ;
2016-05-24 20:29:19 +02:00
let n = if first_read > 0 { first_read } else { instream . read ( & mut ( bytes [ .. ] ) ) . unwrap_or_else ( | _ | die! ( " Error reading from the file/stream. " ) ) } ;
if n = = 0 { break ; }
first_read = 0 ;
let s = PayloadInfo ::from ( & ( bytes [ .. ] ) ) . unwrap_or_else ( | e | die! ( " Invalid RLP in the file/stream: {:?} " , e ) ) . total ( ) ;
bytes . resize ( s , 0 ) ;
2016-06-15 23:12:43 +02:00
instream . read_exact ( & mut ( bytes [ READAHEAD_BYTES .. ] ) ) . unwrap_or_else ( | _ | die! ( " Error reading from the file/stream. " ) ) ;
2016-05-24 20:29:19 +02:00
do_import ( bytes ) ;
}
}
2016-05-26 18:21:15 +02:00
DataFormat ::Hex = > {
2016-05-24 20:29:19 +02:00
for line in BufReader ::new ( instream ) . lines ( ) {
let s = line . unwrap_or_else ( | _ | die! ( " Error reading from the file/stream. " ) ) ;
2016-05-26 18:24:51 +02:00
let s = if first_read > 0 { from_utf8 ( & first_bytes ) . unwrap ( ) . to_owned ( ) + & ( s [ .. ] ) } else { s } ;
2016-05-24 20:29:19 +02:00
first_read = 0 ;
let bytes = FromHex ::from_hex ( & ( s [ .. ] ) ) . unwrap_or_else ( | _ | die! ( " Invalid hex in file/stream. " ) ) ;
do_import ( bytes ) ;
}
}
}
2016-07-19 09:23:53 +02:00
while ! client . queue_info ( ) . is_empty ( ) {
sleep ( Duration ::from_secs ( 1 ) ) ;
2016-07-20 12:36:20 +02:00
informant . tick ( ) ;
2016-07-19 09:23:53 +02:00
}
2016-05-24 20:29:19 +02:00
client . flush_queue ( ) ;
}
2016-06-07 17:21:19 +02:00
fn execute_signer ( conf : Configuration ) {
if ! conf . args . cmd_new_token {
die! ( " Unknown command. " ) ;
}
let path = conf . directories ( ) . signer ;
2016-07-17 23:00:57 +02:00
let code = new_token ( path ) . unwrap_or_else ( | e | {
2016-06-07 17:21:19 +02:00
die! ( " Error generating token: {:?} " , e )
} ) ;
2016-07-17 23:00:57 +02:00
println! ( " This key code will authorise your System Signer UI: {} " , if conf . args . flag_no_color { code } else { format! ( " {} " , Colour ::White . bold ( ) . paint ( code ) ) } ) ;
2016-06-07 17:21:19 +02:00
}
2016-04-21 15:41:25 +02:00
fn execute_account_cli ( conf : Configuration ) {
2016-06-20 15:20:55 +02:00
use ethcore ::ethstore ::{ EthStore , import_accounts } ;
2016-06-20 00:10:34 +02:00
use ethcore ::ethstore ::dir ::DiskDirectory ;
use ethcore ::account_provider ::AccountProvider ;
2016-04-21 15:41:25 +02:00
use rpassword ::read_password ;
2016-06-20 00:10:34 +02:00
let dir = Box ::new ( DiskDirectory ::create ( conf . keys_path ( ) ) . unwrap ( ) ) ;
let iterations = conf . keys_iterations ( ) ;
let secret_store = AccountProvider ::new ( Box ::new ( EthStore ::open_with_iterations ( dir , iterations ) . unwrap ( ) ) ) ;
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 ;
}
2016-06-20 00:10:34 +02:00
2016-04-21 15:41:25 +02:00
if conf . args . cmd_list {
println! ( " Known addresses: " ) ;
2016-06-20 00:10:34 +02:00
for addr in & secret_store . accounts ( ) {
2016-04-21 15:41:25 +02:00
println! ( " {:?} " , addr ) ;
}
2016-06-08 15:17:37 +02:00
return ;
}
2016-06-20 00:10:34 +02:00
2016-06-08 15:17:37 +02:00
if conf . args . cmd_import {
2016-06-20 00:10:34 +02:00
let to = DiskDirectory ::create ( conf . keys_path ( ) ) . unwrap ( ) ;
let mut imported = 0 ;
for path in & conf . args . arg_path {
let from = DiskDirectory ::at ( path ) ;
imported + = import_accounts ( & from , & to ) . unwrap_or_else ( | e | die! ( " Could not import accounts {} " , e ) ) . len ( ) ;
}
2016-06-08 15:17:37 +02:00
println! ( " Imported {} keys " , imported ) ;
2016-04-21 15:41:25 +02:00
}
}
2016-06-21 17:50:22 +02:00
fn execute_wallet_cli ( conf : Configuration ) {
2016-06-23 12:04:54 +02:00
use ethcore ::ethstore ::{ PresaleWallet , EthStore } ;
2016-06-21 17:50:22 +02:00
use ethcore ::ethstore ::dir ::DiskDirectory ;
use ethcore ::account_provider ::AccountProvider ;
let wallet_path = conf . args . arg_path . first ( ) . unwrap ( ) ;
let filename = conf . args . flag_password . first ( ) . unwrap ( ) ;
let mut file = File ::open ( filename ) . unwrap_or_else ( | _ | die! ( " {} Unable to read password file. " , filename ) ) ;
let mut file_content = String ::new ( ) ;
file . read_to_string ( & mut file_content ) . unwrap_or_else ( | _ | die! ( " {} Unable to read password file. " , filename ) ) ;
let dir = Box ::new ( DiskDirectory ::create ( conf . keys_path ( ) ) . unwrap ( ) ) ;
let iterations = conf . keys_iterations ( ) ;
let store = AccountProvider ::new ( Box ::new ( EthStore ::open_with_iterations ( dir , iterations ) . unwrap ( ) ) ) ;
// remove eof
let pass = & file_content [ .. file_content . len ( ) - 1 ] ;
let wallet = PresaleWallet ::open ( wallet_path ) . unwrap_or_else ( | _ | die! ( " Unable to open presale wallet. " ) ) ;
let kp = wallet . decrypt ( pass ) . unwrap_or_else ( | _ | die! ( " Invalid password " ) ) ;
let address = store . insert_account ( kp . secret ( ) . clone ( ) , pass ) . unwrap ( ) ;
println! ( " Imported account: {} " , address ) ;
}
2016-05-27 13:03:00 +02:00
fn wait_for_exit (
panic_handler : Arc < PanicHandler > ,
_rpc_server : Option < RpcServer > ,
_dapps_server : Option < WebappServer > ,
_signer_server : Option < SignerServer >
) {
2016-04-21 15:41:25 +02:00
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 ( ( ) ) ;
2016-07-19 09:25:51 +02:00
exit . wait ( & mut mutex . lock ( ) ) ;
2016-04-21 15:41:25 +02:00
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 ( ) {
}