Support reading keypair from stdin in `solana-validator set-identity`/`solana-validator authorized-voter add` (#26056)
* Add keypair reading from stdin in `validator set-identity` * Add keypair reading from stdin in `validator authorized-voter add`
This commit is contained in:
parent
fbcb4d8216
commit
1884275882
|
@ -152,6 +152,10 @@ pub trait AdminRpc {
|
|||
#[rpc(meta, name = "addAuthorizedVoter")]
|
||||
fn add_authorized_voter(&self, meta: Self::Metadata, keypair_file: String) -> Result<()>;
|
||||
|
||||
#[rpc(meta, name = "addAuthorizedVoterFromBytes")]
|
||||
fn add_authorized_voter_from_bytes(&self, meta: Self::Metadata, keypair: Vec<u8>)
|
||||
-> Result<()>;
|
||||
|
||||
#[rpc(meta, name = "removeAllAuthorizedVoters")]
|
||||
fn remove_all_authorized_voters(&self, meta: Self::Metadata) -> Result<()>;
|
||||
|
||||
|
@ -163,6 +167,14 @@ pub trait AdminRpc {
|
|||
require_tower: bool,
|
||||
) -> Result<()>;
|
||||
|
||||
#[rpc(meta, name = "setIdentityFromBytes")]
|
||||
fn set_identity_from_bytes(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
identity_keypair: Vec<u8>,
|
||||
require_tower: bool,
|
||||
) -> Result<()>;
|
||||
|
||||
#[rpc(meta, name = "contactInfo")]
|
||||
fn contact_info(&self, meta: Self::Metadata) -> Result<AdminRpcContactInfo>;
|
||||
}
|
||||
|
@ -220,19 +232,24 @@ impl AdminRpc for AdminRpcImpl {
|
|||
let authorized_voter = read_keypair_file(keypair_file)
|
||||
.map_err(|err| jsonrpc_core::error::Error::invalid_params(format!("{}", err)))?;
|
||||
|
||||
let mut authorized_voter_keypairs = meta.authorized_voter_keypairs.write().unwrap();
|
||||
AdminRpcImpl::add_authorized_voter_keypair(meta, authorized_voter)
|
||||
}
|
||||
|
||||
if authorized_voter_keypairs
|
||||
.iter()
|
||||
.any(|x| x.pubkey() == authorized_voter.pubkey())
|
||||
{
|
||||
Err(jsonrpc_core::error::Error::invalid_params(
|
||||
"Authorized voter already present",
|
||||
fn add_authorized_voter_from_bytes(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
keypair: Vec<u8>,
|
||||
) -> Result<()> {
|
||||
debug!("add_authorized_voter_from_bytes request received");
|
||||
|
||||
let authorized_voter = Keypair::from_bytes(&keypair).map_err(|err| {
|
||||
jsonrpc_core::error::Error::invalid_params(format!(
|
||||
"Failed to read authorized voter keypair from provided byte array: {}",
|
||||
err
|
||||
))
|
||||
} else {
|
||||
authorized_voter_keypairs.push(Arc::new(authorized_voter));
|
||||
Ok(())
|
||||
}
|
||||
})?;
|
||||
|
||||
AdminRpcImpl::add_authorized_voter_keypair(meta, authorized_voter)
|
||||
}
|
||||
|
||||
fn remove_all_authorized_voters(&self, meta: Self::Metadata) -> Result<()> {
|
||||
|
@ -256,6 +273,57 @@ impl AdminRpc for AdminRpcImpl {
|
|||
))
|
||||
})?;
|
||||
|
||||
AdminRpcImpl::set_identity_keypair(meta, identity_keypair, require_tower)
|
||||
}
|
||||
|
||||
fn set_identity_from_bytes(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
identity_keypair: Vec<u8>,
|
||||
require_tower: bool,
|
||||
) -> Result<()> {
|
||||
debug!("set_identity_from_bytes request received");
|
||||
|
||||
let identity_keypair = Keypair::from_bytes(&identity_keypair).map_err(|err| {
|
||||
jsonrpc_core::error::Error::invalid_params(format!(
|
||||
"Failed to read identity keypair from provided byte array: {}",
|
||||
err
|
||||
))
|
||||
})?;
|
||||
|
||||
AdminRpcImpl::set_identity_keypair(meta, identity_keypair, require_tower)
|
||||
}
|
||||
|
||||
fn contact_info(&self, meta: Self::Metadata) -> Result<AdminRpcContactInfo> {
|
||||
meta.with_post_init(|post_init| Ok(post_init.cluster_info.my_contact_info().into()))
|
||||
}
|
||||
}
|
||||
|
||||
impl AdminRpcImpl {
|
||||
fn add_authorized_voter_keypair(
|
||||
meta: AdminRpcRequestMetadata,
|
||||
authorized_voter: Keypair,
|
||||
) -> Result<()> {
|
||||
let mut authorized_voter_keypairs = meta.authorized_voter_keypairs.write().unwrap();
|
||||
|
||||
if authorized_voter_keypairs
|
||||
.iter()
|
||||
.any(|x| x.pubkey() == authorized_voter.pubkey())
|
||||
{
|
||||
Err(jsonrpc_core::error::Error::invalid_params(
|
||||
"Authorized voter already present",
|
||||
))
|
||||
} else {
|
||||
authorized_voter_keypairs.push(Arc::new(authorized_voter));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn set_identity_keypair(
|
||||
meta: AdminRpcRequestMetadata,
|
||||
identity_keypair: Keypair,
|
||||
require_tower: bool,
|
||||
) -> Result<()> {
|
||||
meta.with_post_init(|post_init| {
|
||||
if require_tower {
|
||||
let _ = Tower::restore(meta.tower_storage.as_ref(), &identity_keypair.pubkey())
|
||||
|
@ -276,10 +344,6 @@ impl AdminRpc for AdminRpcImpl {
|
|||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
fn contact_info(&self, meta: Self::Metadata) -> Result<AdminRpcContactInfo> {
|
||||
meta.with_post_init(|post_init| Ok(post_init.cluster_info.my_contact_info().into()))
|
||||
}
|
||||
}
|
||||
|
||||
// Start the Admin RPC interface
|
||||
|
|
|
@ -66,7 +66,7 @@ use {
|
|||
commitment_config::CommitmentConfig,
|
||||
hash::Hash,
|
||||
pubkey::Pubkey,
|
||||
signature::{Keypair, Signer},
|
||||
signature::{read_keypair, Keypair, Signer},
|
||||
},
|
||||
solana_send_transaction_service::send_transaction_service::{
|
||||
self, MAX_BATCH_SEND_RATE_MS, MAX_TRANSACTION_BATCH_SIZE,
|
||||
|
@ -1822,9 +1822,11 @@ pub fn main() {
|
|||
Arg::with_name("authorized_voter_keypair")
|
||||
.index(1)
|
||||
.value_name("KEYPAIR")
|
||||
.required(false)
|
||||
.takes_value(true)
|
||||
.validator(is_keypair)
|
||||
.help("Keypair of the authorized voter to add"),
|
||||
.help("Path to keypair of the authorized voter to add \
|
||||
[default: read JSON keypair from stdin]"),
|
||||
)
|
||||
.after_help("Note: the new authorized voter only applies to the \
|
||||
currently running validator instance")
|
||||
|
@ -1867,9 +1869,11 @@ pub fn main() {
|
|||
Arg::with_name("identity")
|
||||
.index(1)
|
||||
.value_name("KEYPAIR")
|
||||
.required(false)
|
||||
.takes_value(true)
|
||||
.validator(is_keypair)
|
||||
.help("Validator identity keypair")
|
||||
.help("Path to validator identity keypair \
|
||||
[default: read JSON keypair from stdin]")
|
||||
)
|
||||
.arg(
|
||||
clap::Arg::with_name("require_tower")
|
||||
|
@ -1938,36 +1942,64 @@ pub fn main() {
|
|||
("authorized-voter", Some(authorized_voter_subcommand_matches)) => {
|
||||
match authorized_voter_subcommand_matches.subcommand() {
|
||||
("add", Some(subcommand_matches)) => {
|
||||
let authorized_voter_keypair =
|
||||
value_t_or_exit!(subcommand_matches, "authorized_voter_keypair", String);
|
||||
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()
|
||||
);
|
||||
|
||||
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: {}",
|
||||
authorized_voter_keypair.display()
|
||||
);
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
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);
|
||||
});
|
||||
return;
|
||||
}
|
||||
("remove-all", _) => {
|
||||
|
@ -2049,26 +2081,54 @@ pub fn main() {
|
|||
}
|
||||
("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| {
|
||||
println!("Unable to access path: {}: {:?}", identity_keypair, err);
|
||||
exit(1);
|
||||
});
|
||||
println!("Validator identity: {}", identity_keypair.display());
|
||||
|
||||
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);
|
||||
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()
|
||||
);
|
||||
|
||||
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);
|
||||
exit(1);
|
||||
});
|
||||
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);
|
||||
});
|
||||
};
|
||||
|
||||
return;
|
||||
}
|
||||
("set-log-filter", Some(subcommand_matches)) => {
|
||||
|
|
Loading…
Reference in New Issue