2016-07-25 16:09:47 +02: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/>.
use std ::sync ::{ Arc , Mutex , Condvar } ;
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-11-03 22:22:25 +01:00
use util ::{ Colour , version , RotatingLogger } ;
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-10-20 23:36:18 +02:00
use ethcore ::client ::{ Mode , DatabaseCompactionProfile , VMType , ChainNotify , 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-10-11 18:42:20 +02:00
use ethsync ::SyncConfig ;
2016-07-25 16:09:47 +02:00
use informant ::Informant ;
use rpc ::{ HttpServer , IpcServer , HttpConfiguration , IpcConfiguration } ;
use signer ::SignerServer ;
use dapps ::WebappServer ;
use io_handler ::ClientIoHandler ;
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 } ;
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 18:08:16 +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-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-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-11-02 19:42:21 +01:00
pub fn execute ( cmd : RunCmd , logger : Arc < RotatingLogger > ) -> Result < ( ) , 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-11-14 11:56:01 +01:00
return open_ui ( & cmd . dapps_conf , & cmd . signer_conf ) ;
2016-11-03 12:00:39 +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
// create dirs used by parity
2016-11-15 10:28:52 +01:00
try ! ( cmd . dirs . create_dirs ( cmd . dapps_conf . enabled , cmd . signer_conf . enabled ) ) ;
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
let db_dirs = cmd . dirs . database ( genesis_hash , spec . fork_name . clone ( ) ) ;
// 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-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-10-21 23:21:57 +02:00
try ! ( execute_upgrades ( & db_dirs , algorithm , cmd . compaction . compaction_profile ( db_dirs . fork_path ( ) . as_path ( ) ) ) ) ;
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-10-03 11:13:10 +02:00
info! ( " State DB configuation: {}{}{} " ,
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-05 20:23:03 +01:00
let account_provider = Arc ::new ( try ! ( prepare_account_provider ( & cmd . dirs , 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 ;
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`. " , cmd . miner_extras . engine_signer ) ) ;
2016-12-05 20:23:03 +01:00
}
2016-07-25 16:09:47 +02:00
// create client config
let client_config = to_client_config (
& 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
) ;
// 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-10-18 18:16:00 +02:00
& mut hypervisor , sync_config , net_conf . into ( ) , client . clone ( ) , snapshot_service . clone ( ) , & 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 ( ) ;
}
// 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 ( ) ,
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 ) ) ;
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
} ;
// start dapps server
let dapps_server = try ! ( dapps ::new ( cmd . dapps_conf . clone ( ) , dapps_deps ) ) ;
let signer_deps = signer ::Dependencies {
panic_handler : panic_handler . clone ( ) ,
apis : deps_for_rpc_apis . clone ( ) ,
} ;
// start signer server
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-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-07-26 00:19:37 +02:00
let info_notify : Arc < ChainNotify > = informant . clone ( ) ;
service . add_notify ( info_notify ) ;
2016-07-25 16:09:47 +02:00
let io_handler = Arc ::new ( ClientIoHandler {
client : service . client ( ) ,
2016-07-26 00:19:37 +02:00
info : informant ,
2016-07-25 16:09:47 +02:00
sync : sync_provider . clone ( ) ,
net : manage_network . clone ( ) ,
accounts : account_provider . clone ( ) ,
2016-09-03 10:31:29 +02:00
shutdown : Default ::default ( ) ,
2016-07-25 16:09:47 +02:00
} ) ;
2016-09-03 10:31:29 +02:00
service . register_io_handler ( io_handler . clone ( ) ) . expect ( " Error registering IO handler " ) ;
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 ) ) ;
let on_mode_change = move | mode : & Mode | {
user_defaults . mode = mode . clone ( ) ;
let _ = user_defaults . save ( & user_defaults_path ) ; // discard failures - there's nothing we can do
} ;
// tell client how to save the default mode if it gets changed.
client . on_mode_change ( on_mode_change ) ;
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
wait_for_exit ( panic_handler , http_server , ipc_server , dapps_server , signer_server ) ;
2016-09-03 10:31:29 +02:00
// to make sure timer does not spawn requests while shutdown is in progress
io_handler . shutdown . store ( true , ::std ::sync ::atomic ::Ordering ::SeqCst ) ;
// just Arc is dropping here, to allow other reference release in its default time
drop ( io_handler ) ;
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-07-25 16:09:47 +02:00
Ok ( ( ) )
}
#[ cfg(not(windows)) ]
fn daemonize ( pid_file : String ) -> Result < ( ) , String > {
extern crate daemonize ;
daemonize ::Daemonize ::new ( )
. pid_file ( pid_file )
. chown_pid_file ( true )
. start ( )
. map ( | _ | ( ) )
. map_err ( | e | format! ( " Couldn't daemonize; {} " , e ) )
}
#[ cfg(windows) ]
fn daemonize ( _pid_file : String ) -> Result < ( ) , String > {
Err ( " daemon is no supported on windows " . into ( ) )
}
2016-12-05 20:23:03 +01:00
fn prepare_account_provider ( dirs : & Directories , 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-08-03 17:58:22 +02:00
let dir = Box ::new ( try ! ( DiskDirectory ::create ( dirs . keys . clone ( ) ) . map_err ( | e | format! ( " Could not open keys directory: {} " , e ) ) ) ) ;
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-05 20:23:03 +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 > ,
_http_server : Option < HttpServer > ,
_ipc_server : Option < IpcServer > ,
_dapps_server : Option < WebappServer > ,
_signer_server : Option < SignerServer >
) {
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 ( ) ) ;
info! ( " Finishing work, please wait... " ) ;
}