* clap-utils: Rename KeypairUrl to SignerSource (cherry picked from commit09dcc9ea04
) * clap-utils: Reduce SignerSource's visibility (cherry picked from commitc5ab3ba6f1
) * clap-utils: Use `uriparse` crate to parse `SignerSource` (cherry picked from commit5d1ef5d01d
) * clap-utils: Add explicit schemes for `ask` and `file` `SignerSource`s (cherry picked from commit6444f0e57b
) Co-authored-by: Trent Nelson <trent@solana.com>
This commit is contained in:
11
Cargo.lock
generated
11
Cargo.lock
generated
@ -4145,6 +4145,7 @@ dependencies = [
|
||||
"solana-sdk",
|
||||
"thiserror",
|
||||
"tiny-bip39 0.8.0",
|
||||
"uriparse",
|
||||
"url 2.2.0",
|
||||
]
|
||||
|
||||
@ -6567,6 +6568,16 @@ version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
||||
|
||||
[[package]]
|
||||
name = "uriparse"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e515b1ada404168e145ac55afba3c42f04cf972201a8552d42e2abb17c1b7221"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "1.7.2"
|
||||
|
@ -16,6 +16,7 @@ solana-remote-wallet = { path = "../remote-wallet", version = "=1.6.6" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.6.6" }
|
||||
thiserror = "1.0.21"
|
||||
tiny-bip39 = "0.8.0"
|
||||
uriparse = "0.6.3"
|
||||
url = "2.1.0"
|
||||
chrono = "0.4"
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::keypair::{parse_keypair_path, KeypairUrl, ASK_KEYWORD};
|
||||
use crate::keypair::{parse_signer_source, SignerSource, ASK_KEYWORD};
|
||||
use chrono::DateTime;
|
||||
use solana_sdk::{
|
||||
clock::{Epoch, Slot},
|
||||
@ -108,8 +108,8 @@ pub fn is_valid_pubkey<T>(string: T) -> Result<(), String>
|
||||
where
|
||||
T: AsRef<str> + Display,
|
||||
{
|
||||
match parse_keypair_path(string.as_ref()) {
|
||||
KeypairUrl::Filepath(path) => is_keypair(path),
|
||||
match parse_signer_source(string.as_ref()) {
|
||||
SignerSource::Filepath(path) => is_keypair(path),
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ use solana_sdk::{
|
||||
},
|
||||
};
|
||||
use std::{
|
||||
convert::TryFrom,
|
||||
error,
|
||||
io::{stdin, stdout, Write},
|
||||
process::exit,
|
||||
@ -133,7 +134,7 @@ impl DefaultSigner {
|
||||
}
|
||||
}
|
||||
|
||||
pub enum KeypairUrl {
|
||||
pub(crate) enum SignerSource {
|
||||
Ask,
|
||||
Filepath(String),
|
||||
Usb(String),
|
||||
@ -141,17 +142,30 @@ pub enum KeypairUrl {
|
||||
Pubkey(Pubkey),
|
||||
}
|
||||
|
||||
pub fn parse_keypair_path(path: &str) -> KeypairUrl {
|
||||
if path == "-" {
|
||||
KeypairUrl::Stdin
|
||||
} else if path == ASK_KEYWORD {
|
||||
KeypairUrl::Ask
|
||||
} else if path.starts_with("usb://") {
|
||||
KeypairUrl::Usb(path.to_string())
|
||||
} else if let Ok(pubkey) = Pubkey::from_str(path) {
|
||||
KeypairUrl::Pubkey(pubkey)
|
||||
} else {
|
||||
KeypairUrl::Filepath(path.to_string())
|
||||
pub(crate) fn parse_signer_source<S: AsRef<str>>(source: S) -> SignerSource {
|
||||
let source = source.as_ref();
|
||||
match uriparse::URIReference::try_from(source) {
|
||||
Err(_) => SignerSource::Filepath(source.to_string()),
|
||||
Ok(uri) => {
|
||||
if let Some(scheme) = uri.scheme() {
|
||||
let scheme = scheme.as_str().to_ascii_lowercase();
|
||||
match scheme.as_str() {
|
||||
"ask" => SignerSource::Ask,
|
||||
"file" => SignerSource::Filepath(uri.path().to_string()),
|
||||
"usb" => SignerSource::Usb(source.to_string()),
|
||||
_ => SignerSource::Filepath(source.to_string()),
|
||||
}
|
||||
} else {
|
||||
match source {
|
||||
"-" => SignerSource::Stdin,
|
||||
ASK_KEYWORD => SignerSource::Ask,
|
||||
_ => match Pubkey::from_str(source) {
|
||||
Ok(pubkey) => SignerSource::Pubkey(pubkey),
|
||||
Err(_) => SignerSource::Filepath(source.to_string()),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -198,8 +212,8 @@ pub fn signer_from_path_with_config(
|
||||
wallet_manager: &mut Option<Arc<RemoteWalletManager>>,
|
||||
config: &SignerFromPathConfig,
|
||||
) -> Result<Box<dyn Signer>, Box<dyn error::Error>> {
|
||||
match parse_keypair_path(path) {
|
||||
KeypairUrl::Ask => {
|
||||
match parse_signer_source(path) {
|
||||
SignerSource::Ask => {
|
||||
let skip_validation = matches.is_present(SKIP_SEED_PHRASE_VALIDATION_ARG.name);
|
||||
Ok(Box::new(keypair_from_seed_phrase(
|
||||
keypair_name,
|
||||
@ -207,7 +221,7 @@ pub fn signer_from_path_with_config(
|
||||
false,
|
||||
)?))
|
||||
}
|
||||
KeypairUrl::Filepath(path) => match read_keypair_file(&path) {
|
||||
SignerSource::Filepath(path) => match read_keypair_file(&path) {
|
||||
Err(e) => Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
format!("could not read keypair file \"{}\". Run \"solana-keygen new\" to create a keypair file: {}", path, e),
|
||||
@ -215,11 +229,11 @@ pub fn signer_from_path_with_config(
|
||||
.into()),
|
||||
Ok(file) => Ok(Box::new(file)),
|
||||
},
|
||||
KeypairUrl::Stdin => {
|
||||
SignerSource::Stdin => {
|
||||
let mut stdin = std::io::stdin();
|
||||
Ok(Box::new(read_keypair(&mut stdin)?))
|
||||
}
|
||||
KeypairUrl::Usb(path) => {
|
||||
SignerSource::Usb(path) => {
|
||||
if wallet_manager.is_none() {
|
||||
*wallet_manager = maybe_wallet_manager()?;
|
||||
}
|
||||
@ -234,7 +248,7 @@ pub fn signer_from_path_with_config(
|
||||
Err(RemoteWalletError::NoDeviceFound.into())
|
||||
}
|
||||
}
|
||||
KeypairUrl::Pubkey(pubkey) => {
|
||||
SignerSource::Pubkey(pubkey) => {
|
||||
let presigner = pubkeys_sigs_of(matches, SIGNER_ARG.name)
|
||||
.as_ref()
|
||||
.and_then(|presigners| presigner_from_pubkey_sigs(&pubkey, presigners));
|
||||
@ -259,8 +273,8 @@ pub fn pubkey_from_path(
|
||||
keypair_name: &str,
|
||||
wallet_manager: &mut Option<Arc<RemoteWalletManager>>,
|
||||
) -> Result<Pubkey, Box<dyn error::Error>> {
|
||||
match parse_keypair_path(path) {
|
||||
KeypairUrl::Pubkey(pubkey) => Ok(pubkey),
|
||||
match parse_signer_source(path) {
|
||||
SignerSource::Pubkey(pubkey) => Ok(pubkey),
|
||||
_ => Ok(signer_from_path(matches, path, keypair_name, wallet_manager)?.pubkey()),
|
||||
}
|
||||
}
|
||||
@ -271,14 +285,14 @@ pub fn resolve_signer_from_path(
|
||||
keypair_name: &str,
|
||||
wallet_manager: &mut Option<Arc<RemoteWalletManager>>,
|
||||
) -> Result<Option<String>, Box<dyn error::Error>> {
|
||||
match parse_keypair_path(path) {
|
||||
KeypairUrl::Ask => {
|
||||
match parse_signer_source(path) {
|
||||
SignerSource::Ask => {
|
||||
let skip_validation = matches.is_present(SKIP_SEED_PHRASE_VALIDATION_ARG.name);
|
||||
// This method validates the seed phrase, but returns `None` because there is no path
|
||||
// on disk or to a device
|
||||
keypair_from_seed_phrase(keypair_name, skip_validation, false).map(|_| None)
|
||||
}
|
||||
KeypairUrl::Filepath(path) => match read_keypair_file(&path) {
|
||||
SignerSource::Filepath(path) => match read_keypair_file(&path) {
|
||||
Err(e) => Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
format!("could not read keypair file \"{}\". Run \"solana-keygen new\" to create a keypair file: {}", path, e),
|
||||
@ -286,13 +300,13 @@ pub fn resolve_signer_from_path(
|
||||
.into()),
|
||||
Ok(_) => Ok(Some(path.to_string())),
|
||||
},
|
||||
KeypairUrl::Stdin => {
|
||||
SignerSource::Stdin => {
|
||||
let mut stdin = std::io::stdin();
|
||||
// This method validates the keypair from stdin, but returns `None` because there is no
|
||||
// path on disk or to a device
|
||||
read_keypair(&mut stdin).map(|_| None)
|
||||
}
|
||||
KeypairUrl::Usb(path) => {
|
||||
SignerSource::Usb(path) => {
|
||||
if wallet_manager.is_none() {
|
||||
*wallet_manager = maybe_wallet_manager()?;
|
||||
}
|
||||
@ -443,4 +457,38 @@ mod tests {
|
||||
];
|
||||
assert_eq!(signer_pubkeys, expect);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_signer_source() {
|
||||
assert!(matches!(parse_signer_source("-"), SignerSource::Stdin));
|
||||
assert!(matches!(
|
||||
parse_signer_source(ASK_KEYWORD),
|
||||
SignerSource::Ask
|
||||
));
|
||||
let pubkey = Pubkey::new_unique();
|
||||
assert!(
|
||||
matches!(parse_signer_source(&pubkey.to_string()), SignerSource::Pubkey(p) if p == pubkey)
|
||||
);
|
||||
let path = "/absolute/path".to_string();
|
||||
assert!(matches!(parse_signer_source(&path), SignerSource::Filepath(p) if p == path));
|
||||
let path = "relative/path".to_string();
|
||||
assert!(matches!(parse_signer_source(&path), SignerSource::Filepath(p) if p == path));
|
||||
let usb = "usb://ledger".to_string();
|
||||
assert!(matches!(parse_signer_source(&usb), SignerSource::Usb(u) if u == usb));
|
||||
// Catchall into SignerSource::Filepath
|
||||
let junk = "sometextthatisnotapubkey".to_string();
|
||||
assert!(Pubkey::from_str(&junk).is_err());
|
||||
assert!(matches!(parse_signer_source(&junk), SignerSource::Filepath(j) if j == junk));
|
||||
|
||||
let ask = "ask:".to_string();
|
||||
assert!(matches!(parse_signer_source(&ask), SignerSource::Ask));
|
||||
let path = "/absolute/path".to_string();
|
||||
assert!(
|
||||
matches!(parse_signer_source(&format!("file:{}", path)), SignerSource::Filepath(p) if p == path)
|
||||
);
|
||||
let path = "relative/path".to_string();
|
||||
assert!(
|
||||
matches!(parse_signer_source(&format!("file:{}", path)), SignerSource::Filepath(p) if p == path)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -2553,7 +2553,7 @@ mod tests {
|
||||
}
|
||||
);
|
||||
|
||||
// Test ResolveSigner Subcommand, KeypairUrl::Filepath
|
||||
// Test ResolveSigner Subcommand, SignerSource::Filepath
|
||||
let test_resolve_signer =
|
||||
test_commands
|
||||
.clone()
|
||||
@ -2565,7 +2565,7 @@ mod tests {
|
||||
signers: vec![],
|
||||
}
|
||||
);
|
||||
// Test ResolveSigner Subcommand, KeypairUrl::Pubkey (Presigner)
|
||||
// Test ResolveSigner Subcommand, SignerSource::Pubkey (Presigner)
|
||||
let test_resolve_signer =
|
||||
test_commands
|
||||
.clone()
|
||||
|
11
programs/bpf/Cargo.lock
generated
11
programs/bpf/Cargo.lock
generated
@ -2949,6 +2949,7 @@ dependencies = [
|
||||
"solana-sdk",
|
||||
"thiserror",
|
||||
"tiny-bip39",
|
||||
"uriparse",
|
||||
"url",
|
||||
]
|
||||
|
||||
@ -4111,6 +4112,16 @@ version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
||||
|
||||
[[package]]
|
||||
name = "uriparse"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e515b1ada404168e145ac55afba3c42f04cf972201a8552d42e2abb17c1b7221"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.2.1"
|
||||
|
Reference in New Issue
Block a user