solana-keygen - Poor mans keypair encryption (#6259)
* SDK: Refactor (read|write)_keypair Split file opening and data writing operations Drop filename == "-" stdio signal. It is an app-level feature * keygen: Move all non-key printing to stderr * keygen: Adapt to SDK refactor * keygen: Factor keypair output out to a helper function
This commit is contained in:
		@@ -1,7 +1,7 @@
 | 
			
		||||
use clap::{crate_description, crate_name, crate_version, value_t, App, Arg, ArgMatches};
 | 
			
		||||
use solana_core::gen_keys::GenKeys;
 | 
			
		||||
use solana_drone::drone::DRONE_PORT;
 | 
			
		||||
use solana_sdk::signature::{read_keypair, Keypair, KeypairUtil};
 | 
			
		||||
use solana_sdk::signature::{read_keypair_file, Keypair, KeypairUtil};
 | 
			
		||||
use std::net::SocketAddr;
 | 
			
		||||
use std::process::exit;
 | 
			
		||||
use std::time::Duration;
 | 
			
		||||
@@ -179,7 +179,7 @@ pub fn extract_args<'a>(matches: &ArgMatches<'a>) -> Config {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    if matches.is_present("identity") {
 | 
			
		||||
        args.identity = read_keypair(matches.value_of("identity").unwrap())
 | 
			
		||||
        args.identity = read_keypair_file(matches.value_of("identity").unwrap())
 | 
			
		||||
            .expect("can't read client identity");
 | 
			
		||||
    } else {
 | 
			
		||||
        args.identity = {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
use clap::{crate_description, crate_name, crate_version, App, Arg, ArgMatches};
 | 
			
		||||
use solana_drone::drone::DRONE_PORT;
 | 
			
		||||
use solana_sdk::fee_calculator::FeeCalculator;
 | 
			
		||||
use solana_sdk::signature::{read_keypair, Keypair, KeypairUtil};
 | 
			
		||||
use solana_sdk::signature::{read_keypair_file, Keypair, KeypairUtil};
 | 
			
		||||
use std::{net::SocketAddr, process::exit, time::Duration};
 | 
			
		||||
 | 
			
		||||
const NUM_LAMPORTS_PER_ACCOUNT_DEFAULT: u64 = 64 * 1024;
 | 
			
		||||
@@ -181,7 +181,7 @@ pub fn extract_args<'a>(matches: &ArgMatches<'a>) -> Config {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if matches.is_present("identity") {
 | 
			
		||||
        args.id = read_keypair(matches.value_of("identity").unwrap())
 | 
			
		||||
        args.id = read_keypair_file(matches.value_of("identity").unwrap())
 | 
			
		||||
            .expect("can't read client identity");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1385,7 +1385,7 @@ mod tests {
 | 
			
		||||
    use serde_json::Value;
 | 
			
		||||
    use solana_client::mock_rpc_client_request::SIGNATURE;
 | 
			
		||||
    use solana_sdk::{
 | 
			
		||||
        signature::{gen_keypair_file, read_keypair},
 | 
			
		||||
        signature::{gen_keypair_file, read_keypair_file},
 | 
			
		||||
        transaction::TransactionError,
 | 
			
		||||
    };
 | 
			
		||||
    use std::path::PathBuf;
 | 
			
		||||
@@ -1442,7 +1442,7 @@ mod tests {
 | 
			
		||||
        // Test Balance Subcommand, incl pubkey and keypair-file inputs
 | 
			
		||||
        let keypair_file = make_tmp_path("keypair_file");
 | 
			
		||||
        gen_keypair_file(&keypair_file).unwrap();
 | 
			
		||||
        let keypair = read_keypair(&keypair_file).unwrap();
 | 
			
		||||
        let keypair = read_keypair_file(&keypair_file).unwrap();
 | 
			
		||||
        let test_balance = test_commands.clone().get_matches_from(vec![
 | 
			
		||||
            "test",
 | 
			
		||||
            "balance",
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@ use clap::ArgMatches;
 | 
			
		||||
use solana_sdk::{
 | 
			
		||||
    native_token::sol_to_lamports,
 | 
			
		||||
    pubkey::Pubkey,
 | 
			
		||||
    signature::{read_keypair, Keypair, KeypairUtil},
 | 
			
		||||
    signature::{read_keypair_file, Keypair, KeypairUtil},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Return parsed values from matches at `name`
 | 
			
		||||
@@ -32,7 +32,7 @@ where
 | 
			
		||||
// Return the keypair for an argument with filename `name` or None if not present.
 | 
			
		||||
pub fn keypair_of(matches: &ArgMatches<'_>, name: &str) -> Option<Keypair> {
 | 
			
		||||
    if let Some(value) = matches.value_of(name) {
 | 
			
		||||
        read_keypair(value).ok()
 | 
			
		||||
        read_keypair_file(value).ok()
 | 
			
		||||
    } else {
 | 
			
		||||
        None
 | 
			
		||||
    }
 | 
			
		||||
@@ -56,7 +56,7 @@ pub fn amount_of(matches: &ArgMatches<'_>, name: &str, unit: &str) -> Option<u64
 | 
			
		||||
mod tests {
 | 
			
		||||
    use super::*;
 | 
			
		||||
    use clap::{App, Arg};
 | 
			
		||||
    use solana_sdk::signature::write_keypair;
 | 
			
		||||
    use solana_sdk::signature::write_keypair_file;
 | 
			
		||||
    use std::fs;
 | 
			
		||||
 | 
			
		||||
    fn app<'ab, 'v>() -> App<'ab, 'v> {
 | 
			
		||||
@@ -120,7 +120,7 @@ mod tests {
 | 
			
		||||
    fn test_keypair_of() {
 | 
			
		||||
        let keypair = Keypair::new();
 | 
			
		||||
        let outfile = tmp_file_path("test_gen_keypair_file.json", &keypair.pubkey());
 | 
			
		||||
        let _ = write_keypair(&keypair, &outfile).unwrap();
 | 
			
		||||
        let _ = write_keypair_file(&keypair, &outfile).unwrap();
 | 
			
		||||
 | 
			
		||||
        let matches = app()
 | 
			
		||||
            .clone()
 | 
			
		||||
@@ -141,7 +141,7 @@ mod tests {
 | 
			
		||||
    fn test_pubkey_of() {
 | 
			
		||||
        let keypair = Keypair::new();
 | 
			
		||||
        let outfile = tmp_file_path("test_gen_keypair_file.json", &keypair.pubkey());
 | 
			
		||||
        let _ = write_keypair(&keypair, &outfile).unwrap();
 | 
			
		||||
        let _ = write_keypair_file(&keypair, &outfile).unwrap();
 | 
			
		||||
 | 
			
		||||
        let matches = app()
 | 
			
		||||
            .clone()
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
use solana_sdk::pubkey::Pubkey;
 | 
			
		||||
use solana_sdk::signature::read_keypair;
 | 
			
		||||
use solana_sdk::signature::read_keypair_file;
 | 
			
		||||
 | 
			
		||||
// Return an error if a pubkey cannot be parsed.
 | 
			
		||||
pub fn is_pubkey(string: String) -> Result<(), String> {
 | 
			
		||||
@@ -11,7 +11,7 @@ pub fn is_pubkey(string: String) -> Result<(), String> {
 | 
			
		||||
 | 
			
		||||
// Return an error if a keypair file cannot be parsed.
 | 
			
		||||
pub fn is_keypair(string: String) -> Result<(), String> {
 | 
			
		||||
    read_keypair(&string)
 | 
			
		||||
    read_keypair_file(&string)
 | 
			
		||||
        .map(|_| ())
 | 
			
		||||
        .map_err(|err| format!("{:?}", err))
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@ use solana_cli::{
 | 
			
		||||
    display::{println_name_value, println_name_value_or},
 | 
			
		||||
    input_validators::is_url,
 | 
			
		||||
};
 | 
			
		||||
use solana_sdk::signature::{read_keypair, KeypairUtil};
 | 
			
		||||
use solana_sdk::signature::{read_keypair_file, KeypairUtil};
 | 
			
		||||
use std::error;
 | 
			
		||||
 | 
			
		||||
fn parse_settings(matches: &ArgMatches<'_>) -> Result<bool, Box<dyn error::Error>> {
 | 
			
		||||
@@ -94,7 +94,7 @@ pub fn parse_args(matches: &ArgMatches<'_>) -> Result<CliConfig, Box<dyn error::
 | 
			
		||||
        }
 | 
			
		||||
        default.keypair_path
 | 
			
		||||
    };
 | 
			
		||||
    let keypair = read_keypair(&keypair_path).or_else(|err| {
 | 
			
		||||
    let keypair = read_keypair_file(&keypair_path).or_else(|err| {
 | 
			
		||||
        Err(CliError::BadParameter(format!(
 | 
			
		||||
            "{}: Unable to open keypair file: {}",
 | 
			
		||||
            err, keypair_path
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
use clap::{crate_description, crate_name, crate_version, App, Arg};
 | 
			
		||||
use solana_drone::drone::{run_drone, Drone, DRONE_PORT};
 | 
			
		||||
use solana_drone::socketaddr;
 | 
			
		||||
use solana_sdk::signature::read_keypair;
 | 
			
		||||
use solana_sdk::signature::read_keypair_file;
 | 
			
		||||
use std::error;
 | 
			
		||||
use std::net::{Ipv4Addr, SocketAddr};
 | 
			
		||||
use std::sync::{Arc, Mutex};
 | 
			
		||||
@@ -38,8 +38,8 @@ fn main() -> Result<(), Box<dyn error::Error>> {
 | 
			
		||||
        )
 | 
			
		||||
        .get_matches();
 | 
			
		||||
 | 
			
		||||
    let mint_keypair =
 | 
			
		||||
        read_keypair(matches.value_of("keypair").unwrap()).expect("failed to read client keypair");
 | 
			
		||||
    let mint_keypair = read_keypair_file(matches.value_of("keypair").unwrap())
 | 
			
		||||
        .expect("failed to read client keypair");
 | 
			
		||||
 | 
			
		||||
    let time_slice: Option<u64>;
 | 
			
		||||
    if let Some(secs) = matches.value_of("slice") {
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@ use solana_sdk::{
 | 
			
		||||
    poh_config::PohConfig,
 | 
			
		||||
    pubkey::Pubkey,
 | 
			
		||||
    rent_calculator::RentCalculator,
 | 
			
		||||
    signature::{read_keypair, Keypair, KeypairUtil},
 | 
			
		||||
    signature::{read_keypair_file, Keypair, KeypairUtil},
 | 
			
		||||
    system_program, timing,
 | 
			
		||||
};
 | 
			
		||||
use solana_stake_api::stake_state;
 | 
			
		||||
@@ -298,11 +298,11 @@ fn main() -> Result<(), Box<dyn error::Error>> {
 | 
			
		||||
    let bootstrap_leader_stake_lamports =
 | 
			
		||||
        value_t_or_exit!(matches, "bootstrap_leader_stake_lamports", u64);
 | 
			
		||||
 | 
			
		||||
    let bootstrap_leader_keypair = read_keypair(bootstrap_leader_keypair_file)?;
 | 
			
		||||
    let bootstrap_vote_keypair = read_keypair(bootstrap_vote_keypair_file)?;
 | 
			
		||||
    let bootstrap_stake_keypair = read_keypair(bootstrap_stake_keypair_file)?;
 | 
			
		||||
    let bootstrap_storage_keypair = read_keypair(bootstrap_storage_keypair_file)?;
 | 
			
		||||
    let mint_keypair = read_keypair(mint_keypair_file)?;
 | 
			
		||||
    let bootstrap_leader_keypair = read_keypair_file(bootstrap_leader_keypair_file)?;
 | 
			
		||||
    let bootstrap_vote_keypair = read_keypair_file(bootstrap_vote_keypair_file)?;
 | 
			
		||||
    let bootstrap_stake_keypair = read_keypair_file(bootstrap_stake_keypair_file)?;
 | 
			
		||||
    let bootstrap_storage_keypair = read_keypair_file(bootstrap_storage_keypair_file)?;
 | 
			
		||||
    let mint_keypair = read_keypair_file(mint_keypair_file)?;
 | 
			
		||||
 | 
			
		||||
    let vote_account = vote_state::create_account(
 | 
			
		||||
        &bootstrap_vote_keypair.pubkey(),
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@ use solana_client::rpc_client::RpcClient;
 | 
			
		||||
use solana_config_api::{config_instruction, get_config_data};
 | 
			
		||||
use solana_sdk::message::Message;
 | 
			
		||||
use solana_sdk::pubkey::Pubkey;
 | 
			
		||||
use solana_sdk::signature::{read_keypair, Keypair, KeypairUtil, Signable};
 | 
			
		||||
use solana_sdk::signature::{read_keypair_file, Keypair, KeypairUtil, Signable};
 | 
			
		||||
use solana_sdk::transaction::Transaction;
 | 
			
		||||
use std::fs::{self, File};
 | 
			
		||||
use std::io::{self, BufReader, Read};
 | 
			
		||||
@@ -626,9 +626,9 @@ pub fn deploy(
 | 
			
		||||
    download_url: &str,
 | 
			
		||||
    update_manifest_keypair_file: &str,
 | 
			
		||||
) -> Result<(), String> {
 | 
			
		||||
    let from_keypair = read_keypair(from_keypair_file)
 | 
			
		||||
    let from_keypair = read_keypair_file(from_keypair_file)
 | 
			
		||||
        .map_err(|err| format!("Unable to read {}: {}", from_keypair_file, err))?;
 | 
			
		||||
    let update_manifest_keypair = read_keypair(update_manifest_keypair_file)
 | 
			
		||||
    let update_manifest_keypair = read_keypair_file(update_manifest_keypair_file)
 | 
			
		||||
        .map_err(|err| format!("Unable to read {}: {}", update_manifest_keypair_file, err))?;
 | 
			
		||||
 | 
			
		||||
    println_name_value("JSON RPC URL:", json_rpc_url);
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,10 @@ use clap::{
 | 
			
		||||
    crate_description, crate_name, crate_version, App, AppSettings, Arg, ArgMatches, SubCommand,
 | 
			
		||||
};
 | 
			
		||||
use solana_sdk::pubkey::write_pubkey;
 | 
			
		||||
use solana_sdk::signature::{keypair_from_seed, read_keypair, write_keypair, KeypairUtil};
 | 
			
		||||
use solana_sdk::signature::{
 | 
			
		||||
    keypair_from_seed, read_keypair, read_keypair_file, write_keypair, write_keypair_file, Keypair,
 | 
			
		||||
    KeypairUtil,
 | 
			
		||||
};
 | 
			
		||||
use std::error;
 | 
			
		||||
use std::path::Path;
 | 
			
		||||
use std::process::exit;
 | 
			
		||||
@@ -18,6 +21,21 @@ fn check_for_overwrite(outfile: &str, matches: &ArgMatches) {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn output_keypair(
 | 
			
		||||
    keypair: &Keypair,
 | 
			
		||||
    outfile: &str,
 | 
			
		||||
    source: &str,
 | 
			
		||||
) -> Result<(), Box<dyn error::Error>> {
 | 
			
		||||
    if outfile == "-" {
 | 
			
		||||
        let mut stdout = std::io::stdout();
 | 
			
		||||
        write_keypair(&keypair, &mut stdout)?;
 | 
			
		||||
    } else {
 | 
			
		||||
        write_keypair_file(&keypair, outfile)?;
 | 
			
		||||
        eprintln!("Wrote {} keypair to {}", source, outfile);
 | 
			
		||||
    }
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn main() -> Result<(), Box<dyn error::Error>> {
 | 
			
		||||
    let matches = App::new(crate_name!())
 | 
			
		||||
        .about(crate_description!())
 | 
			
		||||
@@ -45,7 +63,7 @@ fn main() -> Result<(), Box<dyn error::Error>> {
 | 
			
		||||
                    Arg::with_name("silent")
 | 
			
		||||
                        .short("s")
 | 
			
		||||
                        .long("silent")
 | 
			
		||||
                        .help("Do not display mnemonic phrase"),
 | 
			
		||||
                        .help("Do not display mnemonic phrase. Useful when piping output to other programs that prompt for user input, like gpg"),
 | 
			
		||||
                ),
 | 
			
		||||
        )
 | 
			
		||||
        .subcommand(
 | 
			
		||||
@@ -104,7 +122,12 @@ fn main() -> Result<(), Box<dyn error::Error>> {
 | 
			
		||||
                path.extend(&[".config", "solana", "id.json"]);
 | 
			
		||||
                path.to_str().unwrap()
 | 
			
		||||
            };
 | 
			
		||||
            let keypair = read_keypair(infile)?;
 | 
			
		||||
            let keypair = if infile == "-" {
 | 
			
		||||
                let mut stdin = std::io::stdin();
 | 
			
		||||
                read_keypair(&mut stdin)?
 | 
			
		||||
            } else {
 | 
			
		||||
                read_keypair_file(infile)?
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            if matches.is_present("outfile") {
 | 
			
		||||
                let outfile = matches.value_of("outfile").unwrap();
 | 
			
		||||
@@ -132,17 +155,12 @@ fn main() -> Result<(), Box<dyn error::Error>> {
 | 
			
		||||
            let seed = Seed::new(&mnemonic, NO_PASSPHRASE);
 | 
			
		||||
            let keypair = keypair_from_seed(seed.as_bytes())?;
 | 
			
		||||
 | 
			
		||||
            let serialized_keypair = write_keypair(&keypair, outfile)?;
 | 
			
		||||
            if outfile == "-" {
 | 
			
		||||
                println!("{}", serialized_keypair);
 | 
			
		||||
            } else {
 | 
			
		||||
                println!("Wrote new keypair to {}", outfile);
 | 
			
		||||
            }
 | 
			
		||||
            output_keypair(&keypair, &outfile, "new")?;
 | 
			
		||||
 | 
			
		||||
            let silent = matches.is_present("silent");
 | 
			
		||||
            if !silent {
 | 
			
		||||
                let divider = String::from_utf8(vec![b'='; phrase.len()]).unwrap();
 | 
			
		||||
                println!(
 | 
			
		||||
                eprintln!(
 | 
			
		||||
                    "{}\nSave this mnemonic phrase to recover your new keypair:\n{}\n{}",
 | 
			
		||||
                    ÷r, phrase, ÷r
 | 
			
		||||
                );
 | 
			
		||||
@@ -161,17 +179,12 @@ fn main() -> Result<(), Box<dyn error::Error>> {
 | 
			
		||||
                check_for_overwrite(&outfile, &matches);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            let phrase = rpassword::prompt_password_stdout("Mnemonic recovery phrase: ").unwrap();
 | 
			
		||||
            let phrase = rpassword::prompt_password_stderr("Mnemonic recovery phrase: ").unwrap();
 | 
			
		||||
            let mnemonic = Mnemonic::from_phrase(phrase.trim(), Language::English)?;
 | 
			
		||||
            let seed = Seed::new(&mnemonic, NO_PASSPHRASE);
 | 
			
		||||
            let keypair = keypair_from_seed(seed.as_bytes())?;
 | 
			
		||||
 | 
			
		||||
            let serialized_keypair = write_keypair(&keypair, outfile)?;
 | 
			
		||||
            if outfile == "-" {
 | 
			
		||||
                println!("{}", serialized_keypair);
 | 
			
		||||
            } else {
 | 
			
		||||
                println!("Wrote recovered keypair to {}", outfile);
 | 
			
		||||
            }
 | 
			
		||||
            output_keypair(&keypair, &outfile, "recovered")?;
 | 
			
		||||
        }
 | 
			
		||||
        _ => unreachable!(),
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@ use console::style;
 | 
			
		||||
use solana_core::cluster_info::{Node, FULLNODE_PORT_RANGE};
 | 
			
		||||
use solana_core::contact_info::ContactInfo;
 | 
			
		||||
use solana_core::replicator::Replicator;
 | 
			
		||||
use solana_sdk::signature::{read_keypair, Keypair, KeypairUtil};
 | 
			
		||||
use solana_sdk::signature::{read_keypair_file, Keypair, KeypairUtil};
 | 
			
		||||
use std::net::SocketAddr;
 | 
			
		||||
use std::path::PathBuf;
 | 
			
		||||
use std::process::exit;
 | 
			
		||||
@@ -11,7 +11,7 @@ use std::sync::Arc;
 | 
			
		||||
 | 
			
		||||
// Return an error if a keypair file cannot be parsed.
 | 
			
		||||
fn is_keypair(string: String) -> Result<(), String> {
 | 
			
		||||
    read_keypair(&string)
 | 
			
		||||
    read_keypair_file(&string)
 | 
			
		||||
        .map(|_| ())
 | 
			
		||||
        .map_err(|err| format!("{:?}", err))
 | 
			
		||||
}
 | 
			
		||||
@@ -65,7 +65,7 @@ fn main() {
 | 
			
		||||
    let ledger_path = PathBuf::from(matches.value_of("ledger").unwrap());
 | 
			
		||||
 | 
			
		||||
    let keypair = if let Some(identity) = matches.value_of("identity") {
 | 
			
		||||
        read_keypair(identity).unwrap_or_else(|err| {
 | 
			
		||||
        read_keypair_file(identity).unwrap_or_else(|err| {
 | 
			
		||||
            eprintln!("{}: Unable to open keypair file: {}", err, identity);
 | 
			
		||||
            exit(1);
 | 
			
		||||
        })
 | 
			
		||||
@@ -73,7 +73,7 @@ fn main() {
 | 
			
		||||
        Keypair::new()
 | 
			
		||||
    };
 | 
			
		||||
    let storage_keypair = if let Some(storage_keypair) = matches.value_of("storage_keypair") {
 | 
			
		||||
        read_keypair(storage_keypair).unwrap_or_else(|err| {
 | 
			
		||||
        read_keypair_file(storage_keypair).unwrap_or_else(|err| {
 | 
			
		||||
            eprintln!("{}: Unable to open keypair file: {}", err, storage_keypair);
 | 
			
		||||
            exit(1);
 | 
			
		||||
        })
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@ use std::borrow::Cow;
 | 
			
		||||
use std::error;
 | 
			
		||||
use std::fmt;
 | 
			
		||||
use std::fs::{self, File};
 | 
			
		||||
use std::io::Write;
 | 
			
		||||
use std::io::{Read, Write};
 | 
			
		||||
use std::mem;
 | 
			
		||||
use std::path::Path;
 | 
			
		||||
use std::str::FromStr;
 | 
			
		||||
@@ -125,28 +125,41 @@ impl KeypairUtil for Keypair {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn read_keypair(path: &str) -> Result<Keypair, Box<dyn error::Error>> {
 | 
			
		||||
    let file = File::open(path.to_string())?;
 | 
			
		||||
    let bytes: Vec<u8> = serde_json::from_reader(file)?;
 | 
			
		||||
pub fn read_keypair<R: Read>(reader: &mut R) -> Result<Keypair, Box<dyn error::Error>> {
 | 
			
		||||
    let bytes: Vec<u8> = serde_json::from_reader(reader)?;
 | 
			
		||||
    let keypair = Keypair::from_bytes(&bytes)
 | 
			
		||||
        .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?;
 | 
			
		||||
    Ok(keypair)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn write_keypair(keypair: &Keypair, outfile: &str) -> Result<String, Box<dyn error::Error>> {
 | 
			
		||||
pub fn read_keypair_file(path: &str) -> Result<Keypair, Box<dyn error::Error>> {
 | 
			
		||||
    assert!(path != "-");
 | 
			
		||||
    let mut file = File::open(path.to_string())?;
 | 
			
		||||
    read_keypair(&mut file)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn write_keypair<W: Write>(
 | 
			
		||||
    keypair: &Keypair,
 | 
			
		||||
    writer: &mut W,
 | 
			
		||||
) -> Result<String, Box<dyn error::Error>> {
 | 
			
		||||
    let keypair_bytes = keypair.to_bytes();
 | 
			
		||||
    let serialized = serde_json::to_string(&keypair_bytes.to_vec())?;
 | 
			
		||||
 | 
			
		||||
    if outfile != "-" {
 | 
			
		||||
        if let Some(outdir) = Path::new(outfile).parent() {
 | 
			
		||||
            fs::create_dir_all(outdir)?;
 | 
			
		||||
        }
 | 
			
		||||
        let mut f = File::create(outfile)?;
 | 
			
		||||
        f.write_all(&serialized.clone().into_bytes())?;
 | 
			
		||||
    }
 | 
			
		||||
    writer.write_all(&serialized.clone().into_bytes())?;
 | 
			
		||||
    Ok(serialized)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn write_keypair_file(
 | 
			
		||||
    keypair: &Keypair,
 | 
			
		||||
    outfile: &str,
 | 
			
		||||
) -> Result<String, Box<dyn error::Error>> {
 | 
			
		||||
    assert!(outfile != "-");
 | 
			
		||||
    if let Some(outdir) = Path::new(outfile).parent() {
 | 
			
		||||
        fs::create_dir_all(outdir)?;
 | 
			
		||||
    }
 | 
			
		||||
    let mut f = File::create(outfile)?;
 | 
			
		||||
    write_keypair(keypair, &mut f)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn keypair_from_seed(seed: &[u8]) -> Result<Keypair, Box<dyn error::Error>> {
 | 
			
		||||
    if seed.len() < ed25519_dalek::SECRET_KEY_LENGTH {
 | 
			
		||||
        return Err("Seed is too short".into());
 | 
			
		||||
@@ -159,7 +172,7 @@ pub fn keypair_from_seed(seed: &[u8]) -> Result<Keypair, Box<dyn error::Error>>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn gen_keypair_file(outfile: &str) -> Result<String, Box<dyn error::Error>> {
 | 
			
		||||
    write_keypair(&Keypair::new(), outfile)
 | 
			
		||||
    write_keypair_file(&Keypair::new(), outfile)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
@@ -183,10 +196,10 @@ mod tests {
 | 
			
		||||
        assert!(Path::new(&outfile).exists());
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            keypair_vec,
 | 
			
		||||
            read_keypair(&outfile).unwrap().to_bytes().to_vec()
 | 
			
		||||
            read_keypair_file(&outfile).unwrap().to_bytes().to_vec()
 | 
			
		||||
        );
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            read_keypair(&outfile).unwrap().pubkey().as_ref().len(),
 | 
			
		||||
            read_keypair_file(&outfile).unwrap().pubkey().as_ref().len(),
 | 
			
		||||
            mem::size_of::<Pubkey>()
 | 
			
		||||
        );
 | 
			
		||||
        fs::remove_file(&outfile).unwrap();
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@ use solana_core::socketaddr;
 | 
			
		||||
use solana_core::validator::{Validator, ValidatorConfig};
 | 
			
		||||
use solana_sdk::clock::Slot;
 | 
			
		||||
use solana_sdk::hash::Hash;
 | 
			
		||||
use solana_sdk::signature::{read_keypair, Keypair, KeypairUtil};
 | 
			
		||||
use solana_sdk::signature::{read_keypair_file, Keypair, KeypairUtil};
 | 
			
		||||
use std::fs::{self, File};
 | 
			
		||||
use std::io::{self, Read};
 | 
			
		||||
use std::net::{SocketAddr, TcpListener};
 | 
			
		||||
@@ -219,7 +219,7 @@ fn initialize_ledger_path(
 | 
			
		||||
 | 
			
		||||
// Return an error if a keypair file cannot be parsed.
 | 
			
		||||
fn is_keypair(string: String) -> Result<(), String> {
 | 
			
		||||
    read_keypair(&string)
 | 
			
		||||
    read_keypair_file(&string)
 | 
			
		||||
        .map(|_| ())
 | 
			
		||||
        .map_err(|err| format!("{:?}", err))
 | 
			
		||||
}
 | 
			
		||||
@@ -419,7 +419,7 @@ pub fn main() {
 | 
			
		||||
 | 
			
		||||
    let mut validator_config = ValidatorConfig::default();
 | 
			
		||||
    let keypair = if let Some(identity) = matches.value_of("identity") {
 | 
			
		||||
        read_keypair(identity).unwrap_or_else(|err| {
 | 
			
		||||
        read_keypair_file(identity).unwrap_or_else(|err| {
 | 
			
		||||
            error!("{}: Unable to open keypair file: {}", err, identity);
 | 
			
		||||
            exit(1);
 | 
			
		||||
        })
 | 
			
		||||
@@ -428,7 +428,7 @@ pub fn main() {
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let voting_keypair = if let Some(identity) = matches.value_of("voting_keypair") {
 | 
			
		||||
        read_keypair(identity).unwrap_or_else(|err| {
 | 
			
		||||
        read_keypair_file(identity).unwrap_or_else(|err| {
 | 
			
		||||
            error!("{}: Unable to open keypair file: {}", err, identity);
 | 
			
		||||
            exit(1);
 | 
			
		||||
        })
 | 
			
		||||
@@ -436,7 +436,7 @@ pub fn main() {
 | 
			
		||||
        Keypair::new()
 | 
			
		||||
    };
 | 
			
		||||
    let storage_keypair = if let Some(storage_keypair) = matches.value_of("storage_keypair") {
 | 
			
		||||
        read_keypair(storage_keypair).unwrap_or_else(|err| {
 | 
			
		||||
        read_keypair_file(storage_keypair).unwrap_or_else(|err| {
 | 
			
		||||
            error!("{}: Unable to open keypair file: {}", err, storage_keypair);
 | 
			
		||||
            exit(1);
 | 
			
		||||
        })
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user