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_cli_config::{Config, CONFIG_FILE},
|
||||||
solana_remote_wallet::remote_wallet::RemoteWalletManager,
|
solana_remote_wallet::remote_wallet::RemoteWalletManager,
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
|
derivation_path::DerivationPath,
|
||||||
instruction::{AccountMeta, Instruction},
|
instruction::{AccountMeta, Instruction},
|
||||||
message::Message,
|
message::Message,
|
||||||
pubkey::{write_pubkey_file, Pubkey},
|
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::{
|
std::{
|
||||||
collections::HashSet,
|
collections::HashSet,
|
||||||
|
@ -34,6 +38,7 @@ use {
|
||||||
};
|
};
|
||||||
|
|
||||||
const NO_PASSPHRASE: &str = "";
|
const NO_PASSPHRASE: &str = "";
|
||||||
|
const DEFAULT_DERIVATION_PATH: &str = "m/44'/501'/0'/0'";
|
||||||
|
|
||||||
struct GrindMatch {
|
struct GrindMatch {
|
||||||
starts: String,
|
starts: String,
|
||||||
|
@ -325,6 +330,33 @@ fn grind_parse_args(
|
||||||
grind_matches
|
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>> {
|
fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
let default_num_threads = num_cpus::get().to_string();
|
let default_num_threads = num_cpus::get().to_string();
|
||||||
let matches = Command::new(crate_name!())
|
let matches = Command::new(crate_name!())
|
||||||
|
@ -389,6 +421,9 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
.long("silent")
|
.long("silent")
|
||||||
.help("Do not display seed phrase. Useful when piping output to other programs that prompt for user input, like gpg"),
|
.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()
|
.key_generation_common_args()
|
||||||
.arg(no_outfile_arg()
|
.arg(no_outfile_arg()
|
||||||
.conflicts_with_all(&["outfile", "silent"])
|
.conflicts_with_all(&["outfile", "silent"])
|
||||||
|
@ -450,6 +485,10 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
.long("use-mnemonic")
|
.long("use-mnemonic")
|
||||||
.help("Generate using a mnemonic key phrase. Expect a significant slowdown in this mode"),
|
.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()
|
.key_generation_common_args()
|
||||||
.arg(
|
.arg(
|
||||||
no_outfile_arg()
|
no_outfile_arg()
|
||||||
|
@ -576,11 +615,17 @@ fn do_main(matches: &ArgMatches) -> Result<(), Box<dyn error::Error>> {
|
||||||
if !silent {
|
if !silent {
|
||||||
println!("Generating a new keypair");
|
println!("Generating a new keypair");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let derivation_path = acquire_derivation_path(matches)?;
|
||||||
|
|
||||||
let mnemonic = Mnemonic::new(mnemonic_type, language);
|
let mnemonic = Mnemonic::new(mnemonic_type, language);
|
||||||
let (passphrase, passphrase_message) = acquire_passphrase_and_message(matches).unwrap();
|
let (passphrase, passphrase_message) = acquire_passphrase_and_message(matches).unwrap();
|
||||||
|
|
||||||
let seed = Seed::new(&mnemonic, &passphrase);
|
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 {
|
if let Some(outfile) = outfile {
|
||||||
output_keypair(&keypair, outfile, "new")
|
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 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 word_count: usize = matches.value_of_t(WORD_COUNT_ARG.name).unwrap();
|
||||||
let mnemonic_type = MnemonicType::for_word_count(word_count)?;
|
let mnemonic_type = MnemonicType::for_word_count(word_count)?;
|
||||||
let language = acquire_language(matches);
|
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 grind_matches_thread_safe = grind_matches_thread_safe.clone();
|
||||||
let passphrase = passphrase.clone();
|
let passphrase = passphrase.clone();
|
||||||
let passphrase_message = passphrase_message.clone();
|
let passphrase_message = passphrase_message.clone();
|
||||||
|
let derivation_path = derivation_path.clone();
|
||||||
|
|
||||||
thread::spawn(move || loop {
|
thread::spawn(move || loop {
|
||||||
if done.load(Ordering::Relaxed) {
|
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 (keypair, phrase) = if use_mnemonic {
|
||||||
let mnemonic = Mnemonic::new(mnemonic_type, language);
|
let mnemonic = Mnemonic::new(mnemonic_type, language);
|
||||||
let seed = Seed::new(&mnemonic, &passphrase);
|
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 {
|
} else {
|
||||||
(Keypair::new(), "".to_string())
|
(Keypair::new(), "".to_string())
|
||||||
};
|
};
|
||||||
|
|
|
@ -79,7 +79,7 @@ impl DerivationPath {
|
||||||
Ok(Self::new_bip44_with_coin(coin, account, change))
|
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)?
|
let inner = DerivationPath::_from_absolute_path_insecure_str(path)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|c| ChildIndex::Hardened(c.to_u32()))
|
.map(|c| ChildIndex::Hardened(c.to_u32()))
|
||||||
|
|
Loading…
Reference in New Issue