Adds support for inspecting a hex encoded public key (#7344)

* Adds support for inspecting a hex encoded public key

This adds support for inspecting hex encoded public keys to subkey. The
command looks like:

`subkey inspect --public 0xPUBLICHEX`

* Update client/cli/src/commands/utils.rs

Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com>

Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com>
This commit is contained in:
Bastian Köcher
2020-10-17 09:43:46 +02:00
committed by GitHub
parent da8ce4f258
commit 158fdecc0b
7 changed files with 139 additions and 26 deletions
@@ -70,7 +70,7 @@ impl GenerateCmd {
mnemonic.phrase(),
password,
self.network_scheme.network.clone(),
output
output,
)
);
Ok(())
@@ -18,8 +18,8 @@
//! Implementation of the `inspect` subcommand
use crate::{
utils, KeystoreParams, with_crypto_scheme, NetworkSchemeFlag,
OutputTypeFlag, CryptoSchemeFlag, Error,
utils::{self, print_from_uri, print_from_public}, KeystoreParams,
with_crypto_scheme, NetworkSchemeFlag, OutputTypeFlag, CryptoSchemeFlag, Error,
};
use structopt::StructOpt;
/// The `inspect` command
@@ -30,7 +30,9 @@ use structopt::StructOpt;
)]
pub struct InspectKeyCmd {
/// A Key URI to be inspected. May be a secret seed, secret URI
/// (with derivation paths and password), SS58 or public URI.
/// (with derivation paths and password), SS58, public URI or a hex encoded public key.
///
/// If it is a hex encoded public key, `--public` needs to be given as argument.
///
/// If the given value is a file, the file content will be used
/// as URI.
@@ -38,6 +40,10 @@ pub struct InspectKeyCmd {
/// If omitted, you will be prompted for the URI.
uri: Option<String>,
/// Is the given `uri` a hex encoded public key?
#[structopt(long)]
public: bool,
#[allow(missing_docs)]
#[structopt(flatten)]
pub keystore_params: KeystoreParams,
@@ -61,16 +67,26 @@ impl InspectKeyCmd {
let uri = utils::read_uri(self.uri.as_ref())?;
let password = self.keystore_params.read_password()?;
use utils::print_from_uri;
with_crypto_scheme!(
self.crypto_scheme.scheme,
print_from_uri(
&uri,
password,
self.network_scheme.network.clone(),
self.output_scheme.output_type.clone()
)
);
if self.public {
with_crypto_scheme!(
self.crypto_scheme.scheme,
print_from_public(
&uri,
self.network_scheme.network.clone(),
self.output_scheme.output_type.clone(),
)
)?;
} else {
with_crypto_scheme!(
self.crypto_scheme.scheme,
print_from_uri(
&uri,
password,
self.network_scheme.network.clone(),
self.output_scheme.output_type.clone(),
)
);
}
Ok(())
}
@@ -94,4 +110,12 @@ mod tests {
let inspect = InspectKeyCmd::from_iter(&["inspect-key", seed]);
assert!(inspect.run().is_ok());
}
#[test]
fn inspect_public_key() {
let public = "0x12e76e0ae8ce41b6516cce52b3f23a08dcb4cfeed53c6ee8f5eb9f7367341069";
let inspect = InspectKeyCmd::from_iter(&["inspect-key", "--public", public]);
assert!(inspect.run().is_ok());
}
}
+1 -1
View File
@@ -22,7 +22,7 @@ use structopt::StructOpt;
use super::{
insert::InsertCmd,
inspect::InspectKeyCmd,
inspect_key::InspectKeyCmd,
generate::GenerateCmd,
inspect_node_key::InspectNodeKeyCmd,
generate_node_key::GenerateNodeKeyCmd,
+2 -2
View File
@@ -30,7 +30,7 @@ mod generate_node_key;
mod generate;
mod insert;
mod inspect_node_key;
mod inspect;
mod inspect_key;
mod key;
pub mod utils;
@@ -44,7 +44,7 @@ pub use self::{
sign::SignCmd,
generate::GenerateCmd,
insert::InsertCmd,
inspect::InspectKeyCmd,
inspect_key::InspectKeyCmd,
generate_node_key::GenerateNodeKeyCmd,
inspect_node_key::InspectNodeKeyCmd,
key::KeySubcommand,
+64 -8
View File
@@ -17,7 +17,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//! subcommand utilities
use std::{io::Read, path::PathBuf};
use std::{io::Read, path::PathBuf, convert::TryFrom};
use sp_core::{
Pair, hexdisplay::HexDisplay,
crypto::{Ss58Codec, Ss58AddressFormat},
@@ -50,13 +50,23 @@ pub fn read_uri(uri: Option<&String>) -> error::Result<String> {
Ok(uri)
}
/// print formatted pair from uri
/// Try to parse given `uri` and print relevant information.
///
/// 1. Try to construct the `Pair` while using `uri` as input for [`sp_core::Pair::from_phrase`].
///
/// 2. Try to construct the `Pair` while using `uri` as input for [`sp_core::Pair::from_string_with_seed`].
///
/// 3. Try to construct the `Pair::Public` while using `uri` as input for
/// [`sp_core::Pair::Public::from_string_with_version`].
pub fn print_from_uri<Pair>(
uri: &str,
password: Option<SecretString>,
network_override: Option<Ss58AddressFormat>,
output: OutputType,
) where Pair: sp_core::Pair, Pair::Public: Into<MultiSigner> {
) where
Pair: sp_core::Pair,
Pair::Public: Into<MultiSigner>,
{
let password = password.as_ref().map(|s| s.expose_secret().as_str());
if let Ok((pair, seed)) = Pair::from_phrase(uri, password.clone()) {
let public_key = pair.public();
@@ -130,28 +140,74 @@ pub fn print_from_uri<Pair>(
"accountId": format_account_id::<Pair>(public_key.clone()),
"ss58Address": public_key.to_ss58check_with_version(network_override),
});
println!("{}", serde_json::to_string_pretty(&json).expect("Json pretty print failed"));
},
OutputType::Text => {
println!(
"Public Key URI `{}` is account:\n \
Network ID/version: {}\n \
Public key (hex): {}\n \
Account ID: {}\n \
SS58 Address: {}",
Network ID/version: {}\n \
Public key (hex): {}\n \
Account ID: {}\n \
SS58 Address: {}",
uri,
String::from(network_override),
format_public_key::<Pair>(public_key.clone()),
format_account_id::<Pair>(public_key.clone()),
public_key.to_ss58check_with_version(network_override),
);
},
}
}
} else {
println!("Invalid phrase/URI given");
}
}
/// Try to parse given `public` as hex encoded public key and print relevant information.
pub fn print_from_public<Pair>(
public_str: &str,
network_override: Option<Ss58AddressFormat>,
output: OutputType,
) -> Result<(), Error>
where
Pair: sp_core::Pair,
Pair::Public: Into<MultiSigner>,
{
let public = decode_hex(public_str)?;
let public_key = Pair::Public::try_from(&public)
.map_err(|_| "Failed to construct public key from given hex")?;
let network_override = network_override.unwrap_or_default();
match output {
OutputType::Json => {
let json = json!({
"networkId": String::from(network_override),
"publicKey": format_public_key::<Pair>(public_key.clone()),
"accountId": format_account_id::<Pair>(public_key.clone()),
"ss58Address": public_key.to_ss58check_with_version(network_override),
});
println!("{}", serde_json::to_string_pretty(&json).expect("Json pretty print failed"));
},
OutputType::Text => {
println!(
"Network ID/version: {}\n \
Public key (hex): {}\n \
Account ID: {}\n \
SS58 Address: {}",
String::from(network_override),
format_public_key::<Pair>(public_key.clone()),
format_account_id::<Pair>(public_key.clone()),
public_key.to_ss58check_with_version(network_override),
);
}
}
Ok(())
}
/// generate a pair from suri
pub fn pair_from_suri<P: Pair>(suri: &str, password: Option<SecretString>) -> Result<P, Error> {
let result = if let Some(pass) = password {