2019-10-11 13:30:52 -06:00
|
|
|
//! The `validator` module hosts all the validator microservices.
|
2018-07-02 15:24:40 -07:00
|
|
|
|
2019-11-04 11:03:39 -07:00
|
|
|
use crate::{
|
|
|
|
broadcast_stage::BroadcastStageType,
|
|
|
|
cluster_info::{ClusterInfo, Node},
|
2019-11-04 16:44:27 -07:00
|
|
|
commitment::BlockCommitmentCache,
|
2019-11-04 11:03:39 -07:00
|
|
|
contact_info::ContactInfo,
|
|
|
|
gossip_service::{discover_cluster, GossipService},
|
2019-11-15 08:36:33 -08:00
|
|
|
partition_cfg::PartitionCfg,
|
2019-11-04 11:03:39 -07:00
|
|
|
poh_recorder::PohRecorder,
|
|
|
|
poh_service::PohService,
|
|
|
|
rpc::JsonRpcConfig,
|
|
|
|
rpc_pubsub_service::PubSubService,
|
|
|
|
rpc_service::JsonRpcService,
|
|
|
|
rpc_subscriptions::RpcSubscriptions,
|
|
|
|
sigverify,
|
|
|
|
storage_stage::StorageState,
|
|
|
|
tpu::Tpu,
|
2019-11-20 16:43:10 -07:00
|
|
|
transaction_status_service::TransactionStatusService,
|
2019-11-04 11:03:39 -07:00
|
|
|
tvu::{Sockets, Tvu},
|
|
|
|
};
|
2019-11-21 14:23:40 -07:00
|
|
|
use crossbeam_channel::unbounded;
|
2019-11-04 11:03:39 -07:00
|
|
|
use solana_ledger::{
|
|
|
|
bank_forks::{BankForks, SnapshotConfig},
|
2019-11-04 19:10:06 -07:00
|
|
|
bank_forks_utils,
|
2020-01-13 14:13:52 -07:00
|
|
|
blockstore::{Blockstore, CompletedSlotsReceiver},
|
|
|
|
blockstore_processor::{self, BankForksInfo},
|
2019-11-13 08:14:09 -07:00
|
|
|
create_new_tmp_ledger,
|
2019-12-03 16:31:59 -08:00
|
|
|
leader_schedule::FixedSchedule,
|
2019-11-04 11:03:39 -07:00
|
|
|
leader_schedule_cache::LeaderScheduleCache,
|
|
|
|
};
|
2019-06-13 14:37:12 -07:00
|
|
|
use solana_metrics::datapoint_info;
|
2019-11-04 11:03:39 -07:00
|
|
|
use solana_sdk::{
|
|
|
|
clock::{Slot, DEFAULT_SLOTS_PER_TURN},
|
2019-11-08 23:56:57 -05:00
|
|
|
genesis_config::GenesisConfig,
|
2019-11-04 11:03:39 -07:00
|
|
|
hash::Hash,
|
|
|
|
poh_config::PohConfig,
|
|
|
|
pubkey::Pubkey,
|
|
|
|
signature::{Keypair, KeypairUtil},
|
|
|
|
timing::timestamp,
|
|
|
|
};
|
|
|
|
|
2019-11-18 18:05:02 -08:00
|
|
|
use solana_ledger::shred::Shred;
|
2019-11-04 11:03:39 -07:00
|
|
|
use std::{
|
|
|
|
net::{IpAddr, Ipv4Addr, SocketAddr},
|
|
|
|
path::{Path, PathBuf},
|
|
|
|
process,
|
|
|
|
sync::atomic::{AtomicBool, Ordering},
|
2019-11-21 14:23:40 -07:00
|
|
|
sync::mpsc::Receiver,
|
2019-11-04 11:03:39 -07:00
|
|
|
sync::{Arc, Mutex, RwLock},
|
2020-01-07 14:18:34 -07:00
|
|
|
thread::{sleep, Result},
|
|
|
|
time::Duration,
|
2019-11-04 11:03:39 -07:00
|
|
|
};
|
2018-07-02 11:20:35 -07:00
|
|
|
|
2019-04-15 15:27:45 -07:00
|
|
|
#[derive(Clone, Debug)]
|
2019-05-23 22:05:16 -07:00
|
|
|
pub struct ValidatorConfig {
|
2019-08-08 09:14:30 -07:00
|
|
|
pub dev_sigverify_disabled: bool,
|
|
|
|
pub dev_halt_at_slot: Option<Slot>,
|
2019-11-08 23:56:57 -05:00
|
|
|
pub expected_genesis_hash: Option<Hash>,
|
2019-01-30 17:16:55 -07:00
|
|
|
pub voting_disabled: bool,
|
2019-11-20 16:43:10 -07:00
|
|
|
pub transaction_status_service_disabled: bool,
|
2019-07-30 19:47:24 -07:00
|
|
|
pub blockstream_unix_socket: Option<PathBuf>,
|
2019-07-10 13:33:29 -07:00
|
|
|
pub storage_slots_per_turn: u64,
|
2019-12-05 21:41:29 -05:00
|
|
|
pub account_paths: Vec<PathBuf>,
|
2019-03-03 22:01:09 -08:00
|
|
|
pub rpc_config: JsonRpcConfig,
|
2019-07-31 17:58:10 -07:00
|
|
|
pub snapshot_config: Option<SnapshotConfig>,
|
2019-07-20 13:13:55 -07:00
|
|
|
pub max_ledger_slots: Option<u64>,
|
2019-06-19 00:13:19 -07:00
|
|
|
pub broadcast_stage_type: BroadcastStageType,
|
2019-11-15 08:36:33 -08:00
|
|
|
pub partition_cfg: Option<PartitionCfg>,
|
2019-12-03 16:31:59 -08:00
|
|
|
pub fixed_leader_schedule: Option<FixedSchedule>,
|
2020-01-07 14:39:41 -07:00
|
|
|
pub wait_for_supermajority: bool,
|
2019-01-29 08:51:01 -08:00
|
|
|
}
|
2019-06-19 00:13:19 -07:00
|
|
|
|
2019-05-23 22:05:16 -07:00
|
|
|
impl Default for ValidatorConfig {
|
2019-01-29 08:51:01 -08:00
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
2019-08-08 09:14:30 -07:00
|
|
|
dev_sigverify_disabled: false,
|
|
|
|
dev_halt_at_slot: None,
|
2019-11-08 23:56:57 -05:00
|
|
|
expected_genesis_hash: None,
|
2019-01-30 17:16:55 -07:00
|
|
|
voting_disabled: false,
|
2019-11-20 16:43:10 -07:00
|
|
|
transaction_status_service_disabled: false,
|
2019-07-30 19:47:24 -07:00
|
|
|
blockstream_unix_socket: None,
|
2019-07-10 13:33:29 -07:00
|
|
|
storage_slots_per_turn: DEFAULT_SLOTS_PER_TURN,
|
2019-07-20 13:13:55 -07:00
|
|
|
max_ledger_slots: None,
|
2019-12-05 21:41:29 -05:00
|
|
|
account_paths: Vec::new(),
|
2019-03-03 22:01:09 -08:00
|
|
|
rpc_config: JsonRpcConfig::default(),
|
2019-07-31 17:58:10 -07:00
|
|
|
snapshot_config: None,
|
2019-06-19 00:13:19 -07:00
|
|
|
broadcast_stage_type: BroadcastStageType::Standard,
|
2019-11-15 08:36:33 -08:00
|
|
|
partition_cfg: None,
|
2019-12-03 16:31:59 -08:00
|
|
|
fixed_leader_schedule: None,
|
2020-01-07 14:39:41 -07:00
|
|
|
wait_for_supermajority: false,
|
2019-01-29 08:51:01 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-20 23:59:31 -07:00
|
|
|
#[derive(Default)]
|
|
|
|
pub struct ValidatorExit {
|
2019-08-23 08:55:51 -07:00
|
|
|
exits: Vec<Box<dyn FnOnce() + Send + Sync>>,
|
2019-08-20 23:59:31 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
impl ValidatorExit {
|
2019-08-23 08:55:51 -07:00
|
|
|
pub fn register_exit(&mut self, exit: Box<dyn FnOnce() -> () + Send + Sync>) {
|
2019-08-20 23:59:31 -07:00
|
|
|
self.exits.push(exit);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn exit(self) {
|
|
|
|
for exit in self.exits {
|
|
|
|
exit();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-23 22:05:16 -07:00
|
|
|
pub struct Validator {
|
2019-03-03 16:44:06 -08:00
|
|
|
pub id: Pubkey,
|
2019-08-20 23:59:31 -07:00
|
|
|
validator_exit: Arc<RwLock<Option<ValidatorExit>>>,
|
2018-10-25 16:58:40 -07:00
|
|
|
rpc_service: Option<JsonRpcService>,
|
|
|
|
rpc_pubsub_service: Option<PubSubService>,
|
2019-11-20 16:43:10 -07:00
|
|
|
transaction_status_service: Option<TransactionStatusService>,
|
2018-12-06 13:52:47 -07:00
|
|
|
gossip_service: GossipService,
|
2019-02-26 10:48:18 -08:00
|
|
|
poh_recorder: Arc<Mutex<PohRecorder>>,
|
2019-03-04 19:02:03 -08:00
|
|
|
poh_service: PohService,
|
|
|
|
tpu: Tpu,
|
|
|
|
tvu: Tvu,
|
2019-11-13 05:37:13 +09:00
|
|
|
ip_echo_server: solana_net_utils::IpEchoServer,
|
2018-07-02 15:24:40 -07:00
|
|
|
}
|
2018-07-02 11:20:35 -07:00
|
|
|
|
2019-05-23 22:05:16 -07:00
|
|
|
impl Validator {
|
2019-05-20 13:32:32 -07:00
|
|
|
pub fn new(
|
2019-01-29 18:12:32 -08:00
|
|
|
mut node: Node,
|
2019-01-30 20:51:50 -07:00
|
|
|
keypair: &Arc<Keypair>,
|
2019-07-30 15:53:41 -07:00
|
|
|
ledger_path: &Path,
|
2019-03-09 19:28:43 -08:00
|
|
|
vote_account: &Pubkey,
|
2019-05-20 13:32:32 -07:00
|
|
|
voting_keypair: &Arc<Keypair>,
|
2019-05-15 15:19:29 -07:00
|
|
|
storage_keypair: &Arc<Keypair>,
|
2019-03-08 17:23:07 -08:00
|
|
|
entrypoint_info_option: Option<&ContactInfo>,
|
2019-11-04 22:14:55 -07:00
|
|
|
poh_verify: bool,
|
2019-05-23 22:05:16 -07:00
|
|
|
config: &ValidatorConfig,
|
2019-05-20 13:32:32 -07:00
|
|
|
) -> Self {
|
2019-08-08 15:38:23 -07:00
|
|
|
let id = keypair.pubkey();
|
|
|
|
assert_eq!(id, node.info.id);
|
|
|
|
|
|
|
|
warn!("identity pubkey: {:?}", id);
|
2019-08-16 15:56:06 -07:00
|
|
|
warn!("vote pubkey: {:?}", vote_account);
|
2020-01-07 14:33:39 -07:00
|
|
|
report_target_features();
|
2019-11-04 11:03:39 -07:00
|
|
|
|
2019-08-08 15:38:23 -07:00
|
|
|
info!("entrypoint: {:?}", entrypoint_info_option);
|
2019-09-14 12:32:57 -07:00
|
|
|
|
|
|
|
Self::print_node_info(&node);
|
|
|
|
|
|
|
|
info!("Initializing sigverify, this could take a while...");
|
|
|
|
sigverify::init();
|
|
|
|
info!("Done.");
|
2019-02-06 19:21:31 -08:00
|
|
|
|
2019-06-17 07:29:12 -07:00
|
|
|
info!("creating bank...");
|
2019-05-09 14:10:04 -07:00
|
|
|
let (
|
2019-11-08 23:56:57 -05:00
|
|
|
genesis_hash,
|
2019-05-09 14:10:04 -07:00
|
|
|
bank_forks,
|
|
|
|
bank_forks_info,
|
2020-01-13 14:13:52 -07:00
|
|
|
blockstore,
|
2019-05-09 14:10:04 -07:00
|
|
|
ledger_signal_receiver,
|
|
|
|
completed_slots_receiver,
|
|
|
|
leader_schedule_cache,
|
2019-05-18 14:01:36 -07:00
|
|
|
poh_config,
|
2020-01-13 14:13:52 -07:00
|
|
|
) = new_banks_from_blockstore(
|
2019-11-08 23:56:57 -05:00
|
|
|
config.expected_genesis_hash,
|
2019-05-30 21:31:35 -07:00
|
|
|
ledger_path,
|
|
|
|
config.account_paths.clone(),
|
2019-07-31 17:58:10 -07:00
|
|
|
config.snapshot_config.clone(),
|
2019-11-04 22:14:55 -07:00
|
|
|
poh_verify,
|
2019-08-08 09:14:30 -07:00
|
|
|
config.dev_halt_at_slot,
|
2019-12-03 16:31:59 -08:00
|
|
|
config.fixed_leader_schedule.clone(),
|
2019-05-30 21:31:35 -07:00
|
|
|
);
|
2019-02-20 17:05:57 -08:00
|
|
|
|
2019-04-19 02:39:44 -07:00
|
|
|
let leader_schedule_cache = Arc::new(leader_schedule_cache);
|
2019-02-26 10:48:18 -08:00
|
|
|
let exit = Arc::new(AtomicBool::new(false));
|
|
|
|
let bank_info = &bank_forks_info[0];
|
2019-03-04 16:40:28 -08:00
|
|
|
let bank = bank_forks[bank_info.bank_slot].clone();
|
2019-02-20 21:23:44 -08:00
|
|
|
let bank_forks = Arc::new(RwLock::new(bank_forks));
|
2019-11-04 16:44:27 -07:00
|
|
|
let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::default()));
|
2019-11-18 18:05:02 -08:00
|
|
|
// The version used by shreds, derived from genesis
|
|
|
|
let shred_version = Shred::version_from_hash(&genesis_hash);
|
2018-08-14 18:03:48 -06:00
|
|
|
|
2019-08-20 23:59:31 -07:00
|
|
|
let mut validator_exit = ValidatorExit::default();
|
|
|
|
let exit_ = exit.clone();
|
|
|
|
validator_exit.register_exit(Box::new(move || exit_.store(true, Ordering::Relaxed)));
|
|
|
|
let validator_exit = Arc::new(RwLock::new(Some(validator_exit)));
|
|
|
|
|
2018-11-15 13:23:26 -08:00
|
|
|
node.info.wallclock = timestamp();
|
2019-03-06 19:09:37 -08:00
|
|
|
let cluster_info = Arc::new(RwLock::new(ClusterInfo::new(
|
2019-01-29 09:11:49 -08:00
|
|
|
node.info.clone(),
|
2018-12-01 12:00:30 -08:00
|
|
|
keypair.clone(),
|
|
|
|
)));
|
2018-08-22 18:50:19 -06:00
|
|
|
|
2019-07-10 13:33:29 -07:00
|
|
|
let storage_state = StorageState::new(
|
|
|
|
&bank.last_blockhash(),
|
|
|
|
config.storage_slots_per_turn,
|
|
|
|
bank.slots_per_segment(),
|
|
|
|
);
|
2019-01-28 14:53:50 -08:00
|
|
|
|
2020-01-13 14:13:52 -07:00
|
|
|
let blockstore = Arc::new(blockstore);
|
2019-11-11 13:18:34 -05:00
|
|
|
|
2019-04-12 18:17:34 -07:00
|
|
|
let rpc_service = if node.info.rpc.port() == 0 {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(JsonRpcService::new(
|
|
|
|
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), node.info.rpc.port()),
|
|
|
|
config.rpc_config.clone(),
|
|
|
|
bank_forks.clone(),
|
2019-11-04 16:44:27 -07:00
|
|
|
block_commitment_cache.clone(),
|
2020-01-13 14:13:52 -07:00
|
|
|
blockstore.clone(),
|
2019-12-19 23:27:54 -08:00
|
|
|
cluster_info.clone(),
|
2019-11-08 23:56:57 -05:00
|
|
|
genesis_hash,
|
2019-11-11 13:18:34 -05:00
|
|
|
ledger_path,
|
|
|
|
storage_state.clone(),
|
2019-12-19 23:27:54 -08:00
|
|
|
validator_exit.clone(),
|
2019-04-12 18:17:34 -07:00
|
|
|
))
|
|
|
|
};
|
2019-01-15 12:20:07 -08:00
|
|
|
|
2019-02-18 17:25:17 -07:00
|
|
|
let subscriptions = Arc::new(RpcSubscriptions::default());
|
2019-04-12 18:17:34 -07:00
|
|
|
let rpc_pubsub_service = if node.info.rpc_pubsub.port() == 0 {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(PubSubService::new(
|
|
|
|
&subscriptions,
|
|
|
|
SocketAddr::new(
|
|
|
|
IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)),
|
|
|
|
node.info.rpc_pubsub.port(),
|
|
|
|
),
|
|
|
|
&exit,
|
|
|
|
))
|
|
|
|
};
|
2018-10-12 11:04:14 -07:00
|
|
|
|
2019-11-20 16:43:10 -07:00
|
|
|
let (transaction_status_sender, transaction_status_service) =
|
|
|
|
if rpc_service.is_some() && !config.transaction_status_service_disabled {
|
2019-11-21 14:23:40 -07:00
|
|
|
let (transaction_status_sender, transaction_status_receiver) = unbounded();
|
2019-11-20 16:43:10 -07:00
|
|
|
(
|
|
|
|
Some(transaction_status_sender),
|
|
|
|
Some(TransactionStatusService::new(
|
|
|
|
transaction_status_receiver,
|
2020-01-13 14:13:52 -07:00
|
|
|
blockstore.clone(),
|
2019-11-20 16:43:10 -07:00
|
|
|
&exit,
|
|
|
|
)),
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
(None, None)
|
|
|
|
};
|
|
|
|
|
2019-08-16 16:20:20 -07:00
|
|
|
info!(
|
|
|
|
"Starting PoH: epoch={} slot={} tick_height={} blockhash={} leader={:?}",
|
|
|
|
bank.epoch(),
|
|
|
|
bank.slot(),
|
|
|
|
bank.tick_height(),
|
|
|
|
bank.last_blockhash(),
|
|
|
|
leader_schedule_cache.slot_leader_at(bank.slot(), Some(&bank))
|
|
|
|
);
|
|
|
|
|
2019-08-08 09:14:30 -07:00
|
|
|
if config.dev_halt_at_slot.is_some() {
|
|
|
|
// Park with the RPC service running, ready for inspection!
|
2019-08-16 16:20:20 -07:00
|
|
|
warn!("Validator halted");
|
2019-08-08 09:14:30 -07:00
|
|
|
std::thread::park();
|
|
|
|
}
|
|
|
|
|
|
|
|
let poh_config = Arc::new(poh_config);
|
|
|
|
let (mut poh_recorder, entry_receiver) = PohRecorder::new_with_clear_signal(
|
|
|
|
bank.tick_height(),
|
|
|
|
bank.last_blockhash(),
|
|
|
|
bank.slot(),
|
2020-01-13 14:13:52 -07:00
|
|
|
leader_schedule_cache.next_leader_slot(&id, bank.slot(), &bank, Some(&blockstore)),
|
2019-08-08 09:14:30 -07:00
|
|
|
bank.ticks_per_slot(),
|
|
|
|
&id,
|
2020-01-13 14:13:52 -07:00
|
|
|
&blockstore,
|
|
|
|
blockstore.new_shreds_signals.first().cloned(),
|
2019-08-08 09:14:30 -07:00
|
|
|
&leader_schedule_cache,
|
|
|
|
&poh_config,
|
|
|
|
);
|
|
|
|
if config.snapshot_config.is_some() {
|
|
|
|
poh_recorder.set_bank(&bank);
|
|
|
|
}
|
|
|
|
let poh_recorder = Arc::new(Mutex::new(poh_recorder));
|
|
|
|
|
2019-11-13 05:37:13 +09:00
|
|
|
let ip_echo_server = solana_net_utils::ip_echo_server(node.sockets.ip_echo.unwrap());
|
2019-08-08 09:14:30 -07:00
|
|
|
|
2018-12-06 13:52:47 -07:00
|
|
|
let gossip_service = GossipService::new(
|
2018-10-08 20:55:54 -06:00
|
|
|
&cluster_info,
|
2020-01-13 14:13:52 -07:00
|
|
|
Some(blockstore.clone()),
|
2019-02-20 21:36:08 -08:00
|
|
|
Some(bank_forks.clone()),
|
2018-08-22 19:00:56 -06:00
|
|
|
node.sockets.gossip,
|
2019-03-04 16:33:14 -08:00
|
|
|
&exit,
|
2018-09-02 23:23:43 -10:00
|
|
|
);
|
2018-08-22 19:00:56 -06:00
|
|
|
|
2019-01-21 11:14:27 -08:00
|
|
|
// Insert the entrypoint info, should only be None if this node
|
2018-10-10 16:49:41 -07:00
|
|
|
// is the bootstrap leader
|
2019-01-21 11:14:27 -08:00
|
|
|
if let Some(entrypoint_info) = entrypoint_info_option {
|
2018-11-15 13:23:26 -08:00
|
|
|
cluster_info
|
|
|
|
.write()
|
|
|
|
.unwrap()
|
2019-03-08 18:08:24 -08:00
|
|
|
.set_entrypoint(entrypoint_info.clone());
|
2018-08-22 18:51:53 -06:00
|
|
|
}
|
2018-08-22 18:50:19 -06:00
|
|
|
|
2020-01-07 14:39:41 -07:00
|
|
|
if config.wait_for_supermajority {
|
2020-01-07 14:18:34 -07:00
|
|
|
info!(
|
2020-01-07 20:35:09 -07:00
|
|
|
"Waiting for more than 66% of activated stake at slot {} to be in gossip...",
|
2020-01-07 14:18:34 -07:00
|
|
|
bank.slot()
|
|
|
|
);
|
|
|
|
loop {
|
|
|
|
let gossip_stake_percent = get_stake_percent_in_gossip(&bank, &cluster_info);
|
|
|
|
|
|
|
|
info!("{}% of activated stake in gossip", gossip_stake_percent,);
|
|
|
|
if gossip_stake_percent > 66 {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
sleep(Duration::new(1, 0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-26 13:58:08 +05:30
|
|
|
let sockets = Sockets {
|
|
|
|
repair: node
|
|
|
|
.sockets
|
|
|
|
.repair
|
|
|
|
.try_clone()
|
|
|
|
.expect("Failed to clone repair socket"),
|
|
|
|
retransmit: node
|
|
|
|
.sockets
|
2019-10-10 13:24:03 -07:00
|
|
|
.retransmit_sockets
|
|
|
|
.iter()
|
|
|
|
.map(|s| s.try_clone().expect("Failed to clone retransmit socket"))
|
|
|
|
.collect(),
|
2019-01-26 13:58:08 +05:30
|
|
|
fetch: node
|
|
|
|
.sockets
|
|
|
|
.tvu
|
|
|
|
.iter()
|
|
|
|
.map(|s| s.try_clone().expect("Failed to clone TVU Sockets"))
|
|
|
|
.collect(),
|
2019-08-20 17:16:06 -07:00
|
|
|
forwards: node
|
|
|
|
.sockets
|
|
|
|
.tvu_forwards
|
|
|
|
.iter()
|
|
|
|
.map(|s| s.try_clone().expect("Failed to clone TVU forwards Sockets"))
|
|
|
|
.collect(),
|
2019-01-26 13:58:08 +05:30
|
|
|
};
|
2018-12-03 00:10:43 -08:00
|
|
|
|
2019-03-08 18:29:08 -08:00
|
|
|
let voting_keypair = if config.voting_disabled {
|
2019-01-30 17:16:55 -07:00
|
|
|
None
|
|
|
|
} else {
|
2019-12-04 11:17:17 -07:00
|
|
|
Some(voting_keypair.clone())
|
2019-01-30 17:16:55 -07:00
|
|
|
};
|
|
|
|
|
2020-01-07 14:18:34 -07:00
|
|
|
let poh_service = PohService::new(poh_recorder.clone(), &poh_config, &exit);
|
|
|
|
assert_eq!(
|
2020-01-13 14:13:52 -07:00
|
|
|
blockstore.new_shreds_signals.len(),
|
2020-01-07 14:18:34 -07:00
|
|
|
1,
|
|
|
|
"New shred signal for the TVU should be the same as the clear bank signal."
|
|
|
|
);
|
|
|
|
|
2019-02-11 17:56:52 -08:00
|
|
|
let tvu = Tvu::new(
|
2019-03-08 18:29:08 -08:00
|
|
|
vote_account,
|
|
|
|
voting_keypair,
|
2019-05-15 15:19:29 -07:00
|
|
|
storage_keypair,
|
2019-02-21 11:19:45 -08:00
|
|
|
&bank_forks,
|
2019-01-26 13:58:08 +05:30
|
|
|
&cluster_info,
|
|
|
|
sockets,
|
2020-01-13 14:13:52 -07:00
|
|
|
blockstore.clone(),
|
2019-01-28 14:53:50 -08:00
|
|
|
&storage_state,
|
2019-07-30 19:47:24 -07:00
|
|
|
config.blockstream_unix_socket.as_ref(),
|
2019-07-20 13:13:55 -07:00
|
|
|
config.max_ledger_slots,
|
2019-02-04 15:33:43 -08:00
|
|
|
ledger_signal_receiver,
|
2019-02-18 19:08:54 -07:00
|
|
|
&subscriptions,
|
2019-03-03 16:44:06 -08:00
|
|
|
&poh_recorder,
|
2019-04-19 02:39:44 -07:00
|
|
|
&leader_schedule_cache,
|
2019-03-04 16:33:14 -08:00
|
|
|
&exit,
|
2019-05-09 14:10:04 -07:00
|
|
|
completed_slots_receiver,
|
2019-11-04 16:44:27 -07:00
|
|
|
block_commitment_cache,
|
2019-10-28 16:07:51 -07:00
|
|
|
config.dev_sigverify_disabled,
|
2019-11-15 08:36:33 -08:00
|
|
|
config.partition_cfg.clone(),
|
2019-11-18 18:05:02 -08:00
|
|
|
shred_version,
|
2019-11-20 16:43:10 -07:00
|
|
|
transaction_status_sender.clone(),
|
2019-03-03 16:44:06 -08:00
|
|
|
);
|
2019-04-19 14:18:19 -07:00
|
|
|
|
2019-08-08 09:14:30 -07:00
|
|
|
if config.dev_sigverify_disabled {
|
2019-04-19 14:18:19 -07:00
|
|
|
warn!("signature verification disabled");
|
|
|
|
}
|
|
|
|
|
2019-03-03 16:44:06 -08:00
|
|
|
let tpu = Tpu::new(
|
|
|
|
&cluster_info,
|
|
|
|
&poh_recorder,
|
|
|
|
entry_receiver,
|
|
|
|
node.sockets.tpu,
|
2019-07-30 14:50:02 -07:00
|
|
|
node.sockets.tpu_forwards,
|
2019-03-03 16:44:06 -08:00
|
|
|
node.sockets.broadcast,
|
2019-08-08 09:14:30 -07:00
|
|
|
config.dev_sigverify_disabled,
|
2019-11-20 16:43:10 -07:00
|
|
|
transaction_status_sender,
|
2020-01-13 14:13:52 -07:00
|
|
|
&blockstore,
|
2019-06-19 00:13:19 -07:00
|
|
|
&config.broadcast_stage_type,
|
2019-03-04 16:33:14 -08:00
|
|
|
&exit,
|
2019-11-18 18:05:02 -08:00
|
|
|
shred_version,
|
2019-01-26 13:58:08 +05:30
|
|
|
);
|
2018-12-12 12:38:00 -08:00
|
|
|
|
2019-07-30 16:18:33 -04:00
|
|
|
datapoint_info!("validator-new", ("id", id.to_string(), String));
|
2019-02-21 11:37:48 -08:00
|
|
|
Self {
|
2019-01-30 20:02:35 -07:00
|
|
|
id,
|
2018-12-06 13:52:47 -07:00
|
|
|
gossip_service,
|
2019-04-12 18:17:34 -07:00
|
|
|
rpc_service,
|
|
|
|
rpc_pubsub_service,
|
2019-11-20 16:43:10 -07:00
|
|
|
transaction_status_service,
|
2019-03-04 19:02:03 -08:00
|
|
|
tpu,
|
|
|
|
tvu,
|
2019-02-26 10:48:18 -08:00
|
|
|
poh_service,
|
|
|
|
poh_recorder,
|
2019-05-03 11:01:35 -07:00
|
|
|
ip_echo_server,
|
2019-08-20 23:59:31 -07:00
|
|
|
validator_exit,
|
2019-02-01 18:09:38 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-28 20:10:38 -08:00
|
|
|
// Used for notifying many nodes in parallel to exit
|
2019-08-20 23:59:31 -07:00
|
|
|
pub fn exit(&mut self) {
|
|
|
|
if let Some(x) = self.validator_exit.write().unwrap().take() {
|
|
|
|
x.exit()
|
|
|
|
}
|
2018-07-16 22:22:29 -07:00
|
|
|
}
|
2018-09-13 14:00:17 -07:00
|
|
|
|
2019-08-20 23:59:31 -07:00
|
|
|
pub fn close(mut self) -> Result<()> {
|
2018-07-17 08:18:42 -07:00
|
|
|
self.exit();
|
2018-07-09 14:53:18 -06:00
|
|
|
self.join()
|
2018-07-02 15:24:40 -07:00
|
|
|
}
|
2019-09-14 12:32:57 -07:00
|
|
|
|
|
|
|
fn print_node_info(node: &Node) {
|
|
|
|
info!("{:?}", node.info);
|
|
|
|
info!(
|
|
|
|
"local gossip address: {}",
|
|
|
|
node.sockets.gossip.local_addr().unwrap()
|
|
|
|
);
|
|
|
|
info!(
|
|
|
|
"local broadcast address: {}",
|
2019-12-16 17:11:18 -08:00
|
|
|
node.sockets
|
|
|
|
.broadcast
|
|
|
|
.first()
|
|
|
|
.unwrap()
|
|
|
|
.local_addr()
|
|
|
|
.unwrap()
|
2019-09-14 12:32:57 -07:00
|
|
|
);
|
|
|
|
info!(
|
|
|
|
"local repair address: {}",
|
|
|
|
node.sockets.repair.local_addr().unwrap()
|
|
|
|
);
|
|
|
|
info!(
|
|
|
|
"local retransmit address: {}",
|
2019-10-10 13:24:03 -07:00
|
|
|
node.sockets.retransmit_sockets[0].local_addr().unwrap()
|
2019-09-14 12:32:57 -07:00
|
|
|
);
|
|
|
|
}
|
2019-11-13 11:12:09 -07:00
|
|
|
|
|
|
|
pub fn join(self) -> Result<()> {
|
|
|
|
self.poh_service.join()?;
|
|
|
|
drop(self.poh_recorder);
|
|
|
|
if let Some(rpc_service) = self.rpc_service {
|
|
|
|
rpc_service.join()?;
|
|
|
|
}
|
|
|
|
if let Some(rpc_pubsub_service) = self.rpc_pubsub_service {
|
|
|
|
rpc_pubsub_service.join()?;
|
|
|
|
}
|
2019-11-20 16:43:10 -07:00
|
|
|
if let Some(transaction_status_service) = self.transaction_status_service {
|
|
|
|
transaction_status_service.join()?;
|
|
|
|
}
|
2019-11-13 11:12:09 -07:00
|
|
|
|
|
|
|
self.gossip_service.join()?;
|
|
|
|
self.tpu.join()?;
|
|
|
|
self.tvu.join()?;
|
|
|
|
self.ip_echo_server.shutdown_now();
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2019-02-06 19:47:55 -08:00
|
|
|
}
|
2018-09-14 01:53:18 -07:00
|
|
|
|
2020-01-13 14:13:52 -07:00
|
|
|
pub fn new_banks_from_blockstore(
|
2019-11-08 23:56:57 -05:00
|
|
|
expected_genesis_hash: Option<Hash>,
|
2020-01-13 14:13:52 -07:00
|
|
|
blockstore_path: &Path,
|
2019-12-05 21:41:29 -05:00
|
|
|
account_paths: Vec<PathBuf>,
|
2019-07-31 17:58:10 -07:00
|
|
|
snapshot_config: Option<SnapshotConfig>,
|
2019-11-04 22:14:55 -07:00
|
|
|
poh_verify: bool,
|
2019-08-08 09:14:30 -07:00
|
|
|
dev_halt_at_slot: Option<Slot>,
|
2019-12-03 16:31:59 -08:00
|
|
|
fixed_leader_schedule: Option<FixedSchedule>,
|
2019-04-19 02:39:44 -07:00
|
|
|
) -> (
|
2019-08-21 18:16:40 -07:00
|
|
|
Hash,
|
2019-04-19 02:39:44 -07:00
|
|
|
BankForks,
|
|
|
|
Vec<BankForksInfo>,
|
2020-01-13 14:13:52 -07:00
|
|
|
Blockstore,
|
2019-04-19 02:39:44 -07:00
|
|
|
Receiver<bool>,
|
2019-05-09 14:10:04 -07:00
|
|
|
CompletedSlotsReceiver,
|
2019-04-19 02:39:44 -07:00
|
|
|
LeaderScheduleCache,
|
2019-05-18 14:01:36 -07:00
|
|
|
PohConfig,
|
2019-04-19 02:39:44 -07:00
|
|
|
) {
|
2020-01-13 14:13:52 -07:00
|
|
|
let genesis_config = GenesisConfig::load(blockstore_path).unwrap_or_else(|err| {
|
|
|
|
error!("Failed to load genesis from {:?}: {}", blockstore_path, err);
|
2019-11-12 10:24:49 -07:00
|
|
|
process::exit(1);
|
|
|
|
});
|
2019-11-08 23:56:57 -05:00
|
|
|
let genesis_hash = genesis_config.hash();
|
|
|
|
info!("genesis hash: {}", genesis_hash);
|
|
|
|
|
|
|
|
if let Some(expected_genesis_hash) = expected_genesis_hash {
|
|
|
|
if genesis_hash != expected_genesis_hash {
|
|
|
|
error!("genesis hash mismatch: expected {}", expected_genesis_hash);
|
2019-08-30 09:10:22 -07:00
|
|
|
error!(
|
|
|
|
"Delete the ledger directory to continue: {:?}",
|
2020-01-13 14:13:52 -07:00
|
|
|
blockstore_path
|
2019-08-30 09:10:22 -07:00
|
|
|
);
|
2019-11-04 11:03:39 -07:00
|
|
|
process::exit(1);
|
2019-08-21 18:16:40 -07:00
|
|
|
}
|
|
|
|
}
|
2019-02-19 18:31:56 -08:00
|
|
|
|
2020-01-13 14:13:52 -07:00
|
|
|
let (blockstore, ledger_signal_receiver, completed_slots_receiver) =
|
|
|
|
Blockstore::open_with_signal(blockstore_path).expect("Failed to open ledger database");
|
2019-02-26 21:16:18 -08:00
|
|
|
|
2020-01-13 14:13:52 -07:00
|
|
|
let process_options = blockstore_processor::ProcessOptions {
|
2019-11-04 22:14:55 -07:00
|
|
|
poh_verify,
|
2019-11-04 19:10:06 -07:00
|
|
|
dev_halt_at_slot,
|
2020-01-13 14:13:52 -07:00
|
|
|
..blockstore_processor::ProcessOptions::default()
|
2019-11-04 19:10:06 -07:00
|
|
|
};
|
|
|
|
|
2019-12-03 16:31:59 -08:00
|
|
|
let (mut bank_forks, bank_forks_info, mut leader_schedule_cache) = bank_forks_utils::load(
|
2019-11-08 23:56:57 -05:00
|
|
|
&genesis_config,
|
2020-01-13 14:13:52 -07:00
|
|
|
&blockstore,
|
2019-07-12 16:58:13 -07:00
|
|
|
account_paths,
|
2019-08-25 21:33:41 -07:00
|
|
|
snapshot_config.as_ref(),
|
2019-11-04 19:10:06 -07:00
|
|
|
process_options,
|
|
|
|
)
|
|
|
|
.unwrap_or_else(|err| {
|
|
|
|
error!("Failed to load ledger: {:?}", err);
|
|
|
|
std::process::exit(1);
|
|
|
|
});
|
2019-02-06 19:47:55 -08:00
|
|
|
|
2019-12-03 16:31:59 -08:00
|
|
|
leader_schedule_cache.set_fixed_leader_schedule(fixed_leader_schedule);
|
|
|
|
|
2019-11-04 19:10:06 -07:00
|
|
|
bank_forks.set_snapshot_config(snapshot_config);
|
2019-08-25 21:33:41 -07:00
|
|
|
|
2019-02-06 19:47:55 -08:00
|
|
|
(
|
2019-11-08 23:56:57 -05:00
|
|
|
genesis_hash,
|
2019-02-20 17:05:57 -08:00
|
|
|
bank_forks,
|
|
|
|
bank_forks_info,
|
2020-01-13 14:13:52 -07:00
|
|
|
blockstore,
|
2019-02-16 20:58:07 -07:00
|
|
|
ledger_signal_receiver,
|
2019-05-09 14:10:04 -07:00
|
|
|
completed_slots_receiver,
|
2019-04-19 02:39:44 -07:00
|
|
|
leader_schedule_cache,
|
2019-11-08 23:56:57 -05:00
|
|
|
genesis_config.poh_config,
|
2019-02-16 20:58:07 -07:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2019-07-30 15:53:41 -07:00
|
|
|
pub fn new_validator_for_tests() -> (Validator, ContactInfo, Keypair, PathBuf) {
|
2019-11-08 23:56:57 -05:00
|
|
|
use crate::genesis_utils::{create_genesis_config_with_leader, GenesisConfigInfo};
|
2019-03-12 18:27:52 -06:00
|
|
|
|
|
|
|
let node_keypair = Arc::new(Keypair::new());
|
|
|
|
let node = Node::new_localhost_with_pubkey(&node_keypair.pubkey());
|
|
|
|
let contact_info = node.info.clone();
|
|
|
|
|
2019-11-08 23:56:57 -05:00
|
|
|
let GenesisConfigInfo {
|
|
|
|
mut genesis_config,
|
2019-05-22 20:39:00 -07:00
|
|
|
mint_keypair,
|
2019-11-06 14:15:00 -07:00
|
|
|
voting_keypair,
|
2019-11-14 10:56:49 +05:30
|
|
|
} = create_genesis_config_with_leader(1_000_000, &contact_info.id, 42);
|
2019-11-08 23:56:57 -05:00
|
|
|
genesis_config
|
2019-04-02 08:57:00 -06:00
|
|
|
.native_instruction_processors
|
2019-05-14 10:44:16 -07:00
|
|
|
.push(solana_budget_program!());
|
2019-03-12 18:27:52 -06:00
|
|
|
|
2019-11-08 23:56:57 -05:00
|
|
|
genesis_config.rent.lamports_per_byte_year = 1;
|
|
|
|
genesis_config.rent.exemption_threshold = 1.0;
|
2019-10-01 01:14:49 +05:30
|
|
|
|
2019-11-08 23:56:57 -05:00
|
|
|
let (ledger_path, _blockhash) = create_new_tmp_ledger!(&genesis_config);
|
2019-03-12 18:27:52 -06:00
|
|
|
|
2019-11-06 14:15:00 -07:00
|
|
|
let leader_voting_keypair = Arc::new(voting_keypair);
|
2019-05-15 15:19:29 -07:00
|
|
|
let storage_keypair = Arc::new(Keypair::new());
|
2019-11-20 16:43:10 -07:00
|
|
|
let mut config = ValidatorConfig::default();
|
|
|
|
config.transaction_status_service_disabled = true;
|
2019-05-23 22:05:16 -07:00
|
|
|
let node = Validator::new(
|
2019-03-12 18:27:52 -06:00
|
|
|
node,
|
|
|
|
&node_keypair,
|
|
|
|
&ledger_path,
|
2019-11-06 14:15:00 -07:00
|
|
|
&leader_voting_keypair.pubkey(),
|
|
|
|
&leader_voting_keypair,
|
2019-05-15 15:19:29 -07:00
|
|
|
&storage_keypair,
|
2019-03-12 18:27:52 -06:00
|
|
|
None,
|
2019-07-12 16:58:13 -07:00
|
|
|
true,
|
2019-11-20 16:43:10 -07:00
|
|
|
&config,
|
2019-03-12 18:27:52 -06:00
|
|
|
);
|
2019-05-16 07:14:58 -07:00
|
|
|
discover_cluster(&contact_info.gossip, 1).expect("Node startup failed");
|
2019-03-12 18:27:52 -06:00
|
|
|
(node, contact_info, mint_keypair, ledger_path)
|
|
|
|
}
|
|
|
|
|
2020-01-07 14:33:39 -07:00
|
|
|
fn report_target_features() {
|
|
|
|
warn!(
|
|
|
|
"CUDA is {}abled",
|
|
|
|
if solana_perf::perf_libs::api().is_some() {
|
|
|
|
"en"
|
|
|
|
} else {
|
|
|
|
"dis"
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
// Validator binaries built on a machine with AVX support will generate invalid opcodes
|
|
|
|
// when run on machines without AVX causing a non-obvious process abort. Instead detect
|
|
|
|
// the mismatch and error cleanly.
|
|
|
|
#[target_feature(enable = "avx")]
|
|
|
|
{
|
|
|
|
if is_x86_feature_detected!("avx") {
|
|
|
|
info!("AVX detected");
|
|
|
|
} else {
|
|
|
|
error!("Your machine does not have AVX support, please rebuild from source on your machine");
|
|
|
|
process::exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-07 14:18:34 -07:00
|
|
|
// Get the activated stake percentage (based on the provided bank) that is visible in gossip
|
|
|
|
fn get_stake_percent_in_gossip(
|
|
|
|
bank: &Arc<solana_runtime::bank::Bank>,
|
|
|
|
cluster_info: &Arc<RwLock<ClusterInfo>>,
|
|
|
|
) -> u64 {
|
|
|
|
let mut gossip_stake = 0;
|
|
|
|
let mut total_activated_stake = 0;
|
|
|
|
let tvu_peers = cluster_info.read().unwrap().tvu_peers();
|
|
|
|
|
|
|
|
for (activated_stake, vote_account) in bank.vote_accounts().values() {
|
|
|
|
let vote_state =
|
|
|
|
solana_vote_program::vote_state::VoteState::from(&vote_account).unwrap_or_default();
|
|
|
|
total_activated_stake += activated_stake;
|
|
|
|
if tvu_peers
|
|
|
|
.iter()
|
|
|
|
.any(|peer| peer.id == vote_state.node_pubkey)
|
|
|
|
{
|
|
|
|
trace!(
|
|
|
|
"observed {} in gossip, (activated_stake={})",
|
|
|
|
vote_state.node_pubkey,
|
|
|
|
activated_stake
|
|
|
|
);
|
|
|
|
gossip_stake += activated_stake;
|
2020-01-07 20:35:09 -07:00
|
|
|
} else if vote_state.node_pubkey == cluster_info.read().unwrap().id() {
|
|
|
|
gossip_stake += activated_stake;
|
2020-01-07 14:18:34 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
gossip_stake * 100 / total_activated_stake
|
|
|
|
}
|
|
|
|
|
2018-07-02 15:24:40 -07:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2019-01-31 20:41:03 -08:00
|
|
|
use super::*;
|
2019-11-08 23:56:57 -05:00
|
|
|
use crate::genesis_utils::create_genesis_config_with_leader;
|
2018-09-14 01:53:18 -07:00
|
|
|
use std::fs::remove_dir_all;
|
2018-08-03 11:06:06 -07:00
|
|
|
|
2018-07-02 15:24:40 -07:00
|
|
|
#[test]
|
|
|
|
fn validator_exit() {
|
2019-05-23 14:50:23 -07:00
|
|
|
solana_logger::setup();
|
2019-01-29 18:12:32 -08:00
|
|
|
let leader_keypair = Keypair::new();
|
2019-03-09 19:28:43 -08:00
|
|
|
let leader_node = Node::new_localhost_with_pubkey(&leader_keypair.pubkey());
|
2018-10-25 16:58:40 -07:00
|
|
|
|
2019-01-29 18:12:32 -08:00
|
|
|
let validator_keypair = Keypair::new();
|
2019-03-09 19:28:43 -08:00
|
|
|
let validator_node = Node::new_localhost_with_pubkey(&validator_keypair.pubkey());
|
2019-11-08 23:56:57 -05:00
|
|
|
let genesis_config =
|
|
|
|
create_genesis_config_with_leader(10_000, &leader_keypair.pubkey(), 1000)
|
|
|
|
.genesis_config;
|
|
|
|
let (validator_ledger_path, _blockhash) = create_new_tmp_ledger!(&genesis_config);
|
2019-01-29 18:12:32 -08:00
|
|
|
|
2019-05-15 15:19:29 -07:00
|
|
|
let voting_keypair = Arc::new(Keypair::new());
|
|
|
|
let storage_keypair = Arc::new(Keypair::new());
|
2019-11-20 16:43:10 -07:00
|
|
|
let mut config = ValidatorConfig::default();
|
|
|
|
config.transaction_status_service_disabled = true;
|
2019-05-23 22:05:16 -07:00
|
|
|
let validator = Validator::new(
|
2019-01-29 18:12:32 -08:00
|
|
|
validator_node,
|
2019-01-30 20:51:50 -07:00
|
|
|
&Arc::new(validator_keypair),
|
2019-01-24 12:04:04 -08:00
|
|
|
&validator_ledger_path,
|
2019-03-09 19:28:43 -08:00
|
|
|
&voting_keypair.pubkey(),
|
2019-05-15 15:19:29 -07:00
|
|
|
&voting_keypair,
|
|
|
|
&storage_keypair,
|
2019-01-29 18:12:32 -08:00
|
|
|
Some(&leader_node.info),
|
2019-07-12 16:58:13 -07:00
|
|
|
true,
|
2019-11-20 16:43:10 -07:00
|
|
|
&config,
|
2018-09-14 01:53:18 -07:00
|
|
|
);
|
2019-01-29 18:12:32 -08:00
|
|
|
validator.close().unwrap();
|
2018-09-14 01:53:18 -07:00
|
|
|
remove_dir_all(validator_ledger_path).unwrap();
|
2018-07-02 11:20:35 -07:00
|
|
|
}
|
2018-09-25 15:41:29 -07:00
|
|
|
|
2018-07-17 08:18:42 -07:00
|
|
|
#[test]
|
|
|
|
fn validator_parallel_exit() {
|
2019-01-29 18:12:32 -08:00
|
|
|
let leader_keypair = Keypair::new();
|
2019-03-09 19:28:43 -08:00
|
|
|
let leader_node = Node::new_localhost_with_pubkey(&leader_keypair.pubkey());
|
2019-01-29 18:12:32 -08:00
|
|
|
|
2018-09-14 01:53:18 -07:00
|
|
|
let mut ledger_paths = vec![];
|
2019-08-20 23:59:31 -07:00
|
|
|
let mut validators: Vec<Validator> = (0..2)
|
2019-02-26 19:36:46 -08:00
|
|
|
.map(|_| {
|
2019-01-29 18:12:32 -08:00
|
|
|
let validator_keypair = Keypair::new();
|
2019-03-09 19:28:43 -08:00
|
|
|
let validator_node = Node::new_localhost_with_pubkey(&validator_keypair.pubkey());
|
2019-11-08 23:56:57 -05:00
|
|
|
let genesis_config =
|
|
|
|
create_genesis_config_with_leader(10_000, &leader_keypair.pubkey(), 1000)
|
|
|
|
.genesis_config;
|
|
|
|
let (validator_ledger_path, _blockhash) = create_new_tmp_ledger!(&genesis_config);
|
2018-09-14 01:53:18 -07:00
|
|
|
ledger_paths.push(validator_ledger_path.clone());
|
2019-05-15 15:19:29 -07:00
|
|
|
let voting_keypair = Arc::new(Keypair::new());
|
|
|
|
let storage_keypair = Arc::new(Keypair::new());
|
2019-11-20 16:43:10 -07:00
|
|
|
let mut config = ValidatorConfig::default();
|
|
|
|
config.transaction_status_service_disabled = true;
|
2019-05-23 22:05:16 -07:00
|
|
|
Validator::new(
|
2019-01-29 18:12:32 -08:00
|
|
|
validator_node,
|
2019-01-30 20:51:50 -07:00
|
|
|
&Arc::new(validator_keypair),
|
2019-01-24 12:04:04 -08:00
|
|
|
&validator_ledger_path,
|
2019-03-09 19:28:43 -08:00
|
|
|
&voting_keypair.pubkey(),
|
2019-05-15 15:19:29 -07:00
|
|
|
&voting_keypair,
|
|
|
|
&storage_keypair,
|
2019-01-29 18:12:32 -08:00
|
|
|
Some(&leader_node.info),
|
2019-07-12 16:58:13 -07:00
|
|
|
true,
|
2019-11-20 16:43:10 -07:00
|
|
|
&config,
|
2018-09-14 01:53:18 -07:00
|
|
|
)
|
2018-12-07 20:01:28 -07:00
|
|
|
})
|
|
|
|
.collect();
|
2018-09-14 01:53:18 -07:00
|
|
|
|
2019-01-29 18:12:32 -08:00
|
|
|
// Each validator can exit in parallel to speed many sequential calls to `join`
|
2019-08-20 23:59:31 -07:00
|
|
|
validators.iter_mut().for_each(|v| v.exit());
|
2019-01-29 18:12:32 -08:00
|
|
|
// While join is called sequentially, the above exit call notified all the
|
|
|
|
// validators to exit from all their threads
|
|
|
|
validators.into_iter().for_each(|validator| {
|
|
|
|
validator.join().unwrap();
|
2018-08-03 11:06:06 -07:00
|
|
|
});
|
2018-09-14 01:53:18 -07:00
|
|
|
|
|
|
|
for path in ledger_paths {
|
|
|
|
remove_dir_all(path).unwrap();
|
|
|
|
}
|
2018-07-17 08:18:42 -07:00
|
|
|
}
|
2018-07-02 11:20:35 -07:00
|
|
|
}
|