Remove ask-seed-phrase arg from validator, archiver (#8697)

* Remove ask-seed-phrase from validator

* Update paper-wallet docs

* Remove ask-seed-phrase from archiver

* Remove unused structs, methods
This commit is contained in:
Tyera Eulberg 2020-03-06 22:22:23 -07:00 committed by GitHub
parent 983ec5debc
commit a7d1346d51
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 32 additions and 155 deletions

View File

@ -2,21 +2,20 @@ use clap::{crate_description, crate_name, App, Arg};
use console::style; use console::style;
use solana_archiver_lib::archiver::Archiver; use solana_archiver_lib::archiver::Archiver;
use solana_clap_utils::{ use solana_clap_utils::{
input_validators::is_keypair, input_parsers::keypair_of, input_validators::is_keypair_or_ask_keyword,
keypair::{ keypair::SKIP_SEED_PHRASE_VALIDATION_ARG,
self, keypair_input, KeypairWithSource, ASK_SEED_PHRASE_ARG,
SKIP_SEED_PHRASE_VALIDATION_ARG,
},
}; };
use solana_core::{ use solana_core::{
cluster_info::{Node, VALIDATOR_PORT_RANGE}, cluster_info::{Node, VALIDATOR_PORT_RANGE},
contact_info::ContactInfo, contact_info::ContactInfo,
}; };
use solana_sdk::{commitment_config::CommitmentConfig, signature::Signer}; use solana_sdk::{
commitment_config::CommitmentConfig,
signature::{Keypair, Signer},
};
use std::{ use std::{
net::{IpAddr, Ipv4Addr, SocketAddr}, net::{IpAddr, Ipv4Addr, SocketAddr},
path::PathBuf, path::PathBuf,
process::exit,
sync::Arc, sync::Arc,
}; };
@ -32,7 +31,7 @@ fn main() {
.long("identity-keypair") .long("identity-keypair")
.value_name("PATH") .value_name("PATH")
.takes_value(true) .takes_value(true)
.validator(is_keypair) .validator(is_keypair_or_ask_keyword)
.help("File containing an identity (keypair)"), .help("File containing an identity (keypair)"),
) )
.arg( .arg(
@ -60,48 +59,27 @@ fn main() {
.long("storage-keypair") .long("storage-keypair")
.value_name("PATH") .value_name("PATH")
.takes_value(true) .takes_value(true)
.validator(is_keypair) .validator(is_keypair_or_ask_keyword)
.help("File containing the storage account keypair"), .help("File containing the storage account keypair"),
) )
.arg(
Arg::with_name(ASK_SEED_PHRASE_ARG.name)
.long(ASK_SEED_PHRASE_ARG.long)
.value_name("KEYPAIR NAME")
.multiple(true)
.takes_value(true)
.possible_values(&["identity-keypair", "storage-keypair"])
.help(ASK_SEED_PHRASE_ARG.help),
)
.arg( .arg(
Arg::with_name(SKIP_SEED_PHRASE_VALIDATION_ARG.name) Arg::with_name(SKIP_SEED_PHRASE_VALIDATION_ARG.name)
.long(SKIP_SEED_PHRASE_VALIDATION_ARG.long) .long(SKIP_SEED_PHRASE_VALIDATION_ARG.long)
.requires(ASK_SEED_PHRASE_ARG.name)
.help(SKIP_SEED_PHRASE_VALIDATION_ARG.help), .help(SKIP_SEED_PHRASE_VALIDATION_ARG.help),
) )
.get_matches(); .get_matches();
let ledger_path = PathBuf::from(matches.value_of("ledger").unwrap()); let ledger_path = PathBuf::from(matches.value_of("ledger").unwrap());
let identity_keypair = keypair_input(&matches, "identity_keypair") let identity_keypair = keypair_of(&matches, "identity_keypair").unwrap_or_else(Keypair::new);
.unwrap_or_else(|err| {
eprintln!("Identity keypair input failed: {}", err); let storage_keypair = keypair_of(&matches, "storage_keypair").unwrap_or_else(|| {
exit(1);
})
.keypair;
let KeypairWithSource {
keypair: storage_keypair,
source: storage_keypair_source,
} = keypair_input(&matches, "storage_keypair").unwrap_or_else(|err| {
eprintln!("Storage keypair input failed: {}", err);
exit(1);
});
if storage_keypair_source == keypair::Source::Generated {
clap::Error::with_description( clap::Error::with_description(
"The `storage-keypair` argument was not found", "The `storage-keypair` argument was not found",
clap::ErrorKind::ArgumentNotFound, clap::ErrorKind::ArgumentNotFound,
) )
.exit(); .exit();
} });
let entrypoint_addr = matches let entrypoint_addr = matches
.value_of("entrypoint") .value_of("entrypoint")

View File

@ -4,7 +4,7 @@ use crate::{
ArgConstant, ArgConstant,
}; };
use bip39::{Language, Mnemonic, Seed}; use bip39::{Language, Mnemonic, Seed};
use clap::{values_t, ArgMatches, Error, ErrorKind}; use clap::{ArgMatches, Error, ErrorKind};
use rpassword::prompt_password_stderr; use rpassword::prompt_password_stderr;
use solana_remote_wallet::{ use solana_remote_wallet::{
remote_keypair::generate_remote_keypair, remote_keypair::generate_remote_keypair,
@ -113,36 +113,12 @@ pub fn signer_from_path(
// Keyword used to indicate that the user should be asked for a keypair seed phrase // Keyword used to indicate that the user should be asked for a keypair seed phrase
pub const ASK_KEYWORD: &str = "ASK"; pub const ASK_KEYWORD: &str = "ASK";
pub const ASK_SEED_PHRASE_ARG: ArgConstant<'static> = ArgConstant {
long: "ask-seed-phrase",
name: "ask_seed_phrase",
help: "Recover a keypair using a seed phrase and optional passphrase",
};
pub const SKIP_SEED_PHRASE_VALIDATION_ARG: ArgConstant<'static> = ArgConstant { pub const SKIP_SEED_PHRASE_VALIDATION_ARG: ArgConstant<'static> = ArgConstant {
long: "skip-seed-phrase-validation", long: "skip-seed-phrase-validation",
name: "skip_seed_phrase_validation", name: "skip_seed_phrase_validation",
help: "Skip validation of seed phrases. Use this if your phrase does not use the BIP39 official English word list", help: "Skip validation of seed phrases. Use this if your phrase does not use the BIP39 official English word list",
}; };
#[derive(Debug, PartialEq)]
pub enum Source {
Generated,
Path,
SeedPhrase,
}
pub struct KeypairWithSource {
pub keypair: Keypair,
pub source: Source,
}
impl KeypairWithSource {
fn new(keypair: Keypair, source: Source) -> Self {
Self { keypair, source }
}
}
/// Prompts user for a passphrase and then asks for confirmirmation to check for mistakes /// Prompts user for a passphrase and then asks for confirmirmation to check for mistakes
pub fn prompt_passphrase(prompt: &str) -> Result<String, Box<dyn error::Error>> { pub fn prompt_passphrase(prompt: &str) -> Result<String, Box<dyn error::Error>> {
let passphrase = prompt_password_stderr(&prompt)?; let passphrase = prompt_password_stderr(&prompt)?;
@ -196,47 +172,6 @@ pub fn keypair_from_seed_phrase(
Ok(keypair) Ok(keypair)
} }
/// Checks CLI arguments to determine whether a keypair should be:
/// - inputted securely via stdin,
/// - read in from a file,
/// - or newly generated
pub fn keypair_input(
matches: &clap::ArgMatches,
keypair_name: &str,
) -> Result<KeypairWithSource, Box<dyn error::Error>> {
let ask_seed_phrase_matches =
values_t!(matches.values_of(ASK_SEED_PHRASE_ARG.name), String).unwrap_or_default();
let keypair_match_name = keypair_name.replace('-', "_");
if ask_seed_phrase_matches
.iter()
.any(|s| s.as_str() == keypair_name)
{
if matches.value_of(keypair_match_name).is_some() {
clap::Error::with_description(
&format!(
"`--{} {}` cannot be used with `{} <PATH>`",
ASK_SEED_PHRASE_ARG.long, keypair_name, keypair_name
),
clap::ErrorKind::ArgumentConflict,
)
.exit();
}
let skip_validation = matches.is_present(SKIP_SEED_PHRASE_VALIDATION_ARG.name);
keypair_from_seed_phrase(keypair_name, skip_validation, true)
.map(|keypair| KeypairWithSource::new(keypair, Source::SeedPhrase))
} else if let Some(keypair_file) = matches.value_of(keypair_match_name) {
if keypair_file.starts_with("usb://") {
Ok(KeypairWithSource::new(Keypair::new(), Source::Path))
} else {
read_keypair_file(keypair_file)
.map(|keypair| KeypairWithSource::new(keypair, Source::Path))
}
} else {
Ok(KeypairWithSource::new(Keypair::new(), Source::Generated))
}
}
fn sanitize_seed_phrase(seed_phrase: &str) -> String { fn sanitize_seed_phrase(seed_phrase: &str) -> String {
seed_phrase seed_phrase
.split_whitespace() .split_whitespace()
@ -247,14 +182,6 @@ fn sanitize_seed_phrase(seed_phrase: &str) -> String {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use clap::ArgMatches;
#[test]
fn test_keypair_input() {
let arg_matches = ArgMatches::default();
let KeypairWithSource { source, .. } = keypair_input(&arg_matches, "").unwrap();
assert_eq!(source, Source::Generated);
}
#[test] #[test]
fn test_sanitize_seed_phrase() { fn test_sanitize_seed_phrase() {

View File

@ -233,21 +233,20 @@ done < public_keys.txt
In order to run a validator, you will need to specify an "identity keypair" In order to run a validator, you will need to specify an "identity keypair"
which will be used to fund all of the vote transactions signed by your validator. which will be used to fund all of the vote transactions signed by your validator.
Rather than specifying a path with `--identity-keypair <PATH>` you can use the Rather than specifying a path with `--identity-keypair <PATH>` you can pass
`--ask-seed-phrase` option. `ASK` to securely input the funding keypair.
```bash ```bash
solana-validator --ask-seed-phrase identity-keypair --ledger ... solana-validator --identity-keypair ASK --ledger ...
[identity-keypair] seed phrase: 🔒 [identity-keypair] seed phrase: 🔒
[identity-keypair] If this seed phrase has an associated passphrase, enter it now. Otherwise, press ENTER to continue: [identity-keypair] If this seed phrase has an associated passphrase, enter it now. Otherwise, press ENTER to continue:
``` ```
The `--ask-seed-phrase` option accepts multiple keypairs. If you wish to use this You can use this input method for your voting keypair as well:
input method for your voting keypair as well you can do the following:
```bash ```bash
solana-validator --ask-seed-phrase identity-keypair voting-keypair --ledger ... solana-validator --identity-keypair ASK --voting-keypair ASK --ledger ...
[identity-keypair] seed phrase: 🔒 [identity-keypair] seed phrase: 🔒
[identity-keypair] If this seed phrase has an associated passphrase, enter it now. Otherwise, press ENTER to continue: [identity-keypair] If this seed phrase has an associated passphrase, enter it now. Otherwise, press ENTER to continue:

View File

@ -7,12 +7,9 @@ use indicatif::{ProgressBar, ProgressStyle};
use log::*; use log::*;
use rand::{thread_rng, Rng}; use rand::{thread_rng, Rng};
use solana_clap_utils::{ use solana_clap_utils::{
input_parsers::pubkey_of, input_parsers::{keypair_of, pubkey_of},
input_validators::{is_keypair, is_pubkey, is_pubkey_or_keypair, is_slot}, input_validators::{is_keypair_or_ask_keyword, is_pubkey, is_pubkey_or_keypair, is_slot},
keypair::{ keypair::SKIP_SEED_PHRASE_VALIDATION_ARG,
self, keypair_input, KeypairWithSource, ASK_SEED_PHRASE_ARG,
SKIP_SEED_PHRASE_VALIDATION_ARG,
},
}; };
use solana_client::rpc_client::RpcClient; use solana_client::rpc_client::RpcClient;
use solana_core::ledger_cleanup_service::DEFAULT_MAX_LEDGER_SLOTS; use solana_core::ledger_cleanup_service::DEFAULT_MAX_LEDGER_SLOTS;
@ -553,19 +550,9 @@ pub fn main() {
.value_name("UNIX DOMAIN SOCKET") .value_name("UNIX DOMAIN SOCKET")
.help("Stream entries to this unix domain socket path") .help("Stream entries to this unix domain socket path")
) )
.arg(
Arg::with_name(ASK_SEED_PHRASE_ARG.name)
.long(ASK_SEED_PHRASE_ARG.long)
.value_name("KEYPAIR NAME")
.multiple(true)
.takes_value(true)
.possible_values(&["identity-keypair", "storage-keypair", "voting-keypair"])
.help(ASK_SEED_PHRASE_ARG.help),
)
.arg( .arg(
Arg::with_name(SKIP_SEED_PHRASE_VALIDATION_ARG.name) Arg::with_name(SKIP_SEED_PHRASE_VALIDATION_ARG.name)
.long(SKIP_SEED_PHRASE_VALIDATION_ARG.long) .long(SKIP_SEED_PHRASE_VALIDATION_ARG.long)
.requires(ASK_SEED_PHRASE_ARG.name)
.help(SKIP_SEED_PHRASE_VALIDATION_ARG.help), .help(SKIP_SEED_PHRASE_VALIDATION_ARG.help),
) )
.arg( .arg(
@ -574,7 +561,7 @@ pub fn main() {
.long("identity-keypair") .long("identity-keypair")
.value_name("PATH") .value_name("PATH")
.takes_value(true) .takes_value(true)
.validator(is_keypair) .validator(is_keypair_or_ask_keyword)
.help("File containing the identity keypair for the validator"), .help("File containing the identity keypair for the validator"),
) )
.arg( .arg(
@ -582,7 +569,7 @@ pub fn main() {
.long("voting-keypair") .long("voting-keypair")
.value_name("PATH") .value_name("PATH")
.takes_value(true) .takes_value(true)
.validator(is_keypair) .validator(is_keypair_or_ask_keyword)
.help("File containing the authorized voting keypair. Default is an ephemeral keypair, which may disable voting without --vote-account."), .help("File containing the authorized voting keypair. Default is an ephemeral keypair, which may disable voting without --vote-account."),
) )
.arg( .arg(
@ -598,7 +585,7 @@ pub fn main() {
.long("storage-keypair") .long("storage-keypair")
.value_name("PATH") .value_name("PATH")
.takes_value(true) .takes_value(true)
.validator(is_keypair) .validator(is_keypair_or_ask_keyword)
.help("File containing the storage account keypair. Default is an ephemeral keypair"), .help("File containing the storage account keypair. Default is an ephemeral keypair"),
) )
.arg( .arg(
@ -854,28 +841,14 @@ pub fn main() {
) )
.get_matches(); .get_matches();
let identity_keypair = Arc::new( let identity_keypair =
keypair_input(&matches, "identity-keypair") Arc::new(keypair_of(&matches, "identity_keypair").unwrap_or_else(Keypair::new));
.unwrap_or_else(|err| {
eprintln!("Identity keypair input failed: {}", err); let (voting_keypair, ephemeral_voting_keypair) = keypair_of(&matches, "voting_keypair")
exit(1); .map(|keypair| (keypair, false))
}) .unwrap_or_else(|| (Keypair::new(), true));
.keypair,
); let storage_keypair = keypair_of(&matches, "storage_keypair").unwrap_or_else(Keypair::new);
let KeypairWithSource {
keypair: voting_keypair,
source: voting_keypair_source,
} = keypair_input(&matches, "voting-keypair").unwrap_or_else(|err| {
eprintln!("Voting keypair input failed: {}", err);
exit(1);
});
let ephemeral_voting_keypair = voting_keypair_source == keypair::Source::Generated;
let storage_keypair = keypair_input(&matches, "storage-keypair")
.unwrap_or_else(|err| {
eprintln!("Storage keypair input failed: {}", err);
exit(1);
})
.keypair;
let ledger_path = PathBuf::from(matches.value_of("ledger_path").unwrap()); let ledger_path = PathBuf::from(matches.value_of("ledger_path").unwrap());
let entrypoint = matches.value_of("entrypoint"); let entrypoint = matches.value_of("entrypoint");