Skip to content

Commit

Permalink
solana-validator set-identity now supports the --require-tower flag
Browse files Browse the repository at this point in the history
  • Loading branch information
mvines authored and jeffwashington committed Mar 4, 2022
1 parent 452ef49 commit 57acac9
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 35 deletions.
5 changes: 4 additions & 1 deletion core/src/validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ pub struct Validator {
tvu: Tvu,
ip_echo_server: Option<solana_net_utils::IpEchoServer>,
pub cluster_info: Arc<ClusterInfo>,
pub bank_forks: Arc<RwLock<BankForks>>,
accountsdb_repl_service: Option<AccountsDbReplService>,
accountsdb_plugin_service: Option<AccountsDbPluginService>,
}
Expand Down Expand Up @@ -897,7 +898,7 @@ impl Validator {
&exit,
node.info.shred_version,
vote_tracker,
bank_forks,
bank_forks.clone(),
verified_vote_sender,
gossip_verified_vote_hash_sender,
replay_vote_receiver,
Expand Down Expand Up @@ -934,6 +935,7 @@ impl Validator {
ip_echo_server,
validator_exit: config.validator_exit.clone(),
cluster_info,
bank_forks,
accountsdb_repl_service,
accountsdb_plugin_service,
}
Expand Down Expand Up @@ -975,6 +977,7 @@ impl Validator {
}

pub fn join(self) {
drop(self.bank_forks);
drop(self.cluster_info);

self.poh_service.join().expect("poh_service");
Expand Down
6 changes: 5 additions & 1 deletion test-validator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use {
solana_net_utils::PortRange,
solana_rpc::{rpc::JsonRpcConfig, rpc_pubsub_service::PubSubConfig},
solana_runtime::{
genesis_utils::create_genesis_config_with_leader_ex,
bank_forks::BankForks, genesis_utils::create_genesis_config_with_leader_ex,
hardened_unpack::MAX_GENESIS_ARCHIVE_UNPACKED_SIZE, snapshot_config::SnapshotConfig,
},
solana_sdk::{
Expand Down Expand Up @@ -830,6 +830,10 @@ impl TestValidator {
pub fn cluster_info(&self) -> Arc<ClusterInfo> {
self.validator.as_ref().unwrap().cluster_info.clone()
}

pub fn bank_forks(&self) -> Arc<RwLock<BankForks>> {
self.validator.as_ref().unwrap().bank_forks.clone()
}
}

impl Drop for TestValidator {
Expand Down
106 changes: 80 additions & 26 deletions validator/src/admin_rpc_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ use {
consensus::Tower, tower_storage::TowerStorage, validator::ValidatorStartProgress,
},
solana_gossip::{cluster_info::ClusterInfo, contact_info::ContactInfo},
solana_runtime::bank_forks::BankForks,
solana_sdk::{
exit::Exit,
pubkey::Pubkey,
signature::{read_keypair_file, Keypair, Signer},
},
std::{
Expand All @@ -24,18 +26,40 @@ use {
},
};

#[derive(Clone)]
pub struct AdminRpcRequestMetadataPostInit {
pub cluster_info: Arc<ClusterInfo>,
pub bank_forks: Arc<RwLock<BankForks>>,
pub vote_account: Pubkey,
}

#[derive(Clone)]
pub struct AdminRpcRequestMetadata {
pub rpc_addr: Option<SocketAddr>,
pub start_time: SystemTime,
pub start_progress: Arc<RwLock<ValidatorStartProgress>>,
pub validator_exit: Arc<RwLock<Exit>>,
pub authorized_voter_keypairs: Arc<RwLock<Vec<Arc<Keypair>>>>,
pub cluster_info: Arc<RwLock<Option<Arc<ClusterInfo>>>>,
pub tower_storage: Arc<dyn TowerStorage>,
pub post_init: Arc<RwLock<Option<AdminRpcRequestMetadataPostInit>>>,
}
impl Metadata for AdminRpcRequestMetadata {}

impl AdminRpcRequestMetadata {
fn with_post_init<F, R>(&self, func: F) -> Result<R>
where
F: FnOnce(&AdminRpcRequestMetadataPostInit) -> Result<R>,
{
if let Some(post_init) = self.post_init.read().unwrap().as_ref() {
func(post_init)
} else {
Err(jsonrpc_core::error::Error::invalid_params(
"Retry once validator start up is complete",
))
}
}
}

#[derive(Debug, Deserialize, Serialize)]
pub struct AdminRpcContactInfo {
pub id: String,
Expand Down Expand Up @@ -132,7 +156,12 @@ pub trait AdminRpc {
fn remove_all_authorized_voters(&self, meta: Self::Metadata) -> Result<()>;

#[rpc(meta, name = "setIdentity")]
fn set_identity(&self, meta: Self::Metadata, keypair_file: String) -> Result<()>;
fn set_identity(
&self,
meta: Self::Metadata,
keypair_file: String,
require_tower: bool,
) -> Result<()>;

#[rpc(meta, name = "contactInfo")]
fn contact_info(&self, meta: Self::Metadata) -> Result<AdminRpcContactInfo>;
Expand Down Expand Up @@ -212,7 +241,12 @@ impl AdminRpc for AdminRpcImpl {
Ok(())
}

fn set_identity(&self, meta: Self::Metadata, keypair_file: String) -> Result<()> {
fn set_identity(
&self,
meta: Self::Metadata,
keypair_file: String,
require_tower: bool,
) -> Result<()> {
debug!("set_identity request received");

let identity_keypair = read_keypair_file(&keypair_file).map_err(|err| {
Expand All @@ -222,35 +256,55 @@ impl AdminRpc for AdminRpcImpl {
))
})?;

// Ensure a Tower exists for the new identity and exit gracefully.
// ReplayStage will be less forgiving if it fails to load the new tower.
Tower::restore(meta.tower_storage.as_ref(), &identity_keypair.pubkey()).map_err(|err| {
jsonrpc_core::error::Error::invalid_params(format!(
"Unable to load tower file for new identity: {}",
err
))
})?;
meta.with_post_init(|post_init| {
// Ensure a Tower exists for the new identity and exit gracefully.
// ReplayStage will be less forgiving if it fails to load the new tower.
if let Err(err) =
Tower::restore(meta.tower_storage.as_ref(), &identity_keypair.pubkey()).map_err(
|err| {
jsonrpc_core::error::Error::invalid_params(format!(
"Unable to load tower file for identity {}: {}",
identity_keypair.pubkey(),
err
))
},
)
{
if require_tower {
return Err(err);
}

let root_bank = post_init.bank_forks.read().unwrap().root_bank();
let mut tower = Tower::new(
&identity_keypair.pubkey(),
&post_init.vote_account,
root_bank.slot(),
&root_bank,
);
// Forge a single vote to pacify `Tower::adjust_lockouts_after_replay` when its called
// by replay_stage
tower.record_bank_vote(&root_bank, &post_init.vote_account);
tower
.save(meta.tower_storage.as_ref(), &identity_keypair)
.map_err(|err| {
jsonrpc_core::error::Error::invalid_params(format!(
"Unable to create default tower file for ephemeral identity: {}",
err
))
})?;
}

if let Some(cluster_info) = meta.cluster_info.read().unwrap().as_ref() {
solana_metrics::set_host_id(identity_keypair.pubkey().to_string());
cluster_info.set_keypair(Arc::new(identity_keypair));
warn!("Identity set to {}", cluster_info.id());
post_init
.cluster_info
.set_keypair(Arc::new(identity_keypair));
warn!("Identity set to {}", post_init.cluster_info.id());
Ok(())
} else {
Err(jsonrpc_core::error::Error::invalid_params(
"Retry once validator start up is complete",
))
}
})
}

fn contact_info(&self, meta: Self::Metadata) -> Result<AdminRpcContactInfo> {
if let Some(cluster_info) = meta.cluster_info.read().unwrap().as_ref() {
Ok(cluster_info.my_contact_info().into())
} else {
Err(jsonrpc_core::error::Error::invalid_params(
"Retry once validator start up is complete",
))
}
meta.with_post_init(|post_init| Ok(post_init.cluster_info.my_contact_info().into()))
}
}

Expand Down
11 changes: 8 additions & 3 deletions validator/src/bin/solana-test-validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,7 @@ fn main() {

let tower_storage = Arc::new(FileTowerStorage::new(ledger_path.clone()));

let admin_service_cluster_info = Arc::new(RwLock::new(None));
let admin_service_post_init = Arc::new(RwLock::new(None));
admin_rpc_service::run(
&ledger_path,
admin_rpc_service::AdminRpcRequestMetadata {
Expand All @@ -601,7 +601,7 @@ fn main() {
start_time: std::time::SystemTime::now(),
validator_exit: genesis.validator_exit.clone(),
authorized_voter_keypairs: genesis.authorized_voter_keypairs.clone(),
cluster_info: admin_service_cluster_info.clone(),
post_init: admin_service_post_init.clone(),
tower_storage: tower_storage.clone(),
},
);
Expand Down Expand Up @@ -695,7 +695,12 @@ fn main() {

match genesis.start_with_mint_address(mint_address, socket_addr_space) {
Ok(test_validator) => {
*admin_service_cluster_info.write().unwrap() = Some(test_validator.cluster_info());
*admin_service_post_init.write().unwrap() =
Some(admin_rpc_service::AdminRpcRequestMetadataPostInit {
bank_forks: test_validator.bank_forks(),
cluster_info: test_validator.cluster_info(),
vote_account: test_validator.vote_account_address(),
});
if let Some(dashboard) = dashboard {
dashboard.run(Duration::from_millis(250));
}
Expand Down
20 changes: 16 additions & 4 deletions validator/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1678,6 +1678,12 @@ pub fn main() {
.validator(is_keypair)
.help("Validator identity keypair")
)
.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"),
)
.after_help("Note: the new identity only applies to the \
currently running validator instance")
)
Expand Down Expand Up @@ -1849,6 +1855,7 @@ pub fn main() {
return;
}
("set-identity", Some(subcommand_matches)) => {
let require_tower = subcommand_matches.is_present("require_tower");
let identity_keypair = value_t_or_exit!(subcommand_matches, "identity", String);

let identity_keypair = fs::canonicalize(&identity_keypair).unwrap_or_else(|err| {
Expand All @@ -1862,7 +1869,7 @@ pub fn main() {
.block_on(async move {
admin_client
.await?
.set_identity(identity_keypair.display().to_string())
.set_identity(identity_keypair.display().to_string(), require_tower)
.await
})
.unwrap_or_else(|err| {
Expand Down Expand Up @@ -2519,7 +2526,7 @@ pub fn main() {
let _ledger_write_guard = lock_ledger(&ledger_path, &mut ledger_lock);

let start_progress = Arc::new(RwLock::new(ValidatorStartProgress::default()));
let admin_service_cluster_info = Arc::new(RwLock::new(None));
let admin_service_post_init = Arc::new(RwLock::new(None));
admin_rpc_service::run(
&ledger_path,
admin_rpc_service::AdminRpcRequestMetadata {
Expand All @@ -2528,7 +2535,7 @@ pub fn main() {
validator_exit: validator_config.validator_exit.clone(),
start_progress: start_progress.clone(),
authorized_voter_keypairs: authorized_voter_keypairs.clone(),
cluster_info: admin_service_cluster_info.clone(),
post_init: admin_service_post_init.clone(),
tower_storage: validator_config.tower_storage.clone(),
},
);
Expand Down Expand Up @@ -2673,7 +2680,12 @@ pub fn main() {
start_progress,
socket_addr_space,
);
*admin_service_cluster_info.write().unwrap() = Some(validator.cluster_info.clone());
*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,
});

if let Some(filename) = init_complete_file {
File::create(filename).unwrap_or_else(|_| {
Expand Down

0 comments on commit 57acac9

Please sign in to comment.