Add --starts-with for vanity key grinding (#6647)

This commit is contained in:
Michael Vines 2019-10-30 20:47:42 -07:00 committed by GitHub
parent 0559212df7
commit 83d5115a02
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 39 additions and 9 deletions

1
Cargo.lock generated
View File

@ -3503,6 +3503,7 @@ dependencies = [
name = "solana-keygen" name = "solana-keygen"
version = "0.21.0" version = "0.21.0"
dependencies = [ dependencies = [
"bs58 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rpassword 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rpassword 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@ -8,10 +8,8 @@ license = "Apache-2.0"
homepage = "https://solana.com/" homepage = "https://solana.com/"
edition = "2018" edition = "2018"
[dependencies] [dependencies]
bs58 = "0.3.0"
clap = "2.33" clap = "2.33"
dirs = "2.0.2" dirs = "2.0.2"
rpassword = "4.0" rpassword = "4.0"

View File

@ -1,4 +1,5 @@
use bip39::{Language, Mnemonic, MnemonicType, Seed}; use bip39::{Language, Mnemonic, MnemonicType, Seed};
use bs58;
use clap::{ use clap::{
crate_description, crate_name, crate_version, App, AppSettings, Arg, ArgMatches, SubCommand, crate_description, crate_name, crate_version, App, AppSettings, Arg, ArgMatches, SubCommand,
}; };
@ -64,6 +65,18 @@ fn main() -> Result<(), Box<dyn error::Error>> {
.short("s") .short("s")
.long("silent") .long("silent")
.help("Do not display mnemonic phrase. Useful when piping output to other programs that prompt for user input, like gpg"), .help("Do not display mnemonic phrase. Useful when piping output to other programs that prompt for user input, like gpg"),
)
.arg(
Arg::with_name("starts_with")
.long("starts-with")
.value_name("BASE58 PREFIX")
.takes_value(true)
.validator(|value| {
bs58::decode(value).into_vec()
.map(|_| ())
.map_err(|err| format!("{:?}", err))
})
.help("Grind a keypair with public key starting with this prefix"),
), ),
) )
.subcommand( .subcommand(
@ -150,19 +163,37 @@ fn main() -> Result<(), Box<dyn error::Error>> {
check_for_overwrite(&outfile, &matches); check_for_overwrite(&outfile, &matches);
} }
let mnemonic = Mnemonic::new(MnemonicType::Words12, Language::English); let mut attempts = 0;
let phrase: &str = mnemonic.phrase(); let (pubkey, keypair, mnemonic) = loop {
let seed = Seed::new(&mnemonic, NO_PASSPHRASE); let mnemonic = Mnemonic::new(MnemonicType::Words12, Language::English);
let keypair = keypair_from_seed(seed.as_bytes())?; let seed = Seed::new(&mnemonic, NO_PASSPHRASE);
let keypair = keypair_from_seed(seed.as_bytes())?;
let pubkey = bs58::encode(keypair.pubkey()).into_string();
if let Some(prefix) = matches.value_of("starts_with") {
if !pubkey.starts_with(prefix) {
if attempts % 10_000 == 0 {
println!(
"Searching for pubkey prefix of {} ({} attempts)",
prefix, attempts
);
}
attempts += 1;
continue;
}
}
break (pubkey, keypair, mnemonic);
};
output_keypair(&keypair, &outfile, "new")?; output_keypair(&keypair, &outfile, "new")?;
let silent = matches.is_present("silent"); let silent = matches.is_present("silent");
if !silent { if !silent {
let phrase: &str = mnemonic.phrase();
let divider = String::from_utf8(vec![b'='; phrase.len()]).unwrap(); let divider = String::from_utf8(vec![b'='; phrase.len()]).unwrap();
eprintln!( eprintln!(
"{}\nSave this mnemonic phrase to recover your new keypair:\n{}\n{}", "{}\npubkey: {}\n{}\nSave this mnemonic phrase to recover your new keypair:\n{}\n{}",
&divider, phrase, &divider &divider, pubkey, &divider, phrase, &divider
); );
} }
} }