2017-01-25 18:51:41 +01:00
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
2016-02-05 13:40:41 +01: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-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
2017-02-13 16:38:47 +01:00
extern crate ansi_term ;
extern crate app_dirs ;
extern crate ctrlc ;
2016-01-23 23:53:20 +01:00
extern crate docopt ;
2016-01-09 23:21:57 +01:00
extern crate env_logger ;
2016-02-05 13:49:36 +01:00
extern crate fdlimit ;
2017-02-14 22:45:43 +01:00
extern crate hyper ;
2017-02-13 16:38:47 +01:00
extern crate isatty ;
extern crate jsonrpc_core ;
extern crate num_cpus ;
2016-02-25 14:09:39 +01:00
extern crate number_prefix ;
2017-02-13 16:38:47 +01:00
extern crate regex ;
extern crate rlp ;
2016-03-09 14:11:15 +01:00
extern crate rpassword ;
2017-02-13 16:38:47 +01:00
extern crate rustc_serialize ;
2016-04-10 15:12:20 +02:00
extern crate semver ;
2016-09-26 19:21:25 +02:00
extern crate serde ;
extern crate serde_json ;
2017-02-13 16:38:47 +01:00
extern crate time ;
extern crate toml ;
2016-09-01 14:55:07 +02:00
2017-02-13 16:38:47 +01:00
extern crate ethcore ;
extern crate ethcore_devtools as devtools ;
extern crate ethcore_io as io ;
extern crate ethcore_ipc as ipc ;
2016-07-09 17:18:34 +02:00
extern crate ethcore_ipc_hypervisor as hypervisor ;
2017-02-13 16:38:47 +01:00
extern crate ethcore_ipc_nano as nanoipc ;
extern crate ethcore_light as light ;
extern crate ethcore_logger ;
2016-04-21 13:12:43 +02:00
extern crate ethcore_rpc ;
2016-07-11 17:11:49 +02:00
extern crate ethcore_signer ;
2016-09-01 14:55:07 +02:00
extern crate ethcore_util as util ;
2017-02-13 16:38:47 +01:00
extern crate ethsync ;
extern crate parity_hash_fetch as hash_fetch ;
2017-02-16 14:51:33 +01:00
extern crate parity_ipfs_api ;
2017-02-13 16:38:47 +01:00
extern crate parity_reactor ;
extern crate parity_updater as updater ;
2017-02-20 17:21:55 +01:00
extern crate parity_local_store as local_store ;
2017-02-13 16:38:47 +01:00
extern crate rpc_cli ;
2016-09-01 14:55:07 +02:00
2017-02-14 22:45:43 +01:00
#[ macro_use ]
extern crate log as rlog ;
2016-08-24 18:35:38 +02:00
#[ cfg(feature= " stratum " ) ]
extern crate ethcore_stratum ;
2017-02-20 16:13:21 +01:00
#[ cfg(feature= " secretstore " ) ]
extern crate ethcore_secretstore ;
2016-05-26 18:21:15 +02:00
#[ cfg(feature = " dapps " ) ]
extern crate ethcore_dapps ;
2016-01-20 04:19:38 +01:00
2016-08-24 18:35:38 +02:00
macro_rules ! dependency {
( $dep_ty :ident , $url :expr ) = > {
{
let dep = boot ::dependency ::< $dep_ty < _ > > ( $url )
. unwrap_or_else ( | e | panic! ( " Fatal: error connecting service ( {:?} ) " , e ) ) ;
dep . handshake ( )
. unwrap_or_else ( | e | panic! ( " Fatal: error in connected service ( {:?} ) " , e ) ) ;
dep
}
}
}
2017-02-13 16:38:47 +01:00
mod account ;
mod blockchain ;
2016-07-25 16:09:47 +02:00
mod cache ;
2016-04-21 15:41:25 +02:00
mod cli ;
2016-04-21 16:45:04 +02:00
mod configuration ;
2017-02-13 16:38:47 +01:00
mod dapps ;
2017-02-16 14:41:33 +01:00
mod ipfs ;
2016-07-25 16:09:47 +02:00
mod deprecated ;
mod dir ;
2017-02-13 16:38:47 +01:00
mod helpers ;
mod informant ;
mod migration ;
2016-07-16 14:24:57 +02:00
mod modules ;
2017-02-13 16:38:47 +01:00
mod params ;
2016-07-25 16:09:47 +02:00
mod presale ;
2017-02-13 16:38:47 +01:00
mod rpc ;
mod rpc_apis ;
2016-07-25 16:09:47 +02:00
mod run ;
2017-02-13 16:38:47 +01:00
mod signer ;
mod snapshot ;
2017-02-20 16:13:21 +01:00
mod secretstore ;
2017-02-13 16:38:47 +01:00
mod upgrade ;
mod url ;
mod user_defaults ;
2016-09-06 15:31:13 +02:00
#[ cfg(feature= " ipc " ) ]
2016-08-24 18:35:38 +02:00
mod boot ;
2017-02-13 16:38:47 +01:00
#[ cfg(feature= " ipc " ) ]
mod sync ;
2016-08-24 18:35:38 +02:00
#[ cfg(feature= " stratum " ) ]
mod stratum ;
2016-04-21 16:45:04 +02:00
2016-07-25 16:09:47 +02:00
use std ::{ process , env } ;
2016-12-10 23:58:39 +01:00
use std ::collections ::HashMap ;
2016-12-11 03:33:10 +01:00
use std ::io ::{ self as stdio , BufReader , Read , Write } ;
2017-03-11 14:46:17 +01:00
use std ::fs ::{ metadata , File } ;
2016-12-10 23:58:39 +01:00
use std ::path ::PathBuf ;
2016-09-23 15:28:09 +02:00
use util ::sha3 ::sha3 ;
2016-09-10 11:37:14 +02:00
use cli ::Args ;
2016-11-02 19:42:21 +01:00
use configuration ::{ Cmd , Execute , Configuration } ;
2016-07-25 16:09:47 +02:00
use deprecated ::find_deprecated ;
2016-11-02 19:42:21 +01:00
use ethcore_logger ::setup_log ;
2016-12-15 19:53:13 +01:00
use dir ::default_hypervisor_path ;
2016-07-25 16:09:47 +02:00
2016-09-23 15:28:09 +02:00
fn print_hash_of ( maybe_file : Option < String > ) -> Result < String , String > {
if let Some ( file ) = maybe_file {
2016-12-27 12:53:56 +01:00
let mut f = BufReader ::new ( File ::open ( & file ) . map_err ( | _ | " Unable to open file " . to_owned ( ) ) ? ) ;
let hash = sha3 ( & mut f ) . map_err ( | _ | " Unable to read from file " . to_owned ( ) ) ? ;
2016-09-23 15:28:09 +02:00
Ok ( hash . hex ( ) )
} else {
Err ( " Streaming from standard input not yet supported. Specify a file. " . to_owned ( ) )
}
}
2016-12-10 23:58:39 +01:00
enum PostExecutionAction {
Print ( String ) ,
Restart ,
Quit ,
}
2016-12-11 04:05:02 +01:00
fn execute ( command : Execute , can_restart : bool ) -> Result < PostExecutionAction , String > {
2016-11-02 19:42:21 +01:00
let logger = setup_log ( & command . logger ) . expect ( " Logger is initialized only once; qed " ) ;
match command . cmd {
2016-07-25 16:09:47 +02:00
Cmd ::Run ( run_cmd ) = > {
2016-12-11 04:05:02 +01:00
let restart = run ::execute ( run_cmd , can_restart , logger ) ? ;
2016-12-10 23:58:39 +01:00
Ok ( if restart { PostExecutionAction ::Restart } else { PostExecutionAction ::Quit } )
2016-04-21 15:41:25 +02:00
} ,
2016-12-10 23:58:39 +01:00
Cmd ::Version = > Ok ( PostExecutionAction ::Print ( Args ::print_version ( ) ) ) ,
Cmd ::Hash ( maybe_file ) = > print_hash_of ( maybe_file ) . map ( | s | PostExecutionAction ::Print ( s ) ) ,
Cmd ::Account ( account_cmd ) = > account ::execute ( account_cmd ) . map ( | s | PostExecutionAction ::Print ( s ) ) ,
Cmd ::ImportPresaleWallet ( presale_cmd ) = > presale ::execute ( presale_cmd ) . map ( | s | PostExecutionAction ::Print ( s ) ) ,
2016-12-16 11:00:17 +01:00
Cmd ::Blockchain ( blockchain_cmd ) = > blockchain ::execute ( blockchain_cmd ) . map ( | _ | PostExecutionAction ::Quit ) ,
2016-12-10 23:58:39 +01:00
Cmd ::SignerToken ( signer_cmd ) = > signer ::execute ( signer_cmd ) . map ( | s | PostExecutionAction ::Print ( s ) ) ,
2016-12-15 18:23:02 +01:00
Cmd ::SignerSign { id , pwfile , port , authfile } = > rpc_cli ::signer_sign ( id , pwfile , port , authfile ) . map ( | s | PostExecutionAction ::Print ( s ) ) ,
Cmd ::SignerList { port , authfile } = > rpc_cli ::signer_list ( port , authfile ) . map ( | s | PostExecutionAction ::Print ( s ) ) ,
Cmd ::SignerReject { id , port , authfile } = > rpc_cli ::signer_reject ( id , port , authfile ) . map ( | s | PostExecutionAction ::Print ( s ) ) ,
2016-12-10 23:58:39 +01:00
Cmd ::Snapshot ( snapshot_cmd ) = > snapshot ::execute ( snapshot_cmd ) . map ( | s | PostExecutionAction ::Print ( s ) ) ,
2016-05-26 18:24:51 +02:00
}
2016-04-21 15:41:25 +02:00
}
2016-12-11 04:05:02 +01:00
fn start ( can_restart : bool ) -> Result < PostExecutionAction , String > {
2016-09-10 11:37:14 +02:00
let args : Vec < String > = env ::args ( ) . collect ( ) ;
let conf = Configuration ::parse ( & args ) . unwrap_or_else ( | e | e . exit ( ) ) ;
2016-04-21 15:41:25 +02:00
2016-07-25 16:09:47 +02:00
let deprecated = find_deprecated ( & conf . args ) ;
for d in deprecated {
println! ( " {} " , d ) ;
2016-06-14 16:12:46 +02:00
}
2016-12-27 12:53:56 +01:00
let cmd = conf . into_command ( ) ? ;
2016-12-11 04:05:02 +01:00
execute ( cmd , can_restart )
2016-05-23 18:42:59 +02:00
}
2016-12-10 23:58:39 +01:00
#[ cfg(not(feature= " stratum " )) ]
fn stratum_main ( _ : & mut HashMap < String , fn ( ) > ) { }
2016-08-24 18:35:38 +02:00
#[ cfg(feature= " stratum " ) ]
2016-12-10 23:58:39 +01:00
fn stratum_main ( alt_mains : & mut HashMap < String , fn ( ) > ) {
alt_mains . insert ( " stratum " . to_owned ( ) , stratum ::main ) ;
2016-08-24 18:35:38 +02:00
}
2016-12-10 23:58:39 +01:00
#[ cfg(not(feature= " ipc " )) ]
fn sync_main ( _ : & mut HashMap < String , fn ( ) > ) { }
#[ cfg(feature= " ipc " ) ]
fn sync_main ( alt_mains : & mut HashMap < String , fn ( ) > ) {
alt_mains . insert ( " sync " . to_owned ( ) , sync ::main ) ;
2016-08-24 18:35:38 +02:00
}
2016-12-11 03:33:10 +01:00
fn updates_path ( name : & str ) -> PathBuf {
2016-12-15 19:53:13 +01:00
let mut dest = PathBuf ::from ( default_hypervisor_path ( ) ) ;
2016-12-11 03:33:10 +01:00
dest . push ( name ) ;
2016-12-10 23:58:39 +01:00
dest
2016-09-06 15:31:13 +02:00
}
2016-12-11 03:33:10 +01:00
fn latest_exe_path ( ) -> Option < PathBuf > {
File ::open ( updates_path ( " latest " ) ) . ok ( )
. and_then ( | mut f | { let mut exe = String ::new ( ) ; f . read_to_string ( & mut exe ) . ok ( ) . map ( | _ | updates_path ( & exe ) ) } )
2016-12-22 18:26:39 +01:00
}
2016-12-11 03:33:10 +01:00
2017-01-17 23:34:46 +01:00
#[ cfg(windows) ]
fn global_cleanup ( ) {
extern " system " { pub fn WSACleanup ( ) -> i32 ; }
// We need to cleanup all sockets before spawning another Parity process. This makes shure everything is cleaned up.
2017-02-13 16:38:47 +01:00
// The loop is required because of internal refernce counter for winsock dll. We don't know how many crates we use do
2017-01-17 23:34:46 +01:00
// initialize it. There's at least 2 now.
for _ in 0 .. 10 {
unsafe { WSACleanup ( ) ; }
}
}
#[ cfg(not(windows)) ]
fn global_cleanup ( ) { }
2016-12-10 23:58:39 +01:00
// Starts ~/.parity-updates/parity and returns the code it exits with.
fn run_parity ( ) -> Option < i32 > {
2017-01-17 23:34:46 +01:00
global_cleanup ( ) ;
2016-12-11 04:05:02 +01:00
use ::std ::ffi ::OsString ;
let prefix = vec! [ OsString ::from ( " --can-restart " ) , OsString ::from ( " --force-direct " ) ] ;
2016-12-11 03:33:10 +01:00
latest_exe_path ( ) . and_then ( | exe | process ::Command ::new ( exe )
2017-01-17 23:34:46 +01:00
. args ( & ( env ::args_os ( ) . skip ( 1 ) . chain ( prefix . into_iter ( ) ) . collect ::< Vec < _ > > ( ) ) )
2016-12-11 04:05:02 +01:00
. status ( )
. map ( | es | es . code ( ) . unwrap_or ( 128 ) )
. ok ( )
)
2016-12-10 23:58:39 +01:00
}
const PLEASE_RESTART_EXIT_CODE : i32 = 69 ;
// Run our version of parity.
2016-12-22 18:26:39 +01:00
// Returns the exit error code.
2016-12-11 04:05:02 +01:00
fn main_direct ( can_restart : bool ) -> i32 {
2016-12-10 23:58:39 +01:00
let mut alt_mains = HashMap ::new ( ) ;
sync_main ( & mut alt_mains ) ;
stratum_main ( & mut alt_mains ) ;
if let Some ( f ) = std ::env ::args ( ) . nth ( 1 ) . and_then ( | arg | alt_mains . get ( & arg . to_string ( ) ) ) {
f ( ) ;
0
2016-09-06 15:31:13 +02:00
} else {
2016-12-11 04:05:02 +01:00
match start ( can_restart ) {
2016-12-10 23:58:39 +01:00
Ok ( result ) = > match result {
2016-12-13 20:20:10 +01:00
PostExecutionAction ::Print ( s ) = > { println! ( " {} " , s ) ; 0 } ,
2016-12-10 23:58:39 +01:00
PostExecutionAction ::Restart = > PLEASE_RESTART_EXIT_CODE ,
PostExecutionAction ::Quit = > 0 ,
} ,
Err ( err ) = > {
writeln! ( & mut stdio ::stderr ( ) , " {} " , err ) . expect ( " StdErr available; qed " ) ;
1
} ,
}
2016-09-06 15:31:13 +02:00
}
}
2016-12-10 23:58:39 +01:00
fn println_trace_main ( s : String ) {
if env ::var ( " RUST_LOG " ) . ok ( ) . and_then ( | s | s . find ( " main=trace " ) ) . is_some ( ) {
println! ( " {} " , s ) ;
2016-07-26 00:21:08 +02:00
}
2016-12-10 23:58:39 +01:00
}
2016-07-26 00:21:08 +02:00
2016-12-10 23:58:39 +01:00
#[ macro_export ]
macro_rules ! trace_main {
( $arg :expr ) = > ( println_trace_main ( $arg . into ( ) ) ) ;
( $( $arg :tt ) * ) = > ( println_trace_main ( format! ( " {} " , format_args! ( $( $arg ) * ) ) ) ) ;
}
2016-08-24 18:35:38 +02:00
2016-12-10 23:58:39 +01:00
fn main ( ) {
// Always print backtrace on panic.
env ::set_var ( " RUST_BACKTRACE " , " 1 " ) ;
// assuming the user is not running with `--force-direct`, then:
// if argv[0] == "parity" and this executable != ~/.parity-updates/parity, run that instead.
let force_direct = std ::env ::args ( ) . any ( | arg | arg = = " --force-direct " ) ;
let exe = std ::env ::current_exe ( ) . ok ( ) ;
2016-12-11 02:02:40 +01:00
let development = exe . as_ref ( ) . and_then ( | p | p . parent ( ) . and_then ( | p | p . parent ( ) ) . and_then ( | p | p . file_name ( ) ) . map ( | n | n = = " target " ) ) . unwrap_or ( false ) ;
2016-12-11 03:33:10 +01:00
let same_name = exe . as_ref ( ) . map ( | p | p . file_stem ( ) . map_or ( false , | s | s = = " parity " ) & & p . extension ( ) . map_or ( true , | x | x = = " exe " ) ) . unwrap_or ( false ) ;
2017-01-17 23:34:46 +01:00
trace_main! ( " Starting up {} (force-direct: {}, development: {}, same-name: {}) " , std ::env ::current_exe ( ) . map ( | x | format! ( " {} " , x . display ( ) ) ) . unwrap_or ( " <unknown> " . to_owned ( ) ) , force_direct , development , same_name ) ;
if ! force_direct & & ! development & & same_name {
2016-12-10 23:58:39 +01:00
// looks like we're not running ~/.parity-updates/parity when the user is expecting otherwise.
2016-12-22 18:26:39 +01:00
// Everything run inside a loop, so we'll be able to restart from the child into a new version seamlessly.
2016-12-10 23:58:39 +01:00
loop {
2016-12-22 18:26:39 +01:00
// If we fail to run the updated parity then fallback to local version.
2017-01-17 23:34:46 +01:00
let latest_exe = latest_exe_path ( ) ;
let have_update = latest_exe . as_ref ( ) . map_or ( false , | p | p . exists ( ) ) ;
let is_non_updated_current = exe . as_ref ( ) . map_or ( false , | exe | latest_exe . as_ref ( ) . map_or ( false , | lexe | exe . canonicalize ( ) . ok ( ) ! = lexe . canonicalize ( ) . ok ( ) ) ) ;
2017-03-11 14:46:17 +01:00
let update_is_newer = match (
latest_exe . as_ref ( )
. and_then ( | p | metadata ( p . as_path ( ) ) . ok ( ) )
. and_then ( | m | m . modified ( ) . ok ( ) ) ,
exe . as_ref ( )
. and_then ( | p | metadata ( p . as_path ( ) ) . ok ( ) )
. and_then ( | m | m . modified ( ) . ok ( ) )
) {
( Some ( latest_exe_time ) , Some ( this_exe_time ) ) if latest_exe_time > this_exe_time = > true ,
_ = > false ,
} ;
trace_main! ( " Starting... (have-update: {}, non-updated-current: {}) " , have_update , is_non_updated_current ) ; trace_main! ( " Starting... (have-update: {}, non-updated-current: {}) " , have_update , is_non_updated_current ) ;
let exit_code = if have_update & & is_non_updated_current & & update_is_newer {
2017-01-17 23:34:46 +01:00
trace_main! ( " Attempting to run latest update ({})... " , latest_exe . as_ref ( ) . expect ( " guarded by have_update; latest_exe must exist for have_update; qed " ) . display ( ) ) ;
run_parity ( ) . unwrap_or_else ( | | { trace_main! ( " Falling back to local... " ) ; main_direct ( true ) } )
} else {
trace_main! ( " No latest update. Attempting to direct... " ) ;
main_direct ( true )
} ;
2016-12-10 23:58:39 +01:00
trace_main! ( " Latest exited with {} " , exit_code ) ;
if exit_code ! = PLEASE_RESTART_EXIT_CODE {
trace_main! ( " Quitting... " ) ;
process ::exit ( exit_code ) ;
}
trace_main! ( " Rerunning... " ) ;
2016-05-24 20:29:19 +02:00
}
2016-12-10 23:58:39 +01:00
} else {
trace_main! ( " Running direct " ) ;
// Otherwise, we're presumably running the version we want. Just run and fall-through.
2016-12-11 04:05:02 +01:00
let can_restart = std ::env ::args ( ) . any ( | arg | arg = = " --can-restart " ) ;
process ::exit ( main_direct ( can_restart ) ) ;
2016-05-24 20:29:19 +02:00
}
2016-06-07 17:21:19 +02:00
}