2016-12-11 19:14:42 +01:00
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
2016-07-25 16:09:47 +02:00
// 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-12-11 02:02:40 +01:00
use std ::sync ::Arc ;
2016-11-03 12:00:39 +01:00
use std ::net ::{ TcpListener } ;
2016-07-25 16:09:47 +02:00
use ctrlc ::CtrlC ;
use fdlimit ::raise_fd_limit ;
2016-10-20 23:36:18 +02:00
use ethcore_rpc ::{ NetworkSettings , is_major_importing } ;
2016-08-05 10:32:04 +02:00
use ethsync ::NetworkConfiguration ;
2016-12-11 02:02:40 +01:00
use util ::{ Colour , version , RotatingLogger , Mutex , Condvar } ;
2016-08-05 10:32:04 +02:00
use io ::{ MayPanic , ForwardPanic , PanicHandler } ;
2016-11-02 19:42:21 +01:00
use ethcore_logger ::{ Config as LogConfig } ;
2016-12-11 02:02:40 +01:00
use ethcore ::client ::{ Mode , DatabaseCompactionProfile , VMType , BlockChainClient } ;
2016-07-25 16:09:47 +02:00
use ethcore ::service ::ClientService ;
use ethcore ::account_provider ::AccountProvider ;
use ethcore ::miner ::{ Miner , MinerService , ExternalMiner , MinerOptions } ;
2016-09-02 18:48:07 +02:00
use ethcore ::snapshot ;
2016-12-02 18:21:54 +01:00
use ethcore ::verification ::queue ::VerifierSettings ;
2016-10-11 18:42:20 +02:00
use ethsync ::SyncConfig ;
2016-07-25 16:09:47 +02:00
use informant ::Informant ;
2016-12-11 02:02:40 +01:00
use updater ::{ UpdatePolicy , Updater } ;
2016-07-25 16:09:47 +02:00
2016-12-17 00:44:18 +01:00
use rpc ::{ HttpConfiguration , IpcConfiguration } ;
2016-10-03 11:13:10 +02:00
use params ::{
SpecType , Pruning , AccountsConfig , GasPricerConfig , MinerExtras , Switch ,
2016-11-05 10:38:00 +01:00
tracing_switch_to_bool , fatdb_switch_to_bool , mode_switch_to_bool
2016-10-03 11:13:10 +02:00
} ;
2016-07-25 16:09:47 +02:00
use helpers ::{ to_client_config , execute_upgrades , passwords_from_files } ;
2016-12-12 16:51:07 +01:00
use upgrade ::upgrade_key_location ;
2016-07-25 16:09:47 +02:00
use dir ::Directories ;
use cache ::CacheConfig ;
2016-09-26 19:21:25 +02:00
use user_defaults ::UserDefaults ;
2016-07-25 16:09:47 +02:00
use dapps ;
use signer ;
use modules ;
use rpc_apis ;
use rpc ;
use url ;
2016-09-02 20:24:59 +02:00
// how often to take periodic snapshots.
2016-09-02 18:48:07 +02:00
const SNAPSHOT_PERIOD : u64 = 10000 ;
2016-09-02 20:24:59 +02:00
// how many blocks to wait before starting a periodic snapshot.
2016-10-30 15:39:36 +01:00
const SNAPSHOT_HISTORY : u64 = 100 ;
2016-09-02 18:48:07 +02:00
2016-07-25 16:09:47 +02:00
#[ derive(Debug, PartialEq) ]
pub struct RunCmd {
pub cache_config : CacheConfig ,
pub dirs : Directories ,
pub spec : SpecType ,
pub pruning : Pruning ,
2016-10-14 14:44:56 +02:00
pub pruning_history : u64 ,
2016-07-25 16:09:47 +02:00
/// Some if execution should be daemonized. Contains pid_file path.
pub daemon : Option < String > ,
pub logger_config : LogConfig ,
pub miner_options : MinerOptions ,
pub http_conf : HttpConfiguration ,
pub ipc_conf : IpcConfiguration ,
pub net_conf : NetworkConfiguration ,
2016-12-05 15:54:31 +01:00
pub network_id : Option < u64 > ,
2016-10-18 18:16:00 +02:00
pub warp_sync : bool ,
2016-07-25 16:09:47 +02:00
pub acc_conf : AccountsConfig ,
pub gas_pricer : GasPricerConfig ,
pub miner_extras : MinerExtras ,
2016-11-23 20:35:21 +01:00
pub update_policy : UpdatePolicy ,
2016-11-05 10:38:00 +01:00
pub mode : Option < Mode > ,
2016-07-25 16:09:47 +02:00
pub tracing : Switch ,
2016-10-03 11:13:10 +02:00
pub fat_db : Switch ,
2016-07-25 16:09:47 +02:00
pub compaction : DatabaseCompactionProfile ,
2016-07-29 15:36:00 +02:00
pub wal : bool ,
2016-07-25 16:09:47 +02:00
pub vm_type : VMType ,
pub geth_compatibility : bool ,
2016-11-09 19:41:47 +01:00
pub ui_address : Option < ( String , u16 ) > ,
2016-07-25 16:09:47 +02:00
pub net_settings : NetworkSettings ,
pub dapps_conf : dapps ::Configuration ,
pub signer_conf : signer ::Configuration ,
pub ui : bool ,
pub name : String ,
pub custom_bootnodes : bool ,
2016-09-02 20:24:59 +02:00
pub no_periodic_snapshot : bool ,
2016-10-24 15:09:13 +02:00
pub check_seal : bool ,
2016-11-22 18:03:35 +01:00
pub download_old_blocks : bool ,
2016-12-02 18:21:54 +01:00
pub verifier_settings : VerifierSettings ,
2016-12-16 21:45:51 +01:00
pub light : bool ,
2016-07-25 16:09:47 +02:00
}
2016-11-14 11:56:01 +01:00
pub fn open_ui ( dapps_conf : & dapps ::Configuration , signer_conf : & signer ::Configuration ) -> Result < ( ) , String > {
if ! dapps_conf . enabled {
return Err ( " Cannot use UI command with Dapps turned off. " . into ( ) )
}
if ! signer_conf . enabled {
return Err ( " Cannot use UI command with UI turned off. " . into ( ) )
}
2016-11-16 09:37:48 +01:00
let token = try ! ( signer ::generate_token_and_url ( signer_conf ) ) ;
// Open a browser
url ::open ( & token . url ) ;
// Print a message
println! ( " {} " , token . message ) ;
2016-11-14 11:56:01 +01:00
Ok ( ( ) )
}
2016-12-16 21:45:51 +01:00
// Execute in light client mode.
2016-12-17 00:44:18 +01:00
pub fn execute_light ( cmd : RunCmd ) -> Result < bool , String > {
2016-12-16 21:45:51 +01:00
use light ::client ::{ Config as ClientConfig , Service as LightClientService } ;
use ethsync ::{ LightSync , LightSyncParams , ManageNetwork } ;
let panic_handler = PanicHandler ::new_in_arc ( ) ;
info! (
" Configured in {} mode. Note that this feature is {}. " ,
2016-12-17 00:40:41 +01:00
Colour ::Blue . bold ( ) . paint ( " Light Client " ) ,
2016-12-16 21:45:51 +01:00
Colour ::Red . bold ( ) . paint ( " experimental " ) ,
) ;
let mut client_config = ClientConfig ::default ( ) ;
let queue_size = cmd . cache_config . queue ( ) ;
client_config . queue . max_queue_size = queue_size as usize ;
client_config . queue . verifier_settings = cmd . verifier_settings ;
let spec = try ! ( cmd . spec . spec ( ) ) ;
let service = try ! ( LightClientService ::start ( client_config , & spec )
. map_err ( | e | format! ( " Error starting light client service: {} " , e ) ) ) ;
let net_conf = try ! ( cmd . net_conf . into_basic ( )
. map_err ( | e | format! ( " Failed to create network config: {} " , e ) ) ) ;
let sync_params = LightSyncParams {
network_config : net_conf ,
client : service . client ( ) . clone ( ) ,
network_id : cmd . network_id . unwrap_or ( spec . network_id ( ) ) ,
subprotocol_name : * b " les " ,
} ;
let sync = try ! ( LightSync ::new ( sync_params )
. map_err ( | e | format! ( " Failed to initialize sync service: {} " , e ) ) ) ;
sync . start_network ( ) ;
let log_client = service . client ( ) . clone ( ) ;
::std ::thread ::spawn ( move | | {
2016-12-17 00:44:18 +01:00
// TODO: proper informant.
2016-12-16 21:45:51 +01:00
loop {
::std ::thread ::sleep ( ::std ::time ::Duration ::from_secs ( 5 ) ) ;
2016-12-17 00:40:41 +01:00
let chain_info = log_client . chain_info ( ) ;
let queue_info = log_client . queue_info ( ) ;
println! (
" #{} {:5}+{:5} Qed " ,
chain_info . best_block_number ,
queue_info . unverified_queue_size ,
queue_info . verified_queue_size
) ;
2016-12-16 21:45:51 +01:00
}
} ) ;
wait_for_exit ( panic_handler , None , false ) ;
Ok ( false )
}
2016-12-11 04:05:02 +01:00
pub fn execute ( cmd : RunCmd , can_restart : bool , logger : Arc < RotatingLogger > ) -> Result < bool , String > {
2016-11-03 12:00:39 +01:00
if cmd . ui & & cmd . dapps_conf . enabled {
// Check if Parity is already running
let addr = format! ( " {} : {} " , cmd . dapps_conf . interface , cmd . dapps_conf . port ) ;
if ! TcpListener ::bind ( & addr as & str ) . is_ok ( ) {
2016-12-10 23:58:39 +01:00
return open_ui ( & cmd . dapps_conf , & cmd . signer_conf ) . map ( | _ | false ) ;
2016-11-03 12:00:39 +01:00
}
}
2016-12-16 21:45:51 +01:00
if cmd . light {
2016-12-17 00:44:18 +01:00
return execute_light ( cmd ) ;
2016-12-16 21:45:51 +01:00
}
2016-09-26 19:21:25 +02:00
// set up panic handler
let panic_handler = PanicHandler ::new_in_arc ( ) ;
2016-07-25 16:09:47 +02:00
2016-09-26 19:21:25 +02:00
// increase max number of open files
raise_fd_limit ( ) ;
2016-07-25 16:09:47 +02:00
// load spec
let spec = try ! ( cmd . spec . spec ( ) ) ;
// load genesis hash
let genesis_hash = spec . genesis_header ( ) . hash ( ) ;
2016-09-26 19:21:25 +02:00
// database paths
2016-12-12 16:51:07 +01:00
let db_dirs = cmd . dirs . database ( genesis_hash , cmd . spec . legacy_fork_name ( ) , spec . data_dir . clone ( ) ) ;
2016-09-26 19:21:25 +02:00
// user defaults path
let user_defaults_path = db_dirs . user_defaults_path ( ) ;
// load user defaults
let mut user_defaults = try ! ( UserDefaults ::load ( & user_defaults_path ) ) ;
2016-10-03 11:13:10 +02:00
// select pruning algorithm
let algorithm = cmd . pruning . to_algorithm ( & user_defaults ) ;
2016-09-26 19:21:25 +02:00
// check if tracing is on
let tracing = try ! ( tracing_switch_to_bool ( cmd . tracing , & user_defaults ) ) ;
2016-10-03 11:13:10 +02:00
// check if fatdb is on
let fat_db = try ! ( fatdb_switch_to_bool ( cmd . fat_db , & user_defaults , algorithm ) ) ;
2016-07-25 16:09:47 +02:00
2016-11-05 10:38:00 +01:00
// get the mode
let mode = try ! ( mode_switch_to_bool ( cmd . mode , & user_defaults ) ) ;
trace! ( target : " mode " , " mode is {:?} " , mode ) ;
2016-11-28 13:20:49 +01:00
let network_enabled = match mode { Mode ::Dark ( _ ) | Mode ::Off = > false , _ = > true , } ;
2016-11-05 10:38:00 +01:00
2016-11-23 20:35:21 +01:00
// get the update policy
let update_policy = cmd . update_policy ;
2016-09-07 15:27:28 +02:00
// prepare client and snapshot paths.
2016-09-26 19:21:25 +02:00
let client_path = db_dirs . client_path ( algorithm ) ;
let snapshot_path = db_dirs . snapshot_path ( ) ;
2016-07-25 16:09:47 +02:00
// execute upgrades
2016-12-15 21:56:45 +01:00
try ! ( execute_upgrades ( & cmd . dirs . base , & db_dirs , algorithm , cmd . compaction . compaction_profile ( db_dirs . db_root_path ( ) . as_path ( ) ) ) ) ;
2016-07-25 16:09:47 +02:00
2016-12-13 23:38:29 +01:00
// create dirs used by parity
try ! ( cmd . dirs . create_dirs ( cmd . dapps_conf . enabled , cmd . signer_conf . enabled ) ) ;
2016-07-25 16:09:47 +02:00
// run in daemon mode
if let Some ( pid_file ) = cmd . daemon {
try ! ( daemonize ( pid_file ) ) ;
}
// display info about used pruning algorithm
info! ( " Starting {} " , Colour ::White . bold ( ) . paint ( version ( ) ) ) ;
2016-12-14 15:15:19 +01:00
info! ( " State DB configuration: {}{}{} " ,
2016-10-03 11:13:10 +02:00
Colour ::White . bold ( ) . paint ( algorithm . as_str ( ) ) ,
match fat_db {
true = > Colour ::White . bold ( ) . paint ( " +Fat " ) . to_string ( ) ,
false = > " " . to_owned ( ) ,
} ,
match tracing {
true = > Colour ::White . bold ( ) . paint ( " +Trace " ) . to_string ( ) ,
false = > " " . to_owned ( ) ,
}
) ;
2016-11-05 10:38:00 +01:00
info! ( " Operating mode: {} " , Colour ::White . bold ( ) . paint ( format! ( " {} " , mode ) ) ) ;
2016-07-25 16:09:47 +02:00
// display warning about using experimental journaldb alorithm
if ! algorithm . is_stable ( ) {
warn! ( " Your chosen strategy is {}! You can re-run with --pruning to change. " , Colour ::Red . bold ( ) . paint ( " unstable " ) ) ;
}
// create sync config
let mut sync_config = SyncConfig ::default ( ) ;
sync_config . network_id = match cmd . network_id {
Some ( id ) = > id ,
None = > spec . network_id ( ) ,
} ;
2016-09-28 14:21:59 +02:00
if spec . subprotocol_name ( ) . len ( ) ! = 3 {
warn! ( " Your chain specification's subprotocol length is not 3. Ignoring. " ) ;
} else {
sync_config . subprotocol_name . clone_from_slice ( spec . subprotocol_name ( ) . as_bytes ( ) ) ;
}
2016-08-03 19:01:48 +02:00
sync_config . fork_block = spec . fork_block ( ) ;
2016-10-18 18:16:00 +02:00
sync_config . warp_sync = cmd . warp_sync ;
2016-11-22 18:03:35 +01:00
sync_config . download_old_blocks = cmd . download_old_blocks ;
2016-07-25 16:09:47 +02:00
2016-12-05 20:23:03 +01:00
let passwords = try ! ( passwords_from_files ( & cmd . acc_conf . password_files ) ) ;
2016-07-25 16:09:47 +02:00
// prepare account provider
2016-12-12 16:51:07 +01:00
let account_provider = Arc ::new ( try ! ( prepare_account_provider ( & cmd . dirs , & spec . data_dir , cmd . acc_conf , & passwords ) ) ) ;
2016-07-25 16:09:47 +02:00
2016-12-05 18:08:16 +01:00
// let the Engine access the accounts
spec . engine . register_account_provider ( account_provider . clone ( ) ) ;
2016-07-25 16:09:47 +02:00
// create miner
2016-08-05 23:33:55 +02:00
let miner = Miner ::new ( cmd . miner_options , cmd . gas_pricer . into ( ) , & spec , Some ( account_provider . clone ( ) ) ) ;
2016-07-25 16:09:47 +02:00
miner . set_author ( cmd . miner_extras . author ) ;
miner . set_gas_floor_target ( cmd . miner_extras . gas_floor_target ) ;
miner . set_gas_ceil_target ( cmd . miner_extras . gas_ceil_target ) ;
miner . set_extra_data ( cmd . miner_extras . extra_data ) ;
miner . set_transactions_limit ( cmd . miner_extras . transactions_limit ) ;
2016-12-05 22:31:38 +01:00
let engine_signer = cmd . miner_extras . engine_signer ;
2016-12-07 10:34:06 +01:00
if engine_signer ! = Default ::default ( ) {
if ! passwords . into_iter ( ) . any ( | p | miner . set_engine_signer ( engine_signer , p ) . is_ok ( ) ) {
return Err ( format! ( " No password found for the consensus signer {} . Make sure valid password is present in files passed using `--password`. " , engine_signer ) ) ;
}
2016-12-05 20:23:03 +01:00
}
2016-07-25 16:09:47 +02:00
// create client config
2016-12-02 18:21:54 +01:00
let mut client_config = to_client_config (
2016-07-25 16:09:47 +02:00
& cmd . cache_config ,
2016-11-27 11:11:56 +01:00
mode . clone ( ) ,
2016-09-26 19:21:25 +02:00
tracing ,
2016-10-03 11:13:10 +02:00
fat_db ,
2016-07-25 16:09:47 +02:00
cmd . compaction ,
2016-07-29 15:36:00 +02:00
cmd . wal ,
2016-07-25 16:09:47 +02:00
cmd . vm_type ,
cmd . name ,
2016-09-26 19:21:25 +02:00
algorithm ,
2016-10-14 14:44:56 +02:00
cmd . pruning_history ,
2016-10-24 15:09:13 +02:00
cmd . check_seal ,
2016-07-25 16:09:47 +02:00
) ;
2016-12-02 18:21:54 +01:00
client_config . queue . verifier_settings = cmd . verifier_settings ;
2016-07-25 16:09:47 +02:00
// set up bootnodes
let mut net_conf = cmd . net_conf ;
if ! cmd . custom_bootnodes {
net_conf . boot_nodes = spec . nodes . clone ( ) ;
}
2016-10-11 18:42:20 +02:00
// set network path.
net_conf . net_config_path = Some ( db_dirs . network_path ( ) . to_string_lossy ( ) . into_owned ( ) ) ;
2016-08-10 21:07:01 +02:00
// create supervisor
2016-09-07 15:27:28 +02:00
let mut hypervisor = modules ::hypervisor ( & cmd . dirs . ipc_path ( ) ) ;
2016-08-10 21:07:01 +02:00
2016-08-05 17:00:46 +02:00
// create client service.
2016-07-25 16:09:47 +02:00
let service = try ! ( ClientService ::start (
client_config ,
2016-08-05 23:33:55 +02:00
& spec ,
2016-09-07 15:27:28 +02:00
& client_path ,
& snapshot_path ,
& cmd . dirs . ipc_path ( ) ,
2016-07-25 16:09:47 +02:00
miner . clone ( ) ,
) . map_err ( | e | format! ( " Client service error: {:?} " , e ) ) ) ;
2016-11-15 19:07:23 +01:00
// drop the spec to free up genesis state.
drop ( spec ) ;
2016-07-25 16:09:47 +02:00
// forward panics from service
panic_handler . forward_from ( & service ) ;
// take handle to client
let client = service . client ( ) ;
2016-09-06 15:31:13 +02:00
let snapshot_service = service . snapshot_service ( ) ;
2016-07-25 16:09:47 +02:00
// create external miner
let external_miner = Arc ::new ( ExternalMiner ::default ( ) ) ;
// create sync object
let ( sync_provider , manage_network , chain_notify ) = try ! ( modules ::sync (
2016-12-16 21:45:51 +01:00
& mut hypervisor ,
sync_config ,
net_conf . into ( ) ,
client . clone ( ) ,
snapshot_service . clone ( ) ,
client . clone ( ) ,
2016-12-08 23:21:47 +01:00
& cmd . logger_config ,
2016-07-25 16:09:47 +02:00
) . map_err ( | e | format! ( " Sync error: {} " , e ) ) ) ;
service . add_notify ( chain_notify . clone ( ) ) ;
// start network
2016-11-05 10:38:00 +01:00
if network_enabled {
2016-07-25 16:09:47 +02:00
chain_notify . start ( ) ;
}
2016-12-10 23:58:39 +01:00
// the updater service
2016-12-16 10:31:10 +01:00
let updater = Updater ::new ( Arc ::downgrade ( & ( service . client ( ) as Arc < BlockChainClient > ) ) , Arc ::downgrade ( & sync_provider ) , update_policy ) ;
2016-12-11 02:02:40 +01:00
service . add_notify ( updater . clone ( ) ) ;
2016-12-10 23:58:39 +01:00
2016-07-25 16:09:47 +02:00
// set up dependencies for rpc servers
2016-09-21 12:44:49 +02:00
let signer_path = cmd . signer_conf . signer_path . clone ( ) ;
2016-07-25 16:09:47 +02:00
let deps_for_rpc_apis = Arc ::new ( rpc_apis ::Dependencies {
2016-10-03 15:01:10 +02:00
signer_service : Arc ::new ( rpc_apis ::SignerService ::new ( move | | {
signer ::generate_new_token ( signer_path . clone ( ) ) . map_err ( | e | format! ( " {:?} " , e ) )
2016-11-09 19:41:47 +01:00
} , cmd . ui_address ) ) ,
2016-10-31 17:32:53 +01:00
snapshot : snapshot_service . clone ( ) ,
2016-07-25 16:09:47 +02:00
client : client . clone ( ) ,
sync : sync_provider . clone ( ) ,
net : manage_network . clone ( ) ,
secret_store : account_provider . clone ( ) ,
miner : miner . clone ( ) ,
external_miner : external_miner . clone ( ) ,
logger : logger . clone ( ) ,
settings : Arc ::new ( cmd . net_settings . clone ( ) ) ,
2016-08-03 15:31:00 +02:00
net_service : manage_network . clone ( ) ,
2016-12-11 19:14:42 +01:00
updater : updater . clone ( ) ,
2016-08-03 15:31:00 +02:00
geth_compatibility : cmd . geth_compatibility ,
2016-11-09 19:41:47 +01:00
dapps_interface : match cmd . dapps_conf . enabled {
true = > Some ( cmd . dapps_conf . interface . clone ( ) ) ,
false = > None ,
} ,
2016-10-24 12:21:15 +02:00
dapps_port : match cmd . dapps_conf . enabled {
true = > Some ( cmd . dapps_conf . port ) ,
false = > None ,
} ,
2016-07-25 16:09:47 +02:00
} ) ;
let dependencies = rpc ::Dependencies {
panic_handler : panic_handler . clone ( ) ,
apis : deps_for_rpc_apis . clone ( ) ,
} ;
// start rpc servers
let http_server = try ! ( rpc ::new_http ( cmd . http_conf , & dependencies ) ) ;
let ipc_server = try ! ( rpc ::new_ipc ( cmd . ipc_conf , & dependencies ) ) ;
2016-12-10 23:58:39 +01:00
// the dapps server
2016-07-25 16:09:47 +02:00
let dapps_deps = dapps ::Dependencies {
panic_handler : panic_handler . clone ( ) ,
apis : deps_for_rpc_apis . clone ( ) ,
2016-08-23 19:28:21 +02:00
client : client . clone ( ) ,
2016-09-01 11:16:19 +02:00
sync : sync_provider . clone ( ) ,
2016-07-25 16:09:47 +02:00
} ;
let dapps_server = try ! ( dapps ::new ( cmd . dapps_conf . clone ( ) , dapps_deps ) ) ;
2016-12-10 23:58:39 +01:00
// the signer server
2016-07-25 16:09:47 +02:00
let signer_deps = signer ::Dependencies {
panic_handler : panic_handler . clone ( ) ,
apis : deps_for_rpc_apis . clone ( ) ,
} ;
2016-11-14 11:56:01 +01:00
let signer_server = try ! ( signer ::start ( cmd . signer_conf . clone ( ) , signer_deps ) ) ;
2016-07-25 16:09:47 +02:00
2016-12-10 23:58:39 +01:00
// the informant
2016-10-18 18:16:00 +02:00
let informant = Arc ::new ( Informant ::new (
service . client ( ) ,
Some ( sync_provider . clone ( ) ) ,
Some ( manage_network . clone ( ) ) ,
Some ( snapshot_service . clone ( ) ) ,
cmd . logger_config . color
) ) ;
2016-12-10 23:58:39 +01:00
service . add_notify ( informant . clone ( ) ) ;
service . register_io_handler ( informant . clone ( ) ) . map_err ( | _ | " Unable to register informant handler " . to_owned ( ) ) ? ;
2016-07-25 16:09:47 +02:00
2016-11-05 10:38:00 +01:00
// save user defaults
user_defaults . pruning = algorithm ;
user_defaults . tracing = tracing ;
2016-11-27 11:11:56 +01:00
user_defaults . fat_db = fat_db ;
user_defaults . mode = mode ;
2016-11-05 10:38:00 +01:00
try ! ( user_defaults . save ( & user_defaults_path ) ) ;
2016-12-10 23:58:39 +01:00
// tell client how to save the default mode if it gets changed.
client . on_mode_change ( move | mode : & Mode | {
2016-11-05 10:38:00 +01:00
user_defaults . mode = mode . clone ( ) ;
let _ = user_defaults . save ( & user_defaults_path ) ; // discard failures - there's nothing we can do
2016-12-10 23:58:39 +01:00
} ) ;
2016-11-05 10:38:00 +01:00
2016-09-05 14:25:56 +02:00
// the watcher must be kept alive.
let _watcher = match cmd . no_periodic_snapshot {
true = > None ,
false = > {
2016-09-07 15:27:14 +02:00
let sync = sync_provider . clone ( ) ;
2016-09-05 14:25:56 +02:00
let watcher = Arc ::new ( snapshot ::Watcher ::new (
service . client ( ) ,
2016-10-20 23:36:18 +02:00
move | | is_major_importing ( Some ( sync . status ( ) . state ) , client . queue_info ( ) ) ,
2016-09-05 14:25:56 +02:00
service . io ( ) . channel ( ) ,
SNAPSHOT_PERIOD ,
SNAPSHOT_HISTORY ,
) ) ;
service . add_notify ( watcher . clone ( ) ) ;
Some ( watcher )
} ,
} ;
2016-07-25 16:09:47 +02:00
// start ui
if cmd . ui {
2016-11-14 11:56:01 +01:00
try ! ( open_ui ( & cmd . dapps_conf , & cmd . signer_conf ) ) ;
2016-07-25 16:09:47 +02:00
}
// Handle exit
2016-12-16 21:45:51 +01:00
let restart = wait_for_exit ( panic_handler , Some ( updater ) , can_restart ) ;
2016-12-10 23:58:39 +01:00
2016-12-17 00:44:18 +01:00
// drop this stuff as soon as exit detected.
drop ( ( http_server , ipc_server , dapps_server , signer_server ) ) ;
2016-12-10 23:58:39 +01:00
info! ( " Finishing work, please wait... " ) ;
2016-07-25 16:09:47 +02:00
2016-09-03 10:31:29 +02:00
// to make sure timer does not spawn requests while shutdown is in progress
2016-12-11 02:02:40 +01:00
informant . shutdown ( ) ;
2016-09-03 10:31:29 +02:00
// just Arc is dropping here, to allow other reference release in its default time
2016-12-11 02:02:40 +01:00
drop ( informant ) ;
2016-09-03 10:31:29 +02:00
2016-08-30 14:05:02 +02:00
// hypervisor should be shutdown first while everything still works and can be
// terminated gracefully
drop ( hypervisor ) ;
2016-12-11 13:10:33 +01:00
Ok ( restart )
2016-07-25 16:09:47 +02:00
}
#[ cfg(not(windows)) ]
fn daemonize ( pid_file : String ) -> Result < ( ) , String > {
extern crate daemonize ;
daemonize ::Daemonize ::new ( )
2016-12-10 23:58:39 +01:00
. pid_file ( pid_file )
. chown_pid_file ( true )
. start ( )
. map ( | _ | ( ) )
. map_err ( | e | format! ( " Couldn't daemonize; {} " , e ) )
2016-07-25 16:09:47 +02:00
}
#[ cfg(windows) ]
fn daemonize ( _pid_file : String ) -> Result < ( ) , String > {
Err ( " daemon is no supported on windows " . into ( ) )
}
2016-12-12 16:51:07 +01:00
fn prepare_account_provider ( dirs : & Directories , data_dir : & str , cfg : AccountsConfig , passwords : & [ String ] ) -> Result < AccountProvider , String > {
2016-10-04 10:44:47 +02:00
use ethcore ::ethstore ::EthStore ;
use ethcore ::ethstore ::dir ::DiskDirectory ;
2016-07-25 16:09:47 +02:00
2016-12-12 16:51:07 +01:00
let path = dirs . keys_path ( data_dir ) ;
upgrade_key_location ( & dirs . legacy_keys_path ( cfg . testnet ) , & path ) ;
let dir = Box ::new ( try ! ( DiskDirectory ::create ( & path ) . map_err ( | e | format! ( " Could not open keys directory: {} " , e ) ) ) ) ;
2016-08-03 17:58:22 +02:00
let account_service = AccountProvider ::new ( Box ::new (
try ! ( EthStore ::open_with_iterations ( dir , cfg . iterations ) . map_err ( | e | format! ( " Could not open keys directory: {} " , e ) ) )
) ) ;
2016-07-25 16:09:47 +02:00
for a in cfg . unlocked_accounts {
2016-12-06 09:38:41 +01:00
if ! passwords . iter ( ) . any ( | p | account_service . unlock_account_permanently ( a , ( * p ) . clone ( ) ) . is_ok ( ) ) {
2016-08-02 15:12:33 +02:00
return Err ( format! ( " No password found to unlock account {} . Make sure valid password is present in files passed using `--password`. " , a ) ) ;
2016-07-25 16:09:47 +02:00
}
}
Ok ( account_service )
}
fn wait_for_exit (
panic_handler : Arc < PanicHandler > ,
2016-12-16 21:45:51 +01:00
updater : Option < Arc < Updater > > ,
2016-12-11 04:05:02 +01:00
can_restart : bool
2016-12-10 23:58:39 +01:00
) -> bool {
let exit = Arc ::new ( ( Mutex ::new ( false ) , Condvar ::new ( ) ) ) ;
2016-07-25 16:09:47 +02:00
// Handle possible exits
let e = exit . clone ( ) ;
2016-12-10 23:58:39 +01:00
CtrlC ::set_handler ( move | | { e . 1. notify_all ( ) ; } ) ;
2016-07-25 16:09:47 +02:00
// Handle panics
let e = exit . clone ( ) ;
2016-12-10 23:58:39 +01:00
panic_handler . on_panic ( move | _reason | { e . 1. notify_all ( ) ; } ) ;
2016-12-16 21:45:51 +01:00
if let Some ( updater ) = updater {
// Handle updater wanting to restart us
if can_restart {
let e = exit . clone ( ) ;
updater . set_exit_handler ( move | | { * e . 0. lock ( ) = true ; e . 1. notify_all ( ) ; } ) ;
} else {
updater . set_exit_handler ( | | info! ( " Update installed; ready for restart. " ) ) ;
}
2016-12-11 04:05:02 +01:00
}
2016-07-25 16:09:47 +02:00
// Wait for signal
2016-12-11 02:02:40 +01:00
let mut l = exit . 0. lock ( ) ;
let _ = exit . 1. wait ( & mut l ) ;
* l
2016-07-25 16:09:47 +02:00
}