2019-01-07 11:33:07 +01:00
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.
2016-07-25 16:09:47 +02:00
2019-01-07 11:33:07 +01:00
// Parity Ethereum is free software: you can redistribute it and/or modify
2016-07-25 16:09:47 +02:00
// 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.
2019-01-07 11:33:07 +01:00
// Parity Ethereum is distributed in the hope that it will be useful,
2016-07-25 16:09:47 +02:00
// 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
2019-01-07 11:33:07 +01:00
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
2016-07-25 16:09:47 +02:00
2018-04-04 11:50:28 +02:00
use std ::{
any ::Any ,
2018-11-28 11:30:05 +01:00
sync ::{ atomic , Arc , Weak } ,
2020-08-05 06:08:03 +02:00
thread ,
2018-01-31 11:41:29 +01:00
time ::{ Duration , Instant } ,
} ;
2017-07-10 13:21:11 +02:00
2019-02-07 14:34:24 +01:00
use account_utils ;
2018-05-09 08:47:21 +02:00
use ansi_term ::Colour ;
2016-07-25 16:09:47 +02:00
use cache ::CacheConfig ;
2020-08-05 06:08:03 +02:00
use db ;
2019-01-17 16:43:08 +01:00
use dir ::{ DatabaseDirectories , Directories } ;
use ethcore ::{
2020-08-14 12:24:16 +02:00
client ::{ BlockChainClient , BlockInfo , Client , DatabaseCompactionProfile , Mode , VMType } ,
2019-02-07 14:34:24 +01:00
miner ::{ self , stratum , Miner , MinerOptions , MinerService } ,
2018-09-13 12:58:49 +02:00
snapshot ::{ self , SnapshotConfiguration } ,
2016-12-02 18:21:54 +01:00
verification ::queue ::VerifierSettings ,
} ;
2018-01-11 17:49:10 +01:00
use ethcore_logger ::{ Config as LogConfig , RotatingLogger } ;
2018-03-13 11:49:57 +01:00
use ethcore_service ::ClientService ;
2018-04-13 21:14:53 +02:00
use helpers ::{ execute_upgrades , passwords_from_files , to_client_config } ;
2020-08-13 18:25:19 +02:00
use informant ::{ FullNodeInformantData , Informant } ;
2018-01-11 17:49:10 +01:00
use journaldb ::Algorithm ;
2018-05-22 19:07:27 +02:00
use jsonrpc_core ;
2018-01-11 17:49:10 +01:00
use miner ::{ external ::ExternalMiner , work_notify ::WorkPoster } ;
2019-02-07 14:34:24 +01:00
use modules ;
2018-01-11 17:49:10 +01:00
use node_filter ::NodeFilter ;
2018-10-22 09:40:50 +02:00
use params ::{
fatdb_switch_to_bool , mode_switch_to_bool , tracing_switch_to_bool , AccountsConfig ,
2019-02-07 14:34:24 +01:00
GasPricerConfig , MinerExtras , Pruning , SpecType , Switch ,
} ;
use parity_rpc ::{
informant , is_major_importing , FutureOutput , FutureResponse , FutureResult , Metadata ,
NetworkSettings , Origin , PubSubSession ,
} ;
2017-07-10 13:21:11 +02:00
use parity_runtime ::Runtime ;
2017-12-22 14:37:39 +01:00
use parity_version ::version ;
2016-07-25 16:09:47 +02:00
use rpc ;
2017-05-24 12:24:07 +02:00
use rpc_apis ;
use secretstore ;
use signer ;
2020-09-02 17:43:14 +02:00
use sync ::{ self , SyncConfig } ;
2016-09-26 19:21:25 +02:00
use user_defaults ::UserDefaults ;
2016-07-25 16:09:47 +02:00
2016-09-02 20:24:59 +02:00
// how often to take periodic snapshots.
2017-08-22 11:24:56 +02:00
const SNAPSHOT_PERIOD : u64 = 5000 ;
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
2018-09-28 15:26:38 +02:00
// Full client number of DNS threads
const FETCH_FULL_NUM_DNS_THREADS : usize = 4 ;
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 ,
2017-01-20 13:25:53 +01:00
pub pruning_memory : usize ,
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 ,
2018-01-09 12:43:36 +01:00
pub gas_price_percentile : usize ,
2018-06-18 13:42:54 +02:00
pub poll_lifetime : u32 ,
2017-04-13 16:32:07 +02:00
pub ws_conf : rpc ::WsConfiguration ,
2017-04-03 10:27:37 +02:00
pub http_conf : rpc ::HttpConfiguration ,
pub ipc_conf : rpc ::IpcConfiguration ,
2018-04-10 12:13:49 +02:00
pub net_conf : sync ::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 ,
2018-03-29 11:20:27 +02:00
pub warp_barrier : Option < u64 > ,
2016-07-25 16:09:47 +02:00
pub acc_conf : AccountsConfig ,
2017-07-16 18:22:45 +02:00
pub gas_pricer_conf : GasPricerConfig ,
2016-07-25 16:09:47 +02:00
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 ,
pub vm_type : VMType ,
2018-11-16 14:00:34 +01:00
pub experimental_rpcs : bool ,
2016-07-25 16:09:47 +02:00
pub net_settings : NetworkSettings ,
2017-02-20 16:13:21 +01:00
pub secretstore_conf : secretstore ::Configuration ,
2016-07-25 16:09:47 +02:00
pub name : String ,
pub custom_bootnodes : bool ,
2018-04-13 17:34:27 +02:00
pub stratum : Option < stratum ::Options > ,
2018-09-13 12:58:49 +02:00
pub snapshot_conf : SnapshotConfiguration ,
2016-10-24 15:09:13 +02:00
pub check_seal : bool ,
2018-11-26 19:58:27 +01:00
pub allow_missing_blocks : 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 ,
2017-05-04 12:13:50 +02:00
pub no_persistent_txqueue : bool ,
2018-10-26 13:21:36 +02:00
pub max_round_blocks_to_import : usize ,
2016-07-25 16:09:47 +02:00
}
2017-02-20 17:21:55 +01:00
// node info fetcher for the local store.
struct FullNodeInfo {
2017-05-04 12:13:50 +02:00
miner : Option < Arc < Miner > > , // TODO: only TXQ needed, just use that after decoupling.
2017-02-20 17:21:55 +01:00
}
impl ::local_store ::NodeInfo for FullNodeInfo {
2019-01-04 14:05:46 +01:00
fn pending_transactions ( & self ) -> Vec < ::types ::transaction ::PendingTransaction > {
2017-05-04 12:13:50 +02:00
let miner = match self . miner . as_ref ( ) {
Some ( m ) = > m ,
None = > return Vec ::new ( ) ,
} ;
2020-08-05 06:08:03 +02:00
2018-04-13 17:34:27 +02:00
miner
. local_transactions ( )
. values ( )
. filter_map ( | status | match * status {
::miner ::pool ::local_transactions ::Status ::Pending ( ref tx ) = > {
Some ( tx . pending ( ) . clone ( ) )
2020-08-05 06:08:03 +02:00
}
2018-04-13 17:34:27 +02:00
_ = > None ,
} )
2017-02-20 17:21:55 +01:00
. collect ( )
}
}
2017-01-06 16:05:58 +01:00
2020-08-13 18:25:19 +02:00
/// Executes the given run command.
///
/// On error, returns what to print on stderr.
2020-08-14 12:24:16 +02:00
pub fn execute ( cmd : RunCmd , logger : Arc < RotatingLogger > ) -> Result < RunningClient , String > {
2016-07-25 16:09:47 +02:00
// load spec
2017-07-10 12:57:40 +02:00
let spec = cmd . spec . spec ( & cmd . dirs . cache ) ? ;
2020-08-05 06:08:03 +02:00
2016-07-25 16:09:47 +02:00
// load genesis hash
let genesis_hash = spec . genesis_header ( ) . hash ( ) ;
2020-08-05 06:08:03 +02:00
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 ( ) ,
) ;
2020-08-05 06:08:03 +02:00
2016-09-26 19:21:25 +02:00
// user defaults path
let user_defaults_path = db_dirs . user_defaults_path ( ) ;
2020-08-05 06:08:03 +02:00
2016-09-26 19:21:25 +02:00
// load user defaults
2016-12-27 12:53:56 +01:00
let mut user_defaults = UserDefaults ::load ( & user_defaults_path ) ? ;
2020-08-05 06:08:03 +02:00
2016-10-03 11:13:10 +02:00
// select pruning algorithm
let algorithm = cmd . pruning . to_algorithm ( & user_defaults ) ;
2020-08-05 06:08:03 +02:00
2016-09-26 19:21:25 +02:00
// check if tracing is on
2016-12-27 12:53:56 +01:00
let tracing = tracing_switch_to_bool ( cmd . tracing , & user_defaults ) ? ;
2020-08-05 06:08:03 +02:00
2016-10-03 11:13:10 +02:00
// check if fatdb is on
2016-12-27 12:53:56 +01:00
let fat_db = fatdb_switch_to_bool ( cmd . fat_db , & user_defaults , algorithm ) ? ;
2020-08-05 06:08:03 +02:00
2016-11-05 10:38:00 +01:00
// get the mode
2016-12-27 12:53:56 +01:00
let mode = mode_switch_to_bool ( cmd . mode , & user_defaults ) ? ;
2016-11-05 10:38:00 +01:00
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 ,
} ;
2020-08-05 06:08:03 +02: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 ( ) ;
2020-08-05 06:08:03 +02:00
2016-07-25 16:09:47 +02:00
// execute upgrades
2018-04-13 21:14:53 +02:00
execute_upgrades ( & cmd . dirs . base , & db_dirs , algorithm , & cmd . compaction ) ? ;
2020-08-05 06:08:03 +02:00
2016-12-13 23:38:29 +01:00
// create dirs used by parity
2018-07-11 12:19:54 +02:00
cmd . dirs . create_dirs (
cmd . acc_conf . unlocked_accounts . len ( ) = = 0 ,
cmd . secretstore_conf . enabled ,
) ? ;
2020-08-05 06:08:03 +02:00
2017-06-22 20:08:56 +02:00
//print out running parity environment
2018-09-09 00:43:24 +02:00
print_running_environment ( & spec . data_dir , & cmd . dirs , & db_dirs ) ;
2020-08-05 06:08:03 +02:00
2016-07-25 16:09:47 +02:00
// display info about used pruning algorithm
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 ) )
) ;
2020-08-05 06:08:03 +02:00
2017-05-09 17:46:46 +02:00
// display warning about using experimental journaldb algorithm
2016-07-25 16:09:47 +02:00
if ! algorithm . is_stable ( ) {
warn! (
" Your chosen strategy is {}! You can re-run with --pruning to change. " ,
Colour ::Red . bold ( ) . paint ( " unstable " )
) ;
}
2020-08-05 06:08:03 +02:00
2016-07-25 16:09:47 +02:00
// 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 ( ) ) ;
}
2020-08-05 06:08:03 +02:00
2016-08-03 19:01:48 +02:00
sync_config . fork_block = spec . fork_block ( ) ;
2018-03-29 11:20:27 +02:00
let mut warp_sync = spec . engine . supports_warp ( ) & & cmd . warp_sync ;
2017-10-10 17:42:20 +02:00
if warp_sync {
// Logging is not initialized yet, so we print directly to stderr
if fat_db {
warn! ( " Warning: Warp Sync is disabled because Fat DB is turned on. " ) ;
warp_sync = false ;
} else if tracing {
warn! ( " Warning: Warp Sync is disabled because tracing is turned on. " ) ;
warp_sync = false ;
} else if algorithm ! = Algorithm ::OverlayRecent {
warn! ( " Warning: Warp Sync is disabled because of non-default pruning mode. " ) ;
warp_sync = false ;
}
2020-08-05 06:08:03 +02:00
}
2018-03-29 11:20:27 +02:00
sync_config . warp_sync = match ( warp_sync , cmd . warp_barrier ) {
2018-04-10 12:13:49 +02:00
( true , Some ( block ) ) = > sync ::WarpSync ::OnlyAndAfter ( block ) ,
( true , _ ) = > sync ::WarpSync ::Enabled ,
_ = > sync ::WarpSync ::Disabled ,
2018-03-29 11:20:27 +02:00
} ;
2016-11-22 18:03:35 +01:00
sync_config . download_old_blocks = cmd . download_old_blocks ;
2020-08-05 06:08:03 +02:00
2016-12-27 12:53:56 +01:00
let passwords = passwords_from_files ( & cmd . acc_conf . password_files ) ? ;
2020-08-05 06:08:03 +02:00
2016-07-25 16:09:47 +02:00
// prepare account provider
2019-02-07 14:34:24 +01:00
let account_provider = Arc ::new ( account_utils ::prepare_account_provider (
& cmd . spec ,
& cmd . dirs ,
& spec . data_dir ,
cmd . acc_conf ,
& passwords ,
) ? ) ;
2020-08-05 06:08:03 +02:00
2018-04-10 13:51:29 +02:00
// spin up event loop
2018-10-22 09:40:50 +02:00
let runtime = Runtime ::with_default_thread_count ( ) ;
2020-08-05 06:08:03 +02:00
2017-07-16 18:22:45 +02:00
// fetch service
2018-09-28 15:26:38 +02:00
let fetch = fetch ::Client ::new ( FETCH_FULL_NUM_DNS_THREADS )
. map_err ( | e | format! ( " Error starting fetch client: {:?} " , e ) ) ? ;
2020-08-05 06:08:03 +02:00
2018-07-02 19:00:06 +02:00
let txpool_size = cmd . miner_options . pool_limits . max_count ;
2016-07-25 16:09:47 +02:00
// create miner
2018-04-13 17:34:27 +02:00
let miner = Arc ::new ( Miner ::new (
cmd . miner_options ,
2018-10-22 09:40:50 +02:00
cmd . gas_pricer_conf
. to_gas_pricer ( fetch . clone ( ) , runtime . executor ( ) ) ,
2018-04-13 17:34:27 +02:00
& spec ,
2019-02-07 14:34:24 +01:00
(
cmd . miner_extras . local_accounts ,
account_utils ::miner_local_accounts ( account_provider . clone ( ) ) ,
) ,
2018-04-13 17:34:27 +02:00
) ) ;
2019-02-07 14:34:24 +01:00
miner . set_author ( miner ::Author ::External ( cmd . miner_extras . author ) ) ;
2018-04-13 17:34:27 +02:00
miner . set_gas_range_target ( cmd . miner_extras . gas_range_target ) ;
2016-07-25 16:09:47 +02:00
miner . set_extra_data ( cmd . miner_extras . extra_data ) ;
2020-08-05 06:08:03 +02:00
2018-07-13 12:36:58 +02:00
if ! cmd . miner_extras . work_notify . is_empty ( ) {
miner . add_work_listener ( Box ::new ( WorkPoster ::new (
2018-10-22 09:40:50 +02:00
& cmd . miner_extras . work_notify ,
fetch . clone ( ) ,
runtime . executor ( ) ,
2018-07-13 12:36:58 +02:00
) ) ) ;
2018-04-10 13:51:29 +02:00
}
2020-08-05 06:08:03 +02:00
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 ( ) {
2019-02-07 14:34:24 +01:00
if let Some ( author ) = account_utils ::miner_author (
& cmd . spec ,
& cmd . dirs ,
& account_provider ,
engine_signer ,
& passwords ,
) ? {
miner . set_author ( author ) ;
2016-12-05 20:23:03 +01:00
}
2020-08-05 06:08:03 +02: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 ,
2017-03-13 12:10:53 +01:00
spec . name . to_lowercase ( ) ,
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 ,
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 ,
2017-01-20 13:25:53 +01:00
cmd . pruning_memory ,
2016-10-24 15:09:13 +02:00
cmd . check_seal ,
2018-10-26 13:21:36 +02:00
cmd . max_round_blocks_to_import ,
2016-07-25 16:09:47 +02:00
) ;
2020-08-05 06:08:03 +02:00
2016-12-02 18:21:54 +01:00
client_config . queue . verifier_settings = cmd . verifier_settings ;
2018-07-02 19:00:06 +02:00
client_config . transaction_verification_queue_size = ::std ::cmp ::max ( 2048 , txpool_size / 4 ) ;
2018-09-13 12:58:49 +02:00
client_config . snapshot = cmd . snapshot_conf . clone ( ) ;
2020-08-05 06:08:03 +02:00
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 ( ) ;
}
2020-08-05 06:08:03 +02:00
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 ( ) ) ;
2020-08-05 06:08:03 +02:00
2018-04-13 21:14:53 +02:00
let restoration_db_handler = db ::restoration_db_handler ( & client_path , & client_config ) ;
2018-06-20 15:13:07 +02:00
let client_db = restoration_db_handler
. open ( & client_path )
. map_err ( | e | format! ( " Failed to open database {:?} " , e ) ) ? ;
2020-08-05 06:08:03 +02:00
2016-08-05 17:00:46 +02:00
// create client service.
2016-12-27 12:53:56 +01:00
let service = ClientService ::start (
2016-07-25 16:09:47 +02:00
client_config ,
2016-08-05 23:33:55 +02:00
& spec ,
2018-04-09 14:21:37 +02:00
client_db ,
2016-09-07 15:27:28 +02:00
& snapshot_path ,
2018-04-09 14:21:37 +02:00
restoration_db_handler ,
2016-09-07 15:27:28 +02:00
& cmd . dirs . ipc_path ( ) ,
2016-07-25 16:09:47 +02:00
miner . clone ( ) ,
2016-12-27 12:53:56 +01:00
)
. map_err ( | e | format! ( " Client service error: {:?} " , e ) ) ? ;
2020-08-05 06:08:03 +02:00
2017-08-29 14:38:01 +02:00
let connection_filter_address = spec . params ( ) . node_permission_contract ;
2016-11-15 19:07:23 +01:00
// drop the spec to free up genesis state.
drop ( spec ) ;
2020-08-05 06:08:03 +02:00
2016-07-25 16:09:47 +02:00
// take handle to client
let client = service . client ( ) ;
2018-04-13 17:34:27 +02:00
// Update miners block gas limit
miner . update_transaction_queue_limits ( * client . best_block_header ( ) . gas_limit ( ) ) ;
2020-08-05 06:08:03 +02:00
2017-08-29 14:38:01 +02:00
let connection_filter = connection_filter_address . map ( | a | {
Arc ::new ( NodeFilter ::new (
2020-07-29 10:36:15 +02:00
Arc ::downgrade ( & client ) as Weak < dyn BlockChainClient > ,
2020-08-05 06:08:03 +02:00
a ,
2017-08-29 14:38:01 +02:00
) )
} ) ;
2016-09-06 15:31:13 +02:00
let snapshot_service = service . snapshot_service ( ) ;
2020-08-05 06:08:03 +02:00
2017-02-20 17:21:55 +01:00
// initialize the local node information store.
let store = {
let db = service . db ( ) ;
let node_info = FullNodeInfo {
2017-05-04 12:13:50 +02:00
miner : match cmd . no_persistent_txqueue {
true = > None ,
false = > Some ( miner . clone ( ) ) ,
} ,
2017-02-20 17:21:55 +01:00
} ;
2020-08-05 06:08:03 +02:00
2019-01-04 14:05:46 +01:00
let store = ::local_store ::create (
db . key_value ( ) . clone ( ) ,
::ethcore_db ::COL_NODE_INFO ,
node_info ,
) ;
2020-08-05 06:08:03 +02:00
2017-05-04 12:13:50 +02:00
if cmd . no_persistent_txqueue {
info! ( " Running without a persistent transaction queue. " ) ;
2020-08-05 06:08:03 +02:00
2017-05-04 12:13:50 +02:00
if let Err ( e ) = store . clear ( ) {
warn! ( " Error clearing persistent transaction queue: {} " , e ) ;
}
2020-08-05 06:08:03 +02:00
}
2017-02-20 17:21:55 +01:00
// re-queue pending transactions.
match store . pending_transactions ( ) {
Ok ( pending ) = > {
for pending_tx in pending {
if let Err ( e ) = miner . import_own_transaction ( & * client , pending_tx ) {
warn! ( " Error importing saved transaction: {} " , e )
}
2020-08-05 06:08:03 +02:00
}
}
2017-02-20 17:21:55 +01:00
Err ( e ) = > warn! ( " Error loading cached pending transactions from disk: {} " , e ) ,
}
2020-08-05 06:08:03 +02:00
2017-02-20 17:21:55 +01:00
Arc ::new ( store )
} ;
2020-08-05 06:08:03 +02:00
2017-02-20 17:21:55 +01:00
// register it as an IO service to update periodically.
service
. register_io_handler ( store )
. map_err ( | _ | " Unable to register local store handler " . to_owned ( ) ) ? ;
2020-08-05 06:08:03 +02:00
2016-07-25 16:09:47 +02:00
// create external miner
let external_miner = Arc ::new ( ExternalMiner ::default ( ) ) ;
2020-08-05 06:08:03 +02:00
2017-01-25 11:03:36 +01:00
// start stratum
if let Some ( ref stratum_config ) = cmd . stratum {
2018-04-13 17:34:27 +02:00
stratum ::Stratum ::register ( stratum_config , miner . clone ( ) , Arc ::downgrade ( & client ) )
2017-01-25 11:03:36 +01:00
. map_err ( | e | format! ( " Stratum start error: {:?} " , e ) ) ? ;
}
2020-08-05 06:08:03 +02:00
2016-07-25 16:09:47 +02:00
// create sync object
2018-11-28 11:30:05 +01:00
let ( sync_provider , manage_network , chain_notify , priority_tasks ) = modules ::sync (
2016-12-15 23:50:16 +01:00
sync_config ,
2017-07-11 12:23:46 +02:00
net_conf . clone ( ) . into ( ) ,
2016-12-15 23:50:16 +01:00
client . clone ( ) ,
snapshot_service . clone ( ) ,
2016-12-08 23:21:47 +01:00
& cmd . logger_config ,
2018-04-10 12:13:49 +02:00
connection_filter
. clone ( )
2020-07-29 10:36:15 +02:00
. map ( | f | f as Arc < dyn crate ::sync ::ConnectionFilter + 'static > ) ,
2016-12-27 12:53:56 +01:00
)
. map_err ( | e | format! ( " Sync error: {} " , e ) ) ? ;
2020-08-05 06:08:03 +02:00
2016-07-25 16:09:47 +02:00
service . add_notify ( chain_notify . clone ( ) ) ;
2020-08-05 06:08:03 +02:00
2018-11-28 11:30:05 +01:00
// Propagate transactions as soon as they are imported.
let tx = ::parking_lot ::Mutex ::new ( priority_tasks ) ;
let is_ready = Arc ::new ( atomic ::AtomicBool ::new ( true ) ) ;
miner . add_transactions_listener ( Box ::new ( move | _hashes | {
// we want to have only one PendingTransactions task in the queue.
if is_ready . compare_and_swap ( true , false , atomic ::Ordering ::SeqCst ) {
let task =
::sync ::PriorityTask ::PropagateTransactions ( Instant ::now ( ) , is_ready . clone ( ) ) ;
// we ignore error cause it means that we are closing
let _ = tx . lock ( ) . send ( task ) ;
}
} ) ) ;
2020-08-05 06:08:03 +02:00
2016-07-25 16:09:47 +02:00
// start network
2016-11-05 10:38:00 +01:00
if network_enabled {
2016-07-25 16:09:47 +02:00
chain_notify . start ( ) ;
}
2020-08-05 06:08:03 +02:00
2016-07-25 16:09:47 +02:00
// set up dependencies for rpc servers
2017-02-04 22:18:19 +01:00
let rpc_stats = Arc ::new ( informant ::RpcStats ::default ( ) ) ;
2018-06-01 16:49:55 +02:00
let secret_store = account_provider . clone ( ) ;
2018-03-20 18:57:37 +01:00
let signer_service = Arc ::new ( signer ::new_service ( & cmd . ws_conf , & cmd . logger_config ) ) ;
2020-08-05 06:08:03 +02:00
2017-03-22 20:14:40 +01:00
let deps_for_rpc_apis = Arc ::new ( rpc_apis ::FullDependencies {
2017-05-24 12:24:07 +02:00
signer_service : signer_service ,
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 ( ) ,
2019-02-07 14:34:24 +01:00
accounts : secret_store ,
2016-07-25 16:09:47 +02:00
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 ( ) ,
2018-11-16 14:00:34 +01:00
experimental_rpcs : cmd . experimental_rpcs ,
2017-05-24 12:24:07 +02:00
ws_address : cmd . ws_conf . address ( ) ,
2016-12-22 18:26:39 +01:00
fetch : fetch . clone ( ) ,
2018-10-22 09:40:50 +02:00
executor : runtime . executor ( ) ,
2018-01-09 12:43:36 +01:00
gas_price_percentile : cmd . gas_price_percentile ,
2018-06-18 13:42:54 +02:00
poll_lifetime : cmd . poll_lifetime ,
2018-11-26 19:58:27 +01:00
allow_missing_blocks : cmd . allow_missing_blocks ,
2019-05-10 13:48:52 +02:00
no_ancient_blocks : ! cmd . download_old_blocks ,
2016-07-25 16:09:47 +02:00
} ) ;
2020-08-05 06:08:03 +02:00
2016-07-25 16:09:47 +02:00
let dependencies = rpc ::Dependencies {
apis : deps_for_rpc_apis . clone ( ) ,
2018-10-22 09:40:50 +02:00
executor : runtime . executor ( ) ,
2017-02-04 22:18:19 +01:00
stats : rpc_stats . clone ( ) ,
2016-07-25 16:09:47 +02:00
} ;
2020-08-05 06:08:03 +02:00
2017-04-03 10:27:37 +02:00
// start rpc servers
2018-05-22 19:07:27 +02:00
let rpc_direct = rpc ::setup_apis ( rpc_apis ::ApiSet ::All , & dependencies ) ;
2017-05-24 12:24:07 +02:00
let ws_server = rpc ::new_ws ( cmd . ws_conf . clone ( ) , & dependencies ) ? ;
2017-04-03 10:27:37 +02:00
let ipc_server = rpc ::new_ipc ( cmd . ipc_conf , & dependencies ) ? ;
2018-07-11 12:19:54 +02:00
let http_server = rpc ::new_http (
" HTTP JSON-RPC " ,
" jsonrpc " ,
cmd . http_conf . clone ( ) ,
& dependencies ,
) ? ;
2020-08-05 06:08:03 +02:00
2017-02-20 16:13:21 +01:00
// secret store key server
2017-04-03 17:46:51 +02:00
let secretstore_deps = secretstore ::Dependencies {
client : client . clone ( ) ,
2017-11-20 13:18:31 +01:00
sync : sync_provider . clone ( ) ,
2018-11-28 11:30:05 +01:00
miner : miner . clone ( ) ,
2019-02-07 14:34:24 +01:00
account_provider ,
2017-08-09 11:09:40 +02:00
accounts_passwords : & passwords ,
2017-04-03 17:46:51 +02:00
} ;
2018-11-25 18:36:43 +01:00
let secretstore_key_server = secretstore ::start (
cmd . secretstore_conf . clone ( ) ,
secretstore_deps ,
runtime . executor ( ) ,
) ? ;
2020-08-05 06:08:03 +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 (
2017-07-10 13:21:11 +02:00
FullNodeInformantData {
client : service . client ( ) ,
sync : Some ( sync_provider . clone ( ) ) ,
net : Some ( manage_network . clone ( ) ) ,
} ,
2016-10-18 18:16:00 +02:00
Some ( snapshot_service . clone ( ) ) ,
2017-02-04 22:18:19 +01:00
Some ( rpc_stats . clone ( ) ) ,
cmd . logger_config . color ,
2016-10-18 18:16:00 +02:00
) ) ;
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 ( ) ) ? ;
2020-08-05 06:08:03 +02:00
2016-11-05 10:38:00 +01:00
// save user defaults
2017-07-18 15:38:38 +02:00
user_defaults . is_first_launch = false ;
2016-11-05 10:38:00 +01:00
user_defaults . pruning = algorithm ;
user_defaults . tracing = tracing ;
2016-11-27 11:11:56 +01:00
user_defaults . fat_db = fat_db ;
2018-07-23 13:57:50 +02:00
user_defaults . set_mode ( mode ) ;
2016-12-27 12:53:56 +01:00
user_defaults . save ( & user_defaults_path ) ? ;
2020-08-05 06:08:03 +02:00
2016-12-10 23:58:39 +01:00
// tell client how to save the default mode if it gets changed.
2017-03-13 12:10:53 +01:00
client . on_user_defaults_change ( move | mode : Option < Mode > | {
if let Some ( mode ) = mode {
2018-07-23 13:57:50 +02:00
user_defaults . set_mode ( mode ) ;
2017-03-13 12:10:53 +01:00
}
2016-11-05 10:38:00 +01:00
let _ = user_defaults . save ( & user_defaults_path ) ; // discard failures - there's nothing we can do
2016-12-10 23:58:39 +01:00
} ) ;
2020-08-05 06:08:03 +02:00
2016-09-05 14:25:56 +02:00
// the watcher must be kept alive.
2018-09-13 12:58:49 +02:00
let watcher = match cmd . snapshot_conf . no_periodic {
2016-09-05 14:25:56 +02:00
true = > None ,
false = > {
2016-09-07 15:27:14 +02:00
let sync = sync_provider . clone ( ) ;
2017-03-13 12:10:53 +01:00
let client = client . 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 ,
) ) ;
2020-08-05 06:08:03 +02:00
2016-09-05 14:25:56 +02:00
service . add_notify ( watcher . clone ( ) ) ;
Some ( watcher )
}
} ;
2020-08-05 06:08:03 +02:00
2018-05-09 08:47:21 +02:00
Ok ( RunningClient {
inner : RunningClientInner ::Full {
2018-05-22 19:07:27 +02:00
rpc : rpc_direct ,
2018-05-09 08:47:21 +02:00
informant ,
client ,
2018-05-29 12:23:15 +02:00
client_service : Arc ::new ( service ) ,
2018-10-22 09:40:50 +02:00
keep_alive : Box ::new ( (
watcher ,
ws_server ,
http_server ,
ipc_server ,
secretstore_key_server ,
runtime ,
) ) ,
2018-05-09 08:47:21 +02:00
} ,
2018-04-04 11:50:28 +02:00
} )
}
2017-05-24 12:24:07 +02:00
2018-05-09 08:47:21 +02:00
/// Parity client currently executing in background threads.
///
/// Should be destroyed by calling `shutdown()`, otherwise execution will continue in the
/// background.
pub struct RunningClient {
2018-05-22 19:07:27 +02:00
inner : RunningClientInner ,
2018-05-09 08:47:21 +02:00
}
enum RunningClientInner {
2018-04-04 11:50:28 +02:00
Full {
2018-05-22 19:07:27 +02:00
rpc :
jsonrpc_core ::MetaIoHandler < Metadata , informant ::Middleware < informant ::ClientNotifier > > ,
2018-04-04 11:50:28 +02:00
informant : Arc < Informant < FullNodeInformantData > > ,
client : Arc < Client > ,
2018-05-29 12:23:15 +02:00
client_service : Arc < ClientService > ,
2020-07-29 10:36:15 +02:00
keep_alive : Box < dyn Any > ,
2018-04-04 11:50:28 +02:00
} ,
}
2016-09-03 10:31:29 +02:00
2018-04-04 11:50:28 +02:00
impl RunningClient {
2019-01-02 16:49:01 +01:00
/// Performs an asynchronous RPC query.
// FIXME: [tomaka] This API should be better, with for example a Future
pub fn rpc_query (
& self ,
request : & str ,
session : Option < Arc < PubSubSession > > ,
) -> FutureResult < FutureResponse , FutureOutput > {
2018-05-22 19:07:27 +02:00
let metadata = Metadata {
origin : Origin ::CApi ,
2019-01-02 16:49:01 +01:00
session ,
2018-05-22 19:07:27 +02:00
} ;
2020-08-05 06:08:03 +02:00
2018-05-22 19:07:27 +02:00
match self . inner {
2019-01-02 16:49:01 +01:00
RunningClientInner ::Full { ref rpc , .. } = > rpc . handle_request ( request , metadata ) ,
2020-08-05 06:08:03 +02:00
}
2018-05-22 19:07:27 +02:00
}
2020-08-05 06:08:03 +02:00
2018-05-09 08:47:21 +02:00
/// Shuts down the client.
pub fn shutdown ( self ) {
match self . inner {
2018-05-29 12:23:15 +02:00
RunningClientInner ::Full {
rpc ,
informant ,
client ,
client_service ,
keep_alive ,
} = > {
2018-04-04 11:50:28 +02:00
info! ( " Finishing work, please wait... " ) ;
// Create a weak reference to the client so that we can wait on shutdown
// until it is dropped
let weak_client = Arc ::downgrade ( & client ) ;
2019-06-25 15:38:29 +02:00
// Shutdown and drop the ClientService
2018-05-29 12:23:15 +02:00
client_service . shutdown ( ) ;
2019-06-25 15:38:29 +02:00
trace! ( target : " shutdown " , " ClientService shut down " ) ;
2018-05-29 12:23:15 +02:00
drop ( client_service ) ;
2019-06-25 15:38:29 +02:00
trace! ( target : " shutdown " , " ClientService dropped " ) ;
2018-04-04 11:50:28 +02:00
// drop this stuff as soon as exit detected.
2018-05-22 19:07:27 +02:00
drop ( rpc ) ;
2019-06-25 15:38:29 +02:00
trace! ( target : " shutdown " , " RPC dropped " ) ;
2018-04-04 11:50:28 +02:00
drop ( keep_alive ) ;
2019-06-25 15:38:29 +02:00
trace! ( target : " shutdown " , " KeepAlive dropped " ) ;
2018-04-04 11:50:28 +02:00
// to make sure timer does not spawn requests while shutdown is in progress
informant . shutdown ( ) ;
2019-06-25 15:38:29 +02:00
trace! ( target : " shutdown " , " Informant shut down " ) ;
2018-04-04 11:50:28 +02:00
// just Arc is dropping here, to allow other reference release in its default time
drop ( informant ) ;
2019-06-25 15:38:29 +02:00
trace! ( target : " shutdown " , " Informant dropped " ) ;
2018-04-04 11:50:28 +02:00
drop ( client ) ;
2019-06-25 15:38:29 +02:00
trace! ( target : " shutdown " , " Client dropped " ) ;
// This may help when debugging ref cycles. Requires nightly-only `#![feature(weak_counts)]`
// trace!(target: "shutdown", "Waiting for refs to Client to shutdown, strong_count={:?}, weak_count={:?}", weak_client.strong_count(), weak_client.weak_count());
trace! ( target : " shutdown " , " Waiting for refs to Client to shutdown " ) ;
2018-04-04 11:50:28 +02:00
wait_for_drop ( weak_client ) ;
}
}
}
2018-01-31 11:41:29 +01:00
}
2018-09-09 00:43:24 +02:00
fn print_running_environment ( data_dir : & str , dirs : & Directories , db_dirs : & DatabaseDirectories ) {
2017-06-22 20:08:56 +02:00
info! ( " Starting {} " , Colour ::White . bold ( ) . paint ( version ( ) ) ) ;
2018-09-09 00:43:24 +02:00
info! (
" Keys path {} " ,
Colour ::White
. bold ( )
. paint ( dirs . keys_path ( data_dir ) . to_string_lossy ( ) . into_owned ( ) )
) ;
2017-06-22 20:08:56 +02:00
info! (
" DB path {} " ,
Colour ::White
. bold ( )
. paint ( db_dirs . db_root_path ( ) . to_string_lossy ( ) . into_owned ( ) )
) ;
}
2018-01-31 11:41:29 +01:00
fn wait_for_drop < T > ( w : Weak < T > ) {
2019-06-25 15:38:29 +02:00
const SLEEP_DURATION : Duration = Duration ::from_secs ( 1 ) ;
const WARN_TIMEOUT : Duration = Duration ::from_secs ( 60 ) ;
const MAX_TIMEOUT : Duration = Duration ::from_secs ( 300 ) ;
2018-01-31 11:41:29 +01:00
let instant = Instant ::now ( ) ;
let mut warned = false ;
2019-06-25 15:38:29 +02:00
while instant . elapsed ( ) < MAX_TIMEOUT {
2018-01-31 11:41:29 +01:00
if w . upgrade ( ) . is_none ( ) {
return ;
}
2019-06-25 15:38:29 +02:00
if ! warned & & instant . elapsed ( ) > WARN_TIMEOUT {
2018-01-31 11:41:29 +01:00
warned = true ;
warn! ( " Shutdown is taking longer than expected. " ) ;
}
2019-06-25 15:38:29 +02:00
thread ::sleep ( SLEEP_DURATION ) ;
// When debugging shutdown issues on a nightly build it can help to enable this with the
// `#![feature(weak_counts)]` added to lib.rs (TODO: enable when
// https://github.com/rust-lang/rust/issues/57977 is stable)
// trace!(target: "shutdown", "Waiting for client to drop, strong_count={:?}, weak_count={:?}", w.strong_count(), w.weak_count());
trace! ( target : " shutdown " , " Waiting for client to drop " ) ;
2018-01-31 11:41:29 +01:00
}
warn! ( " Shutdown timeout reached, exiting uncleanly. " ) ;
}