Allow secure keypair input for solana-validator cli (#7080)
* Allow secure keypair input for solana-validator cli * feedback * Add --skip-mnemonic-validation * Update --identity to --identity-keypair * Use struct instead of tuple * Fix dependencies * cargo fmt * Add basic tests * Use `seed phrase` instead of `mnemonic` * Update passphrase prompt
This commit is contained in:
parent
c8166aed97
commit
ce8d37984d
|
@ -3197,8 +3197,10 @@ name = "solana-clap-utils"
|
|||
version = "0.21.0"
|
||||
dependencies = [
|
||||
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rpassword 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"solana-sdk 0.21.0",
|
||||
"tiny-bip39 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -3859,12 +3861,14 @@ dependencies = [
|
|||
"ed25519-dalek 1.0.0-pre.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"generic-array 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itertools 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -3874,6 +3878,7 @@ dependencies = [
|
|||
"sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"solana-crate-features 0.21.0",
|
||||
"solana-logger 0.21.0",
|
||||
"tiny-bip39 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -76,19 +76,19 @@ Then use one of the following commands, depending on your installation choice, t
|
|||
If this is a `solana-install`-installation:
|
||||
|
||||
```bash
|
||||
solana-validator --identity ~/validator-keypair.json --voting-keypair ~/validator-vote-keypair.json --ledger ~/validator-config --rpc-port 8899 --entrypoint testnet.solana.com:8001
|
||||
solana-validator --identity-keypair ~/validator-keypair.json --voting-keypair ~/validator-vote-keypair.json --ledger ~/validator-config --rpc-port 8899 --entrypoint testnet.solana.com:8001
|
||||
```
|
||||
|
||||
Alternatively, the `solana-install run` command can be used to run the validator node while periodically checking for and applying software updates:
|
||||
|
||||
```bash
|
||||
solana-install run solana-validator -- --identity ~/validator-keypair.json --voting-keypair ~/validator-vote-keypair.json --ledger ~/validator-config --rpc-port 8899 --entrypoint testnet.solana.com:8001
|
||||
solana-install run solana-validator -- --identity-keypair ~/validator-keypair.json --voting-keypair ~/validator-vote-keypair.json --ledger ~/validator-config --rpc-port 8899 --entrypoint testnet.solana.com:8001
|
||||
```
|
||||
|
||||
If you built from source:
|
||||
|
||||
```bash
|
||||
NDEBUG=1 USE_INSTALL=1 ./multinode-demo/validator.sh --identity ~/validator-keypair.json --voting-keypair ~/validator-vote-keypair.json --rpc-port 8899 --entrypoint testnet.solana.com:8001
|
||||
NDEBUG=1 USE_INSTALL=1 ./multinode-demo/validator.sh --identity-keypair ~/validator-keypair.json --voting-keypair ~/validator-vote-keypair.json --rpc-port 8899 --entrypoint testnet.solana.com:8001
|
||||
```
|
||||
|
||||
### Enabling CUDA
|
||||
|
|
|
@ -63,7 +63,7 @@ solana balance # Same result as command above
|
|||
Solana-gossip and solana-validator commands already require an explicit `--entrypoint` argument. Simply replace testnet.solana.com in the examples with an alternate url to interact with a different testnet. For example:
|
||||
|
||||
```bash
|
||||
solana-validator --identity ~/validator-keypair.json --voting-keypair ~/validator-vote-keypair.json --ledger ~/validator-config --rpc-port 8899 beta.testnet.solana.com
|
||||
solana-validator --identity-keypair ~/validator-keypair.json --voting-keypair ~/validator-vote-keypair.json --ledger ~/validator-config --rpc-port 8899 beta.testnet.solana.com
|
||||
```
|
||||
|
||||
You can also submit JSON-RPC requests to a different testnet, like:
|
||||
|
|
|
@ -10,8 +10,10 @@ edition = "2018"
|
|||
|
||||
[dependencies]
|
||||
clap = "2.33.0"
|
||||
rpassword = "4.0"
|
||||
semver = "0.9.0"
|
||||
solana-sdk = { path = "../sdk", version = "0.21.0" }
|
||||
tiny-bip39 = "0.6.2"
|
||||
url = "2.1.0"
|
||||
|
||||
[lib]
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
use bip39::{Language, Mnemonic, Seed};
|
||||
use clap::values_t;
|
||||
use rpassword::prompt_password_stderr;
|
||||
use solana_sdk::signature::{
|
||||
keypair_from_seed, keypair_from_seed_phrase_and_passphrase, read_keypair_file, Keypair,
|
||||
KeypairUtil,
|
||||
};
|
||||
use std::error;
|
||||
|
||||
pub const ASK_SEED_PHRASE_ARG: &str = "ask_seed_phrase";
|
||||
pub const SKIP_SEED_PHRASE_VALIDATION_ARG: &str = "skip_seed_phrase_validation";
|
||||
|
||||
/// Reads user input from stdin to retrieve a seed phrase and passphrase for keypair derivation
|
||||
pub fn keypair_from_seed_phrase(
|
||||
keypair_name: &str,
|
||||
skip_validation: bool,
|
||||
) -> Result<Keypair, Box<dyn error::Error>> {
|
||||
let seed_phrase = prompt_password_stderr(&format!("[{}] seed phrase: ", keypair_name))?;
|
||||
let seed_phrase = seed_phrase.trim();
|
||||
let passphrase_prompt = format!(
|
||||
"[{}] If this seed phrase has an associated passphrase, enter it now. Otherwise, press ENTER to continue: ",
|
||||
keypair_name,
|
||||
);
|
||||
|
||||
if skip_validation {
|
||||
let passphrase = prompt_password_stderr(&passphrase_prompt)?;
|
||||
keypair_from_seed_phrase_and_passphrase(&seed_phrase, &passphrase)
|
||||
} else {
|
||||
let mnemonic = Mnemonic::from_phrase(seed_phrase, Language::English)?;
|
||||
let passphrase = prompt_password_stderr(&passphrase_prompt)?;
|
||||
let seed = Seed::new(&mnemonic, &passphrase);
|
||||
keypair_from_seed(seed.as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct KeypairWithGenerated {
|
||||
pub keypair: Keypair,
|
||||
pub generated: bool,
|
||||
}
|
||||
|
||||
impl KeypairWithGenerated {
|
||||
fn new(keypair: Keypair, generated: bool) -> Self {
|
||||
Self { keypair, generated }
|
||||
}
|
||||
}
|
||||
|
||||
/// 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<KeypairWithGenerated, Box<dyn error::Error>> {
|
||||
let ask_seed_phrase_matches =
|
||||
values_t!(matches.values_of(ASK_SEED_PHRASE_ARG), 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() {
|
||||
let ask_seed_phrase_kebab = ASK_SEED_PHRASE_ARG.replace('_', "-");
|
||||
clap::Error::with_description(
|
||||
&format!(
|
||||
"`--{} {}` cannot be used with `{} <PATH>`",
|
||||
ask_seed_phrase_kebab, keypair_name, keypair_name
|
||||
),
|
||||
clap::ErrorKind::ArgumentConflict,
|
||||
)
|
||||
.exit();
|
||||
}
|
||||
|
||||
let skip_validation = matches.is_present(SKIP_SEED_PHRASE_VALIDATION_ARG);
|
||||
keypair_from_seed_phrase(keypair_name, skip_validation)
|
||||
.map(|keypair| KeypairWithGenerated::new(keypair, false))
|
||||
} else if let Some(keypair_file) = matches.value_of(keypair_match_name) {
|
||||
read_keypair_file(keypair_file).map(|keypair| KeypairWithGenerated::new(keypair, false))
|
||||
} else {
|
||||
Ok(KeypairWithGenerated::new(Keypair::new(), true))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use clap::ArgMatches;
|
||||
|
||||
#[test]
|
||||
fn test_keypair_input() {
|
||||
let arg_matches = ArgMatches::default();
|
||||
let KeypairWithGenerated { generated, .. } = keypair_input(&arg_matches, "").unwrap();
|
||||
assert!(generated);
|
||||
}
|
||||
}
|
|
@ -19,3 +19,4 @@ macro_rules! version {
|
|||
|
||||
pub mod input_parsers;
|
||||
pub mod input_validators;
|
||||
pub mod keypair;
|
||||
|
|
|
@ -76,10 +76,10 @@ ledger_dir="$SOLANA_CONFIG_DIR"/bootstrap-leader
|
|||
args+=(
|
||||
--accounts "$SOLANA_CONFIG_DIR"/bootstrap-leader/accounts
|
||||
--enable-rpc-exit
|
||||
--identity "$identity_keypair"
|
||||
--ledger "$ledger_dir"
|
||||
--rpc-port 8899
|
||||
--snapshot-interval-slots 100
|
||||
--identity-keypair "$identity_keypair"
|
||||
--storage-keypair "$storage_keypair"
|
||||
--voting-keypair "$vote_keypair"
|
||||
--rpc-drone-address 127.0.0.1:9900
|
||||
|
|
|
@ -70,7 +70,7 @@ while [[ -n $1 ]]; do
|
|||
elif [[ $1 = --expected-genesis-hash ]]; then
|
||||
args+=("$1" "$2")
|
||||
shift 2
|
||||
elif [[ $1 = --identity ]]; then
|
||||
elif [[ $1 = --identity-keypair ]]; then
|
||||
identity_keypair_path=$2
|
||||
args+=("$1" "$2")
|
||||
shift 2
|
||||
|
@ -170,7 +170,7 @@ fi
|
|||
|
||||
if [[ -n $REQUIRE_KEYPAIRS ]]; then
|
||||
if [[ -z $identity_keypair_path ]]; then
|
||||
usage "Error: --identity not specified"
|
||||
usage "Error: --identity-keypair not specified"
|
||||
fi
|
||||
if [[ -z $voting_keypair_path ]]; then
|
||||
usage "Error: --voting-keypair not specified"
|
||||
|
@ -209,7 +209,7 @@ if ((airdrops_enabled)); then
|
|||
default_arg --rpc-drone-address "$drone_address"
|
||||
fi
|
||||
|
||||
default_arg --identity "$identity_keypair_path"
|
||||
default_arg --identity-keypair "$identity_keypair_path"
|
||||
default_arg --voting-keypair "$voting_keypair_path"
|
||||
default_arg --storage-keypair "$storage_keypair_path"
|
||||
default_arg --ledger "$ledger_dir"
|
||||
|
|
|
@ -304,7 +304,7 @@ EOF
|
|||
if [[ ! -f config/validator-identity.json ]]; then
|
||||
solana-keygen new -o config/validator-identity.json
|
||||
fi
|
||||
args+=(--identity config/validator-identity.json)
|
||||
args+=(--identity-keypair config/validator-identity.json)
|
||||
|
||||
if [[ $airdropsEnabled != true ]]; then
|
||||
args+=(--no-airdrop)
|
||||
|
|
|
@ -375,6 +375,15 @@ dependencies = [
|
|||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-mac"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ct-logs"
|
||||
version = "0.6.0"
|
||||
|
@ -681,6 +690,15 @@ name = "hex"
|
|||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "hmac"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "0.1.18"
|
||||
|
@ -1069,6 +1087,15 @@ dependencies = [
|
|||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pbkdf2"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "1.0.1"
|
||||
|
@ -1557,7 +1584,7 @@ version = "0.6.10"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "solana-bpf-loader-api"
|
||||
name = "solana-bpf-loader-program"
|
||||
version = "0.21.0"
|
||||
dependencies = [
|
||||
"bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1570,16 +1597,6 @@ dependencies = [
|
|||
"solana_rbpf 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "solana-bpf-loader-program"
|
||||
version = "0.21.0"
|
||||
dependencies = [
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"solana-bpf-loader-api 0.21.0",
|
||||
"solana-logger 0.21.0",
|
||||
"solana-sdk 0.21.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "solana-bpf-programs"
|
||||
version = "0.21.0"
|
||||
|
@ -1587,7 +1604,7 @@ dependencies = [
|
|||
"bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"elf 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"solana-bpf-loader-api 0.21.0",
|
||||
"solana-bpf-loader-program 0.21.0",
|
||||
"solana-logger 0.21.0",
|
||||
"solana-runtime 0.21.0",
|
||||
"solana-sdk 0.21.0",
|
||||
|
@ -1704,13 +1721,14 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "solana-config-api"
|
||||
name = "solana-config-program"
|
||||
version = "0.21.0"
|
||||
dependencies = [
|
||||
"bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"solana-logger 0.21.0",
|
||||
"solana-sdk 0.21.0",
|
||||
]
|
||||
|
||||
|
@ -1793,17 +1811,14 @@ dependencies = [
|
|||
"serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"solana-bpf-loader-api 0.21.0",
|
||||
"solana-bpf-loader-program 0.21.0",
|
||||
"solana-logger 0.21.0",
|
||||
"solana-measure 0.21.0",
|
||||
"solana-metrics 0.21.0",
|
||||
"solana-rayon-threadlimit 0.21.0",
|
||||
"solana-sdk 0.21.0",
|
||||
"solana-stake-api 0.21.0",
|
||||
"solana-stake-program 0.21.0",
|
||||
"solana-storage-api 0.21.0",
|
||||
"solana-vote-api 0.21.0",
|
||||
"solana-storage-program 0.21.0",
|
||||
"solana-vote-program 0.21.0",
|
||||
"sys-info 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1820,11 +1835,14 @@ dependencies = [
|
|||
"ed25519-dalek 1.0.0-pre.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"generic-array 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itertools 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1840,36 +1858,26 @@ dependencies = [
|
|||
name = "solana-sdk-bpf-test"
|
||||
version = "0.21.0"
|
||||
|
||||
[[package]]
|
||||
name = "solana-stake-api"
|
||||
version = "0.21.0"
|
||||
dependencies = [
|
||||
"bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"solana-config-api 0.21.0",
|
||||
"solana-logger 0.21.0",
|
||||
"solana-metrics 0.21.0",
|
||||
"solana-sdk 0.21.0",
|
||||
"solana-vote-api 0.21.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "solana-stake-program"
|
||||
version = "0.21.0"
|
||||
dependencies = [
|
||||
"bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"solana-config-program 0.21.0",
|
||||
"solana-logger 0.21.0",
|
||||
"solana-metrics 0.21.0",
|
||||
"solana-sdk 0.21.0",
|
||||
"solana-stake-api 0.21.0",
|
||||
"solana-vote-program 0.21.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "solana-storage-api"
|
||||
name = "solana-storage-program"
|
||||
version = "0.21.0"
|
||||
dependencies = [
|
||||
"bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1883,29 +1891,19 @@ dependencies = [
|
|||
"solana-sdk 0.21.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "solana-vote-api"
|
||||
version = "0.21.0"
|
||||
dependencies = [
|
||||
"bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"solana-logger 0.21.0",
|
||||
"solana-metrics 0.21.0",
|
||||
"solana-sdk 0.21.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "solana-vote-program"
|
||||
version = "0.21.0"
|
||||
dependencies = [
|
||||
"bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"solana-logger 0.21.0",
|
||||
"solana-metrics 0.21.0",
|
||||
"solana-sdk 0.21.0",
|
||||
"solana-vote-api 0.21.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1951,6 +1949,11 @@ name = "strsim"
|
|||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.1.1"
|
||||
|
@ -2611,6 +2614,7 @@ dependencies = [
|
|||
"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9"
|
||||
"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b"
|
||||
"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6"
|
||||
"checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5"
|
||||
"checksum ct-logs 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4d3686f5fa27dbc1d76c751300376e167c5a43387f44bb451fd1c24776e49113"
|
||||
"checksum curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8b7dcd30ba50cdf88b55b033456138b7c0ac4afdc436d82e1b79f370f24cc66d"
|
||||
"checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90"
|
||||
|
@ -2646,6 +2650,7 @@ dependencies = [
|
|||
"checksum hash32 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "12d790435639c06a7b798af9e1e331ae245b7ef915b92f70a39b4cf8c00686af"
|
||||
"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
|
||||
"checksum hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "023b39be39e3a2da62a94feb433e91e8bcd37676fbc8bea371daf52b7a769a3e"
|
||||
"checksum hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695"
|
||||
"checksum http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "372bcb56f939e449117fb0869c2e8fd8753a8223d92a172c6e808cf123a5b6e4"
|
||||
"checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d"
|
||||
"checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9"
|
||||
|
@ -2689,6 +2694,7 @@ dependencies = [
|
|||
"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13"
|
||||
"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337"
|
||||
"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9"
|
||||
"checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9"
|
||||
"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
|
||||
"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
||||
"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b"
|
||||
|
@ -2750,6 +2756,7 @@ dependencies = [
|
|||
"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
|
||||
"checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d"
|
||||
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
"checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee"
|
||||
"checksum subtle 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "01f40907d9ffc762709e4ff3eb4a6f6b41b650375a3f09ac92b641942b7fb082"
|
||||
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
|
||||
"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
|
||||
|
|
2
run.sh
2
run.sh
|
@ -99,7 +99,7 @@ solana-drone --keypair "$dataDir"/faucet-keypair.json &
|
|||
drone=$!
|
||||
|
||||
args=(
|
||||
--identity "$dataDir"/leader-keypair.json
|
||||
--identity-keypair "$dataDir"/leader-keypair.json
|
||||
--storage-keypair "$dataDir"/leader-storage-account-keypair.json
|
||||
--voting-keypair "$dataDir"/leader-vote-account-keypair.json
|
||||
--ledger "$ledgerDir"
|
||||
|
|
|
@ -31,12 +31,14 @@ bs58 = "0.3.0"
|
|||
byteorder = { version = "1.3.2", optional = true }
|
||||
generic-array = { version = "0.13.2", default-features = false, features = ["serde", "more_lengths"] }
|
||||
hex = "0.4.0"
|
||||
hmac = "0.7.0"
|
||||
itertools = { version = "0.8.1" }
|
||||
lazy_static = "1.4.0"
|
||||
log = { version = "0.4.8" }
|
||||
memmap = { version = "0.6.2", optional = true }
|
||||
num-derive = { version = "0.3" }
|
||||
num-traits = { version = "0.2" }
|
||||
pbkdf2 = { version = "0.3.0", default-features = false }
|
||||
rand = { version = "0.6.5", optional = true }
|
||||
rand_chacha = { version = "0.1.1", optional = true }
|
||||
serde = "1.0.102"
|
||||
|
@ -47,3 +49,6 @@ sha2 = "0.8.0"
|
|||
ed25519-dalek = { version = "1.0.0-pre.1", optional = true }
|
||||
solana-logger = { path = "../logger", version = "0.21.0", optional = true }
|
||||
solana-crate-features = { path = "../crate-features", version = "0.21.0", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
tiny-bip39 = "0.6.2"
|
||||
|
|
|
@ -4,6 +4,7 @@ use crate::pubkey::Pubkey;
|
|||
use bs58;
|
||||
use ed25519_dalek;
|
||||
use generic_array::{typenum::U64, GenericArray};
|
||||
use hmac::Hmac;
|
||||
use rand::rngs::OsRng;
|
||||
use serde_json;
|
||||
use std::{
|
||||
|
@ -186,9 +187,29 @@ pub fn keypair_from_seed(seed: &[u8]) -> Result<Keypair, Box<dyn error::Error>>
|
|||
Ok(keypair)
|
||||
}
|
||||
|
||||
pub fn keypair_from_seed_phrase_and_passphrase(
|
||||
seed_phrase: &str,
|
||||
passphrase: &str,
|
||||
) -> Result<Keypair, Box<dyn error::Error>> {
|
||||
const PBKDF2_ROUNDS: usize = 2048;
|
||||
const PBKDF2_BYTES: usize = 64;
|
||||
|
||||
let salt = format!("mnemonic{}", passphrase);
|
||||
|
||||
let mut seed = vec![0u8; PBKDF2_BYTES];
|
||||
pbkdf2::pbkdf2::<Hmac<sha2::Sha512>>(
|
||||
seed_phrase.as_bytes(),
|
||||
salt.as_bytes(),
|
||||
PBKDF2_ROUNDS,
|
||||
&mut seed,
|
||||
);
|
||||
keypair_from_seed(&seed[..])
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use bip39::{Language, Mnemonic, MnemonicType, Seed};
|
||||
use std::mem;
|
||||
|
||||
fn tmp_file_path(name: &str) -> String {
|
||||
|
@ -300,4 +321,15 @@ mod tests {
|
|||
Err(ParseSignatureError::Invalid)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keypair_from_seed_phrase_and_passphrase() {
|
||||
let mnemonic = Mnemonic::new(MnemonicType::Words12, Language::English);
|
||||
let passphrase = "42";
|
||||
let seed = Seed::new(&mnemonic, passphrase);
|
||||
let expected_keypair = keypair_from_seed(seed.as_bytes()).unwrap();
|
||||
let keypair =
|
||||
keypair_from_seed_phrase_and_passphrase(mnemonic.phrase(), passphrase).unwrap();
|
||||
assert_eq!(keypair.pubkey(), expected_keypair.pubkey());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,8 +30,8 @@ solana-runtime = { path = "../runtime", version = "0.21.0" }
|
|||
solana-sdk = { path = "../sdk", version = "0.21.0" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "0.21.0" }
|
||||
solana-vote-signer = { path = "../vote-signer", version = "0.21.0" }
|
||||
tempfile = "3.1.0"
|
||||
tar = "0.4.26"
|
||||
tempfile = "3.1.0"
|
||||
|
||||
[target."cfg(unix)".dependencies]
|
||||
gag = "0.1.10"
|
||||
|
|
|
@ -6,6 +6,9 @@ use log::*;
|
|||
use solana_clap_utils::{
|
||||
input_parsers::pubkey_of,
|
||||
input_validators::{is_keypair, is_pubkey_or_keypair},
|
||||
keypair::{
|
||||
keypair_input, KeypairWithGenerated, ASK_SEED_PHRASE_ARG, SKIP_SEED_PHRASE_VALIDATION_ARG,
|
||||
},
|
||||
};
|
||||
use solana_client::rpc_client::RpcClient;
|
||||
use solana_core::{
|
||||
|
@ -21,7 +24,7 @@ use solana_sdk::{
|
|||
clock::Slot,
|
||||
hash::Hash,
|
||||
pubkey::Pubkey,
|
||||
signature::{read_keypair_file, Keypair, KeypairUtil},
|
||||
signature::{Keypair, KeypairUtil},
|
||||
};
|
||||
use std::{
|
||||
fs::{self, File},
|
||||
|
@ -323,9 +326,24 @@ pub fn main() {
|
|||
.help("Stream entries to this unix domain socket path")
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("identity")
|
||||
Arg::with_name(ASK_SEED_PHRASE_ARG)
|
||||
.long("ask-seed-phrase")
|
||||
.value_name("KEYPAIR NAME")
|
||||
.multiple(true)
|
||||
.takes_value(true)
|
||||
.possible_values(&["identity-keypair", "storage-keypair", "voting-keypair"])
|
||||
.help("Securely recover a keypair using a seed phrase and optional passphrase"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name(SKIP_SEED_PHRASE_VALIDATION_ARG)
|
||||
.long("skip-seed-phrase-validation")
|
||||
.requires(ASK_SEED_PHRASE_ARG)
|
||||
.help("Skip validation of seed phrases. Use this if your phrase does not use the BIP39 official English word list"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("identity_keypair")
|
||||
.short("i")
|
||||
.long("identity")
|
||||
.long("identity-keypair")
|
||||
.value_name("PATH")
|
||||
.takes_value(true)
|
||||
.validator(is_keypair)
|
||||
|
@ -520,34 +538,27 @@ pub fn main() {
|
|||
)
|
||||
.get_matches();
|
||||
|
||||
let identity_keypair = if let Some(identity) = matches.value_of("identity") {
|
||||
read_keypair_file(identity).unwrap_or_else(|err| {
|
||||
error!("{}: Unable to open keypair file: {}", err, identity);
|
||||
let identity_keypair = Arc::new(
|
||||
keypair_input(&matches, "identity-keypair")
|
||||
.unwrap_or_else(|err| {
|
||||
eprintln!("Identity keypair input failed: {}", err);
|
||||
exit(1);
|
||||
})
|
||||
.keypair,
|
||||
);
|
||||
let KeypairWithGenerated {
|
||||
keypair: voting_keypair,
|
||||
generated: ephemeral_voting_keypair,
|
||||
} = keypair_input(&matches, "voting-keypair").unwrap_or_else(|err| {
|
||||
eprintln!("Voting keypair input failed: {}", err);
|
||||
exit(1);
|
||||
});
|
||||
let storage_keypair = keypair_input(&matches, "storage-keypair")
|
||||
.unwrap_or_else(|err| {
|
||||
eprintln!("Storage keypair input failed: {}", err);
|
||||
exit(1);
|
||||
})
|
||||
} else {
|
||||
Keypair::new()
|
||||
};
|
||||
let identity_keypair = Arc::new(identity_keypair);
|
||||
|
||||
let mut ephemeral_voting_keypair = false;
|
||||
let voting_keypair = if let Some(identity) = matches.value_of("voting_keypair") {
|
||||
read_keypair_file(identity).unwrap_or_else(|err| {
|
||||
error!("{}: Unable to open keypair file: {}", err, identity);
|
||||
exit(1);
|
||||
})
|
||||
} else {
|
||||
ephemeral_voting_keypair = true;
|
||||
Keypair::new()
|
||||
};
|
||||
let storage_keypair = if let Some(storage_keypair) = matches.value_of("storage_keypair") {
|
||||
read_keypair_file(storage_keypair).unwrap_or_else(|err| {
|
||||
error!("{}: Unable to open keypair file: {}", err, storage_keypair);
|
||||
exit(1);
|
||||
})
|
||||
} else {
|
||||
Keypair::new()
|
||||
};
|
||||
.keypair;
|
||||
|
||||
let ledger_path = PathBuf::from(matches.value_of("ledger_path").unwrap());
|
||||
let entrypoint = matches.value_of("entrypoint");
|
||||
|
@ -582,7 +593,7 @@ pub fn main() {
|
|||
let snapshot_interval_slots = value_t_or_exit!(matches, "snapshot_interval_slots", usize);
|
||||
let snapshot_path = ledger_path.clone().join("snapshot");
|
||||
fs::create_dir_all(&snapshot_path).unwrap_or_else(|err| {
|
||||
error!(
|
||||
eprintln!(
|
||||
"Failed to create snapshots directory {:?}: {}",
|
||||
snapshot_path, err
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue