2021-02-16 13:48:20 -08:00
#![ allow(clippy::integer_arithmetic) ]
2021-12-03 09:00:31 -08:00
#[ cfg(not(target_env = " msvc " )) ]
use jemallocator ::Jemalloc ;
2021-03-04 13:01:11 -08:00
use {
clap ::{
crate_description , crate_name , value_t , value_t_or_exit , values_t , values_t_or_exit , App ,
AppSettings , Arg , ArgMatches , SubCommand ,
2020-06-18 22:38:37 -07:00
} ,
2021-03-04 13:01:11 -08:00
console ::style ,
log ::* ,
2021-10-03 11:13:16 -07:00
rand ::{ seq ::SliceRandom , thread_rng } ,
2021-03-04 13:01:11 -08:00
solana_clap_utils ::{
input_parsers ::{ keypair_of , keypairs_of , pubkey_of , value_of } ,
input_validators ::{
2021-10-26 18:56:16 -07:00
is_keypair , is_keypair_or_ask_keyword , is_niceness_adjustment_valid , is_parsable ,
is_pow2 , is_pubkey , is_pubkey_or_keypair , is_slot , is_valid_percentage ,
2022-04-21 12:43:08 -07:00
is_within_range ,
2021-03-04 13:01:11 -08:00
} ,
keypair ::SKIP_SEED_PHRASE_VALIDATION_ARG ,
} ,
2021-04-21 14:13:41 -07:00
solana_client ::{
2022-06-10 09:25:24 -07:00
connection_cache ::DEFAULT_TPU_CONNECTION_POOL_SIZE , rpc_client ::RpcClient ,
rpc_config ::RpcLeaderScheduleConfig , rpc_request ::MAX_MULTIPLE_ACCOUNTS ,
2021-04-21 14:13:41 -07:00
} ,
2021-03-04 13:01:11 -08:00
solana_core ::{
2021-05-26 08:15:46 -07:00
ledger_cleanup_service ::{ DEFAULT_MAX_LEDGER_SHREDS , DEFAULT_MIN_MAX_LEDGER_SHREDS } ,
2022-01-20 12:38:42 -08:00
system_monitor_service ::SystemMonitorService ,
2021-08-10 13:09:52 -07:00
tower_storage ,
2021-03-04 13:01:11 -08:00
tpu ::DEFAULT_TPU_COALESCE_MS ,
2021-09-07 07:31:54 -07:00
validator ::{ is_snapshot_config_valid , Validator , ValidatorConfig , ValidatorStartProgress } ,
2021-03-04 13:01:11 -08:00
} ,
2022-03-31 12:47:00 -07:00
solana_gossip ::{ cluster_info ::Node , contact_info ::ContactInfo } ,
2022-06-07 00:24:58 -07:00
solana_ledger ::blockstore_options ::{
2022-06-07 16:58:58 -07:00
BlockstoreCompressionType , BlockstoreRecoveryMode , LedgerColumnOptions , ShredStorageType ,
DEFAULT_ROCKS_FIFO_SHRED_STORAGE_SIZE_BYTES ,
2022-03-03 12:43:58 -08:00
} ,
2022-03-31 12:47:00 -07:00
solana_net_utils ::VALIDATOR_PORT_RANGE ,
2021-03-04 13:01:11 -08:00
solana_perf ::recycler ::enable_recycler_warming ,
2021-06-04 08:23:06 -07:00
solana_poh ::poh_service ,
2022-03-18 11:36:52 -07:00
solana_rpc ::{
rpc ::{ JsonRpcConfig , RpcBigtableConfig } ,
rpc_pubsub_service ::PubSubConfig ,
} ,
2021-03-04 13:01:11 -08:00
solana_runtime ::{
2021-06-09 21:21:32 -07:00
accounts_db ::{
2022-04-11 11:10:09 -07:00
AccountShrinkThreshold , AccountsDbConfig , FillerAccountsConfig ,
DEFAULT_ACCOUNTS_SHRINK_OPTIMIZE_TOTAL_SPACE , DEFAULT_ACCOUNTS_SHRINK_RATIO ,
2021-06-09 21:21:32 -07:00
} ,
2021-05-11 15:06:22 -07:00
accounts_index ::{
AccountIndex , AccountSecondaryIndexes , AccountSecondaryIndexesIncludeExclude ,
2022-04-12 07:38:09 -07:00
AccountsIndexConfig , IndexLimitMb ,
2021-05-11 15:06:22 -07:00
} ,
2021-05-24 07:45:36 -07:00
hardened_unpack ::MAX_GENESIS_ARCHIVE_UNPACKED_SIZE ,
2022-04-11 17:28:10 -07:00
runtime_config ::RuntimeConfig ,
2021-08-31 20:03:19 -07:00
snapshot_config ::SnapshotConfig ,
2021-07-22 12:40:37 -07:00
snapshot_utils ::{
2022-05-16 10:44:15 -07:00
self , ArchiveFormat , SnapshotVersion , DEFAULT_ARCHIVE_COMPRESSION ,
DEFAULT_FULL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS ,
2021-09-10 13:59:26 -07:00
DEFAULT_INCREMENTAL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS ,
DEFAULT_MAX_FULL_SNAPSHOT_ARCHIVES_TO_RETAIN ,
2022-05-16 10:44:15 -07:00
DEFAULT_MAX_INCREMENTAL_SNAPSHOT_ARCHIVES_TO_RETAIN , SUPPORTED_ARCHIVE_COMPRESSION ,
2021-07-22 12:40:37 -07:00
} ,
2021-03-04 13:01:11 -08:00
} ,
solana_sdk ::{
clock ::{ Slot , DEFAULT_S_PER_SLOT } ,
commitment_config ::CommitmentConfig ,
hash ::Hash ,
pubkey ::Pubkey ,
2022-06-24 09:21:03 -07:00
signature ::{ read_keypair , Keypair , Signer } ,
2021-03-04 13:01:11 -08:00
} ,
2022-04-21 12:43:08 -07:00
solana_send_transaction_service ::send_transaction_service ::{
self , MAX_BATCH_SEND_RATE_MS , MAX_TRANSACTION_BATCH_SIZE ,
} ,
2021-07-23 08:25:03 -07:00
solana_streamer ::socket ::SocketAddrSpace ,
2021-03-04 13:01:11 -08:00
solana_validator ::{
2021-10-03 11:13:16 -07:00
admin_rpc_service , bootstrap , dashboard ::Dashboard , ledger_lockfile , lock_ledger ,
2021-09-22 14:10:35 -07:00
new_spinner_progress_bar , println_name_value , redirect_stderr_to_file ,
2021-03-04 13:01:11 -08:00
} ,
std ::{
collections ::{ HashSet , VecDeque } ,
env ,
fs ::{ self , File } ,
2021-10-03 11:13:16 -07:00
net ::{ IpAddr , SocketAddr } ,
2021-03-04 13:01:11 -08:00
path ::{ Path , PathBuf } ,
process ::exit ,
str ::FromStr ,
2021-10-03 11:13:16 -07:00
sync ::{ Arc , RwLock } ,
time ::{ Duration , SystemTime } ,
2019-11-18 20:43:14 -08:00
} ,
} ;
2019-11-04 07:11:40 -08:00
2021-09-24 07:26:25 -07:00
#[ cfg(not(target_env = " msvc " )) ]
#[ global_allocator ]
static GLOBAL : Jemalloc = Jemalloc ;
2022-05-22 18:00:42 -07:00
#[ derive(Debug, PartialEq, Eq) ]
2021-01-29 18:01:27 -08:00
enum Operation {
Initialize ,
Run ,
2021-02-19 11:31:16 -08:00
}
2021-05-11 15:06:22 -07:00
const EXCLUDE_KEY : & str = " account-index-exclude-key " ;
const INCLUDE_KEY : & str = " account-index-include-key " ;
2021-05-25 09:32:12 -07:00
// The default minimal snapshot download speed (bytes/second)
const DEFAULT_MIN_SNAPSHOT_DOWNLOAD_SPEED : u64 = 10485760 ;
// The maximum times of snapshot download abort and retry
const MAX_SNAPSHOT_DOWNLOAD_ABORT : u32 = 5 ;
2022-04-21 12:43:08 -07:00
const MILLIS_PER_SECOND : u64 = 1000 ;
2021-05-11 15:06:22 -07:00
2021-03-10 15:28:42 -08:00
fn monitor_validator ( ledger_path : & Path ) {
let dashboard = Dashboard ::new ( ledger_path , None , None ) . unwrap_or_else ( | err | {
println! (
" Error: Unable to connect to validator at {}: {:?} " ,
ledger_path . display ( ) ,
err ,
) ;
exit ( 1 ) ;
} ) ;
dashboard . run ( Duration ::from_secs ( 2 ) ) ;
}
2021-02-19 11:31:16 -08:00
fn wait_for_restart_window (
ledger_path : & Path ,
2021-07-14 18:24:43 -07:00
identity : Option < Pubkey > ,
2021-02-19 11:31:16 -08:00
min_idle_time_in_minutes : usize ,
2021-10-01 12:52:28 -07:00
max_delinquency_percentage : u8 ,
2022-02-15 13:42:23 -08:00
skip_new_snapshot_check : bool ,
2021-02-19 11:31:16 -08:00
) -> Result < ( ) , Box < dyn std ::error ::Error > > {
2021-02-26 12:09:55 -08:00
let sleep_interval = Duration ::from_secs ( 5 ) ;
2021-02-19 11:31:16 -08:00
let min_idle_slots = ( min_idle_time_in_minutes as f64 * 60. / DEFAULT_S_PER_SLOT ) as Slot ;
2021-06-18 06:34:46 -07:00
let admin_client = admin_rpc_service ::connect ( ledger_path ) ;
2021-02-26 21:42:09 -08:00
let rpc_addr = admin_rpc_service ::runtime ( )
. block_on ( async move { admin_client . await ? . rpc_addr ( ) . await } )
. map_err ( | err | format! ( " Unable to get validator RPC address: {} " , err ) ) ? ;
2021-02-19 11:31:16 -08:00
let rpc_client = match rpc_addr {
None = > return Err ( " RPC not available " . into ( ) ) ,
Some ( rpc_addr ) = > RpcClient ::new_socket ( rpc_addr ) ,
} ;
2021-07-14 18:24:43 -07:00
let my_identity = rpc_client . get_identity ( ) ? ;
let identity = identity . unwrap_or ( my_identity ) ;
let monitoring_another_validator = identity ! = my_identity ;
2021-02-19 11:31:16 -08:00
println_name_value ( " Identity: " , & identity . to_string ( ) ) ;
println_name_value (
" Minimum Idle Time: " ,
& format! (
" {} slots (~{} minutes) " ,
min_idle_slots , min_idle_time_in_minutes
) ,
) ;
2021-10-01 12:52:28 -07:00
println! (
" Maximum permitted delinquency: {}% " ,
max_delinquency_percentage
) ;
2021-02-19 11:31:16 -08:00
let mut current_epoch = None ;
let mut leader_schedule = VecDeque ::new ( ) ;
let mut restart_snapshot = None ;
2021-04-02 18:19:15 -07:00
let mut upcoming_idle_windows = vec! [ ] ; // Vec<(starting slot, idle window length in slots)>
2021-02-19 11:31:16 -08:00
let progress_bar = new_spinner_progress_bar ( ) ;
let monitor_start_time = SystemTime ::now ( ) ;
loop {
2021-09-02 13:25:42 -07:00
let snapshot_slot_info = rpc_client . get_highest_snapshot_slot ( ) . ok ( ) ;
2021-02-19 11:31:16 -08:00
let epoch_info = rpc_client . get_epoch_info_with_commitment ( CommitmentConfig ::processed ( ) ) ? ;
let healthy = rpc_client . get_health ( ) . ok ( ) . is_some ( ) ;
2021-02-26 12:09:55 -08:00
let delinquent_stake_percentage = {
let vote_accounts = rpc_client . get_vote_accounts ( ) ? ;
let current_stake : u64 = vote_accounts
. current
. iter ( )
. map ( | va | va . activated_stake )
. sum ( ) ;
let delinquent_stake : u64 = vote_accounts
. delinquent
. iter ( )
. map ( | va | va . activated_stake )
. sum ( ) ;
let total_stake = current_stake + delinquent_stake ;
delinquent_stake as f64 / total_stake as f64
} ;
2021-02-19 11:31:16 -08:00
if match current_epoch {
None = > true ,
Some ( current_epoch ) = > current_epoch ! = epoch_info . epoch ,
} {
2021-06-01 10:38:02 -07:00
progress_bar . set_message ( format! (
2021-02-19 11:31:16 -08:00
" Fetching leader schedule for epoch {}... " ,
epoch_info . epoch
) ) ;
let first_slot_in_epoch = epoch_info . absolute_slot - epoch_info . slot_index ;
leader_schedule = rpc_client
2021-04-21 14:13:41 -07:00
. get_leader_schedule_with_config (
Some ( first_slot_in_epoch ) ,
RpcLeaderScheduleConfig {
identity : Some ( identity . to_string ( ) ) ,
.. RpcLeaderScheduleConfig ::default ( )
} ,
) ?
2021-02-19 11:31:16 -08:00
. ok_or_else ( | | {
format! (
" Unable to get leader schedule from slot {} " ,
first_slot_in_epoch
)
} ) ?
. get ( & identity . to_string ( ) )
. cloned ( )
. unwrap_or_default ( )
. into_iter ( )
. map ( | slot_index | first_slot_in_epoch . saturating_add ( slot_index as u64 ) )
2021-04-02 18:19:15 -07:00
. filter ( | slot | * slot > epoch_info . absolute_slot )
2021-02-19 11:31:16 -08:00
. collect ::< VecDeque < _ > > ( ) ;
2021-04-02 18:19:15 -07:00
upcoming_idle_windows . clear ( ) ;
{
let mut leader_schedule = leader_schedule . clone ( ) ;
let mut max_idle_window = 0 ;
let mut idle_window_start_slot = epoch_info . absolute_slot ;
while let Some ( next_leader_slot ) = leader_schedule . pop_front ( ) {
let idle_window = next_leader_slot - idle_window_start_slot ;
max_idle_window = max_idle_window . max ( idle_window ) ;
if idle_window > min_idle_slots {
upcoming_idle_windows . push ( ( idle_window_start_slot , idle_window ) ) ;
}
idle_window_start_slot = next_leader_slot ;
}
2021-04-04 08:09:19 -07:00
if ! leader_schedule . is_empty ( ) & & upcoming_idle_windows . is_empty ( ) {
2021-04-02 18:19:15 -07:00
return Err ( format! (
" Validator has no idle window of at least {} slots. Largest idle window for epoch {} is {} slots " ,
min_idle_slots , epoch_info . epoch , max_idle_window
)
. into ( ) ) ;
}
}
2021-02-19 11:31:16 -08:00
current_epoch = Some ( epoch_info . epoch ) ;
}
let status = {
if ! healthy {
style ( " Node is unhealthy " ) . red ( ) . to_string ( )
} else {
// Wait until a hole in the leader schedule before restarting the node
2021-04-02 18:19:15 -07:00
let in_leader_schedule_hole = if epoch_info . slot_index + min_idle_slots as u64
> epoch_info . slots_in_epoch
{
Err ( " Current epoch is almost complete " . to_string ( ) )
} else {
while leader_schedule
. get ( 0 )
. map ( | slot | * slot < epoch_info . absolute_slot )
. unwrap_or ( false )
{
leader_schedule . pop_front ( ) ;
}
while upcoming_idle_windows
2022-06-21 13:26:51 -07:00
. first ( )
2021-04-02 18:19:15 -07:00
. map ( | ( slot , _ ) | * slot < epoch_info . absolute_slot )
. unwrap_or ( false )
{
upcoming_idle_windows . pop ( ) ;
}
match leader_schedule . get ( 0 ) {
None = > {
Ok ( ( ) ) // Validator has no leader slots
2021-02-19 11:31:16 -08:00
}
2021-04-02 18:19:15 -07:00
Some ( next_leader_slot ) = > {
let idle_slots =
next_leader_slot . saturating_sub ( epoch_info . absolute_slot ) ;
if idle_slots > = min_idle_slots {
Ok ( ( ) )
} else {
2022-06-21 13:26:51 -07:00
Err ( match upcoming_idle_windows . first ( ) {
2021-04-02 18:19:15 -07:00
Some ( ( starting_slot , length_in_slots ) ) = > {
format! (
" Next idle window in {} slots, for {} slots " ,
starting_slot . saturating_sub ( epoch_info . absolute_slot ) ,
length_in_slots
)
}
None = > format! (
2021-03-10 15:28:42 -08:00
" Validator will be leader soon. Next leader slot is {} " ,
2021-02-19 11:31:16 -08:00
next_leader_slot
2021-04-02 18:19:15 -07:00
) ,
} )
2021-02-19 11:31:16 -08:00
}
}
2021-04-02 18:19:15 -07:00
}
} ;
2021-02-19 11:31:16 -08:00
2021-09-03 09:42:22 -07:00
let snapshot_slot = snapshot_slot_info . map ( | snapshot_slot_info | {
snapshot_slot_info
. incremental
. unwrap_or ( snapshot_slot_info . full )
} ) ;
2021-02-19 11:31:16 -08:00
match in_leader_schedule_hole {
Ok ( _ ) = > {
2022-02-15 13:42:23 -08:00
if skip_new_snapshot_check {
break ; // Restart!
}
2021-02-19 11:31:16 -08:00
if restart_snapshot = = None {
2021-09-03 09:42:22 -07:00
restart_snapshot = snapshot_slot ;
2021-02-19 11:31:16 -08:00
}
2021-09-03 09:42:22 -07:00
if restart_snapshot = = snapshot_slot & & ! monitoring_another_validator {
2021-02-19 11:31:16 -08:00
" Waiting for a new snapshot " . to_string ( )
2021-10-01 12:52:28 -07:00
} else if delinquent_stake_percentage
> = ( max_delinquency_percentage as f64 / 100. )
{
2021-02-26 12:09:55 -08:00
style ( " Delinquency too high " ) . red ( ) . to_string ( )
2021-02-19 11:31:16 -08:00
} else {
break ; // Restart!
}
}
2021-03-10 15:28:42 -08:00
Err ( why ) = > style ( why ) . yellow ( ) . to_string ( ) ,
2021-02-19 11:31:16 -08:00
}
}
} ;
2021-06-01 10:38:02 -07:00
progress_bar . set_message ( format! (
2021-07-14 18:24:43 -07:00
" {} | Processed Slot: {} {} | {:.2}% delinquent stake | {} " ,
2021-02-19 11:31:16 -08:00
{
let elapsed =
chrono ::Duration ::from_std ( monitor_start_time . elapsed ( ) . unwrap ( ) ) . unwrap ( ) ;
format! (
" {:02}:{:02}:{:02} " ,
elapsed . num_hours ( ) ,
elapsed . num_minutes ( ) % 60 ,
elapsed . num_seconds ( ) % 60
)
} ,
epoch_info . absolute_slot ,
2021-07-14 18:24:43 -07:00
if monitoring_another_validator {
" " . to_string ( )
} else {
format! (
2021-09-03 09:42:22 -07:00
" | Full Snapshot Slot: {} | Incremental Snapshot Slot: {} " ,
2021-09-02 13:25:42 -07:00
snapshot_slot_info
2021-09-03 09:42:22 -07:00
. as_ref ( )
2021-09-02 13:25:42 -07:00
. map ( | snapshot_slot_info | snapshot_slot_info . full . to_string ( ) )
. unwrap_or_else ( | | '-' . to_string ( ) ) ,
2021-09-03 09:42:22 -07:00
snapshot_slot_info
. as_ref ( )
2022-01-21 16:01:22 -08:00
. and_then ( | snapshot_slot_info | snapshot_slot_info
2021-09-03 09:42:22 -07:00
. incremental
. map ( | incremental | incremental . to_string ( ) ) )
. unwrap_or_else ( | | '-' . to_string ( ) ) ,
2021-07-14 18:24:43 -07:00
)
} ,
2021-03-13 09:34:43 -08:00
delinquent_stake_percentage * 100. ,
2021-02-19 11:31:16 -08:00
status
) ) ;
2021-02-26 12:09:55 -08:00
std ::thread ::sleep ( sleep_interval ) ;
2021-02-19 11:31:16 -08:00
}
drop ( progress_bar ) ;
println! ( " {} " , style ( " Ready to restart " ) . green ( ) ) ;
Ok ( ( ) )
2021-01-29 18:01:27 -08:00
}
2019-11-04 07:11:40 -08:00
fn hash_validator ( hash : String ) -> Result < ( ) , String > {
Hash ::from_str ( & hash )
. map ( | _ | ( ) )
. map_err ( | e | format! ( " {:?} " , e ) )
}
2020-01-24 17:27:04 -08:00
// This function is duplicated in ledger-tool/src/main.rs...
fn hardforks_of ( matches : & ArgMatches < '_ > , name : & str ) -> Option < Vec < Slot > > {
if matches . is_present ( name ) {
Some ( values_t_or_exit! ( matches , name , Slot ) )
} else {
None
}
}
2020-08-21 00:35:11 -07:00
fn validators_set (
identity_pubkey : & Pubkey ,
matches : & ArgMatches < '_ > ,
matches_name : & str ,
arg_name : & str ,
) -> Option < HashSet < Pubkey > > {
if matches . is_present ( matches_name ) {
let validators_set : HashSet < _ > = values_t_or_exit! ( matches , matches_name , Pubkey )
. into_iter ( )
. collect ( ) ;
if validators_set . contains ( identity_pubkey ) {
eprintln! (
" The validator's identity pubkey cannot be a {}: {} " ,
arg_name , identity_pubkey
) ;
exit ( 1 ) ;
}
Some ( validators_set )
} else {
None
}
}
2021-06-20 08:39:20 -07:00
fn get_cluster_shred_version ( entrypoints : & [ SocketAddr ] ) -> Option < u16 > {
let entrypoints = {
let mut index : Vec < _ > = ( 0 .. entrypoints . len ( ) ) . collect ( ) ;
index . shuffle ( & mut rand ::thread_rng ( ) ) ;
index . into_iter ( ) . map ( | i | & entrypoints [ i ] )
} ;
for entrypoint in entrypoints {
match solana_net_utils ::get_cluster_shred_version ( entrypoint ) {
Err ( err ) = > eprintln! ( " get_cluster_shred_version failed: {} , {} " , entrypoint , err ) ,
2022-05-30 05:51:19 -07:00
Ok ( 0 ) = > eprintln! ( " zero shred-version from entrypoint: {} " , entrypoint ) ,
2021-06-20 08:39:20 -07:00
Ok ( shred_version ) = > {
info! (
" obtained shred-version {} from {} " ,
shred_version , entrypoint
) ;
return Some ( shred_version ) ;
}
}
}
None
}
2019-11-04 07:11:40 -08:00
pub fn main ( ) {
let default_dynamic_port_range =
& format! ( " {} - {} " , VALIDATOR_PORT_RANGE . 0 , VALIDATOR_PORT_RANGE . 1 ) ;
2020-04-29 18:53:34 -07:00
let default_genesis_archive_unpacked_size = & MAX_GENESIS_ARCHIVE_UNPACKED_SIZE . to_string ( ) ;
2020-12-07 09:22:35 -08:00
let default_rpc_max_multiple_accounts = & MAX_MULTIPLE_ACCOUNTS . to_string ( ) ;
2021-09-17 12:40:14 -07:00
2021-06-16 21:28:23 -07:00
let default_rpc_pubsub_max_active_subscriptions =
PubSubConfig ::default ( ) . max_active_subscriptions . to_string ( ) ;
2021-09-17 12:40:14 -07:00
let default_rpc_pubsub_queue_capacity_items =
PubSubConfig ::default ( ) . queue_capacity_items . to_string ( ) ;
let default_rpc_pubsub_queue_capacity_bytes =
PubSubConfig ::default ( ) . queue_capacity_bytes . to_string ( ) ;
2021-10-19 16:11:46 -07:00
let default_send_transaction_service_config = send_transaction_service ::Config ::default ( ) ;
let default_rpc_send_transaction_retry_ms = default_send_transaction_service_config
. retry_rate_ms
2020-12-17 14:37:22 -08:00
. to_string ( ) ;
2022-04-21 12:43:08 -07:00
let default_rpc_send_transaction_batch_ms = default_send_transaction_service_config
. batch_send_rate_ms
. to_string ( ) ;
2021-10-19 16:11:46 -07:00
let default_rpc_send_transaction_leader_forward_count = default_send_transaction_service_config
. leader_forward_count
2020-12-17 14:37:22 -08:00
. to_string ( ) ;
2021-10-19 22:17:06 -07:00
let default_rpc_send_transaction_service_max_retries = default_send_transaction_service_config
. service_max_retries
. to_string ( ) ;
2022-04-21 12:43:08 -07:00
let default_rpc_send_transaction_batch_size = default_send_transaction_service_config
. batch_size
. to_string ( ) ;
2021-01-12 17:13:47 -08:00
let default_rpc_threads = num_cpus ::get ( ) . to_string ( ) ;
2021-09-01 14:10:16 -07:00
let default_accountsdb_repl_threads = num_cpus ::get ( ) . to_string ( ) ;
2021-09-10 13:59:26 -07:00
let default_maximum_full_snapshot_archives_to_retain =
& DEFAULT_MAX_FULL_SNAPSHOT_ARCHIVES_TO_RETAIN . to_string ( ) ;
let default_maximum_incremental_snapshot_archives_to_retain =
& DEFAULT_MAX_INCREMENTAL_SNAPSHOT_ARCHIVES_TO_RETAIN . to_string ( ) ;
let default_full_snapshot_archive_interval_slots =
& DEFAULT_FULL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS . to_string ( ) ;
let default_incremental_snapshot_archive_interval_slots =
& DEFAULT_INCREMENTAL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS . to_string ( ) ;
2021-05-25 09:32:12 -07:00
let default_min_snapshot_download_speed = & DEFAULT_MIN_SNAPSHOT_DOWNLOAD_SPEED . to_string ( ) ;
let default_max_snapshot_download_abort = & MAX_SNAPSHOT_DOWNLOAD_ABORT . to_string ( ) ;
2021-06-09 21:21:32 -07:00
let default_accounts_shrink_optimize_total_space =
& DEFAULT_ACCOUNTS_SHRINK_OPTIMIZE_TOTAL_SPACE . to_string ( ) ;
let default_accounts_shrink_ratio = & DEFAULT_ACCOUNTS_SHRINK_RATIO . to_string ( ) ;
2022-03-03 12:43:58 -08:00
let default_rocksdb_fifo_shred_storage_size =
& DEFAULT_ROCKS_FIFO_SHRED_STORAGE_SIZE_BYTES . to_string ( ) ;
2022-06-10 09:25:24 -07:00
let default_tpu_connection_pool_size = & DEFAULT_TPU_CONNECTION_POOL_SIZE . to_string ( ) ;
2019-11-04 07:11:40 -08:00
let matches = App ::new ( crate_name! ( ) ) . about ( crate_description! ( ) )
2020-05-11 15:02:01 -07:00
. version ( solana_version ::version! ( ) )
2021-01-29 18:01:27 -08:00
. setting ( AppSettings ::VersionlessSubcommands )
2021-02-05 22:39:23 -08:00
. setting ( AppSettings ::InferSubcommands )
2019-11-22 07:20:40 -08:00
. arg (
2019-11-23 08:55:43 -08:00
Arg ::with_name ( SKIP_SEED_PHRASE_VALIDATION_ARG . name )
. long ( SKIP_SEED_PHRASE_VALIDATION_ARG . long )
. help ( SKIP_SEED_PHRASE_VALIDATION_ARG . help ) ,
2019-11-22 07:20:40 -08:00
)
. arg (
2020-03-13 11:41:18 -07:00
Arg ::with_name ( " identity " )
2019-11-04 07:11:40 -08:00
. short ( " i " )
2020-03-13 11:41:18 -07:00
. long ( " identity " )
2021-03-06 09:29:02 -08:00
. value_name ( " KEYPAIR " )
2019-11-04 07:11:40 -08:00
. takes_value ( true )
2020-03-06 21:22:23 -08:00
. validator ( is_keypair_or_ask_keyword )
2020-03-13 11:41:18 -07:00
. help ( " Validator identity keypair " ) ,
2019-11-04 07:11:40 -08:00
)
. arg (
2020-03-31 08:23:42 -07:00
Arg ::with_name ( " authorized_voter_keypairs " )
2020-03-13 11:41:18 -07:00
. long ( " authorized-voter " )
2021-03-06 09:29:02 -08:00
. value_name ( " KEYPAIR " )
2019-11-04 07:11:40 -08:00
. takes_value ( true )
2020-03-06 21:22:23 -08:00
. validator ( is_keypair_or_ask_keyword )
2020-03-22 22:21:00 -07:00
. requires ( " vote_account " )
2020-03-31 08:23:42 -07:00
. multiple ( true )
. help ( " Include an additional authorized voter keypair. \
May be specified multiple times . \
[ default : the - - identity keypair ] " ),
2020-03-15 10:19:07 -07:00
)
2019-11-04 07:11:40 -08:00
. arg (
Arg ::with_name ( " vote_account " )
. long ( " vote-account " )
2021-03-06 09:29:02 -08:00
. value_name ( " ADDRESS " )
2019-11-04 07:11:40 -08:00
. takes_value ( true )
2019-11-11 16:42:08 -08:00
. validator ( is_pubkey_or_keypair )
2020-03-22 22:21:00 -07:00
. requires ( " identity " )
2020-05-29 15:31:52 -07:00
. help ( " Validator vote account public key. \
If unspecified voting will be disabled . \
The authorized voter for the account must either be the \
- - identity keypair or with the - - authorized - voter argument " )
2019-11-04 07:11:40 -08:00
)
. arg (
Arg ::with_name ( " init_complete_file " )
. long ( " init-complete-file " )
. value_name ( " FILE " )
. takes_value ( true )
2020-05-29 15:31:52 -07:00
. help ( " Create this file if it doesn't already exist \
2020-12-30 21:56:37 -08:00
once validator initialization is complete " ),
2019-11-04 07:11:40 -08:00
)
. arg (
Arg ::with_name ( " ledger_path " )
. short ( " l " )
. long ( " ledger " )
. value_name ( " DIR " )
. takes_value ( true )
. required ( true )
2021-03-11 11:14:54 -08:00
. default_value ( " ledger " )
. help ( " Use DIR as ledger location " ) ,
2019-11-04 07:11:40 -08:00
)
. arg (
Arg ::with_name ( " entrypoint " )
. short ( " n " )
. long ( " entrypoint " )
. value_name ( " HOST:PORT " )
. takes_value ( true )
2020-12-18 10:54:48 -08:00
. multiple ( true )
2019-11-12 12:37:13 -08:00
. validator ( solana_net_utils ::is_host_port )
2019-11-18 20:43:14 -08:00
. help ( " Rendezvous with the cluster at this gossip entrypoint " ) ,
2019-11-04 07:11:40 -08:00
)
. arg (
Arg ::with_name ( " no_snapshot_fetch " )
. long ( " no-snapshot-fetch " )
. takes_value ( false )
2020-05-29 15:31:52 -07:00
. help ( " Do not attempt to fetch a snapshot from the cluster, \
start from a local snapshot if present " ),
2019-11-04 07:11:40 -08:00
)
2019-11-12 09:42:04 -08:00
. arg (
Arg ::with_name ( " no_genesis_fetch " )
. long ( " no-genesis-fetch " )
. takes_value ( false )
2019-11-18 20:43:14 -08:00
. help ( " Do not fetch genesis from the cluster " ) ,
2019-11-12 09:42:04 -08:00
)
2019-11-04 07:11:40 -08:00
. arg (
Arg ::with_name ( " no_voting " )
. long ( " no-voting " )
. takes_value ( false )
2020-12-30 21:56:37 -08:00
. help ( " Launch validator without voting " ) ,
2019-11-04 07:11:40 -08:00
)
2020-02-24 22:54:51 -08:00
. arg (
Arg ::with_name ( " no_check_vote_account " )
. long ( " no-check-vote-account " )
. takes_value ( false )
. conflicts_with ( " no_voting " )
. requires ( " entrypoint " )
2022-02-14 22:50:17 -08:00
. hidden ( true )
2020-02-24 22:54:51 -08:00
. help ( " Skip the RPC vote account sanity check " )
)
2022-02-14 22:50:17 -08:00
. arg (
Arg ::with_name ( " check_vote_account " )
. long ( " check-vote-account " )
. takes_value ( true )
. value_name ( " RPC_URL " )
. requires ( " entrypoint " )
. conflicts_with_all ( & [ " no_check_vote_account " , " no_voting " ] )
. help ( " Sanity check vote account state at startup. The JSON RPC endpoint at RPC_URL must expose `--full-rpc-api` " )
)
2020-09-10 13:15:22 -07:00
. arg (
Arg ::with_name ( " restricted_repair_only_mode " )
. long ( " restricted-repair-only-mode " )
. takes_value ( false )
. help ( " Do not publish the Gossip, TPU, TVU or Repair Service ports causing \
the validator to operate in a limited capacity that reduces its \
exposure to the rest of the cluster . \
\
The - - no - voting flag is implicit when this flag is enabled \
" ),
)
2019-11-04 07:11:40 -08:00
. arg (
Arg ::with_name ( " dev_halt_at_slot " )
. long ( " dev-halt-at-slot " )
. value_name ( " SLOT " )
2020-03-02 10:47:58 -08:00
. validator ( is_slot )
2019-11-04 07:11:40 -08:00
. takes_value ( true )
. help ( " Halt the validator when it reaches the given slot " ) ,
)
. arg (
Arg ::with_name ( " rpc_port " )
. long ( " rpc-port " )
. value_name ( " PORT " )
. takes_value ( true )
2020-12-08 23:18:27 -08:00
. validator ( solana_validator ::port_validator )
2021-02-26 21:42:09 -08:00
. help ( " Enable JSON RPC on this port, and the next port for the RPC websocket " ) ,
)
. arg (
Arg ::with_name ( " minimal_rpc_api " )
. long ( " --minimal-rpc-api " )
. takes_value ( false )
2022-01-28 18:00:18 -08:00
. hidden ( true )
2021-02-26 21:42:09 -08:00
. help ( " Only expose the RPC methods required to serve snapshots to other nodes " ) ,
2019-11-04 07:11:40 -08:00
)
2022-01-28 18:00:18 -08:00
. arg (
Arg ::with_name ( " full_rpc_api " )
. long ( " --full-rpc-api " )
. conflicts_with ( " minimal_rpc_api " )
. takes_value ( false )
. help ( " Expose RPC methods for querying chain state and transaction history " ) ,
)
2021-04-12 19:33:40 -07:00
. arg (
Arg ::with_name ( " obsolete_v1_7_rpc_api " )
. long ( " --enable-rpc-obsolete_v1_7 " )
. takes_value ( false )
. help ( " Enable the obsolete RPC methods removed in v1.7 " ) ,
)
2020-01-30 09:17:01 -08:00
. arg (
Arg ::with_name ( " private_rpc " )
. long ( " --private-rpc " )
. takes_value ( false )
2020-12-30 21:56:37 -08:00
. help ( " Do not publish the RPC port for use by others " )
2020-01-30 09:17:01 -08:00
)
2020-10-02 04:36:41 -07:00
. arg (
Arg ::with_name ( " no_port_check " )
. long ( " --no-port-check " )
. takes_value ( false )
. help ( " Do not perform TCP/UDP reachable port checks at start-up " )
)
2020-02-11 17:01:49 -08:00
. arg (
2020-03-23 10:25:39 -07:00
Arg ::with_name ( " enable_rpc_transaction_history " )
. long ( " enable-rpc-transaction-history " )
2020-02-11 17:01:49 -08:00
. takes_value ( false )
2020-05-29 15:31:52 -07:00
. help ( " Enable historical transaction info over JSON RPC, \
including the ' getConfirmedBlock ' API . \
2020-07-23 09:54:57 -07:00
This will cause an increase in disk usage and IOPS " ),
)
. arg (
Arg ::with_name ( " enable_rpc_bigtable_ledger_storage " )
. long ( " enable-rpc-bigtable-ledger-storage " )
. requires ( " enable_rpc_transaction_history " )
. takes_value ( false )
. help ( " Fetch historical transaction info from a BigTable instance \
as a fallback to local ledger data " ),
2020-05-29 15:31:52 -07:00
)
2020-09-03 11:30:21 -07:00
. arg (
Arg ::with_name ( " enable_bigtable_ledger_upload " )
. long ( " enable-bigtable-ledger-upload " )
. requires ( " enable_rpc_transaction_history " )
. takes_value ( false )
. help ( " Upload new confirmed blocks into a BigTable instance " ) ,
)
2021-02-01 13:00:51 -08:00
. arg (
Arg ::with_name ( " enable_cpi_and_log_storage " )
. long ( " enable-cpi-and-log-storage " )
. requires ( " enable_rpc_transaction_history " )
. takes_value ( false )
2022-03-22 15:17:05 -07:00
. hidden ( true )
. help ( " Deprecated, please use \" enable-extended-tx-metadata-storage \" . \
Include CPI inner instructions , logs and return data in \
the historical transaction info stored " ),
)
. arg (
Arg ::with_name ( " enable_extended_tx_metadata_storage " )
. long ( " enable-extended-tx-metadata-storage " )
. requires ( " enable_rpc_transaction_history " )
. takes_value ( false )
. help ( " Include CPI inner instructions, logs, and return data in \
the historical transaction info stored " ),
2021-02-01 13:00:51 -08:00
)
2020-12-07 09:22:35 -08:00
. arg (
Arg ::with_name ( " rpc_max_multiple_accounts " )
. long ( " rpc-max-multiple-accounts " )
. value_name ( " MAX ACCOUNTS " )
. takes_value ( true )
. default_value ( default_rpc_max_multiple_accounts )
. help ( " Override the default maximum accounts accepted by \
the getMultipleAccounts JSON RPC method " )
)
2020-05-29 15:31:52 -07:00
. arg (
Arg ::with_name ( " health_check_slot_distance " )
. long ( " health-check-slot-distance " )
. value_name ( " SLOT_DISTANCE " )
. takes_value ( true )
. default_value ( " 150 " )
2021-08-17 21:17:46 -07:00
. help ( " If --known-validators are specified, report this validator healthy \
2020-05-29 15:31:52 -07:00
if its latest account hash is no further behind than this number of \
2021-08-17 21:17:46 -07:00
slots from the latest known validator account hash . \
If no - - known - validators are specified , the validator will always \
2020-05-29 15:31:52 -07:00
report itself to be healthy " )
2020-02-11 17:01:49 -08:00
)
2019-11-04 07:11:40 -08:00
. arg (
2019-12-16 13:05:17 -08:00
Arg ::with_name ( " rpc_faucet_addr " )
. long ( " rpc-faucet-address " )
2019-11-04 07:11:40 -08:00
. value_name ( " HOST:PORT " )
. takes_value ( true )
2019-11-12 12:37:13 -08:00
. validator ( solana_net_utils ::is_host_port )
2019-12-16 13:05:17 -08:00
. help ( " Enable the JSON RPC 'requestAirdrop' API with this faucet address. " ) ,
2019-11-04 07:11:40 -08:00
)
. arg (
Arg ::with_name ( " account_paths " )
. long ( " accounts " )
. value_name ( " PATHS " )
. takes_value ( true )
2020-12-20 21:36:27 -08:00
. multiple ( true )
2019-11-04 07:11:40 -08:00
. help ( " Comma separated persistent accounts location " ) ,
)
2020-12-21 21:33:37 -08:00
. arg (
Arg ::with_name ( " account_shrink_path " )
. long ( " account-shrink-path " )
. value_name ( " PATH " )
. takes_value ( true )
. multiple ( true )
. help ( " Path to accounts shrink path which can hold a compacted account set. " ) ,
)
2021-03-13 13:48:26 -08:00
. arg (
2021-03-17 04:31:00 -07:00
Arg ::with_name ( " snapshots " )
. long ( " snapshots " )
2021-03-16 14:56:11 -07:00
. value_name ( " DIR " )
2021-03-13 13:48:26 -08:00
. takes_value ( true )
2021-05-04 20:49:18 -07:00
. help ( " Use DIR as snapshot location [default: --ledger value] " ) ,
)
2022-05-10 13:37:41 -07:00
. arg (
Arg ::with_name ( " incremental_snapshot_archive_path " )
. long ( " incremental-snapshot-archive-path " )
. conflicts_with ( " no-incremental-snapshots " )
. value_name ( " DIR " )
. takes_value ( true )
. help ( " Use DIR as separate location for incremental snapshot archives [default: --snapshots value] " ) ,
)
2021-05-04 20:49:18 -07:00
. arg (
Arg ::with_name ( " tower " )
. long ( " tower " )
. value_name ( " DIR " )
. takes_value ( true )
2021-08-10 13:09:52 -07:00
. help ( " Use DIR as file tower storage location [default: --ledger value] " ) ,
)
. arg (
Arg ::with_name ( " tower_storage " )
. long ( " tower-storage " )
. possible_values ( & [ " file " , " etcd " ] )
. default_value ( " file " )
. takes_value ( true )
. help ( " Where to store the tower " ) ,
)
. arg (
Arg ::with_name ( " etcd_endpoint " )
. long ( " etcd-endpoint " )
. required_if ( " tower_storage " , " etcd " )
. value_name ( " HOST:PORT " )
. takes_value ( true )
. multiple ( true )
. validator ( solana_net_utils ::is_host_port )
. help ( " etcd gRPC endpoint to connect with " )
)
. arg (
Arg ::with_name ( " etcd_domain_name " )
. long ( " etcd-domain-name " )
. required_if ( " tower_storage " , " etcd " )
. value_name ( " DOMAIN " )
. default_value ( " localhost " )
. takes_value ( true )
. help ( " domain name against which to verify the etcd server’ s TLS certificate " )
)
. arg (
Arg ::with_name ( " etcd_cacert_file " )
. long ( " etcd-cacert-file " )
. required_if ( " tower_storage " , " etcd " )
. value_name ( " FILE " )
. takes_value ( true )
. help ( " verify the TLS certificate of the etcd endpoint using this CA bundle " )
)
. arg (
Arg ::with_name ( " etcd_key_file " )
. long ( " etcd-key-file " )
. required_if ( " tower_storage " , " etcd " )
. value_name ( " FILE " )
. takes_value ( true )
. help ( " TLS key file to use when establishing a connection to the etcd endpoint " )
)
. arg (
Arg ::with_name ( " etcd_cert_file " )
. long ( " etcd-cert-file " )
. required_if ( " tower_storage " , " etcd " )
. value_name ( " FILE " )
. takes_value ( true )
. help ( " TLS certificate to use when establishing a connection to the etcd endpoint " )
2021-03-13 13:48:26 -08:00
)
2019-11-04 07:11:40 -08:00
. arg (
2020-04-29 18:53:34 -07:00
Arg ::with_name ( " gossip_port " )
2019-11-04 07:11:40 -08:00
. long ( " gossip-port " )
2019-11-20 14:21:34 -08:00
. value_name ( " PORT " )
2019-11-04 07:11:40 -08:00
. takes_value ( true )
2020-12-30 21:56:37 -08:00
. help ( " Gossip port number for the validator " ) ,
2019-11-04 07:11:40 -08:00
)
2019-11-20 14:21:34 -08:00
. arg (
2020-04-29 18:53:34 -07:00
Arg ::with_name ( " gossip_host " )
2019-11-20 14:21:34 -08:00
. long ( " gossip-host " )
. value_name ( " HOST " )
. takes_value ( true )
. validator ( solana_net_utils ::is_host )
2020-12-30 21:56:37 -08:00
. help ( " Gossip DNS name or IP address for the validator to advertise in gossip \
2020-11-12 21:04:15 -08:00
[ default : ask - - entrypoint , or 127. 0. 0.1 when - - entrypoint is not provided ] " ),
2019-11-20 14:21:34 -08:00
)
2022-03-02 00:42:14 -08:00
. arg (
Arg ::with_name ( " tpu_host_addr " )
. long ( " tpu-host-addr " )
. value_name ( " HOST:PORT " )
. takes_value ( true )
. validator ( solana_net_utils ::is_host_port )
. help ( " Specify TPU address to advertise in gossip [default: ask --entrypoint or localhost \
when - - entrypoint is not provided ] " ),
)
2020-10-21 20:31:48 -07:00
. arg (
Arg ::with_name ( " public_rpc_addr " )
. long ( " public-rpc-address " )
. value_name ( " HOST:PORT " )
. takes_value ( true )
. conflicts_with ( " private_rpc " )
. validator ( solana_net_utils ::is_host_port )
2020-12-30 21:56:37 -08:00
. help ( " RPC address for the validator to advertise publicly in gossip. \
Useful for validators running behind a load balancer or proxy \
2020-10-21 20:31:48 -07:00
[ default : use - - rpc - bind - address / - - rpc - port ] " ),
)
2019-11-04 07:11:40 -08:00
. arg (
2020-04-29 18:53:34 -07:00
Arg ::with_name ( " dynamic_port_range " )
2019-11-04 07:11:40 -08:00
. long ( " dynamic-port-range " )
. value_name ( " MIN_PORT-MAX_PORT " )
. takes_value ( true )
. default_value ( default_dynamic_port_range )
2021-04-20 19:40:52 -07:00
. validator ( solana_validator ::port_range_validator )
2019-11-04 07:11:40 -08:00
. help ( " Range to use for dynamically assigned ports " ) ,
)
2020-11-27 22:38:45 -08:00
. arg (
Arg ::with_name ( " maximum_local_snapshot_age " )
. long ( " maximum-local-snapshot-age " )
. value_name ( " NUMBER_OF_SLOTS " )
. takes_value ( true )
2022-04-21 13:49:49 -07:00
. default_value ( " 2500 " )
2020-11-27 22:38:45 -08:00
. help ( " Reuse a local snapshot if it's less than this many \
slots behind the highest snapshot available for \
download from other validators " ),
)
2019-11-04 07:11:40 -08:00
. arg (
2021-09-10 13:59:26 -07:00
Arg ::with_name ( " incremental_snapshots " )
. long ( " incremental-snapshots " )
. takes_value ( false )
2022-02-09 11:26:35 -08:00
. hidden ( true )
. conflicts_with ( " no_incremental_snapshots " )
. help ( " Enable incremental snapshots " )
2021-09-10 13:59:26 -07:00
. long_help ( " Enable incremental snapshots by setting this flag. \
When enabled , - - snapshot - interval - slots will set the \
incremental snapshot interval . To set the full snapshot \
interval , use - - full - snapshot - interval - slots . " )
)
2022-02-09 11:26:35 -08:00
. arg (
Arg ::with_name ( " no_incremental_snapshots " )
. long ( " no-incremental-snapshots " )
. takes_value ( false )
. help ( " Disable incremental snapshots " )
. long_help ( " Disable incremental snapshots by setting this flag. \
When enabled , - - snapshot - interval - slots will set the \
incremental snapshot interval . To set the full snapshot \
interval , use - - full - snapshot - interval - slots . " )
)
2021-09-10 13:59:26 -07:00
. arg (
Arg ::with_name ( " incremental_snapshot_interval_slots " )
. long ( " incremental-snapshot-interval-slots " )
. alias ( " snapshot-interval-slots " )
. value_name ( " NUMBER " )
2019-11-04 07:11:40 -08:00
. takes_value ( true )
2021-09-10 13:59:26 -07:00
. default_value ( default_incremental_snapshot_archive_interval_slots )
2020-05-29 15:31:52 -07:00
. help ( " Number of slots between generating snapshots, \
0 to disable snapshots " ),
2019-11-04 07:11:40 -08:00
)
2021-05-12 10:32:27 -07:00
. arg (
2021-09-10 13:59:26 -07:00
Arg ::with_name ( " full_snapshot_interval_slots " )
. long ( " full-snapshot-interval-slots " )
. value_name ( " NUMBER " )
. takes_value ( true )
. default_value ( default_full_snapshot_archive_interval_slots )
. help ( " Number of slots between generating full snapshots " )
)
. arg (
Arg ::with_name ( " maximum_full_snapshots_to_retain " )
. long ( " maximum-full-snapshots-to-retain " )
. alias ( " maximum-snapshots-to-retain " )
. value_name ( " NUMBER " )
2021-05-12 10:32:27 -07:00
. takes_value ( true )
2021-09-10 13:59:26 -07:00
. default_value ( default_maximum_full_snapshot_archives_to_retain )
. help ( " The maximum number of full snapshot archives to hold on to when purging older snapshots. " )
)
. arg (
Arg ::with_name ( " maximum_incremental_snapshots_to_retain " )
. long ( " maximum-incremental-snapshots-to-retain " )
. value_name ( " NUMBER " )
. takes_value ( true )
. default_value ( default_maximum_incremental_snapshot_archives_to_retain )
. help ( " The maximum number of incremental snapshot archives to hold on to when purging older snapshots. " )
2021-05-12 10:32:27 -07:00
)
2021-10-26 18:56:16 -07:00
. arg (
Arg ::with_name ( " snapshot_packager_niceness_adj " )
. long ( " snapshot-packager-niceness-adjustment " )
. value_name ( " ADJUSTMENT " )
. takes_value ( true )
. validator ( is_niceness_adjustment_valid )
. default_value ( " 0 " )
. help ( " Add this value to niceness of snapshot packager thread. Negative value \
increases priority , positive value decreases priority . " )
)
2021-05-25 09:32:12 -07:00
. arg (
Arg ::with_name ( " minimal_snapshot_download_speed " )
. long ( " minimal-snapshot-download-speed " )
. value_name ( " MINIMAL_SNAPSHOT_DOWNLOAD_SPEED " )
. takes_value ( true )
. default_value ( default_min_snapshot_download_speed )
. help ( " The minimal speed of snapshot downloads measured in bytes/second. \
If the initial download speed falls below this threshold , the system will \
retry the download against a different rpc node . " ),
)
. arg (
Arg ::with_name ( " maximum_snapshot_download_abort " )
. long ( " maximum-snapshot-download-abort " )
. value_name ( " MAXIMUM_SNAPSHOT_DOWNLOAD_ABORT " )
. takes_value ( true )
. default_value ( default_max_snapshot_download_abort )
. help ( " The maximum number of times to abort and retry when encountering a \
slow snapshot download . " ),
)
2020-11-20 14:47:37 -08:00
. arg (
Arg ::with_name ( " contact_debug_interval " )
. long ( " contact-debug-interval " )
. value_name ( " CONTACT_DEBUG_INTERVAL " )
. takes_value ( true )
. default_value ( " 10000 " )
. help ( " Milliseconds between printing contact debug from gossip. " ) ,
)
2020-12-29 09:35:57 -08:00
. arg (
Arg ::with_name ( " no_poh_speed_test " )
. long ( " no-poh-speed-test " )
. help ( " Skip the check for PoH speed. " ) ,
)
2021-10-25 18:25:55 -07:00
. arg (
Arg ::with_name ( " no_os_network_limits_test " )
. hidden ( true )
. long ( " no-os-network-limits-test " )
. help ( " Skip checks for OS network limits. " )
)
2022-03-14 19:38:04 -07:00
. arg (
Arg ::with_name ( " no_os_memory_stats_reporting " )
. long ( " no-os-memory-stats-reporting " )
. help ( " Disable reporting of OS memory statistics. " )
)
2021-11-16 10:26:03 -08:00
. arg (
Arg ::with_name ( " no_os_network_stats_reporting " )
. long ( " no-os-network-stats-reporting " )
. help ( " Disable reporting of OS network statistics. " )
)
2022-06-07 11:34:25 -07:00
. arg (
Arg ::with_name ( " no_os_cpu_stats_reporting " )
. long ( " no-os-cpu-stats-reporting " )
. help ( " Disable reporting of OS CPU statistics. " )
)
2020-04-16 15:12:20 -07:00
. arg (
2021-09-10 13:59:26 -07:00
Arg ::with_name ( " accounts-hash-interval-slots " )
. long ( " accounts-hash-interval-slots " )
. value_name ( " NUMBER " )
2020-04-16 15:12:20 -07:00
. takes_value ( true )
. default_value ( " 100 " )
2021-09-10 13:59:26 -07:00
. help ( " Number of slots between generating accounts hash. " )
. validator ( | val | {
if val . eq ( " 0 " ) {
Err ( String ::from ( " Accounts hash interval cannot be zero " ) )
}
else {
Ok ( ( ) )
}
} ) ,
2020-04-16 15:12:20 -07:00
)
2020-06-18 22:38:37 -07:00
. arg (
Arg ::with_name ( " snapshot_version " )
. long ( " snapshot-version " )
. value_name ( " SNAPSHOT_VERSION " )
2020-08-03 16:27:17 -07:00
. validator ( is_parsable ::< SnapshotVersion > )
. takes_value ( true )
. default_value ( SnapshotVersion ::default ( ) . into ( ) )
. help ( " Output snapshot version " ) ,
2020-06-18 22:38:37 -07:00
)
2019-11-04 07:11:40 -08:00
. arg (
2020-04-29 18:53:34 -07:00
Arg ::with_name ( " limit_ledger_size " )
2019-11-04 07:11:40 -08:00
. long ( " limit-ledger-size " )
2020-03-30 19:02:12 -07:00
. value_name ( " SHRED_COUNT " )
2020-01-20 11:41:05 -08:00
. takes_value ( true )
. min_values ( 0 )
. max_values ( 1 )
2020-08-20 01:10:39 -07:00
/* .default_value() intentionally not used here! */
2020-03-30 19:02:12 -07:00
. help ( " Keep this amount of shreds in root slots. " ) ,
2019-11-04 07:11:40 -08:00
)
2022-03-03 12:43:58 -08:00
. arg (
Arg ::with_name ( " rocksdb_shred_compaction " )
. hidden ( true )
. long ( " rocksdb-shred-compaction " )
. value_name ( " ROCKSDB_COMPACTION_STYLE " )
. takes_value ( true )
. possible_values ( & [ " level " , " fifo " ] )
. default_value ( " level " )
. help ( " EXPERIMENTAL: Controls how RocksDB compacts shreds. \
* WARNING * : You will lose your ledger data when you switch between options . \
Possible values are : \
' level ' : stores shreds using RocksDB ' s default ( level ) compaction . \
' fifo ' : stores shreds under RocksDB ' s FIFO compaction . \
This option is more efficient on disk - write - bytes of the ledger store . " ),
)
. arg (
Arg ::with_name ( " rocksdb_fifo_shred_storage_size " )
. hidden ( true )
. long ( " rocksdb-fifo-shred-storage-size " )
. value_name ( " SHRED_STORAGE_SIZE_BYTES " )
. takes_value ( true )
. validator ( is_parsable ::< u64 > )
. default_value ( default_rocksdb_fifo_shred_storage_size )
. help ( " The shred storage size in bytes. \
The suggested value is 50 % of your ledger storage size in bytes . " ),
)
2022-03-22 02:27:09 -07:00
. arg (
Arg ::with_name ( " rocksdb_ledger_compression " )
. hidden ( true )
. long ( " rocksdb-ledger-compression " )
. value_name ( " COMPRESSION_TYPE " )
. takes_value ( true )
. possible_values ( & [ " none " , " lz4 " , " snappy " , " zlib " ] )
. default_value ( " none " )
. help ( " The compression alrogithm that is used to compress \
transaction status data . \
Turning on compression can save ~ 10 % of the ledger size . " ),
)
2022-04-29 15:28:50 -07:00
. arg (
Arg ::with_name ( " rocksdb_perf_sample_interval " )
. hidden ( true )
. long ( " rocksdb-perf-sample-interval " )
. value_name ( " ROCKS_PERF_SAMPLE_INTERVAL " )
. takes_value ( true )
. validator ( is_parsable ::< usize > )
. default_value ( " 0 " )
. help ( " Controls how often RocksDB read/write performance sample is collected. \
Reads / writes perf samples are collected in 1 / ROCKS_PERF_SAMPLE_INTERVAL sampling rate . " ),
)
2019-11-04 07:11:40 -08:00
. arg (
2020-04-29 18:53:34 -07:00
Arg ::with_name ( " skip_poh_verify " )
2019-11-04 21:14:55 -08:00
. long ( " skip-poh-verify " )
2019-11-04 07:11:40 -08:00
. takes_value ( false )
2020-12-30 21:56:37 -08:00
. help ( " Skip ledger verification at validator bootup " ) ,
2019-11-04 07:11:40 -08:00
)
. arg (
2020-04-29 18:53:34 -07:00
Arg ::with_name ( " cuda " )
2019-11-04 07:11:40 -08:00
. long ( " cuda " )
. takes_value ( false )
. help ( " Use CUDA " ) ,
)
2020-09-18 22:03:54 -07:00
. arg (
clap ::Arg ::with_name ( " require_tower " )
. long ( " require-tower " )
. takes_value ( false )
. help ( " Refuse to start if saved tower state is not found " ) ,
)
2019-11-04 07:11:40 -08:00
. arg (
2019-11-08 20:56:57 -08:00
Arg ::with_name ( " expected_genesis_hash " )
. long ( " expected-genesis-hash " )
2019-11-04 07:11:40 -08:00
. value_name ( " HASH " )
. takes_value ( true )
. validator ( hash_validator )
2019-11-08 20:56:57 -08:00
. help ( " Require the genesis have this hash " ) ,
2019-11-04 07:11:40 -08:00
)
2020-06-30 12:43:48 -07:00
. arg (
Arg ::with_name ( " expected_bank_hash " )
. long ( " expected-bank-hash " )
. value_name ( " HASH " )
. takes_value ( true )
. validator ( hash_validator )
. help ( " When wait-for-supermajority <x>, require the bank at <x> to have this hash " ) ,
)
2020-01-28 15:56:55 -08:00
. arg (
Arg ::with_name ( " expected_shred_version " )
. long ( " expected-shred-version " )
. value_name ( " VERSION " )
. takes_value ( true )
2020-12-17 23:01:26 -08:00
. validator ( is_parsable ::< u16 > )
2020-01-28 15:56:55 -08:00
. help ( " Require the shred version be this value " ) ,
)
2019-11-06 11:47:34 -08:00
. arg (
Arg ::with_name ( " logfile " )
. short ( " o " )
. long ( " log " )
. value_name ( " FILE " )
. takes_value ( true )
2020-04-24 14:26:53 -07:00
. help ( " Redirect logging to the specified file, '-' for standard error. \
Sending the SIGUSR1 signal to the validator process will cause it \
to re - open the log file " ),
2019-11-06 11:47:34 -08:00
)
2020-01-07 13:18:34 -08:00
. arg (
2020-01-07 13:39:41 -08:00
Arg ::with_name ( " wait_for_supermajority " )
. long ( " wait-for-supermajority " )
2020-06-30 12:43:48 -07:00
. requires ( " expected_bank_hash " )
2020-03-02 10:47:58 -08:00
. value_name ( " SLOT " )
. validator ( is_slot )
2020-09-10 13:15:22 -07:00
. help ( " After processing the ledger and the next slot is SLOT, wait until a \
supermajority of stake is visible on gossip before starting PoH " ),
2020-01-07 13:18:34 -08:00
)
2021-03-25 18:54:51 -07:00
. arg (
Arg ::with_name ( " no_wait_for_vote_to_start_leader " )
. hidden ( true )
. long ( " no-wait-for-vote-to-start-leader " )
. help ( " If the validator starts up with no ledger, it will wait to start block
production until it sees a vote land in a rooted slot . This prevents
double signing . Turn off to risk double signing a block . " ),
)
2020-01-24 17:27:04 -08:00
. arg (
Arg ::with_name ( " hard_forks " )
. long ( " hard-fork " )
. value_name ( " SLOT " )
2020-03-02 10:47:58 -08:00
. validator ( is_slot )
2020-01-24 17:27:04 -08:00
. multiple ( true )
. takes_value ( true )
. help ( " Add a hard fork at this slot " ) ,
)
2020-02-21 18:42:24 -08:00
. arg (
2021-11-12 10:57:55 -08:00
Arg ::with_name ( " known_validators " )
2021-08-17 21:17:46 -07:00
. alias ( " trusted-validator " )
. long ( " known-validator " )
2020-02-21 18:42:24 -08:00
. validator ( is_pubkey )
2021-03-06 09:29:02 -08:00
. value_name ( " VALIDATOR IDENTITY " )
2020-02-21 18:42:24 -08:00
. multiple ( true )
. takes_value ( true )
. help ( " A snapshot hash must be published in gossip by this validator to be accepted. \
May be specified multiple times . If unspecified any snapshot hash will be accepted " ),
)
2020-09-23 18:46:42 -07:00
. arg (
Arg ::with_name ( " debug_key " )
. long ( " debug-key " )
. validator ( is_pubkey )
2021-03-06 09:29:02 -08:00
. value_name ( " ADDRESS " )
2020-09-23 18:46:42 -07:00
. multiple ( true )
. takes_value ( true )
. help ( " Log when transactions are processed which reference a given key. " ) ,
)
2020-03-02 10:24:19 -08:00
. arg (
2021-11-12 19:13:59 -08:00
Arg ::with_name ( " only_known_rpc " )
2021-08-17 21:17:46 -07:00
. alias ( " no-untrusted-rpc " )
. long ( " only-known-rpc " )
2020-03-02 10:24:19 -08:00
. takes_value ( false )
2022-03-17 19:27:08 -07:00
. requires ( " known_validators " )
2021-08-17 21:17:46 -07:00
. help ( " Use the RPC service of known validators only " )
2020-03-02 10:24:19 -08:00
)
2020-08-21 00:35:11 -07:00
. arg (
Arg ::with_name ( " repair_validators " )
. long ( " repair-validator " )
. validator ( is_pubkey )
2021-03-06 09:29:02 -08:00
. value_name ( " VALIDATOR IDENTITY " )
2020-08-21 00:35:11 -07:00
. multiple ( true )
. takes_value ( true )
. help ( " A list of validators to request repairs from. If specified, repair will not \
2020-09-11 12:00:16 -07:00
request from validators outside this set [ default : all validators ] " )
)
. arg (
Arg ::with_name ( " gossip_validators " )
. long ( " gossip-validator " )
. validator ( is_pubkey )
2021-03-06 09:29:02 -08:00
. value_name ( " VALIDATOR IDENTITY " )
2020-09-11 12:00:16 -07:00
. multiple ( true )
. takes_value ( true )
. help ( " A list of validators to gossip with. If specified, gossip \
2022-04-29 12:47:04 -07:00
will not push / pull from from validators outside this set . \
2020-09-11 12:00:16 -07:00
[ default : all validators ] " )
2020-08-21 00:35:11 -07:00
)
2020-03-23 08:42:32 -07:00
. arg (
Arg ::with_name ( " no_rocksdb_compaction " )
. long ( " no-rocksdb-compaction " )
. takes_value ( false )
2021-05-28 00:42:56 -07:00
. help ( " Disable manual compaction of the ledger database (this is ignored). " )
2020-03-23 08:42:32 -07:00
)
2021-02-14 10:16:30 -08:00
. arg (
Arg ::with_name ( " rocksdb_compaction_interval " )
. long ( " rocksdb-compaction-interval-slots " )
. value_name ( " ROCKSDB_COMPACTION_INTERVAL_SLOTS " )
. takes_value ( true )
. help ( " Number of slots between compacting ledger " ) ,
)
2021-02-26 09:15:45 -08:00
. arg (
Arg ::with_name ( " tpu_coalesce_ms " )
. long ( " tpu-coalesce-ms " )
. value_name ( " MILLISECS " )
. takes_value ( true )
. validator ( is_parsable ::< u64 > )
. help ( " Milliseconds to wait in the TPU receiver for packet coalescing. " ) ,
)
2022-03-21 09:31:37 -07:00
. arg (
Arg ::with_name ( " tpu_use_quic " )
. long ( " tpu-use-quic " )
2022-03-31 10:04:24 -07:00
. takes_value ( false )
2022-04-13 11:17:10 -07:00
. help ( " Use QUIC to send transactions. " ) ,
2022-03-21 09:31:37 -07:00
)
2022-06-17 15:37:30 -07:00
. arg (
Arg ::with_name ( " enable_quic_servers " )
. hidden ( true )
. long ( " enable-quic-servers " )
)
2022-06-10 09:25:24 -07:00
. arg (
Arg ::with_name ( " tpu_connection_pool_size " )
. long ( " tpu-connection-pool-size " )
. takes_value ( true )
. default_value ( default_tpu_connection_pool_size )
. validator ( is_parsable ::< usize > )
. help ( " Controls the TPU connection pool size per remote addresss " ) ,
)
2021-02-14 10:16:30 -08:00
. arg (
Arg ::with_name ( " rocksdb_max_compaction_jitter " )
. long ( " rocksdb-max-compaction-jitter-slots " )
. value_name ( " ROCKSDB_MAX_COMPACTION_JITTER_SLOTS " )
. takes_value ( true )
. help ( " Introduce jitter into the compaction to offset compaction operation " ) ,
)
2020-03-04 21:46:43 -08:00
. arg (
2020-04-29 18:53:34 -07:00
Arg ::with_name ( " bind_address " )
2020-03-04 21:46:43 -08:00
. long ( " bind-address " )
. value_name ( " HOST " )
. takes_value ( true )
. validator ( solana_net_utils ::is_host )
. default_value ( " 0.0.0.0 " )
. help ( " IP address to bind the validator ports " ) ,
)
. arg (
2020-04-29 18:53:34 -07:00
Arg ::with_name ( " rpc_bind_address " )
2020-03-04 21:46:43 -08:00
. long ( " rpc-bind-address " )
. value_name ( " HOST " )
. takes_value ( true )
. validator ( solana_net_utils ::is_host )
2021-10-04 11:40:54 -07:00
. help ( " IP address to bind the RPC port [default: 127.0.0.1 if --private-rpc is present, otherwise use --bind-address] " ) ,
2020-03-04 21:46:43 -08:00
)
2021-01-12 17:13:47 -08:00
. arg (
Arg ::with_name ( " rpc_threads " )
. long ( " rpc-threads " )
. value_name ( " NUMBER " )
. validator ( is_parsable ::< usize > )
. takes_value ( true )
. default_value ( & default_rpc_threads )
. help ( " Number of threads to use for servicing RPC requests " ) ,
)
2021-10-26 20:13:19 -07:00
. arg (
Arg ::with_name ( " rpc_niceness_adj " )
. long ( " rpc-niceness-adjustment " )
. value_name ( " ADJUSTMENT " )
. takes_value ( true )
. validator ( is_niceness_adjustment_valid )
. default_value ( " 0 " )
. help ( " Add this value to niceness of RPC threads. Negative value \
increases priority , positive value decreases priority . " )
)
2021-01-19 05:57:16 -08:00
. arg (
Arg ::with_name ( " rpc_bigtable_timeout " )
. long ( " rpc-bigtable-timeout " )
. value_name ( " SECONDS " )
. validator ( is_parsable ::< u64 > )
. takes_value ( true )
. default_value ( " 30 " )
. help ( " Number of seconds before timing out RPC requests backed by BigTable " ) ,
)
2022-03-19 00:04:17 -07:00
. arg (
Arg ::with_name ( " rpc_bigtable_instance_name " )
. long ( " rpc-bigtable-instance-name " )
. takes_value ( true )
. value_name ( " INSTANCE_NAME " )
. default_value ( solana_storage_bigtable ::DEFAULT_INSTANCE_NAME )
. help ( " Name of the Bigtable instance to upload to " )
)
2022-06-15 17:58:16 -07:00
. arg (
Arg ::with_name ( " rpc_bigtable_app_profile_id " )
. long ( " rpc-bigtable-app-profile-id " )
. takes_value ( true )
. value_name ( " APP_PROFILE_ID " )
. default_value ( solana_storage_bigtable ::DEFAULT_APP_PROFILE_ID )
. help ( " Bigtable application profile id to use in requests " )
)
2021-10-31 23:17:24 -07:00
. arg (
Arg ::with_name ( " rpc_pubsub_worker_threads " )
. long ( " rpc-pubsub-worker-threads " )
. takes_value ( true )
. value_name ( " NUMBER " )
. validator ( is_parsable ::< usize > )
. default_value ( " 4 " )
. help ( " PubSub worker threads " ) ,
)
2021-12-17 15:03:09 -08:00
. arg (
Arg ::with_name ( " rpc_pubsub_enable_block_subscription " )
. long ( " rpc-pubsub-enable-block-subscription " )
2022-01-14 18:53:34 -08:00
. requires ( " enable_rpc_transaction_history " )
2021-12-17 15:03:09 -08:00
. takes_value ( false )
. help ( " Enable the unstable RPC PubSub `blockSubscribe` subscription " ) ,
)
2020-11-14 09:29:51 -08:00
. arg (
Arg ::with_name ( " rpc_pubsub_enable_vote_subscription " )
. long ( " rpc-pubsub-enable-vote-subscription " )
. takes_value ( false )
. help ( " Enable the unstable RPC PubSub `voteSubscribe` subscription " ) ,
)
2020-10-01 12:36:58 -07:00
. arg (
Arg ::with_name ( " rpc_pubsub_max_connections " )
. long ( " rpc-pubsub-max-connections " )
. value_name ( " NUMBER " )
. takes_value ( true )
. validator ( is_parsable ::< usize > )
2021-09-17 12:40:14 -07:00
. hidden ( true )
2020-10-01 12:36:58 -07:00
. help ( " The maximum number of connections that RPC PubSub will support. \
This is a hard limit and no new connections beyond this limit can \
2021-09-17 12:40:14 -07:00
be made until an old connection is dropped . ( Obsolete ) " ),
2020-10-01 12:36:58 -07:00
)
. arg (
Arg ::with_name ( " rpc_pubsub_max_fragment_size " )
. long ( " rpc-pubsub-max-fragment-size " )
. value_name ( " BYTES " )
. takes_value ( true )
. validator ( is_parsable ::< usize > )
2021-09-17 12:40:14 -07:00
. hidden ( true )
2020-10-01 12:36:58 -07:00
. help ( " The maximum length in bytes of acceptable incoming frames. Messages longer \
2021-09-17 12:40:14 -07:00
than this will be rejected . ( Obsolete ) " ),
2020-10-01 12:36:58 -07:00
)
. arg (
Arg ::with_name ( " rpc_pubsub_max_in_buffer_capacity " )
. long ( " rpc-pubsub-max-in-buffer-capacity " )
. value_name ( " BYTES " )
. takes_value ( true )
. validator ( is_parsable ::< usize > )
2021-09-17 12:40:14 -07:00
. hidden ( true )
. help ( " The maximum size in bytes to which the incoming websocket buffer can grow. \
( Obsolete ) " ),
2020-10-01 12:36:58 -07:00
)
. arg (
Arg ::with_name ( " rpc_pubsub_max_out_buffer_capacity " )
. long ( " rpc-pubsub-max-out-buffer-capacity " )
. value_name ( " BYTES " )
. takes_value ( true )
. validator ( is_parsable ::< usize > )
2021-09-17 12:40:14 -07:00
. hidden ( true )
. help ( " The maximum size in bytes to which the outgoing websocket buffer can grow. \
( Obsolete ) " ),
2020-10-01 12:36:58 -07:00
)
2021-06-16 21:28:23 -07:00
. arg (
Arg ::with_name ( " rpc_pubsub_max_active_subscriptions " )
. long ( " rpc-pubsub-max-active-subscriptions " )
. takes_value ( true )
. value_name ( " NUMBER " )
. validator ( is_parsable ::< usize > )
. default_value ( & default_rpc_pubsub_max_active_subscriptions )
. help ( " The maximum number of active subscriptions that RPC PubSub will accept \
across all connections . " ),
)
2021-09-17 12:40:14 -07:00
. arg (
Arg ::with_name ( " rpc_pubsub_queue_capacity_items " )
. long ( " rpc-pubsub-queue-capacity-items " )
. takes_value ( true )
. value_name ( " NUMBER " )
. validator ( is_parsable ::< usize > )
. default_value ( & default_rpc_pubsub_queue_capacity_items )
. help ( " The maximum number of notifications that RPC PubSub will store \
across all connections . " ),
)
. arg (
Arg ::with_name ( " rpc_pubsub_queue_capacity_bytes " )
. long ( " rpc-pubsub-queue-capacity-bytes " )
. takes_value ( true )
. value_name ( " BYTES " )
. validator ( is_parsable ::< usize > )
. default_value ( & default_rpc_pubsub_queue_capacity_bytes )
. help ( " The maximum total size of notifications that RPC PubSub will store \
across all connections . " ),
)
2021-10-31 23:17:24 -07:00
. arg (
Arg ::with_name ( " rpc_pubsub_notification_threads " )
. long ( " rpc-pubsub-notification-threads " )
2022-05-17 20:23:51 -07:00
. requires ( " full_rpc_api " )
2021-10-31 23:17:24 -07:00
. takes_value ( true )
. value_name ( " NUM_THREADS " )
. validator ( is_parsable ::< usize > )
. help ( " The maximum number of threads that RPC PubSub will use \
2022-05-17 20:23:51 -07:00
for generating notifications . 0 will disable RPC PubSub notifications " ),
2021-10-31 23:17:24 -07:00
)
2020-12-17 14:37:22 -08:00
. arg (
Arg ::with_name ( " rpc_send_transaction_retry_ms " )
. long ( " rpc-send-retry-ms " )
. value_name ( " MILLISECS " )
. takes_value ( true )
. validator ( is_parsable ::< u64 > )
. default_value ( & default_rpc_send_transaction_retry_ms )
. help ( " The rate at which transactions sent via rpc service are retried. " ) ,
)
2022-04-21 12:43:08 -07:00
. arg (
Arg ::with_name ( " rpc_send_transaction_batch_ms " )
. long ( " rpc-send-batch-ms " )
. value_name ( " MILLISECS " )
. hidden ( true )
. takes_value ( true )
. validator ( | s | is_within_range ( s , 1 , MAX_BATCH_SEND_RATE_MS ) )
. default_value ( & default_rpc_send_transaction_batch_ms )
. help ( " The rate at which transactions sent via rpc service are sent in batch. " ) ,
)
2020-12-17 14:37:22 -08:00
. arg (
Arg ::with_name ( " rpc_send_transaction_leader_forward_count " )
. long ( " rpc-send-leader-count " )
. value_name ( " NUMBER " )
. takes_value ( true )
. validator ( is_parsable ::< u64 > )
. default_value ( & default_rpc_send_transaction_leader_forward_count )
. help ( " The number of upcoming leaders to which to forward transactions sent via rpc service. " ) ,
)
2021-10-19 22:17:06 -07:00
. arg (
Arg ::with_name ( " rpc_send_transaction_default_max_retries " )
. long ( " rpc-send-default-max-retries " )
. value_name ( " NUMBER " )
. takes_value ( true )
. validator ( is_parsable ::< usize > )
. help ( " The maximum number of transaction broadcast retries when unspecified by the request, otherwise retried until expiration. " ) ,
)
. arg (
Arg ::with_name ( " rpc_send_transaction_service_max_retries " )
. long ( " rpc-send-service-max-retries " )
. value_name ( " NUMBER " )
. takes_value ( true )
. validator ( is_parsable ::< usize > )
. default_value ( & default_rpc_send_transaction_service_max_retries )
. help ( " The maximum number of transaction broadcast retries, regardless of requested value. " ) ,
)
2022-04-21 12:43:08 -07:00
. arg (
Arg ::with_name ( " rpc_send_transaction_batch_size " )
. long ( " rpc-send-batch-size " )
. value_name ( " NUMBER " )
. hidden ( true )
. takes_value ( true )
. validator ( | s | is_within_range ( s , 1 , MAX_TRANSACTION_BATCH_SIZE ) )
. default_value ( & default_rpc_send_transaction_batch_size )
. help ( " The size of transactions to be sent in batch. " ) ,
)
2021-05-24 12:24:47 -07:00
. arg (
Arg ::with_name ( " rpc_scan_and_fix_roots " )
. long ( " rpc-scan-and-fix-roots " )
. takes_value ( false )
. requires ( " enable_rpc_transaction_history " )
. help ( " Verifies blockstore roots on boot and fixes any gaps " ) ,
)
2021-09-01 14:10:16 -07:00
. arg (
Arg ::with_name ( " enable_accountsdb_repl " )
. long ( " enable-accountsdb-repl " )
. takes_value ( false )
. hidden ( true )
. help ( " Enable AccountsDb Replication " ) ,
)
. arg (
Arg ::with_name ( " accountsdb_repl_bind_address " )
. long ( " accountsdb-repl-bind-address " )
. value_name ( " HOST " )
. takes_value ( true )
. validator ( solana_net_utils ::is_host )
. hidden ( true )
. help ( " IP address to bind the AccountsDb Replication port [default: use --bind-address] " ) ,
)
. arg (
Arg ::with_name ( " accountsdb_repl_port " )
. long ( " accountsdb-repl-port " )
. value_name ( " PORT " )
. takes_value ( true )
. validator ( solana_validator ::port_validator )
. hidden ( true )
. help ( " Enable AccountsDb Replication Service on this port " ) ,
)
. arg (
Arg ::with_name ( " accountsdb_repl_threads " )
. long ( " accountsdb-repl-threads " )
. value_name ( " NUMBER " )
. validator ( is_parsable ::< usize > )
. takes_value ( true )
. default_value ( & default_accountsdb_repl_threads )
. hidden ( true )
. help ( " Number of threads to use for servicing AccountsDb Replication requests " ) ,
)
2021-09-30 14:26:17 -07:00
. arg (
2022-03-14 18:18:46 -07:00
Arg ::with_name ( " geyser_plugin_config " )
. long ( " geyser-plugin-config " )
. alias ( " accountsdb-plugin-config " )
2021-09-30 14:26:17 -07:00
. value_name ( " FILE " )
. takes_value ( true )
2021-10-08 20:06:58 -07:00
. multiple ( true )
2022-03-14 18:18:46 -07:00
. help ( " Specify the configuration file for the Geyser plugin. " ) ,
2021-09-30 14:26:17 -07:00
)
2020-03-16 08:37:31 -07:00
. arg (
2021-11-12 10:57:55 -08:00
Arg ::with_name ( " halt_on_known_validators_accounts_hash_mismatch " )
2021-08-17 21:17:46 -07:00
. alias ( " halt-on-trusted-validators-accounts-hash-mismatch " )
. long ( " halt-on-known-validators-accounts-hash-mismatch " )
2021-11-12 10:57:55 -08:00
. requires ( " known_validators " )
2020-03-16 08:37:31 -07:00
. takes_value ( false )
2021-08-17 21:17:46 -07:00
. help ( " Abort the validator if a bank hash mismatch is detected within known validator set " ) ,
2020-03-16 08:37:31 -07:00
)
2020-04-03 13:13:49 -07:00
. arg (
2021-01-07 22:45:42 -08:00
Arg ::with_name ( " snapshot_archive_format " )
. long ( " snapshot-archive-format " )
. alias ( " snapshot-compression " ) // Legacy name used by Solana v1.5.x and older
2022-05-16 10:44:15 -07:00
. possible_values ( SUPPORTED_ARCHIVE_COMPRESSION )
. default_value ( DEFAULT_ARCHIVE_COMPRESSION )
2021-01-07 22:45:42 -08:00
. value_name ( " ARCHIVE_TYPE " )
2020-04-03 13:13:49 -07:00
. takes_value ( true )
2021-01-07 22:45:42 -08:00
. help ( " Snapshot archive format to use. " ) ,
2020-04-03 13:13:49 -07:00
)
2020-04-29 18:53:34 -07:00
. arg (
Arg ::with_name ( " max_genesis_archive_unpacked_size " )
. long ( " max-genesis-archive-unpacked-size " )
. value_name ( " NUMBER " )
. takes_value ( true )
2021-06-18 06:34:46 -07:00
. default_value ( default_genesis_archive_unpacked_size )
2020-04-29 18:53:34 -07:00
. help (
" maximum total uncompressed file size of downloaded genesis archive " ,
) ,
)
2020-07-06 12:43:45 -07:00
. arg (
Arg ::with_name ( " wal_recovery_mode " )
. long ( " wal-recovery-mode " )
. value_name ( " MODE " )
. takes_value ( true )
. possible_values ( & [
" tolerate_corrupted_tail_records " ,
" absolute_consistency " ,
" point_in_time " ,
" skip_any_corrupted_record " ] )
. help (
" Mode to recovery the ledger db write ahead log. "
) ,
)
2020-12-07 00:49:55 -08:00
. arg (
2021-03-09 16:23:08 -08:00
Arg ::with_name ( " no_bpf_jit " )
. long ( " no-bpf-jit " )
. takes_value ( false )
. help ( " Disable the just-in-time compiler and instead use the interpreter for BPF " ) ,
)
. arg (
// legacy nop argument
2020-12-07 00:49:55 -08:00
Arg ::with_name ( " bpf_jit " )
. long ( " bpf-jit " )
2021-03-09 16:23:08 -08:00
. hidden ( true )
2020-12-07 00:49:55 -08:00
. takes_value ( false )
2021-03-09 16:23:08 -08:00
. conflicts_with ( " no_bpf_jit " )
2020-12-07 00:49:55 -08:00
)
2020-12-29 11:09:47 -08:00
. arg (
Arg ::with_name ( " poh_pinned_cpu_core " )
. hidden ( true )
. long ( " experimental-poh-pinned-cpu-core " )
. takes_value ( true )
. value_name ( " CPU_CORE_INDEX " )
. validator ( | s | {
let core_index = usize ::from_str ( & s ) . map_err ( | e | e . to_string ( ) ) ? ;
let max_index = core_affinity ::get_core_ids ( ) . map ( | cids | cids . len ( ) - 1 ) . unwrap_or ( 0 ) ;
if core_index > max_index {
return Err ( format! ( " core index must be in the range [0, {} ] " , max_index ) ) ;
}
Ok ( ( ) )
} )
2020-12-31 18:06:03 -08:00
. help ( " EXPERIMENTAL: Specify which CPU core PoH is pinned to " ) ,
)
2021-03-05 16:01:21 -08:00
. arg (
Arg ::with_name ( " poh_hashes_per_batch " )
. hidden ( true )
. long ( " poh-hashes-per-batch " )
. takes_value ( true )
. value_name ( " NUM " )
. help ( " Specify hashes per batch in PoH service " ) ,
)
2020-12-31 18:06:03 -08:00
. arg (
Arg ::with_name ( " account_indexes " )
. long ( " account-index " )
. takes_value ( true )
. multiple ( true )
. possible_values ( & [ " program-id " , " spl-token-owner " , " spl-token-mint " ] )
. value_name ( " INDEX " )
. help ( " Enable an accounts index, indexed by the selected account field " ) ,
2020-12-29 11:09:47 -08:00
)
2021-05-11 15:06:22 -07:00
. arg (
Arg ::with_name ( " account_index_exclude_key " )
. long ( EXCLUDE_KEY )
. takes_value ( true )
. validator ( is_pubkey )
. multiple ( true )
. value_name ( " KEY " )
. help ( " When account indexes are enabled, exclude this key from the index. " ) ,
)
. arg (
Arg ::with_name ( " account_index_include_key " )
. long ( INCLUDE_KEY )
. takes_value ( true )
. validator ( is_pubkey )
. conflicts_with ( " account_index_exclude_key " )
. multiple ( true )
. value_name ( " KEY " )
. help ( " When account indexes are enabled, only include specific keys in the index. This overrides --account-index-exclude-key. " ) ,
)
2021-01-11 17:00:23 -08:00
. arg (
2021-01-26 12:06:39 -08:00
Arg ::with_name ( " no_accounts_db_caching " )
. long ( " no-accounts-db-caching " )
. help ( " Disables accounts caching " ) ,
)
2021-08-04 15:28:33 -07:00
. arg (
Arg ::with_name ( " accounts_db_skip_shrink " )
. long ( " accounts-db-skip-shrink " )
. help ( " Enables faster starting of validators by skipping shrink. \
This option is for use during testing . " ),
)
2022-04-20 07:41:00 -07:00
. arg (
Arg ::with_name ( " accounts_db_skip_rewrites " )
. long ( " accounts-db-skip-rewrites " )
. help ( " Accounts that are rent exempt and have no changes are not rewritten. \
This produces snapshots that older versions cannot read . " )
. hidden ( true ) ,
)
2022-05-11 06:47:07 -07:00
. arg (
Arg ::with_name ( " accounts_db_ancient_append_vecs " )
. long ( " accounts-db-ancient-append-vecs " )
. help ( " AppendVecs that are older than an epoch are squashed together. " )
. hidden ( true ) ,
)
2021-12-01 11:10:48 -08:00
. arg (
Arg ::with_name ( " accounts_db_cache_limit_mb " )
. long ( " accounts-db-cache-limit-mb " )
. value_name ( " MEGABYTES " )
. validator ( is_parsable ::< u64 > )
. takes_value ( true )
. help ( " How large the write cache for account data can become. If this is exceeded, the cache is flushed more aggressively. " ) ,
)
2021-11-19 07:00:19 -08:00
. arg (
Arg ::with_name ( " accounts_index_scan_results_limit_mb " )
. long ( " accounts-index-scan-results-limit-mb " )
. value_name ( " MEGABYTES " )
. validator ( is_parsable ::< usize > )
. takes_value ( true )
. help ( " How large accumulated results from an accounts index scan can become. If this is exceeded, the scan aborts. " ) ,
)
2021-09-19 16:00:15 -07:00
. arg (
Arg ::with_name ( " accounts_index_memory_limit_mb " )
. long ( " accounts-index-memory-limit-mb " )
. value_name ( " MEGABYTES " )
. validator ( is_parsable ::< usize > )
. takes_value ( true )
. help ( " How much memory the accounts index can consume. If this is exceeded, some account index entries will be stored on disk. If missing, the entire index is stored in memory. " ) ,
)
2022-02-23 16:07:24 -08:00
. arg (
Arg ::with_name ( " disable_accounts_disk_index " )
. long ( " disable-accounts-disk-index " )
. help ( " Disable the disk-based accounts index if it is enabled by default. " )
. conflicts_with ( " accounts_index_memory_limit_mb " )
)
2021-08-11 09:45:25 -07:00
. arg (
Arg ::with_name ( " accounts_index_bins " )
. long ( " accounts-index-bins " )
. value_name ( " BINS " )
2021-10-25 07:45:46 -07:00
. validator ( is_pow2 )
2021-08-11 09:45:25 -07:00
. takes_value ( true )
. help ( " Number of bins to divide the accounts index into " ) ,
)
2021-10-25 07:45:46 -07:00
. arg (
Arg ::with_name ( " accounts_hash_num_passes " )
. long ( " accounts-hash-num-passes " )
. value_name ( " PASSES " )
. validator ( is_pow2 )
. takes_value ( true )
. help ( " Number of passes to calculate the hash of all accounts " ) ,
)
2021-09-28 09:07:47 -07:00
. arg (
Arg ::with_name ( " accounts_index_path " )
. long ( " accounts-index-path " )
. value_name ( " PATH " )
. takes_value ( true )
. multiple ( true )
. help ( " Persistent accounts-index location. \
May be specified multiple times . \
[ default : [ ledger ] / accounts_index ] " ),
2021-10-11 10:46:27 -07:00
)
. arg ( Arg ::with_name ( " accounts_filler_count " )
. long ( " accounts-filler-count " )
. value_name ( " COUNT " )
. validator ( is_parsable ::< usize > )
. takes_value ( true )
2022-04-11 11:10:09 -07:00
. default_value ( " 0 " )
2021-10-11 10:46:27 -07:00
. help ( " How many accounts to add to stress the system. Accounts are ignored in operations related to correctness. " ) )
2022-04-11 11:10:09 -07:00
. arg ( Arg ::with_name ( " accounts_filler_size " )
. long ( " accounts-filler-size " )
. value_name ( " BYTES " )
. validator ( is_parsable ::< usize > )
. takes_value ( true )
. default_value ( " 0 " )
. requires ( " accounts_filler_count " )
. help ( " Size per filler account in bytes. " ) )
2021-10-11 10:46:27 -07:00
. arg (
2021-02-04 07:00:33 -08:00
Arg ::with_name ( " accounts_db_test_hash_calculation " )
. long ( " accounts-db-test-hash-calculation " )
2021-04-11 20:36:27 -07:00
. help ( " Enables testing of hash calculation using stores in \
AccountsHashVerifier . This has a computational cost . " ),
2021-02-04 07:00:33 -08:00
)
2021-03-03 16:12:18 -08:00
. arg (
Arg ::with_name ( " accounts_db_index_hashing " )
. long ( " accounts-db-index-hashing " )
2021-04-11 20:36:27 -07:00
. help ( " Enables the use of the index in hash calculation in \
2022-03-25 13:32:53 -07:00
AccountsHashVerifier / Accounts Background Service . " )
. hidden ( true ) ,
2021-03-03 16:12:18 -08:00
)
2021-02-16 13:13:48 -08:00
. arg (
Arg ::with_name ( " no_accounts_db_index_hashing " )
. long ( " no-accounts-db-index-hashing " )
2021-04-11 20:36:27 -07:00
. help ( " This is obsolete. See --accounts-db-index-hashing. \
Disables the use of the index in hash calculation in \
2022-03-25 13:32:53 -07:00
AccountsHashVerifier / Accounts Background Service . " )
. hidden ( true ) ,
2021-02-16 13:13:48 -08:00
)
2021-01-26 12:06:39 -08:00
. arg (
// legacy nop argument
2021-01-11 17:00:23 -08:00
Arg ::with_name ( " accounts_db_caching_enabled " )
. long ( " accounts-db-caching-enabled " )
2021-01-26 12:06:39 -08:00
. conflicts_with ( " no_accounts_db_caching " )
. hidden ( true )
2021-01-11 17:00:23 -08:00
)
2021-06-09 21:21:32 -07:00
. arg (
Arg ::with_name ( " accounts_shrink_optimize_total_space " )
. long ( " accounts-shrink-optimize-total-space " )
. takes_value ( true )
. value_name ( " BOOLEAN " )
. default_value ( default_accounts_shrink_optimize_total_space )
. help ( " When this is set to true, the system will shrink the most \
sparse accounts and when the overall shrink ratio is above \
the specified accounts - shrink - ratio , the shrink will stop and \
it will skip all other less sparse accounts . " ),
)
. arg (
Arg ::with_name ( " accounts_shrink_ratio " )
. long ( " accounts-shrink-ratio " )
. takes_value ( true )
. value_name ( " RATIO " )
. default_value ( default_accounts_shrink_ratio )
. help ( " Specifies the shrink ratio for the accounts to be shrunk. \
The shrink ratio is defined as the ratio of the bytes alive over the \
total bytes used . If the account ' s shrink ratio is less than this ratio \
it becomes a candidate for shrinking . The value must between 0. and 1.0 \
inclusive . " ),
)
2021-02-03 08:26:17 -08:00
. arg (
Arg ::with_name ( " no_duplicate_instance_check " )
. long ( " no-duplicate-instance-check " )
. takes_value ( false )
. help ( " Disables duplicate instance check " )
. hidden ( true ) ,
)
2021-07-23 08:25:03 -07:00
. arg (
Arg ::with_name ( " allow_private_addr " )
. long ( " allow-private-addr " )
. takes_value ( false )
. help ( " Allow contacting private ip addresses " )
. hidden ( true ) ,
)
2021-01-29 18:01:27 -08:00
. after_help ( " The default subcommand is run " )
2021-02-26 21:42:09 -08:00
. subcommand (
2021-04-11 20:36:27 -07:00
SubCommand ::with_name ( " exit " )
. about ( " Send an exit request to the validator " )
. arg (
Arg ::with_name ( " force " )
. short ( " f " )
. long ( " force " )
. takes_value ( false )
. help ( " Request the validator exit immediately instead of waiting for a restart window " )
)
. arg (
Arg ::with_name ( " monitor " )
. short ( " m " )
. long ( " monitor " )
. takes_value ( false )
. help ( " Monitor the validator after sending the exit request " )
)
. arg (
Arg ::with_name ( " min_idle_time " )
. long ( " min-idle-time " )
2022-02-15 08:55:47 -08:00
. takes_value ( true )
2021-04-11 20:36:27 -07:00
. validator ( is_parsable ::< usize > )
2021-07-14 18:24:43 -07:00
. value_name ( " MINUTES " )
2021-04-11 20:36:27 -07:00
. default_value ( " 10 " )
. help ( " Minimum time that the validator should not be leader before restarting " )
)
2021-10-01 12:52:28 -07:00
. arg (
Arg ::with_name ( " max_delinquent_stake " )
. long ( " max-delinquent-stake " )
. takes_value ( true )
. validator ( is_valid_percentage )
. default_value ( " 5 " )
. value_name ( " PERCENT " )
. help ( " The maximum delinquent stake % permitted for an exit " )
)
2022-02-15 13:42:23 -08:00
. arg (
Arg ::with_name ( " skip_new_snapshot_check " )
. long ( " skip-new-snapshot-check " )
. help ( " Skip check for a new snapshot " )
)
2021-04-11 20:36:27 -07:00
)
2021-04-11 20:38:30 -07:00
. subcommand (
SubCommand ::with_name ( " authorized-voter " )
. about ( " Adjust the validator authorized voters " )
. setting ( AppSettings ::SubcommandRequiredElseHelp )
. setting ( AppSettings ::InferSubcommands )
. subcommand (
SubCommand ::with_name ( " add " )
. about ( " Add an authorized voter " )
. arg (
Arg ::with_name ( " authorized_voter_keypair " )
. index ( 1 )
. value_name ( " KEYPAIR " )
2022-06-24 09:21:03 -07:00
. required ( false )
2021-04-11 20:38:30 -07:00
. takes_value ( true )
. validator ( is_keypair )
2022-06-24 09:21:03 -07:00
. help ( " Path to keypair of the authorized voter to add \
[ default : read JSON keypair from stdin ] " ),
2021-04-11 20:38:30 -07:00
)
. after_help ( " Note: the new authorized voter only applies to the \
currently running validator instance " )
)
. subcommand (
SubCommand ::with_name ( " remove-all " )
. about ( " Remove all authorized voters " )
. after_help ( " Note: the removal only applies to the \
currently running validator instance " )
)
)
2021-12-22 23:56:16 -08:00
. subcommand (
SubCommand ::with_name ( " contact-info " )
. about ( " Display the validator's contact info " )
. arg (
Arg ::with_name ( " output " )
. long ( " output " )
. takes_value ( true )
. value_name ( " MODE " )
. possible_values ( & [ " json " , " json-compact " ] )
. help ( " Output display mode " )
)
)
2021-01-29 18:01:27 -08:00
. subcommand (
2021-04-11 20:36:27 -07:00
SubCommand ::with_name ( " init " )
. about ( " Initialize the ledger directory then exit " )
)
2021-02-26 21:42:09 -08:00
. subcommand (
2021-04-11 20:36:27 -07:00
SubCommand ::with_name ( " monitor " )
. about ( " Monitor the validator " )
)
2021-01-29 18:01:27 -08:00
. subcommand (
2021-04-11 20:36:27 -07:00
SubCommand ::with_name ( " run " )
. about ( " Run the validator " )
)
2021-06-17 13:51:06 -07:00
. subcommand (
SubCommand ::with_name ( " set-identity " )
. about ( " Set the validator identity " )
. arg (
Arg ::with_name ( " identity " )
. index ( 1 )
. value_name ( " KEYPAIR " )
2022-06-24 09:21:03 -07:00
. required ( false )
2021-06-17 13:51:06 -07:00
. takes_value ( true )
. validator ( is_keypair )
2022-06-24 09:21:03 -07:00
. help ( " Path to validator identity keypair \
[ default : read JSON keypair from stdin ] " )
2021-06-17 13:51:06 -07:00
)
2022-02-14 10:27:11 -08:00
. arg (
clap ::Arg ::with_name ( " require_tower " )
. long ( " require-tower " )
. takes_value ( false )
. help ( " Refuse to set the validator identity if saved tower state is not found " ) ,
)
2021-06-17 13:51:06 -07:00
. after_help ( " Note: the new identity only applies to the \
currently running validator instance " )
)
2021-02-05 22:39:23 -08:00
. subcommand (
2021-04-11 20:36:27 -07:00
SubCommand ::with_name ( " set-log-filter " )
. about ( " Adjust the validator log filter " )
. arg (
Arg ::with_name ( " filter " )
. takes_value ( true )
. index ( 1 )
. help ( " New filter using the same format as the RUST_LOG environment variable " )
)
. after_help ( " Note: the new filter only applies to the currently running validator instance " )
)
2021-02-19 11:31:16 -08:00
. subcommand (
2021-04-11 20:36:27 -07:00
SubCommand ::with_name ( " wait-for-restart-window " )
. about ( " Monitor the validator for a good time to restart " )
. arg (
Arg ::with_name ( " min_idle_time " )
2022-02-15 08:55:47 -08:00
. long ( " min-idle-time " )
2021-04-11 20:36:27 -07:00
. takes_value ( true )
. validator ( is_parsable ::< usize > )
. value_name ( " MINUTES " )
. default_value ( " 10 " )
. help ( " Minimum time that the validator should not be leader before restarting " )
)
2021-07-14 18:24:43 -07:00
. arg (
Arg ::with_name ( " identity " )
. long ( " identity " )
. value_name ( " ADDRESS " )
. takes_value ( true )
. validator ( is_pubkey_or_keypair )
. help ( " Validator identity to monitor [default: your validator] " )
)
2021-10-01 12:52:28 -07:00
. arg (
Arg ::with_name ( " max_delinquent_stake " )
. long ( " max-delinquent-stake " )
. takes_value ( true )
. validator ( is_valid_percentage )
. default_value ( " 5 " )
. value_name ( " PERCENT " )
. help ( " The maximum delinquent stake % permitted for a restart " )
)
2022-02-15 13:42:23 -08:00
. arg (
Arg ::with_name ( " skip_new_snapshot_check " )
. long ( " skip-new-snapshot-check " )
. help ( " Skip check for a new snapshot " )
)
2021-04-11 20:36:27 -07:00
. after_help ( " Note: If this command exits with a non-zero status \
then this not a good time for a restart " )
)
2019-11-04 07:11:40 -08:00
. get_matches ( ) ;
2021-07-23 08:25:03 -07:00
let socket_addr_space = SocketAddrSpace ::new ( matches . is_present ( " allow_private_addr " ) ) ;
2021-03-06 09:29:02 -08:00
let ledger_path = PathBuf ::from ( matches . value_of ( " ledger_path " ) . unwrap ( ) ) ;
2021-02-19 11:31:16 -08:00
let operation = match matches . subcommand ( ) {
( " " , _ ) | ( " run " , _ ) = > Operation ::Run ,
2021-04-11 20:38:30 -07:00
( " authorized-voter " , Some ( authorized_voter_subcommand_matches ) ) = > {
match authorized_voter_subcommand_matches . subcommand ( ) {
( " add " , Some ( subcommand_matches ) ) = > {
2022-06-24 09:21:03 -07:00
if let Some ( authorized_voter_keypair ) =
value_t! ( subcommand_matches , " authorized_voter_keypair " , String ) . ok ( )
{
let authorized_voter_keypair = fs ::canonicalize ( & authorized_voter_keypair )
. unwrap_or_else ( | err | {
println! (
" Unable to access path: {}: {:?} " ,
authorized_voter_keypair , err
) ;
exit ( 1 ) ;
} ) ;
println! (
" Adding authorized voter path: {} " ,
authorized_voter_keypair . display ( )
) ;
2021-04-12 16:33:14 -07:00
2022-06-24 09:21:03 -07:00
let admin_client = admin_rpc_service ::connect ( & ledger_path ) ;
admin_rpc_service ::runtime ( )
. block_on ( async move {
admin_client
. await ?
. add_authorized_voter (
authorized_voter_keypair . display ( ) . to_string ( ) ,
)
. await
} )
. unwrap_or_else ( | err | {
println! ( " addAuthorizedVoter request failed: {} " , err ) ;
exit ( 1 ) ;
} ) ;
} else {
let mut stdin = std ::io ::stdin ( ) ;
let authorized_voter_keypair =
read_keypair ( & mut stdin ) . unwrap_or_else ( | err | {
println! ( " Unable to read JSON keypair from stdin: {:?} " , err ) ;
exit ( 1 ) ;
} ) ;
println! (
" Adding authorized voter: {} " ,
authorized_voter_keypair . pubkey ( )
) ;
let admin_client = admin_rpc_service ::connect ( & ledger_path ) ;
admin_rpc_service ::runtime ( )
. block_on ( async move {
admin_client
. await ?
. add_authorized_voter_from_bytes ( Vec ::from (
authorized_voter_keypair . to_bytes ( ) ,
) )
. await
} )
. unwrap_or_else ( | err | {
println! ( " addAuthorizedVoterFromBytes request failed: {} " , err ) ;
exit ( 1 ) ;
} ) ;
}
2021-04-11 20:38:30 -07:00
return ;
}
( " remove-all " , _ ) = > {
let admin_client = admin_rpc_service ::connect ( & ledger_path ) ;
admin_rpc_service ::runtime ( )
. block_on ( async move {
admin_client . await ? . remove_all_authorized_voters ( ) . await
} )
. unwrap_or_else ( | err | {
println! ( " removeAllAuthorizedVoters request failed: {} " , err ) ;
exit ( 1 ) ;
} ) ;
println! ( " All authorized voters removed " ) ;
return ;
}
_ = > unreachable! ( ) ,
}
}
2021-12-22 23:56:16 -08:00
( " contact-info " , Some ( subcommand_matches ) ) = > {
let output_mode = subcommand_matches . value_of ( " output " ) ;
let admin_client = admin_rpc_service ::connect ( & ledger_path ) ;
let contact_info = admin_rpc_service ::runtime ( )
. block_on ( async move { admin_client . await ? . contact_info ( ) . await } )
. unwrap_or_else ( | err | {
eprintln! ( " Contact info query failed: {} " , err ) ;
exit ( 1 ) ;
} ) ;
if let Some ( mode ) = output_mode {
match mode {
" json " = > println! ( " {} " , serde_json ::to_string_pretty ( & contact_info ) . unwrap ( ) ) ,
" json-compact " = > print! ( " {} " , serde_json ::to_string ( & contact_info ) . unwrap ( ) ) ,
_ = > unreachable! ( ) ,
}
} else {
print! ( " {} " , contact_info ) ;
}
return ;
}
2021-02-19 11:31:16 -08:00
( " init " , _ ) = > Operation ::Initialize ,
2021-03-10 15:28:42 -08:00
( " exit " , Some ( subcommand_matches ) ) = > {
let min_idle_time = value_t_or_exit! ( subcommand_matches , " min_idle_time " , usize ) ;
let force = subcommand_matches . is_present ( " force " ) ;
let monitor = subcommand_matches . is_present ( " monitor " ) ;
2022-02-15 13:42:23 -08:00
let skip_new_snapshot_check = subcommand_matches . is_present ( " skip_new_snapshot_check " ) ;
2021-10-01 12:52:28 -07:00
let max_delinquent_stake =
value_t_or_exit! ( subcommand_matches , " max_delinquent_stake " , u8 ) ;
2021-03-10 15:28:42 -08:00
if ! force {
2022-02-15 13:42:23 -08:00
wait_for_restart_window (
& ledger_path ,
None ,
min_idle_time ,
max_delinquent_stake ,
skip_new_snapshot_check ,
)
. unwrap_or_else ( | err | {
println! ( " {} " , err ) ;
exit ( 1 ) ;
} ) ;
2021-03-10 15:28:42 -08:00
}
2021-03-06 09:29:02 -08:00
let admin_client = admin_rpc_service ::connect ( & ledger_path ) ;
admin_rpc_service ::runtime ( )
. block_on ( async move { admin_client . await ? . exit ( ) . await } )
. unwrap_or_else ( | err | {
println! ( " exit request failed: {} " , err ) ;
exit ( 1 ) ;
} ) ;
2021-03-10 15:28:42 -08:00
println! ( " Exit request sent " ) ;
if monitor {
monitor_validator ( & ledger_path ) ;
}
2021-03-06 09:29:02 -08:00
return ;
}
( " monitor " , _ ) = > {
2021-03-10 15:28:42 -08:00
monitor_validator ( & ledger_path ) ;
2021-03-06 09:29:02 -08:00
return ;
}
2021-06-17 13:51:06 -07:00
( " set-identity " , Some ( subcommand_matches ) ) = > {
2022-02-14 10:27:11 -08:00
let require_tower = subcommand_matches . is_present ( " require_tower " ) ;
2021-06-17 13:51:06 -07:00
2022-06-24 09:21:03 -07:00
if let Some ( identity_keypair ) = value_t! ( subcommand_matches , " identity " , String ) . ok ( ) {
let identity_keypair = fs ::canonicalize ( & identity_keypair ) . unwrap_or_else ( | err | {
println! ( " Unable to access path: {} : {:?} " , identity_keypair , err ) ;
exit ( 1 ) ;
} ) ;
println! (
" New validator identity path: {} " ,
identity_keypair . display ( )
) ;
2021-06-17 13:51:06 -07:00
2022-06-24 09:21:03 -07:00
let admin_client = admin_rpc_service ::connect ( & ledger_path ) ;
admin_rpc_service ::runtime ( )
. block_on ( async move {
admin_client
. await ?
. set_identity ( identity_keypair . display ( ) . to_string ( ) , require_tower )
. await
} )
. unwrap_or_else ( | err | {
println! ( " setIdentity request failed: {} " , err ) ;
exit ( 1 ) ;
} ) ;
} else {
let mut stdin = std ::io ::stdin ( ) ;
let identity_keypair = read_keypair ( & mut stdin ) . unwrap_or_else ( | err | {
println! ( " Unable to read JSON keypair from stdin: {:?} " , err ) ;
2021-06-17 13:51:06 -07:00
exit ( 1 ) ;
} ) ;
2022-06-24 09:21:03 -07:00
println! ( " New validator identity: {} " , identity_keypair . pubkey ( ) ) ;
let admin_client = admin_rpc_service ::connect ( & ledger_path ) ;
admin_rpc_service ::runtime ( )
. block_on ( async move {
admin_client
. await ?
. set_identity_from_bytes (
Vec ::from ( identity_keypair . to_bytes ( ) ) ,
require_tower ,
)
. await
} )
. unwrap_or_else ( | err | {
println! ( " setIdentityFromBytes request failed: {} " , err ) ;
exit ( 1 ) ;
} ) ;
} ;
2021-06-17 13:51:06 -07:00
return ;
}
2021-03-06 09:29:02 -08:00
( " set-log-filter " , Some ( subcommand_matches ) ) = > {
let filter = value_t_or_exit! ( subcommand_matches , " filter " , String ) ;
let admin_client = admin_rpc_service ::connect ( & ledger_path ) ;
admin_rpc_service ::runtime ( )
. block_on ( async move { admin_client . await ? . set_log_filter ( filter ) . await } )
. unwrap_or_else ( | err | {
println! ( " set log filter failed: {} " , err ) ;
exit ( 1 ) ;
} ) ;
return ;
}
( " wait-for-restart-window " , Some ( subcommand_matches ) ) = > {
2021-03-10 15:28:42 -08:00
let min_idle_time = value_t_or_exit! ( subcommand_matches , " min_idle_time " , usize ) ;
2021-07-14 18:24:43 -07:00
let identity = pubkey_of ( subcommand_matches , " identity " ) ;
2021-10-01 12:52:28 -07:00
let max_delinquent_stake =
value_t_or_exit! ( subcommand_matches , " max_delinquent_stake " , u8 ) ;
2022-02-15 13:42:23 -08:00
let skip_new_snapshot_check = subcommand_matches . is_present ( " skip_new_snapshot_check " ) ;
2021-10-01 12:52:28 -07:00
2022-02-15 13:42:23 -08:00
wait_for_restart_window (
& ledger_path ,
identity ,
min_idle_time ,
max_delinquent_stake ,
skip_new_snapshot_check ,
)
. unwrap_or_else ( | err | {
println! ( " {} " , err ) ;
exit ( 1 ) ;
} ) ;
2021-03-06 09:29:02 -08:00
return ;
}
2021-01-29 18:01:27 -08:00
_ = > unreachable! ( ) ,
} ;
2021-06-17 13:51:06 -07:00
let identity_keypair = keypair_of ( & matches , " identity " ) . unwrap_or_else ( | | {
2021-03-06 09:29:02 -08:00
clap ::Error ::with_description (
" The --identity <KEYPAIR> argument is required " ,
clap ::ErrorKind ::ArgumentNotFound ,
)
. exit ( ) ;
2021-06-17 13:51:06 -07:00
} ) ;
2020-03-06 21:22:23 -08:00
2021-07-28 00:54:54 -07:00
let logfile = {
let logfile = matches
. value_of ( " logfile " )
. map ( | s | s . into ( ) )
. unwrap_or_else ( | | format! ( " solana-validator- {} .log " , identity_keypair . pubkey ( ) ) ) ;
if logfile = = " - " {
None
} else {
println! ( " log file: {} " , logfile ) ;
Some ( logfile )
}
} ;
let use_progress_bar = logfile . is_none ( ) ;
let _logger_thread = redirect_stderr_to_file ( logfile ) ;
info! ( " {} {} " , crate_name! ( ) , solana_version ::version! ( ) ) ;
info! ( " Starting validator with: {:#?} " , std ::env ::args_os ( ) ) ;
2021-07-28 00:55:27 -07:00
let cuda = matches . is_present ( " cuda " ) ;
if cuda {
solana_perf ::perf_libs ::init_cuda ( ) ;
enable_recycler_warming ( ) ;
}
solana_core ::validator ::report_target_features ( ) ;
2020-03-31 08:23:42 -07:00
let authorized_voter_keypairs = keypairs_of ( & matches , " authorized_voter_keypairs " )
. map ( | keypairs | keypairs . into_iter ( ) . map ( Arc ::new ) . collect ( ) )
2021-06-17 13:51:06 -07:00
. unwrap_or_else ( | | {
vec! [ Arc ::new (
keypair_of ( & matches , " identity " ) . expect ( " identity " ) ,
) ]
} ) ;
2021-04-11 20:38:30 -07:00
let authorized_voter_keypairs = Arc ::new ( RwLock ::new ( authorized_voter_keypairs ) ) ;
2020-03-06 21:22:23 -08:00
2019-11-06 10:34:31 -08:00
let init_complete_file = matches . value_of ( " init_complete_file " ) ;
2020-09-18 14:35:20 -07:00
2022-02-14 22:50:17 -08:00
if matches . is_present ( " no_check_vote_account " ) {
info! ( " vote account sanity checks are no longer performed by default. --no-check-vote-account is deprecated and can be removed from the command line " ) ;
}
2021-10-03 11:13:16 -07:00
let rpc_bootstrap_config = bootstrap ::RpcBootstrapConfig {
2020-09-18 14:35:20 -07:00
no_genesis_fetch : matches . is_present ( " no_genesis_fetch " ) ,
no_snapshot_fetch : matches . is_present ( " no_snapshot_fetch " ) ,
2022-02-14 22:50:17 -08:00
check_vote_account : matches
. value_of ( " check_vote_account " )
. map ( | url | url . to_string ( ) ) ,
2021-11-12 19:13:59 -08:00
only_known_rpc : matches . is_present ( " only_known_rpc " ) ,
2020-09-18 14:35:20 -07:00
max_genesis_archive_unpacked_size : value_t_or_exit ! (
matches ,
" max_genesis_archive_unpacked_size " ,
u64
) ,
2022-02-09 11:26:35 -08:00
incremental_snapshot_fetch : ! matches . is_present ( " no_incremental_snapshots " ) ,
2020-09-18 14:35:20 -07:00
} ;
2020-01-30 09:17:01 -08:00
let private_rpc = matches . is_present ( " private_rpc " ) ;
2021-10-19 14:35:42 -07:00
let do_port_check = ! matches . is_present ( " no_port_check " ) ;
2021-05-28 00:42:56 -07:00
let no_rocksdb_compaction = true ;
2021-02-14 10:16:30 -08:00
let rocksdb_compaction_interval = value_t! ( matches , " rocksdb_compaction_interval " , u64 ) . ok ( ) ;
let rocksdb_max_compaction_jitter =
value_t! ( matches , " rocksdb_max_compaction_jitter " , u64 ) . ok ( ) ;
2021-02-26 09:15:45 -08:00
let tpu_coalesce_ms =
value_t! ( matches , " tpu_coalesce_ms " , u64 ) . unwrap_or ( DEFAULT_TPU_COALESCE_MS ) ;
2020-07-06 12:43:45 -07:00
let wal_recovery_mode = matches
. value_of ( " wal_recovery_mode " )
. map ( BlockstoreRecoveryMode ::from ) ;
2019-11-04 07:11:40 -08:00
2019-12-05 11:58:02 -08:00
// Canonicalize ledger path to avoid issues with symlink creation
2020-01-20 07:58:03 -08:00
let _ = fs ::create_dir_all ( & ledger_path ) ;
2019-12-05 11:58:02 -08:00
let ledger_path = fs ::canonicalize ( & ledger_path ) . unwrap_or_else ( | err | {
eprintln! ( " Unable to access ledger path: {:?} " , err ) ;
exit ( 1 ) ;
} ) ;
2020-09-23 18:46:42 -07:00
let debug_keys : Option < Arc < HashSet < _ > > > = if matches . is_present ( " debug_key " ) {
Some ( Arc ::new (
values_t_or_exit! ( matches , " debug_key " , Pubkey )
. into_iter ( )
. collect ( ) ,
) )
} else {
None
} ;
2021-11-12 10:57:55 -08:00
let known_validators = validators_set (
2020-08-21 00:35:11 -07:00
& identity_keypair . pubkey ( ) ,
& matches ,
2021-11-12 10:57:55 -08:00
" known_validators " ,
2021-08-17 21:17:46 -07:00
" --known-validator " ,
2020-08-21 00:35:11 -07:00
) ;
let repair_validators = validators_set (
& identity_keypair . pubkey ( ) ,
& matches ,
" repair_validators " ,
" --repair-validator " ,
) ;
2020-09-11 12:00:16 -07:00
let gossip_validators = validators_set (
& identity_keypair . pubkey ( ) ,
& matches ,
" gossip_validators " ,
" --gossip-validator " ,
) ;
2020-02-21 18:42:24 -08:00
2020-09-10 08:56:26 -07:00
let bind_address = solana_net_utils ::parse_host ( matches . value_of ( " bind_address " ) . unwrap ( ) )
. expect ( " invalid bind_address " ) ;
let rpc_bind_address = if matches . is_present ( " rpc_bind_address " ) {
solana_net_utils ::parse_host ( matches . value_of ( " rpc_bind_address " ) . unwrap ( ) )
. expect ( " invalid rpc_bind_address " )
2021-10-04 11:40:54 -07:00
} else if private_rpc {
solana_net_utils ::parse_host ( " 127.0.0.1 " ) . unwrap ( )
2020-09-10 08:56:26 -07:00
} else {
bind_address
} ;
2020-11-20 14:47:37 -08:00
let contact_debug_interval = value_t_or_exit! ( matches , " contact_debug_interval " , u64 ) ;
2021-05-11 15:06:22 -07:00
let account_indexes = process_account_indexes ( & matches ) ;
2020-12-31 18:06:03 -08:00
2020-09-10 13:15:22 -07:00
let restricted_repair_only_mode = matches . is_present ( " restricted_repair_only_mode " ) ;
2021-06-09 21:21:32 -07:00
let accounts_shrink_optimize_total_space =
value_t_or_exit! ( matches , " accounts_shrink_optimize_total_space " , bool ) ;
2022-03-31 10:04:24 -07:00
let tpu_use_quic = matches . is_present ( " tpu_use_quic " ) ;
2022-06-17 15:37:30 -07:00
let enable_quic_servers = matches . is_present ( " enable_quic_servers " ) ;
2022-06-10 09:25:24 -07:00
let tpu_connection_pool_size = value_t_or_exit! ( matches , " tpu_connection_pool_size " , usize ) ;
2022-03-21 09:31:37 -07:00
2021-06-09 21:21:32 -07:00
let shrink_ratio = value_t_or_exit! ( matches , " accounts_shrink_ratio " , f64 ) ;
if ! ( 0. 0 ..= 1.0 ) . contains ( & shrink_ratio ) {
eprintln! (
" The specified account-shrink-ratio is invalid, it must be between 0. and 1.0 inclusive: {} " ,
shrink_ratio
) ;
exit ( 1 ) ;
}
let accounts_shrink_ratio = if accounts_shrink_optimize_total_space {
AccountShrinkThreshold ::TotalSpace { shrink_ratio }
} else {
2022-03-05 18:46:46 -08:00
AccountShrinkThreshold ::IndividualStore { shrink_ratio }
2021-06-09 21:21:32 -07:00
} ;
2021-06-20 08:39:20 -07:00
let entrypoint_addrs = values_t! ( matches , " entrypoint " , String )
. unwrap_or_default ( )
. into_iter ( )
. map ( | entrypoint | {
solana_net_utils ::parse_host_port ( & entrypoint ) . unwrap_or_else ( | e | {
eprintln! ( " failed to parse entrypoint address: {} " , e ) ;
exit ( 1 ) ;
} )
} )
. collect ::< HashSet < _ > > ( )
. into_iter ( )
. collect ::< Vec < _ > > ( ) ;
2022-03-11 06:15:05 -08:00
for addr in & entrypoint_addrs {
if ! socket_addr_space . check ( addr ) {
eprintln! ( " invalid entrypoint address: {} " , addr ) ;
exit ( 1 ) ;
}
}
2021-06-20 08:39:20 -07:00
// TODO: Once entrypoints are updated to return shred-version, this should
// abort if it fails to obtain a shred-version, so that nodes always join
// gossip with a valid shred-version. The code to adopt entrypoint shred
// version can then be deleted from gossip and get_rpc_node above.
let expected_shred_version = value_t! ( matches , " expected_shred_version " , u16 )
. ok ( )
. or_else ( | | get_cluster_shred_version ( & entrypoint_addrs ) ) ;
2021-06-09 21:21:32 -07:00
2021-08-10 13:09:52 -07:00
let tower_storage : Arc < dyn solana_core ::tower_storage ::TowerStorage > =
match value_t_or_exit! ( matches , " tower_storage " , String ) . as_str ( ) {
" file " = > {
let tower_path = value_t! ( matches , " tower " , PathBuf )
. ok ( )
. unwrap_or_else ( | | ledger_path . clone ( ) ) ;
Arc ::new ( tower_storage ::FileTowerStorage ::new ( tower_path ) )
}
" etcd " = > {
let endpoints = values_t_or_exit! ( matches , " etcd_endpoint " , String ) ;
let domain_name = value_t_or_exit! ( matches , " etcd_domain_name " , String ) ;
let ca_certificate_file = value_t_or_exit! ( matches , " etcd_cacert_file " , String ) ;
let identity_certificate_file = value_t_or_exit! ( matches , " etcd_cert_file " , String ) ;
let identity_private_key_file = value_t_or_exit! ( matches , " etcd_key_file " , String ) ;
let read = | file | {
fs ::read ( & file ) . unwrap_or_else ( | err | {
eprintln! ( " Unable to read {} : {} " , file , err ) ;
exit ( 1 )
} )
} ;
let tls_config = tower_storage ::EtcdTlsConfig {
domain_name ,
ca_certificate : read ( ca_certificate_file ) ,
identity_certificate : read ( identity_certificate_file ) ,
identity_private_key : read ( identity_private_key_file ) ,
} ;
Arc ::new (
tower_storage ::EtcdTowerStorage ::new ( endpoints , Some ( tls_config ) )
. unwrap_or_else ( | err | {
eprintln! ( " Failed to connect to etcd: {} " , err ) ;
exit ( 1 ) ;
} ) ,
)
}
_ = > unreachable! ( ) ,
} ;
2021-07-20 22:25:13 -07:00
2022-02-22 07:40:12 -08:00
let mut accounts_index_config = AccountsIndexConfig {
started_from_validator : true , // this is the only place this is set
.. AccountsIndexConfig ::default ( )
} ;
2021-09-17 11:12:06 -07:00
if let Some ( bins ) = value_t! ( matches , " accounts_index_bins " , usize ) . ok ( ) {
accounts_index_config . bins = Some ( bins ) ;
}
2021-09-13 18:39:26 -07:00
2022-04-12 07:38:09 -07:00
accounts_index_config . index_limit_mb =
if let Some ( limit ) = value_t! ( matches , " accounts_index_memory_limit_mb " , usize ) . ok ( ) {
IndexLimitMb ::Limit ( limit )
} else if matches . is_present ( " disable_accounts_disk_index " ) {
IndexLimitMb ::InMemOnly
} else {
IndexLimitMb ::Unspecified
} ;
2021-09-19 16:00:15 -07:00
2021-09-18 07:54:57 -07:00
{
2021-09-28 09:07:47 -07:00
let mut accounts_index_paths : Vec < PathBuf > = if matches . is_present ( " accounts_index_path " ) {
values_t_or_exit! ( matches , " accounts_index_path " , String )
. into_iter ( )
. map ( PathBuf ::from )
. collect ( )
} else {
vec! [ ]
} ;
2021-09-18 07:54:57 -07:00
if accounts_index_paths . is_empty ( ) {
accounts_index_paths = vec! [ ledger_path . join ( " accounts_index " ) ] ;
}
accounts_index_config . drives = Some ( accounts_index_paths ) ;
}
2021-11-19 07:00:19 -08:00
const MB : usize = 1_024 * 1_024 ;
accounts_index_config . scan_results_limit_bytes =
value_t! ( matches , " accounts_index_scan_results_limit_mb " , usize )
. ok ( )
. map ( | mb | mb * MB ) ;
2022-04-11 11:10:09 -07:00
let filler_accounts_config = FillerAccountsConfig {
count : value_t_or_exit ! ( matches , " accounts_filler_count " , usize ) ,
size : value_t_or_exit ! ( matches , " accounts_filler_size " , usize ) ,
} ;
2021-10-25 07:45:46 -07:00
let mut accounts_db_config = AccountsDbConfig {
2021-09-17 11:12:06 -07:00
index : Some ( accounts_index_config ) ,
2021-09-13 18:39:26 -07:00
accounts_hash_cache_path : Some ( ledger_path . clone ( ) ) ,
2022-04-11 11:10:09 -07:00
filler_accounts_config ,
2021-12-01 11:10:48 -08:00
write_cache_limit_bytes : value_t ! ( matches , " accounts_db_cache_limit_mb " , u64 )
. ok ( )
. map ( | mb | mb * MB as u64 ) ,
2022-04-20 07:41:00 -07:00
skip_rewrites : matches . is_present ( " accounts_db_skip_rewrites " ) ,
2022-05-11 06:47:07 -07:00
ancient_append_vecs : matches . is_present ( " accounts_db_ancient_append_vecs " ) ,
2021-10-25 07:45:46 -07:00
.. AccountsDbConfig ::default ( )
} ;
if let Some ( passes ) = value_t! ( matches , " accounts_hash_num_passes " , usize ) . ok ( ) {
accounts_db_config . hash_calc_num_passes = Some ( passes ) ;
}
let accounts_db_config = Some ( accounts_db_config ) ;
2021-08-17 12:50:01 -07:00
2022-03-14 18:18:46 -07:00
let geyser_plugin_config_files = if matches . is_present ( " geyser_plugin_config " ) {
2021-10-08 20:06:58 -07:00
Some (
2022-03-14 18:18:46 -07:00
values_t_or_exit! ( matches , " geyser_plugin_config " , String )
2021-10-08 20:06:58 -07:00
. into_iter ( )
. map ( PathBuf ::from )
. collect ( ) ,
)
} else {
None
} ;
2021-09-30 14:26:17 -07:00
2022-01-28 18:00:18 -08:00
if matches . is_present ( " minimal_rpc_api " ) {
2022-03-22 15:17:05 -07:00
warn! ( " --minimal-rpc-api is now the default behavior. This flag is deprecated and can be removed from the launch args " ) ;
}
if matches . is_present ( " enable_cpi_and_log_storage " ) {
warn! (
" --enable-cpi-and-log-storage is deprecated. Please update the \
launch args to use - - enable - extended - tx - metadata - storage and remove \
- - enable - cpi - and - log - storage "
) ;
2022-01-28 18:00:18 -08:00
}
2022-03-18 11:36:52 -07:00
let rpc_bigtable_config = if matches . is_present ( " enable_rpc_bigtable_ledger_storage " )
| | matches . is_present ( " enable_bigtable_ledger_upload " )
{
Some ( RpcBigtableConfig {
enable_bigtable_ledger_upload : matches . is_present ( " enable_bigtable_ledger_upload " ) ,
2022-03-19 00:04:17 -07:00
bigtable_instance_name : value_t_or_exit ! ( matches , " rpc_bigtable_instance_name " , String ) ,
2022-06-15 17:58:16 -07:00
bigtable_app_profile_id : value_t_or_exit ! (
matches ,
" rpc_bigtable_app_profile_id " ,
String
) ,
2022-03-18 11:36:52 -07:00
timeout : value_t ! ( matches , " rpc_bigtable_timeout " , u64 )
. ok ( )
. map ( Duration ::from_secs ) ,
} )
} else {
None
} ;
2022-03-25 13:32:53 -07:00
if matches . is_present ( " accounts_db_index_hashing " ) {
info! ( " The accounts hash is only calculated without using the index. --accounts-db-index-hashing is deprecated and can be removed from the command line " ) ;
}
if matches . is_present ( " no_accounts_db_index_hashing " ) {
info! ( " The accounts hash is only calculated without using the index. --no-accounts-db-index-hashing is deprecated and can be removed from the command line " ) ;
}
2022-04-21 12:43:08 -07:00
let rpc_send_retry_rate_ms = value_t_or_exit! ( matches , " rpc_send_transaction_retry_ms " , u64 ) ;
let rpc_send_batch_size = value_t_or_exit! ( matches , " rpc_send_transaction_batch_size " , usize ) ;
let rpc_send_batch_send_rate_ms =
value_t_or_exit! ( matches , " rpc_send_transaction_batch_ms " , u64 ) ;
if rpc_send_batch_send_rate_ms > rpc_send_retry_rate_ms {
eprintln! (
" The specified rpc-send-batch-ms ({}) is invalid, it must be <= rpc-send-retry-ms ({}) " ,
rpc_send_batch_send_rate_ms , rpc_send_retry_rate_ms
) ;
exit ( 1 ) ;
}
let tps = rpc_send_batch_size as u64 * MILLIS_PER_SECOND / rpc_send_batch_send_rate_ms ;
if tps > send_transaction_service ::MAX_TRANSACTION_SENDS_PER_SECOND {
eprintln! (
" Either the specified rpc-send-batch-size ({}) or rpc-send-batch-ms ({}) is invalid, \
' rpc - send - batch - size * 1000 / rpc - send - batch - ms ' must be smaller than ( { } ) . " ,
rpc_send_batch_size ,
rpc_send_batch_send_rate_ms ,
send_transaction_service ::MAX_TRANSACTION_SENDS_PER_SECOND
) ;
exit ( 1 ) ;
}
2022-05-17 20:23:51 -07:00
let full_api = matches . is_present ( " full_rpc_api " ) ;
2022-04-21 12:43:08 -07:00
2020-01-24 17:27:04 -08:00
let mut validator_config = ValidatorConfig {
2020-09-18 22:03:54 -07:00
require_tower : matches . is_present ( " require_tower " ) ,
2021-08-10 13:09:52 -07:00
tower_storage ,
2022-04-19 15:06:30 -07:00
halt_at_slot : value_t ! ( matches , " dev_halt_at_slot " , Slot ) . ok ( ) ,
2020-01-24 17:27:04 -08:00
expected_genesis_hash : matches
. value_of ( " expected_genesis_hash " )
2021-06-18 06:34:46 -07:00
. map ( | s | Hash ::from_str ( s ) . unwrap ( ) ) ,
2020-06-30 12:43:48 -07:00
expected_bank_hash : matches
. value_of ( " expected_bank_hash " )
2021-06-18 06:34:46 -07:00
. map ( | s | Hash ::from_str ( s ) . unwrap ( ) ) ,
2021-06-20 08:39:20 -07:00
expected_shred_version ,
2020-01-24 17:27:04 -08:00
new_hard_forks : hardforks_of ( & matches , " hard_forks " ) ,
rpc_config : JsonRpcConfig {
2020-03-23 10:25:39 -07:00
enable_rpc_transaction_history : matches . is_present ( " enable_rpc_transaction_history " ) ,
2022-03-22 15:17:05 -07:00
enable_extended_tx_metadata_storage : matches . is_present ( " enable_cpi_and_log_storage " )
| | matches . is_present ( " enable_extended_tx_metadata_storage " ) ,
2022-03-18 11:36:52 -07:00
rpc_bigtable_config ,
2020-01-24 17:27:04 -08:00
faucet_addr : matches . value_of ( " rpc_faucet_addr " ) . map ( | address | {
solana_net_utils ::parse_host_port ( address ) . expect ( " failed to parse faucet address " )
} ) ,
2022-05-17 20:23:51 -07:00
full_api ,
2021-04-12 19:33:40 -07:00
obsolete_v1_7_api : matches . is_present ( " obsolete_v1_7_rpc_api " ) ,
2020-12-07 09:22:35 -08:00
max_multiple_accounts : Some ( value_t_or_exit! (
matches ,
" rpc_max_multiple_accounts " ,
usize
) ) ,
2020-05-29 15:31:52 -07:00
health_check_slot_distance : value_t_or_exit ! (
matches ,
" health_check_slot_distance " ,
u64
) ,
2021-01-12 17:13:47 -08:00
rpc_threads : value_t_or_exit ! ( matches , " rpc_threads " , usize ) ,
2021-10-26 20:13:19 -07:00
rpc_niceness_adj : value_t_or_exit ! ( matches , " rpc_niceness_adj " , i8 ) ,
2021-05-13 14:04:21 -07:00
account_indexes : account_indexes . clone ( ) ,
2021-05-24 12:24:47 -07:00
rpc_scan_and_fix_roots : matches . is_present ( " rpc_scan_and_fix_roots " ) ,
2020-01-24 17:27:04 -08:00
} ,
2022-03-14 18:18:46 -07:00
geyser_plugin_config_files ,
2020-09-10 08:56:26 -07:00
rpc_addrs : value_t ! ( matches , " rpc_port " , u16 ) . ok ( ) . map ( | rpc_port | {
(
SocketAddr ::new ( rpc_bind_address , rpc_port ) ,
SocketAddr ::new ( rpc_bind_address , rpc_port + 1 ) ,
2020-12-01 19:25:09 -08:00
// If additional ports are added, +2 needs to be skipped to avoid a conflict with
// the websocket port (which is +2) in web3.js This odd port shifting is tracked at
// https://github.com/solana-labs/solana/issues/12250
2020-09-10 08:56:26 -07:00
)
} ) ,
2020-10-01 12:36:58 -07:00
pubsub_config : PubSubConfig {
2021-12-17 15:03:09 -08:00
enable_block_subscription : matches . is_present ( " rpc_pubsub_enable_block_subscription " ) ,
2020-11-14 09:29:51 -08:00
enable_vote_subscription : matches . is_present ( " rpc_pubsub_enable_vote_subscription " ) ,
2021-09-17 12:40:14 -07:00
max_active_subscriptions : value_t_or_exit ! (
2020-10-01 12:36:58 -07:00
matches ,
2021-09-17 12:40:14 -07:00
" rpc_pubsub_max_active_subscriptions " ,
2020-10-01 12:36:58 -07:00
usize
) ,
2021-09-17 12:40:14 -07:00
queue_capacity_items : value_t_or_exit ! (
2020-10-01 12:36:58 -07:00
matches ,
2021-09-17 12:40:14 -07:00
" rpc_pubsub_queue_capacity_items " ,
2020-10-01 12:36:58 -07:00
usize
) ,
2021-09-17 12:40:14 -07:00
queue_capacity_bytes : value_t_or_exit ! (
2021-06-16 21:28:23 -07:00
matches ,
2021-09-17 12:40:14 -07:00
" rpc_pubsub_queue_capacity_bytes " ,
2021-06-16 21:28:23 -07:00
usize
) ,
2021-10-31 23:17:24 -07:00
worker_threads : value_t_or_exit ! ( matches , " rpc_pubsub_worker_threads " , usize ) ,
2022-05-17 20:23:51 -07:00
notification_threads : if full_api {
value_of ( & matches , " rpc_pubsub_notification_threads " )
} else {
Some ( 0 )
} ,
2020-10-01 12:36:58 -07:00
} ,
2020-09-10 13:15:22 -07:00
voting_disabled : matches . is_present ( " no_voting " ) | | restricted_repair_only_mode ,
2020-03-02 10:47:58 -08:00
wait_for_supermajority : value_t ! ( matches , " wait_for_supermajority " , Slot ) . ok ( ) ,
2021-11-12 10:57:55 -08:00
known_validators ,
2020-08-21 00:35:11 -07:00
repair_validators ,
2020-09-11 12:00:16 -07:00
gossip_validators ,
2020-03-23 08:42:32 -07:00
no_rocksdb_compaction ,
2021-02-14 10:16:30 -08:00
rocksdb_compaction_interval ,
rocksdb_max_compaction_jitter ,
2020-07-06 12:43:45 -07:00
wal_recovery_mode ,
2020-09-18 14:35:20 -07:00
poh_verify : ! matches . is_present ( " skip_poh_verify " ) ,
2020-09-23 18:46:42 -07:00
debug_keys ,
2020-11-20 14:47:37 -08:00
contact_debug_interval ,
2021-10-19 16:11:46 -07:00
send_transaction_service_config : send_transaction_service ::Config {
2022-04-21 12:43:08 -07:00
retry_rate_ms : rpc_send_retry_rate_ms ,
2021-10-19 16:11:46 -07:00
leader_forward_count : value_t_or_exit ! (
matches ,
" rpc_send_transaction_leader_forward_count " ,
u64
) ,
2021-10-19 22:17:06 -07:00
default_max_retries : value_t ! (
matches ,
" rpc_send_transaction_default_max_retries " ,
usize
)
. ok ( ) ,
service_max_retries : value_t_or_exit ! (
matches ,
" rpc_send_transaction_service_max_retries " ,
usize
) ,
2022-04-21 12:43:08 -07:00
batch_send_rate_ms : rpc_send_batch_send_rate_ms ,
batch_size : rpc_send_batch_size ,
2021-10-19 16:11:46 -07:00
} ,
2020-12-29 09:35:57 -08:00
no_poh_speed_test : matches . is_present ( " no_poh_speed_test " ) ,
2022-03-14 19:38:04 -07:00
no_os_memory_stats_reporting : matches . is_present ( " no_os_memory_stats_reporting " ) ,
2021-11-16 10:26:03 -08:00
no_os_network_stats_reporting : matches . is_present ( " no_os_network_stats_reporting " ) ,
2022-06-07 11:34:25 -07:00
no_os_cpu_stats_reporting : matches . is_present ( " no_os_cpu_stats_reporting " ) ,
2020-12-29 11:09:47 -08:00
poh_pinned_cpu_core : value_of ( & matches , " poh_pinned_cpu_core " )
. unwrap_or ( poh_service ::DEFAULT_PINNED_CPU_CORE ) ,
2021-03-05 16:01:21 -08:00
poh_hashes_per_batch : value_of ( & matches , " poh_hashes_per_batch " )
. unwrap_or ( poh_service ::DEFAULT_HASHES_PER_BATCH ) ,
2020-12-31 18:06:03 -08:00
account_indexes ,
2021-01-26 12:06:39 -08:00
accounts_db_caching_enabled : ! matches . is_present ( " no_accounts_db_caching " ) ,
2021-02-04 07:00:33 -08:00
accounts_db_test_hash_calculation : matches . is_present ( " accounts_db_test_hash_calculation " ) ,
2021-09-07 21:30:38 -07:00
accounts_db_config ,
2021-08-04 15:28:33 -07:00
accounts_db_skip_shrink : matches . is_present ( " accounts_db_skip_shrink " ) ,
2021-02-26 09:15:45 -08:00
tpu_coalesce_ms ,
2021-03-25 18:54:51 -07:00
no_wait_for_vote_to_start_leader : matches . is_present ( " no_wait_for_vote_to_start_leader " ) ,
2021-06-09 21:21:32 -07:00
accounts_shrink_ratio ,
2022-04-11 17:28:10 -07:00
runtime_config : RuntimeConfig {
bpf_jit : ! matches . is_present ( " no_bpf_jit " ) ,
.. RuntimeConfig ::default ( )
} ,
2022-06-17 15:37:30 -07:00
enable_quic_servers ,
2020-01-24 17:27:04 -08:00
.. ValidatorConfig ::default ( )
} ;
2019-11-04 07:11:40 -08:00
2020-03-15 10:19:07 -07:00
let vote_account = pubkey_of ( & matches , " vote_account " ) . unwrap_or_else ( | | {
2020-09-10 13:15:22 -07:00
if ! validator_config . voting_disabled {
warn! ( " --vote-account not specified, validator will not vote " ) ;
validator_config . voting_disabled = true ;
}
2020-03-31 08:23:42 -07:00
Keypair ::new ( ) . pubkey ( )
2020-03-15 10:19:07 -07:00
} ) ;
2019-11-04 07:11:40 -08:00
let dynamic_port_range =
2019-11-12 12:37:13 -08:00
solana_net_utils ::parse_port_range ( matches . value_of ( " dynamic_port_range " ) . unwrap ( ) )
2019-11-04 07:11:40 -08:00
. expect ( " invalid dynamic_port_range " ) ;
2020-12-20 21:36:27 -08:00
let account_paths : Vec < PathBuf > =
if let Ok ( account_paths ) = values_t! ( matches , " account_paths " , String ) {
account_paths
. join ( " , " )
. split ( ',' )
. map ( PathBuf ::from )
. collect ( )
} else {
vec! [ ledger_path . join ( " accounts " ) ]
} ;
2020-12-21 21:33:37 -08:00
let account_shrink_paths : Option < Vec < PathBuf > > =
values_t! ( matches , " account_shrink_path " , String )
. map ( | shrink_paths | shrink_paths . into_iter ( ) . map ( PathBuf ::from ) . collect ( ) )
. ok ( ) ;
2019-12-05 18:41:29 -08:00
// Create and canonicalize account paths to avoid issues with symlink creation
validator_config . account_paths = account_paths
. into_iter ( )
. map ( | account_path | {
match fs ::create_dir_all ( & account_path ) . and_then ( | _ | fs ::canonicalize ( & account_path ) ) {
Ok ( account_path ) = > account_path ,
Err ( err ) = > {
eprintln! (
" Unable to access account path: {:?}, err: {:?} " ,
account_path , err
) ;
exit ( 1 ) ;
}
}
} )
. collect ( ) ;
2019-11-04 07:11:40 -08:00
2020-12-21 21:33:37 -08:00
validator_config . account_shrink_paths = account_shrink_paths . map ( | paths | {
paths
. into_iter ( )
. map ( | account_path | {
match fs ::create_dir_all ( & account_path )
. and_then ( | _ | fs ::canonicalize ( & account_path ) )
{
Ok ( account_path ) = > account_path ,
Err ( err ) = > {
eprintln! (
" Unable to access account path: {:?}, err: {:?} " ,
account_path , err
) ;
exit ( 1 ) ;
}
}
} )
. collect ( )
} ) ;
2020-11-27 22:38:45 -08:00
let maximum_local_snapshot_age = value_t_or_exit! ( matches , " maximum_local_snapshot_age " , u64 ) ;
2021-09-03 09:28:10 -07:00
let maximum_full_snapshot_archives_to_retain =
2021-09-10 13:59:26 -07:00
value_t_or_exit! ( matches , " maximum_full_snapshots_to_retain " , usize ) ;
let maximum_incremental_snapshot_archives_to_retain =
value_t_or_exit! ( matches , " maximum_incremental_snapshots_to_retain " , usize ) ;
2021-10-26 18:56:16 -07:00
let snapshot_packager_niceness_adj =
value_t_or_exit! ( matches , " snapshot_packager_niceness_adj " , i8 ) ;
2021-05-25 09:32:12 -07:00
let minimal_snapshot_download_speed =
value_t_or_exit! ( matches , " minimal_snapshot_download_speed " , f32 ) ;
let maximum_snapshot_download_abort =
value_t_or_exit! ( matches , " maximum_snapshot_download_abort " , u64 ) ;
2022-05-10 13:37:41 -07:00
let full_snapshot_archives_dir = if matches . is_present ( " snapshots " ) {
2021-03-17 04:36:48 -07:00
PathBuf ::from ( matches . value_of ( " snapshots " ) . unwrap ( ) )
2021-03-13 13:48:26 -08:00
} else {
ledger_path . clone ( )
} ;
2022-05-10 13:37:41 -07:00
let incremental_snapshot_archives_dir =
if matches . is_present ( " incremental_snapshot_archive_path " ) {
let incremental_snapshot_archives_dir = PathBuf ::from (
matches
. value_of ( " incremental_snapshot_archive_path " )
. unwrap ( ) ,
) ;
fs ::create_dir_all ( & incremental_snapshot_archives_dir ) . unwrap_or_else ( | err | {
eprintln! (
" Failed to create incremental snapshot archives directory {:?}: {} " ,
incremental_snapshot_archives_dir . display ( ) ,
err
) ;
exit ( 1 ) ;
} ) ;
incremental_snapshot_archives_dir
} else {
full_snapshot_archives_dir . clone ( )
} ;
let bank_snapshots_dir = incremental_snapshot_archives_dir . join ( " snapshot " ) ;
2021-08-21 13:41:03 -07:00
fs ::create_dir_all ( & bank_snapshots_dir ) . unwrap_or_else ( | err | {
2019-11-22 07:20:40 -08:00
eprintln! (
2019-11-04 07:11:40 -08:00
" Failed to create snapshots directory {:?}: {} " ,
2022-05-10 13:37:41 -07:00
bank_snapshots_dir . display ( ) ,
err
2019-11-04 07:11:40 -08:00
) ;
exit ( 1 ) ;
} ) ;
2021-01-07 22:45:42 -08:00
let archive_format = {
let archive_format_str = value_t_or_exit! ( matches , " snapshot_archive_format " , String ) ;
2022-05-16 10:44:15 -07:00
ArchiveFormat ::from_cli_arg ( & archive_format_str )
. unwrap_or_else ( | | panic! ( " Archive format not recognized: {} " , archive_format_str ) )
2020-09-10 13:15:22 -07:00
} ;
2020-06-18 22:38:37 -07:00
let snapshot_version =
matches
. value_of ( " snapshot_version " )
. map_or ( SnapshotVersion ::default ( ) , | s | {
s . parse ::< SnapshotVersion > ( ) . unwrap_or_else ( | err | {
eprintln! ( " Error: {} " , err ) ;
exit ( 1 )
} )
} ) ;
2021-09-10 13:59:26 -07:00
let incremental_snapshot_interval_slots =
value_t_or_exit! ( matches , " incremental_snapshot_interval_slots " , u64 ) ;
let ( full_snapshot_archive_interval_slots , incremental_snapshot_archive_interval_slots ) =
if incremental_snapshot_interval_slots > 0 {
2022-02-09 11:26:35 -08:00
if ! matches . is_present ( " no_incremental_snapshots " ) {
2021-09-10 13:59:26 -07:00
(
value_t_or_exit! ( matches , " full_snapshot_interval_slots " , u64 ) ,
incremental_snapshot_interval_slots ,
)
} else {
( incremental_snapshot_interval_slots , Slot ::MAX )
}
2019-11-04 07:11:40 -08:00
} else {
2021-09-10 13:59:26 -07:00
( Slot ::MAX , Slot ::MAX )
} ;
validator_config . snapshot_config = Some ( SnapshotConfig {
full_snapshot_archive_interval_slots ,
incremental_snapshot_archive_interval_slots ,
2021-08-21 13:41:03 -07:00
bank_snapshots_dir ,
2022-05-10 13:37:41 -07:00
full_snapshot_archives_dir : full_snapshot_archives_dir . clone ( ) ,
incremental_snapshot_archives_dir : incremental_snapshot_archives_dir . clone ( ) ,
2021-01-07 22:45:42 -08:00
archive_format ,
2020-06-18 22:38:37 -07:00
snapshot_version ,
2021-09-03 09:28:10 -07:00
maximum_full_snapshot_archives_to_retain ,
2021-09-10 13:59:26 -07:00
maximum_incremental_snapshot_archives_to_retain ,
2021-09-13 06:27:50 -07:00
accounts_hash_debug_verify : validator_config . accounts_db_test_hash_calculation ,
2021-10-26 18:56:16 -07:00
packager_thread_niceness_adj : snapshot_packager_niceness_adj ,
2019-11-04 07:11:40 -08:00
} ) ;
2020-04-16 15:12:20 -07:00
validator_config . accounts_hash_interval_slots =
2021-09-10 13:59:26 -07:00
value_t_or_exit! ( matches , " accounts-hash-interval-slots " , u64 ) ;
2021-09-07 07:31:54 -07:00
if ! is_snapshot_config_valid (
2021-09-10 13:59:26 -07:00
full_snapshot_archive_interval_slots ,
incremental_snapshot_archive_interval_slots ,
2020-04-16 15:12:20 -07:00
validator_config . accounts_hash_interval_slots ,
) {
2021-09-10 13:59:26 -07:00
eprintln! ( " Invalid snapshot configuration provided: snapshot intervals are incompatible. \
\ n \ t - full snapshot interval MUST be a multiple of accounts hash interval ( if enabled ) \
\ n \ t - incremental snapshot interval MUST be a multiple of accounts hash interval ( if enabled ) \
\ n \ t - full snapshot interval MUST be larger than incremental snapshot interval ( if enabled ) \
\ nSnapshot configuration values : \
\ n \ tfull snapshot interval : { } \
\ n \ tincremental snapshot interval : { } \
\ n \ taccounts hash interval : { } " ,
if full_snapshot_archive_interval_slots = = Slot ::MAX { " disabled " . to_string ( ) } else { full_snapshot_archive_interval_slots . to_string ( ) } ,
if incremental_snapshot_archive_interval_slots = = Slot ::MAX { " disabled " . to_string ( ) } else { incremental_snapshot_archive_interval_slots . to_string ( ) } ,
validator_config . accounts_hash_interval_slots ) ;
2020-04-16 15:12:20 -07:00
exit ( 1 ) ;
}
2022-02-09 11:26:35 -08:00
if matches . is_present ( " incremental_snapshots " ) {
warn! ( " --incremental-snapshots is now the default behavior. This flag is deprecated and can be removed from the launch args " )
}
2020-04-16 15:12:20 -07:00
2019-11-04 07:11:40 -08:00
if matches . is_present ( " limit_ledger_size " ) {
2020-08-20 01:10:39 -07:00
let limit_ledger_size = match matches . value_of ( " limit_ledger_size " ) {
Some ( _ ) = > value_t_or_exit! ( matches , " limit_ledger_size " , u64 ) ,
None = > DEFAULT_MAX_LEDGER_SHREDS ,
} ;
2020-04-09 16:36:44 -07:00
if limit_ledger_size < DEFAULT_MIN_MAX_LEDGER_SHREDS {
2020-01-20 11:41:05 -08:00
eprintln! (
" The provided --limit-ledger-size value was too small, the minimum value is {} " ,
2020-04-09 16:36:44 -07:00
DEFAULT_MIN_MAX_LEDGER_SHREDS
2020-01-20 11:41:05 -08:00
) ;
exit ( 1 ) ;
}
2020-03-31 17:21:19 -07:00
validator_config . max_ledger_shreds = Some ( limit_ledger_size ) ;
2019-11-04 07:11:40 -08:00
}
2022-03-18 11:13:35 -07:00
validator_config . ledger_column_options = LedgerColumnOptions {
2022-03-22 02:27:09 -07:00
compression_type : match matches . value_of ( " rocksdb_ledger_compression " ) {
None = > BlockstoreCompressionType ::default ( ) ,
Some ( ledger_compression_string ) = > match ledger_compression_string {
" none " = > BlockstoreCompressionType ::None ,
" snappy " = > BlockstoreCompressionType ::Snappy ,
" lz4 " = > BlockstoreCompressionType ::Lz4 ,
" zlib " = > BlockstoreCompressionType ::Zlib ,
_ = > panic! (
" Unsupported ledger_compression: {} " ,
ledger_compression_string
) ,
} ,
} ,
2022-03-11 15:17:34 -08:00
shred_storage_type : match matches . value_of ( " rocksdb_shred_compaction " ) {
None = > ShredStorageType ::default ( ) ,
Some ( shred_compaction_string ) = > match shred_compaction_string {
" level " = > ShredStorageType ::RocksLevel ,
" fifo " = > {
let shred_storage_size =
value_t_or_exit! ( matches , " rocksdb_fifo_shred_storage_size " , u64 ) ;
2022-06-07 16:58:58 -07:00
ShredStorageType ::rocks_fifo ( shred_storage_size )
2022-03-11 15:17:34 -08:00
}
_ = > panic! (
" Unrecognized rocksdb-shred-compaction: {} " ,
shred_compaction_string
) ,
} ,
2022-03-03 12:43:58 -08:00
} ,
2022-04-29 15:28:50 -07:00
rocks_perf_sample_interval : value_t_or_exit ! (
matches ,
" rocksdb_perf_sample_interval " ,
usize
) ,
2022-03-03 12:43:58 -08:00
} ;
2021-11-12 10:57:55 -08:00
if matches . is_present ( " halt_on_known_validators_accounts_hash_mismatch " ) {
validator_config . halt_on_known_validators_accounts_hash_mismatch = true ;
2020-03-16 08:37:31 -07:00
}
2020-10-21 20:31:48 -07:00
let public_rpc_addr = matches . value_of ( " public_rpc_addr " ) . map ( | addr | {
solana_net_utils ::parse_host_port ( addr ) . unwrap_or_else ( | e | {
eprintln! ( " failed to parse public rpc address: {} " , e ) ;
exit ( 1 ) ;
} )
} ) ;
2021-10-25 18:25:55 -07:00
if ! matches . is_present ( " no_os_network_limits_test " ) {
2022-01-20 12:38:42 -08:00
if SystemMonitorService ::check_os_network_limits ( ) {
info! ( " OS network limits test passed. " ) ;
} else {
eprintln! ( " OS network limit test failed. solana-sys-tuner may be used to configure OS network limits. Bypass check with --no-os-network-limits-test. " ) ;
2022-02-14 07:48:30 -08:00
exit ( 1 ) ;
2022-01-20 12:38:42 -08:00
}
2021-10-25 18:25:55 -07:00
}
2021-09-22 14:10:35 -07:00
let mut ledger_lock = ledger_lockfile ( & ledger_path ) ;
let _ledger_write_guard = lock_ledger ( & ledger_path , & mut ledger_lock ) ;
2021-02-05 22:39:23 -08:00
2021-03-04 13:01:11 -08:00
let start_progress = Arc ::new ( RwLock ::new ( ValidatorStartProgress ::default ( ) ) ) ;
2022-02-14 10:27:11 -08:00
let admin_service_post_init = Arc ::new ( RwLock ::new ( None ) ) ;
2021-02-26 21:42:09 -08:00
admin_rpc_service ::run (
& ledger_path ,
admin_rpc_service ::AdminRpcRequestMetadata {
rpc_addr : validator_config . rpc_addrs . map ( | ( rpc_addr , _ ) | rpc_addr ) ,
start_time : std ::time ::SystemTime ::now ( ) ,
validator_exit : validator_config . validator_exit . clone ( ) ,
2021-03-04 13:01:11 -08:00
start_progress : start_progress . clone ( ) ,
2021-04-11 20:38:30 -07:00
authorized_voter_keypairs : authorized_voter_keypairs . clone ( ) ,
2022-02-14 10:27:11 -08:00
post_init : admin_service_post_init . clone ( ) ,
2021-07-20 22:25:13 -07:00
tower_storage : validator_config . tower_storage . clone ( ) ,
2021-02-26 21:42:09 -08:00
} ,
) ;
2020-12-18 10:54:48 -08:00
let gossip_host : IpAddr = matches
2020-11-12 21:04:15 -08:00
. value_of ( " gossip_host " )
. map ( | gossip_host | {
solana_net_utils ::parse_host ( gossip_host ) . unwrap_or_else ( | err | {
eprintln! ( " Failed to parse --gossip-host: {} " , err ) ;
2019-11-12 12:37:13 -08:00
exit ( 1 ) ;
2019-11-20 14:21:34 -08:00
} )
2020-11-12 21:04:15 -08:00
} )
. unwrap_or_else ( | | {
2020-12-18 10:54:48 -08:00
if ! entrypoint_addrs . is_empty ( ) {
let mut order : Vec < _ > = ( 0 .. entrypoint_addrs . len ( ) ) . collect ( ) ;
order . shuffle ( & mut thread_rng ( ) ) ;
let gossip_host = order . into_iter ( ) . find_map ( | i | {
let entrypoint_addr = & entrypoint_addrs [ i ] ;
info! (
" Contacting {} to determine the validator's public IP address " ,
entrypoint_addr
2020-11-12 21:04:15 -08:00
) ;
2020-12-18 10:54:48 -08:00
solana_net_utils ::get_public_ip_addr ( entrypoint_addr ) . map_or_else (
| err | {
eprintln! (
" Failed to contact cluster entrypoint {}: {} " ,
entrypoint_addr , err
) ;
None
} ,
Some ,
)
} ) ;
gossip_host . unwrap_or_else ( | | {
eprintln! ( " Unable to determine the validator's public IP address " ) ;
2020-11-12 21:04:15 -08:00
exit ( 1 ) ;
} )
} else {
std ::net ::IpAddr ::V4 ( std ::net ::Ipv4Addr ::new ( 127 , 0 , 0 , 1 ) )
}
} ) ;
2019-11-06 10:34:31 -08:00
2019-11-20 14:21:34 -08:00
let gossip_addr = SocketAddr ::new (
gossip_host ,
value_t! ( matches , " gossip_port " , u16 ) . unwrap_or_else ( | _ | {
2020-03-04 21:46:43 -08:00
solana_net_utils ::find_available_port_in_range ( bind_address , ( 0 , 1 ) ) . unwrap_or_else (
| err | {
eprintln! ( " Unable to find an available gossip port: {} " , err ) ;
exit ( 1 ) ;
} ,
)
2019-11-20 14:21:34 -08:00
} ) ,
) ;
2022-03-02 00:42:14 -08:00
let overwrite_tpu_addr = matches . value_of ( " tpu_host_addr " ) . map ( | tpu_addr | {
solana_net_utils ::parse_host_port ( tpu_addr ) . unwrap_or_else ( | err | {
eprintln! ( " Failed to parse --overwrite-tpu-addr: {} " , err ) ;
exit ( 1 ) ;
} )
} ) ;
2020-12-18 10:54:48 -08:00
let cluster_entrypoints = entrypoint_addrs
. iter ( )
. map ( ContactInfo ::new_gossip_entry_point )
. collect ::< Vec < _ > > ( ) ;
2019-11-04 07:11:40 -08:00
2020-03-04 21:46:43 -08:00
let mut node = Node ::new_with_external_ip (
& identity_keypair . pubkey ( ) ,
& gossip_addr ,
dynamic_port_range ,
bind_address ,
2022-03-02 00:42:14 -08:00
overwrite_tpu_addr ,
2020-03-04 21:46:43 -08:00
) ;
2020-01-30 09:17:01 -08:00
2020-09-10 13:15:22 -07:00
if restricted_repair_only_mode {
let any = SocketAddr ::new ( std ::net ::IpAddr ::V4 ( std ::net ::Ipv4Addr ::new ( 0 , 0 , 0 , 0 ) ) , 0 ) ;
// When in --restricted_repair_only_mode is enabled only the gossip and repair ports
// need to be reachable by the entrypoint to respond to gossip pull requests and repair
// requests initiated by the node. All other ports are unused.
node . info . tpu = any ;
node . info . tpu_forwards = any ;
node . info . tvu = any ;
node . info . tvu_forwards = any ;
node . info . serve_repair = any ;
2020-09-18 14:35:20 -07:00
// A node in this configuration shouldn't be an entrypoint to other nodes
node . sockets . ip_echo = None ;
2020-09-10 13:15:22 -07:00
}
2020-01-30 09:17:01 -08:00
if ! private_rpc {
2020-10-21 20:31:48 -07:00
if let Some ( public_rpc_addr ) = public_rpc_addr {
node . info . rpc = public_rpc_addr ;
node . info . rpc_pubsub = public_rpc_addr ;
2020-12-01 19:25:09 -08:00
} else if let Some ( ( rpc_addr , rpc_pubsub_addr ) ) = validator_config . rpc_addrs {
2020-09-10 08:56:26 -07:00
node . info . rpc = SocketAddr ::new ( node . info . gossip . ip ( ) , rpc_addr . port ( ) ) ;
node . info . rpc_pubsub = SocketAddr ::new ( node . info . gossip . ip ( ) , rpc_pubsub_addr . port ( ) ) ;
2020-01-30 09:17:01 -08:00
}
}
2019-11-04 07:11:40 -08:00
2020-09-18 14:35:20 -07:00
solana_metrics ::set_host_id ( identity_keypair . pubkey ( ) . to_string ( ) ) ;
2022-02-11 10:04:10 -08:00
solana_metrics ::set_panic_hook ( " validator " , {
let version = format! ( " {:?} " , solana_version ::version! ( ) ) ;
Some ( version )
} ) ;
2021-07-14 05:16:29 -07:00
solana_entry ::entry ::init_poh ( ) ;
2022-05-10 13:37:41 -07:00
snapshot_utils ::remove_tmp_snapshot_archives ( & full_snapshot_archives_dir ) ;
snapshot_utils ::remove_tmp_snapshot_archives ( & incremental_snapshot_archives_dir ) ;
2021-01-29 18:01:27 -08:00
2021-06-17 13:51:06 -07:00
let identity_keypair = Arc ::new ( identity_keypair ) ;
2021-02-03 08:26:17 -08:00
let should_check_duplicate_instance = ! matches . is_present ( " no_duplicate_instance_check " ) ;
2021-01-29 18:01:27 -08:00
if ! cluster_entrypoints . is_empty ( ) {
2021-10-03 11:13:16 -07:00
bootstrap ::rpc_bootstrap (
2021-01-29 18:01:27 -08:00
& node ,
& identity_keypair ,
& ledger_path ,
2022-05-10 13:37:41 -07:00
& full_snapshot_archives_dir ,
& incremental_snapshot_archives_dir ,
2021-01-29 18:01:27 -08:00
& vote_account ,
2021-04-11 20:38:30 -07:00
authorized_voter_keypairs . clone ( ) ,
2021-01-29 18:01:27 -08:00
& cluster_entrypoints ,
& mut validator_config ,
rpc_bootstrap_config ,
2021-10-19 14:35:42 -07:00
do_port_check ,
2021-01-29 18:01:27 -08:00
use_progress_bar ,
maximum_local_snapshot_age ,
2021-02-03 08:26:17 -08:00
should_check_duplicate_instance ,
2021-03-04 13:01:11 -08:00
& start_progress ,
2021-05-25 09:32:12 -07:00
minimal_snapshot_download_speed ,
maximum_snapshot_download_abort ,
2021-07-23 08:25:03 -07:00
socket_addr_space ,
2021-01-29 18:01:27 -08:00
) ;
2021-03-04 13:01:11 -08:00
* start_progress . write ( ) . unwrap ( ) = ValidatorStartProgress ::Initializing ;
2021-01-29 18:01:27 -08:00
}
if operation = = Operation ::Initialize {
info! ( " Validator ledger initialization complete " ) ;
return ;
}
2021-04-11 20:38:30 -07:00
2021-01-29 18:01:27 -08:00
let validator = Validator ::new (
2019-11-04 07:11:40 -08:00
node ,
2021-06-17 13:51:06 -07:00
identity_keypair ,
2019-11-04 07:11:40 -08:00
& ledger_path ,
& vote_account ,
2020-03-31 08:23:42 -07:00
authorized_voter_keypairs ,
2020-12-18 10:54:48 -08:00
cluster_entrypoints ,
2021-01-29 18:01:27 -08:00
& validator_config ,
2021-02-03 08:26:17 -08:00
should_check_duplicate_instance ,
2021-03-04 13:01:11 -08:00
start_progress ,
2021-07-23 08:25:03 -07:00
socket_addr_space ,
2022-04-30 20:52:38 -07:00
tpu_use_quic ,
2022-06-10 09:25:24 -07:00
tpu_connection_pool_size ,
2019-11-04 07:11:40 -08:00
) ;
2022-02-14 10:27:11 -08:00
* admin_service_post_init . write ( ) . unwrap ( ) =
Some ( admin_rpc_service ::AdminRpcRequestMetadataPostInit {
bank_forks : validator . bank_forks . clone ( ) ,
cluster_info : validator . cluster_info . clone ( ) ,
vote_account ,
} ) ;
2019-11-04 07:11:40 -08:00
if let Some ( filename ) = init_complete_file {
File ::create ( filename ) . unwrap_or_else ( | _ | {
error! ( " Unable to create: {} " , filename ) ;
exit ( 1 ) ;
} ) ;
}
info! ( " Validator initialized " ) ;
2020-12-10 17:28:52 -08:00
validator . join ( ) ;
2019-11-04 07:11:40 -08:00
info! ( " Validator exiting.. " ) ;
2018-05-23 13:03:19 -07:00
}
2021-05-11 15:06:22 -07:00
fn process_account_indexes ( matches : & ArgMatches ) -> AccountSecondaryIndexes {
let account_indexes : HashSet < AccountIndex > = matches
. values_of ( " account_indexes " )
. unwrap_or_default ( )
. map ( | value | match value {
" program-id " = > AccountIndex ::ProgramId ,
" spl-token-mint " = > AccountIndex ::SplTokenMint ,
" spl-token-owner " = > AccountIndex ::SplTokenOwner ,
_ = > unreachable! ( ) ,
} )
. collect ( ) ;
let account_indexes_include_keys : HashSet < Pubkey > =
values_t! ( matches , " account_index_include_key " , Pubkey )
. unwrap_or_default ( )
. iter ( )
. cloned ( )
. collect ( ) ;
let account_indexes_exclude_keys : HashSet < Pubkey > =
values_t! ( matches , " account_index_exclude_key " , Pubkey )
. unwrap_or_default ( )
. iter ( )
. cloned ( )
. collect ( ) ;
let exclude_keys = ! account_indexes_exclude_keys . is_empty ( ) ;
let include_keys = ! account_indexes_include_keys . is_empty ( ) ;
let keys = if ! account_indexes . is_empty ( ) & & ( exclude_keys | | include_keys ) {
let account_indexes_keys = AccountSecondaryIndexesIncludeExclude {
exclude : exclude_keys ,
keys : if exclude_keys {
account_indexes_exclude_keys
} else {
account_indexes_include_keys
} ,
} ;
Some ( account_indexes_keys )
} else {
None
} ;
AccountSecondaryIndexes {
keys ,
indexes : account_indexes ,
}
}