keygen: add the ability to use derivation path for new & grind commands (#21614)
* keygen: add --use-derivation-path for new & grind * keygen: add prompt:// uri scheme to new and grind * fmt * migrate to clap-v3-utils * Revert "migrate to clap-v3-utils" This reverts commit 77f33262ce6c4e95ac1cc62cca32749516f7f357. * Revert "fmt" This reverts commit 038cd4ce9628c57dec1f5a4716e2c5baacbe57b3. * Revert "keygen: add prompt:// uri scheme to new and grind" This reverts commit 029ea61409a1a16ba2c45483ade2c01f84f25fac. * - remove `use` from arg - fix issue from first commit with default value for derivation path - refactor arg definition and acquiring
This commit is contained in:
parent
d6a1e7498f
commit
6899af26b0
|
@ -14,10 +14,14 @@ use {
|
|||
solana_cli_config::{Config, CONFIG_FILE},
|
||||
solana_remote_wallet::remote_wallet::RemoteWalletManager,
|
||||
solana_sdk::{
|
||||
derivation_path::DerivationPath,
|
||||
instruction::{AccountMeta, Instruction},
|
||||
message::Message,
|
||||
pubkey::{write_pubkey_file, Pubkey},
|
||||
signature::{keypair_from_seed, write_keypair, write_keypair_file, Keypair, Signer},
|
||||
signature::{
|
||||
keypair_from_seed, keypair_from_seed_and_derivation_path, write_keypair,
|
||||
write_keypair_file, Keypair, Signer,
|
||||
},
|
||||
},
|
||||
std::{
|
||||
collections::HashSet,
|
||||
|
@ -34,6 +38,7 @@ use {
|
|||
};
|
||||
|
||||
const NO_PASSPHRASE: &str = "";
|
||||
const DEFAULT_DERIVATION_PATH: &str = "m/44'/501'/0'/0'";
|
||||
|
||||
struct GrindMatch {
|
||||
starts: String,
|
||||
|
@ -325,6 +330,33 @@ fn grind_parse_args(
|
|||
grind_matches
|
||||
}
|
||||
|
||||
fn derivation_path_arg<'a>() -> Arg<'a> {
|
||||
Arg::new("derivation_path")
|
||||
.long("derivation-path")
|
||||
.value_name("DERIVATION_PATH")
|
||||
.takes_value(true)
|
||||
.min_values(0)
|
||||
.max_values(1)
|
||||
.help("Derivation path. All indexes will be promoted to hardened. \
|
||||
If arg is not presented then derivation path will not be used. \
|
||||
If arg is presented with empty DERIVATION_PATH value then m/44'/501'/0'/0' will be used."
|
||||
)
|
||||
}
|
||||
|
||||
fn acquire_derivation_path(
|
||||
matches: &ArgMatches,
|
||||
) -> Result<Option<DerivationPath>, Box<dyn error::Error>> {
|
||||
if matches.is_present("derivation_path") {
|
||||
Ok(Some(DerivationPath::from_absolute_path_str(
|
||||
matches
|
||||
.value_of("derivation_path")
|
||||
.unwrap_or(DEFAULT_DERIVATION_PATH),
|
||||
)?))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn error::Error>> {
|
||||
let default_num_threads = num_cpus::get().to_string();
|
||||
let matches = Command::new(crate_name!())
|
||||
|
@ -389,6 +421,9 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
|||
.long("silent")
|
||||
.help("Do not display seed phrase. Useful when piping output to other programs that prompt for user input, like gpg"),
|
||||
)
|
||||
.arg(
|
||||
derivation_path_arg()
|
||||
)
|
||||
.key_generation_common_args()
|
||||
.arg(no_outfile_arg()
|
||||
.conflicts_with_all(&["outfile", "silent"])
|
||||
|
@ -450,6 +485,10 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
|||
.long("use-mnemonic")
|
||||
.help("Generate using a mnemonic key phrase. Expect a significant slowdown in this mode"),
|
||||
)
|
||||
.arg(
|
||||
derivation_path_arg()
|
||||
.requires("use_mnemonic")
|
||||
)
|
||||
.key_generation_common_args()
|
||||
.arg(
|
||||
no_outfile_arg()
|
||||
|
@ -576,11 +615,17 @@ fn do_main(matches: &ArgMatches) -> Result<(), Box<dyn error::Error>> {
|
|||
if !silent {
|
||||
println!("Generating a new keypair");
|
||||
}
|
||||
|
||||
let derivation_path = acquire_derivation_path(matches)?;
|
||||
|
||||
let mnemonic = Mnemonic::new(mnemonic_type, language);
|
||||
let (passphrase, passphrase_message) = acquire_passphrase_and_message(matches).unwrap();
|
||||
|
||||
let seed = Seed::new(&mnemonic, &passphrase);
|
||||
let keypair = keypair_from_seed(seed.as_bytes())?;
|
||||
let keypair = match derivation_path {
|
||||
Some(_) => keypair_from_seed_and_derivation_path(seed.as_bytes(), derivation_path),
|
||||
None => keypair_from_seed(seed.as_bytes()),
|
||||
}?;
|
||||
|
||||
if let Some(outfile) = outfile {
|
||||
output_keypair(&keypair, outfile, "new")
|
||||
|
@ -671,6 +716,8 @@ fn do_main(matches: &ArgMatches) -> Result<(), Box<dyn error::Error>> {
|
|||
|
||||
let use_mnemonic = matches.is_present("use_mnemonic");
|
||||
|
||||
let derivation_path = acquire_derivation_path(matches)?;
|
||||
|
||||
let word_count: usize = matches.value_of_t(WORD_COUNT_ARG.name).unwrap();
|
||||
let mnemonic_type = MnemonicType::for_word_count(word_count)?;
|
||||
let language = acquire_language(matches);
|
||||
|
@ -696,6 +743,7 @@ fn do_main(matches: &ArgMatches) -> Result<(), Box<dyn error::Error>> {
|
|||
let grind_matches_thread_safe = grind_matches_thread_safe.clone();
|
||||
let passphrase = passphrase.clone();
|
||||
let passphrase_message = passphrase_message.clone();
|
||||
let derivation_path = derivation_path.clone();
|
||||
|
||||
thread::spawn(move || loop {
|
||||
if done.load(Ordering::Relaxed) {
|
||||
|
@ -713,7 +761,11 @@ fn do_main(matches: &ArgMatches) -> Result<(), Box<dyn error::Error>> {
|
|||
let (keypair, phrase) = if use_mnemonic {
|
||||
let mnemonic = Mnemonic::new(mnemonic_type, language);
|
||||
let seed = Seed::new(&mnemonic, &passphrase);
|
||||
(keypair_from_seed(seed.as_bytes()).unwrap(), mnemonic.phrase().to_string())
|
||||
let keypair = match derivation_path {
|
||||
Some(_) => keypair_from_seed_and_derivation_path(seed.as_bytes(), derivation_path.clone()),
|
||||
None => keypair_from_seed(seed.as_bytes()),
|
||||
}.unwrap();
|
||||
(keypair, mnemonic.phrase().to_string())
|
||||
} else {
|
||||
(Keypair::new(), "".to_string())
|
||||
};
|
||||
|
|
|
@ -79,7 +79,7 @@ impl DerivationPath {
|
|||
Ok(Self::new_bip44_with_coin(coin, account, change))
|
||||
}
|
||||
|
||||
fn from_absolute_path_str(path: &str) -> Result<Self, DerivationPathError> {
|
||||
pub fn from_absolute_path_str(path: &str) -> Result<Self, DerivationPathError> {
|
||||
let inner = DerivationPath::_from_absolute_path_insecure_str(path)?
|
||||
.into_iter()
|
||||
.map(|c| ChildIndex::Hardened(c.to_u32()))
|
||||
|
|
Loading…
Reference in New Issue