forked from ghostchain/ghost-node
		
	rustfmt ghost client cli and fix typos
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
This commit is contained in:
		
							parent
							
								
									a74e42369b
								
							
						
					
					
						commit
						767161ac9c
					
				@ -1,6 +1,6 @@
 | 
				
			|||||||
[package]
 | 
					[package]
 | 
				
			||||||
name = "ghost-client-cli"
 | 
					name = "ghost-client-cli"
 | 
				
			||||||
version = "0.1.3"
 | 
					version = "0.1.4"
 | 
				
			||||||
description = "Ghost CLI interface"
 | 
					description = "Ghost CLI interface"
 | 
				
			||||||
license.workspace = true
 | 
					license.workspace = true
 | 
				
			||||||
authors.workspace = true
 | 
					authors.workspace = true
 | 
				
			||||||
 | 
				
			|||||||
@ -3,13 +3,10 @@
 | 
				
			|||||||
use bip39::Mnemonic;
 | 
					use bip39::Mnemonic;
 | 
				
			||||||
use clap::Parser;
 | 
					use clap::Parser;
 | 
				
			||||||
use itertools::Itertools;
 | 
					use itertools::Itertools;
 | 
				
			||||||
use sc_cli::{
 | 
					use sc_cli::{with_crypto_scheme, CryptoSchemeFlag, Error, KeystoreParams, OutputTypeFlag};
 | 
				
			||||||
    with_crypto_scheme, KeystoreParams, OutputTypeFlag, 
 | 
					 | 
				
			||||||
    CryptoSchemeFlag, Error,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::params::NetworkSchemeFlag;
 | 
					 | 
				
			||||||
use crate::commands::utils::print_from_uri;
 | 
					use crate::commands::utils::print_from_uri;
 | 
				
			||||||
 | 
					use crate::params::NetworkSchemeFlag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// The `generate` command
 | 
					/// The `generate` command
 | 
				
			||||||
#[derive(Debug, Clone, Parser)]
 | 
					#[derive(Debug, Clone, Parser)]
 | 
				
			||||||
@ -17,58 +14,58 @@ use crate::commands::utils::print_from_uri;
 | 
				
			|||||||
pub struct GenerateCmd {
 | 
					pub struct GenerateCmd {
 | 
				
			||||||
    /// The number of words in the phrase to generate. One of 12 (default),
 | 
					    /// The number of words in the phrase to generate. One of 12 (default),
 | 
				
			||||||
    /// 15, 18, 21 and 24.
 | 
					    /// 15, 18, 21 and 24.
 | 
				
			||||||
	#[arg(short = 'w', long, value_name = "WORDS")]
 | 
					    #[arg(short = 'w', long, value_name = "WORDS")]
 | 
				
			||||||
	words: Option<usize>,
 | 
					    words: Option<usize>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#[allow(missing_docs)]
 | 
					    #[allow(missing_docs)]
 | 
				
			||||||
	#[clap(flatten)]
 | 
					    #[clap(flatten)]
 | 
				
			||||||
	pub keystore_params: KeystoreParams,
 | 
					    pub keystore_params: KeystoreParams,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#[allow(missing_docs)]
 | 
					    #[allow(missing_docs)]
 | 
				
			||||||
	#[clap(flatten)]
 | 
					    #[clap(flatten)]
 | 
				
			||||||
	pub network_scheme: NetworkSchemeFlag,
 | 
					    pub network_scheme: NetworkSchemeFlag,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#[allow(missing_docs)]
 | 
					    #[allow(missing_docs)]
 | 
				
			||||||
	#[clap(flatten)]
 | 
					    #[clap(flatten)]
 | 
				
			||||||
	pub output_scheme: OutputTypeFlag,
 | 
					    pub output_scheme: OutputTypeFlag,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#[allow(missing_docs)]
 | 
					    #[allow(missing_docs)]
 | 
				
			||||||
	#[clap(flatten)]
 | 
					    #[clap(flatten)]
 | 
				
			||||||
	pub crypto_scheme: CryptoSchemeFlag,
 | 
					    pub crypto_scheme: CryptoSchemeFlag,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl GenerateCmd {
 | 
					impl GenerateCmd {
 | 
				
			||||||
	/// Run the command
 | 
					    /// Run the command
 | 
				
			||||||
	pub fn run(&self) -> Result<(), Error> {
 | 
					    pub fn run(&self) -> Result<(), Error> {
 | 
				
			||||||
		let words = match self.words {
 | 
					        let words = match self.words {
 | 
				
			||||||
            Some(words_count) if [12, 15, 18, 21, 24].contains(&words_count) => Ok(words_count),
 | 
					            Some(words_count) if [12, 15, 18, 21, 24].contains(&words_count) => Ok(words_count),
 | 
				
			||||||
            Some(_) => Err(Error::Input(
 | 
					            Some(_) => Err(Error::Input(
 | 
				
			||||||
                "Invalid number of words given for phrase: must be 12/15/18/21/24".into(),
 | 
					                "Invalid number of words given for phrase: must be 12/15/18/21/24".into(),
 | 
				
			||||||
            )),
 | 
					            )),
 | 
				
			||||||
            None => Ok(12),
 | 
					            None => Ok(12),
 | 
				
			||||||
		}?;
 | 
					        }?;
 | 
				
			||||||
		let mnemonic = Mnemonic::generate(words)
 | 
					        let mnemonic = Mnemonic::generate(words)
 | 
				
			||||||
            .map_err(|e| Error::Input(format!("Mnemonic generation failed: {e}").into()))?;
 | 
					            .map_err(|e| Error::Input(format!("Mnemonic generation failed: {e}").into()))?;
 | 
				
			||||||
		let password = self.keystore_params.read_password()?;
 | 
					        let password = self.keystore_params.read_password()?;
 | 
				
			||||||
		let output = self.output_scheme.output_type;
 | 
					        let output = self.output_scheme.output_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let phrase = mnemonic.words().join(" ");
 | 
					        let phrase = mnemonic.words().join(" ");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		with_crypto_scheme!(
 | 
					        with_crypto_scheme!(
 | 
				
			||||||
			self.crypto_scheme.scheme,
 | 
					            self.crypto_scheme.scheme,
 | 
				
			||||||
			print_from_uri(&phrase, password, self.network_scheme.network, output)
 | 
					            print_from_uri(&phrase, password, self.network_scheme.network, output)
 | 
				
			||||||
		);
 | 
					        );
 | 
				
			||||||
		Ok(())
 | 
					        Ok(())
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[cfg(test)]
 | 
					#[cfg(test)]
 | 
				
			||||||
mod tests {
 | 
					mod tests {
 | 
				
			||||||
	use super::*;
 | 
					    use super::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#[test]
 | 
					    #[test]
 | 
				
			||||||
	fn generate() {
 | 
					    fn generate() {
 | 
				
			||||||
		let generate = GenerateCmd::parse_from(&["generate", "--password", "12345"]);
 | 
					        let generate = GenerateCmd::parse_from(&["generate", "--password", "12345"]);
 | 
				
			||||||
		assert!(generate.run().is_ok())
 | 
					        assert!(generate.run().is_ok())
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,102 +1,101 @@
 | 
				
			|||||||
//! Implementation of the `inspect` subcommand
 | 
					//! Implementation of the `inspect` subcommand
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use crate::commands::utils::{print_from_public, print_from_uri};
 | 
				
			||||||
 | 
					use crate::params::NetworkSchemeFlag;
 | 
				
			||||||
use clap::Parser;
 | 
					use clap::Parser;
 | 
				
			||||||
 | 
					use sc_cli::{
 | 
				
			||||||
 | 
					    utils::read_uri, with_crypto_scheme, CryptoSchemeFlag, Error, KeystoreParams, OutputTypeFlag,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
use sp_core::crypto::{ExposeSecret, SecretString, SecretUri, Ss58Codec};
 | 
					use sp_core::crypto::{ExposeSecret, SecretString, SecretUri, Ss58Codec};
 | 
				
			||||||
use std::str::FromStr;
 | 
					use std::str::FromStr;
 | 
				
			||||||
use sc_cli::{
 | 
					 | 
				
			||||||
    with_crypto_scheme, KeystoreParams, OutputTypeFlag, CryptoSchemeFlag, Error,
 | 
					 | 
				
			||||||
    utils::read_uri,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
use crate::params::NetworkSchemeFlag;
 | 
					 | 
				
			||||||
use crate::commands::utils::{print_from_public, print_from_uri};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// The `inspect` command
 | 
					/// The `inspect` command
 | 
				
			||||||
#[derive(Debug, Parser)]
 | 
					#[derive(Debug, Parser)]
 | 
				
			||||||
#[command(
 | 
					#[command(
 | 
				
			||||||
	name = "inspect",
 | 
					    name = "inspect",
 | 
				
			||||||
	about = "Gets a public key and a SS58 address from the provided Secret URI"
 | 
					    about = "Gets a public key and a SS58 address from the provided Secret URI"
 | 
				
			||||||
)]
 | 
					)]
 | 
				
			||||||
pub struct InspectKeyCmd {
 | 
					pub struct InspectKeyCmd {
 | 
				
			||||||
	/// A Key URI to be inspected. May be a secret seed, secret URI
 | 
					    /// A Key URI to be inspected. May be a secret seed, secret URI
 | 
				
			||||||
	/// (with derivation paths and password), SS58, public URI or a hex encoded public key.
 | 
					    /// (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 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
 | 
					    /// If the given value is a file, the file content will be used
 | 
				
			||||||
	/// as URI.
 | 
					    /// as URI.
 | 
				
			||||||
	///
 | 
					    ///
 | 
				
			||||||
	/// If omitted, you will be prompted for the URI.
 | 
					    /// If omitted, you will be prompted for the URI.
 | 
				
			||||||
	uri: Option<String>,
 | 
					    uri: Option<String>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// Is the given `uri` a hex encoded public key?
 | 
					    /// Is the given `uri` a hex encoded public key?
 | 
				
			||||||
	#[arg(long)]
 | 
					    #[arg(long)]
 | 
				
			||||||
	public: bool,
 | 
					    public: bool,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#[allow(missing_docs)]
 | 
					    #[allow(missing_docs)]
 | 
				
			||||||
	#[clap(flatten)]
 | 
					    #[clap(flatten)]
 | 
				
			||||||
	pub keystore_params: KeystoreParams,
 | 
					    pub keystore_params: KeystoreParams,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#[allow(missing_docs)]
 | 
					    #[allow(missing_docs)]
 | 
				
			||||||
	#[clap(flatten)]
 | 
					    #[clap(flatten)]
 | 
				
			||||||
	pub network_scheme: NetworkSchemeFlag,
 | 
					    pub network_scheme: NetworkSchemeFlag,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#[allow(missing_docs)]
 | 
					    #[allow(missing_docs)]
 | 
				
			||||||
	#[clap(flatten)]
 | 
					    #[clap(flatten)]
 | 
				
			||||||
	pub output_scheme: OutputTypeFlag,
 | 
					    pub output_scheme: OutputTypeFlag,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#[allow(missing_docs)]
 | 
					    #[allow(missing_docs)]
 | 
				
			||||||
	#[clap(flatten)]
 | 
					    #[clap(flatten)]
 | 
				
			||||||
	pub crypto_scheme: CryptoSchemeFlag,
 | 
					    pub crypto_scheme: CryptoSchemeFlag,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// Expect that `--uri` has the given public key/account-id.
 | 
					    /// Expect that `--uri` has the given public key/account-id.
 | 
				
			||||||
	///
 | 
					    ///
 | 
				
			||||||
	/// If `--uri` has any derivations, the public key is checked against the base `uri`, i.e. the
 | 
					    /// If `--uri` has any derivations, the public key is checked against the base `uri`, i.e. the
 | 
				
			||||||
	/// `uri` without any derivation applied. However, if `uri` has a password or there is one
 | 
					    /// `uri` without any derivation applied. However, if `uri` has a password or there is one
 | 
				
			||||||
	/// given by `--password`, it will be used to decrypt `uri` before comparing the public
 | 
					    /// given by `--password`, it will be used to decrypt `uri` before comparing the public
 | 
				
			||||||
	/// key/account-id.
 | 
					    /// key/account-id.
 | 
				
			||||||
	///
 | 
					    ///
 | 
				
			||||||
	/// If there is no derivation in `--uri`, the public key will be checked against the public key
 | 
					    /// If there is no derivation in `--uri`, the public key will be checked against the public key
 | 
				
			||||||
	/// of `--uri` directly.
 | 
					    /// of `--uri` directly.
 | 
				
			||||||
	#[arg(long, conflicts_with = "public")]
 | 
					    #[arg(long, conflicts_with = "public")]
 | 
				
			||||||
	pub expect_public: Option<String>,
 | 
					    pub expect_public: Option<String>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl InspectKeyCmd {
 | 
					impl InspectKeyCmd {
 | 
				
			||||||
	/// Run the command
 | 
					    /// Run the command
 | 
				
			||||||
	pub fn run(&self) -> Result<(), Error> {
 | 
					    pub fn run(&self) -> Result<(), Error> {
 | 
				
			||||||
		let uri = read_uri(self.uri.as_ref())?;
 | 
					        let uri = read_uri(self.uri.as_ref())?;
 | 
				
			||||||
		let password = self.keystore_params.read_password()?;
 | 
					        let password = self.keystore_params.read_password()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if self.public {
 | 
					        if self.public {
 | 
				
			||||||
			with_crypto_scheme!(
 | 
					            with_crypto_scheme!(
 | 
				
			||||||
				self.crypto_scheme.scheme,
 | 
					                self.crypto_scheme.scheme,
 | 
				
			||||||
				print_from_public(
 | 
					                print_from_public(
 | 
				
			||||||
					&uri,
 | 
					                    &uri,
 | 
				
			||||||
					self.network_scheme.network,
 | 
					                    self.network_scheme.network,
 | 
				
			||||||
					self.output_scheme.output_type,
 | 
					                    self.output_scheme.output_type,
 | 
				
			||||||
				)
 | 
					                )
 | 
				
			||||||
			)?;
 | 
					            )?;
 | 
				
			||||||
		} else {
 | 
					        } else {
 | 
				
			||||||
			if let Some(ref expect_public) = self.expect_public {
 | 
					            if let Some(ref expect_public) = self.expect_public {
 | 
				
			||||||
				with_crypto_scheme!(
 | 
					                with_crypto_scheme!(
 | 
				
			||||||
					self.crypto_scheme.scheme,
 | 
					                    self.crypto_scheme.scheme,
 | 
				
			||||||
					expect_public_from_phrase(expect_public, &uri, password.as_ref())
 | 
					                    expect_public_from_phrase(expect_public, &uri, password.as_ref())
 | 
				
			||||||
				)?;
 | 
					                )?;
 | 
				
			||||||
			}
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			with_crypto_scheme!(
 | 
					            with_crypto_scheme!(
 | 
				
			||||||
				self.crypto_scheme.scheme,
 | 
					                self.crypto_scheme.scheme,
 | 
				
			||||||
				print_from_uri(
 | 
					                print_from_uri(
 | 
				
			||||||
					&uri,
 | 
					                    &uri,
 | 
				
			||||||
					password,
 | 
					                    password,
 | 
				
			||||||
					self.network_scheme.network,
 | 
					                    self.network_scheme.network,
 | 
				
			||||||
					self.output_scheme.output_type,
 | 
					                    self.output_scheme.output_type,
 | 
				
			||||||
				)
 | 
					                )
 | 
				
			||||||
			);
 | 
					            );
 | 
				
			||||||
		}
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Ok(())
 | 
					        Ok(())
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Checks that `expect_public` is the public key of `suri`.
 | 
					/// Checks that `expect_public` is the public key of `suri`.
 | 
				
			||||||
@ -106,148 +105,156 @@ impl InspectKeyCmd {
 | 
				
			|||||||
///
 | 
					///
 | 
				
			||||||
/// Returns an error if the public key does not match.
 | 
					/// Returns an error if the public key does not match.
 | 
				
			||||||
fn expect_public_from_phrase<Pair: sp_core::Pair>(
 | 
					fn expect_public_from_phrase<Pair: sp_core::Pair>(
 | 
				
			||||||
	expect_public: &str,
 | 
					    expect_public: &str,
 | 
				
			||||||
	suri: &str,
 | 
					    suri: &str,
 | 
				
			||||||
	password: Option<&SecretString>,
 | 
					    password: Option<&SecretString>,
 | 
				
			||||||
) -> Result<(), Error> {
 | 
					) -> Result<(), Error> {
 | 
				
			||||||
	let secret_uri = SecretUri::from_str(suri).map_err(|e| format!("{:?}", e))?;
 | 
					    let secret_uri = SecretUri::from_str(suri).map_err(|e| format!("{:?}", e))?;
 | 
				
			||||||
	let expected_public = if let Some(public) = expect_public.strip_prefix("0x") {
 | 
					    let expected_public = if let Some(public) = expect_public.strip_prefix("0x") {
 | 
				
			||||||
		let hex_public = array_bytes::hex2bytes(public)
 | 
					        let hex_public = array_bytes::hex2bytes(public)
 | 
				
			||||||
			.map_err(|_| format!("Invalid expected public key hex: `{}`", expect_public))?;
 | 
					            .map_err(|_| format!("Invalid expected public key hex: `{}`", expect_public))?;
 | 
				
			||||||
		Pair::Public::try_from(&hex_public)
 | 
					        Pair::Public::try_from(&hex_public)
 | 
				
			||||||
			.map_err(|_| format!("Invalid expected public key: `{}`", expect_public))?
 | 
					            .map_err(|_| format!("Invalid expected public key: `{}`", expect_public))?
 | 
				
			||||||
	} else {
 | 
					    } else {
 | 
				
			||||||
		Pair::Public::from_string_with_version(expect_public)
 | 
					        Pair::Public::from_string_with_version(expect_public)
 | 
				
			||||||
			.map_err(|_| format!("Invalid expected account id: `{}`", expect_public))?
 | 
					            .map_err(|_| format!("Invalid expected account id: `{}`", expect_public))?
 | 
				
			||||||
			.0
 | 
					            .0
 | 
				
			||||||
	};
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let pair = Pair::from_string_with_seed(
 | 
					    let pair = Pair::from_string_with_seed(
 | 
				
			||||||
		secret_uri.phrase.expose_secret().as_str(),
 | 
					        secret_uri.phrase.expose_secret().as_str(),
 | 
				
			||||||
		password
 | 
					        password
 | 
				
			||||||
			.or_else(|| secret_uri.password.as_ref())
 | 
					            .or_else(|| secret_uri.password.as_ref())
 | 
				
			||||||
			.map(|p| p.expose_secret().as_str()),
 | 
					            .map(|p| p.expose_secret().as_str()),
 | 
				
			||||||
	)
 | 
					    )
 | 
				
			||||||
	.map_err(|_| format!("Invalid secret uri: {}", suri))?
 | 
					    .map_err(|_| format!("Invalid secret uri: {}", suri))?
 | 
				
			||||||
	.0;
 | 
					    .0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if pair.public() == expected_public {
 | 
					    if pair.public() == expected_public {
 | 
				
			||||||
		Ok(())
 | 
					        Ok(())
 | 
				
			||||||
	} else {
 | 
					    } else {
 | 
				
			||||||
		Err(format!("Expected public ({}) key does not match.", expect_public).into())
 | 
					        Err(format!("Expected public ({}) key does not match.", expect_public).into())
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[cfg(test)]
 | 
					#[cfg(test)]
 | 
				
			||||||
mod tests {
 | 
					mod tests {
 | 
				
			||||||
	use super::*;
 | 
					    use super::*;
 | 
				
			||||||
	use sp_core::crypto::{ByteArray, Pair};
 | 
					    use sp_core::crypto::{ByteArray, Pair};
 | 
				
			||||||
	use sp_runtime::traits::IdentifyAccount;
 | 
					    use sp_runtime::traits::IdentifyAccount;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#[test]
 | 
					    #[test]
 | 
				
			||||||
	fn inspect() {
 | 
					    fn inspect() {
 | 
				
			||||||
		let words =
 | 
					        let words =
 | 
				
			||||||
			"remember fiber forum demise paper uniform squirrel feel access exclude casual effort";
 | 
					            "remember fiber forum demise paper uniform squirrel feel access exclude casual effort";
 | 
				
			||||||
		let seed = "0xad1fb77243b536b90cfe5f0d351ab1b1ac40e3890b41dc64f766ee56340cfca5";
 | 
					        let seed = "0xad1fb77243b536b90cfe5f0d351ab1b1ac40e3890b41dc64f766ee56340cfca5";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let inspect = InspectKeyCmd::parse_from(&["inspect-key", words, "--password", "12345"]);
 | 
					        let inspect = InspectKeyCmd::parse_from(&["inspect-key", words, "--password", "12345"]);
 | 
				
			||||||
		assert!(inspect.run().is_ok());
 | 
					        assert!(inspect.run().is_ok());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let inspect = InspectKeyCmd::parse_from(&["inspect-key", seed]);
 | 
					        let inspect = InspectKeyCmd::parse_from(&["inspect-key", seed]);
 | 
				
			||||||
		assert!(inspect.run().is_ok());
 | 
					        assert!(inspect.run().is_ok());
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#[test]
 | 
					    #[test]
 | 
				
			||||||
	fn inspect_public_key() {
 | 
					    fn inspect_public_key() {
 | 
				
			||||||
		let public = "0x12e76e0ae8ce41b6516cce52b3f23a08dcb4cfeed53c6ee8f5eb9f7367341069";
 | 
					        let public = "0x12e76e0ae8ce41b6516cce52b3f23a08dcb4cfeed53c6ee8f5eb9f7367341069";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let inspect = InspectKeyCmd::parse_from(&["inspect-key", "--public", public]);
 | 
					        let inspect = InspectKeyCmd::parse_from(&["inspect-key", "--public", public]);
 | 
				
			||||||
		assert!(inspect.run().is_ok());
 | 
					        assert!(inspect.run().is_ok());
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#[test]
 | 
					    #[test]
 | 
				
			||||||
	fn inspect_with_expected_public_key() {
 | 
					    fn inspect_with_expected_public_key() {
 | 
				
			||||||
		let check_cmd = |seed, expected_public, success| {
 | 
					        let check_cmd = |seed, expected_public, success| {
 | 
				
			||||||
			let inspect = InspectKeyCmd::parse_from(&[
 | 
					            let inspect = InspectKeyCmd::parse_from(&[
 | 
				
			||||||
				"inspect-key",
 | 
					                "inspect-key",
 | 
				
			||||||
				"--expect-public",
 | 
					                "--expect-public",
 | 
				
			||||||
				expected_public,
 | 
					                expected_public,
 | 
				
			||||||
				seed,
 | 
					                seed,
 | 
				
			||||||
			]);
 | 
					            ]);
 | 
				
			||||||
			let res = inspect.run();
 | 
					            let res = inspect.run();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if success {
 | 
					            if success {
 | 
				
			||||||
				assert!(res.is_ok());
 | 
					                assert!(res.is_ok());
 | 
				
			||||||
			} else {
 | 
					            } else {
 | 
				
			||||||
				assert!(res.unwrap_err().to_string().contains(&format!(
 | 
					                assert!(res.unwrap_err().to_string().contains(&format!(
 | 
				
			||||||
					"Expected public ({}) key does not match.",
 | 
					                    "Expected public ({}) key does not match.",
 | 
				
			||||||
					expected_public
 | 
					                    expected_public
 | 
				
			||||||
				)));
 | 
					                )));
 | 
				
			||||||
			}
 | 
					            }
 | 
				
			||||||
		};
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let seed =
 | 
					        let seed =
 | 
				
			||||||
			"remember fiber forum demise paper uniform squirrel feel access exclude casual effort";
 | 
					            "remember fiber forum demise paper uniform squirrel feel access exclude casual effort";
 | 
				
			||||||
		let invalid_public = "0x12e76e0ae8ce41b6516cce52b3f23a08dcb4cfeed53c6ee8f5eb9f7367341069";
 | 
					        let invalid_public = "0x12e76e0ae8ce41b6516cce52b3f23a08dcb4cfeed53c6ee8f5eb9f7367341069";
 | 
				
			||||||
		let valid_public = sp_core::sr25519::Pair::from_string_with_seed(seed, None)
 | 
					        let valid_public = sp_core::sr25519::Pair::from_string_with_seed(seed, None)
 | 
				
			||||||
			.expect("Valid")
 | 
					            .expect("Valid")
 | 
				
			||||||
			.0
 | 
					            .0
 | 
				
			||||||
			.public();
 | 
					            .public();
 | 
				
			||||||
		let valid_public_hex = array_bytes::bytes2hex("0x", valid_public.as_slice());
 | 
					        let valid_public_hex = array_bytes::bytes2hex("0x", valid_public.as_slice());
 | 
				
			||||||
		let valid_accountid = format!("{}", valid_public.into_account());
 | 
					        let valid_accountid = format!("{}", valid_public.into_account());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// It should fail with the invalid public key
 | 
					        // It should fail with the invalid public key
 | 
				
			||||||
		check_cmd(seed, invalid_public, false);
 | 
					        check_cmd(seed, invalid_public, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// It should work with the valid public key & account id
 | 
					        // It should work with the valid public key & account id
 | 
				
			||||||
		check_cmd(seed, &valid_public_hex, true);
 | 
					        check_cmd(seed, &valid_public_hex, true);
 | 
				
			||||||
		check_cmd(seed, &valid_accountid, true);
 | 
					        check_cmd(seed, &valid_accountid, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let password = "test12245";
 | 
					        let password = "test12245";
 | 
				
			||||||
		let seed_with_password = format!("{}///{}", seed, password);
 | 
					        let seed_with_password = format!("{}///{}", seed, password);
 | 
				
			||||||
		let valid_public_with_password =
 | 
					        let valid_public_with_password =
 | 
				
			||||||
			sp_core::sr25519::Pair::from_string_with_seed(&seed_with_password, Some(password))
 | 
					            sp_core::sr25519::Pair::from_string_with_seed(&seed_with_password, Some(password))
 | 
				
			||||||
				.expect("Valid")
 | 
					                .expect("Valid")
 | 
				
			||||||
				.0
 | 
					                .0
 | 
				
			||||||
				.public();
 | 
					                .public();
 | 
				
			||||||
		let valid_public_hex_with_password =
 | 
					        let valid_public_hex_with_password =
 | 
				
			||||||
			array_bytes::bytes2hex("0x", valid_public_with_password.as_slice());
 | 
					            array_bytes::bytes2hex("0x", valid_public_with_password.as_slice());
 | 
				
			||||||
		let valid_accountid_with_password =
 | 
					        let valid_accountid_with_password =
 | 
				
			||||||
			format!("{}", &valid_public_with_password.into_account());
 | 
					            format!("{}", &valid_public_with_password.into_account());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Only the public key that corresponds to the seed with password should be accepted.
 | 
					        // Only the public key that corresponds to the seed with password should be accepted.
 | 
				
			||||||
		check_cmd(&seed_with_password, &valid_public_hex, false);
 | 
					        check_cmd(&seed_with_password, &valid_public_hex, false);
 | 
				
			||||||
		check_cmd(&seed_with_password, &valid_accountid, false);
 | 
					        check_cmd(&seed_with_password, &valid_accountid, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		check_cmd(&seed_with_password, &valid_public_hex_with_password, true);
 | 
					        check_cmd(&seed_with_password, &valid_public_hex_with_password, true);
 | 
				
			||||||
		check_cmd(&seed_with_password, &valid_accountid_with_password, true);
 | 
					        check_cmd(&seed_with_password, &valid_accountid_with_password, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let seed_with_password_and_derivation = format!("{}//test//account///{}", seed, password);
 | 
					        let seed_with_password_and_derivation = format!("{}//test//account///{}", seed, password);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let valid_public_with_password_and_derivation =
 | 
					        let valid_public_with_password_and_derivation =
 | 
				
			||||||
			sp_core::sr25519::Pair::from_string_with_seed(
 | 
					            sp_core::sr25519::Pair::from_string_with_seed(
 | 
				
			||||||
				&seed_with_password_and_derivation,
 | 
					                &seed_with_password_and_derivation,
 | 
				
			||||||
				Some(password),
 | 
					                Some(password),
 | 
				
			||||||
			)
 | 
					            )
 | 
				
			||||||
			.expect("Valid")
 | 
					            .expect("Valid")
 | 
				
			||||||
			.0
 | 
					            .0
 | 
				
			||||||
			.public();
 | 
					            .public();
 | 
				
			||||||
		let valid_public_hex_with_password_and_derivation =
 | 
					        let valid_public_hex_with_password_and_derivation =
 | 
				
			||||||
			array_bytes::bytes2hex("0x", valid_public_with_password_and_derivation.as_slice());
 | 
					            array_bytes::bytes2hex("0x", valid_public_with_password_and_derivation.as_slice());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// They should still be valid, because we check the base secret key.
 | 
					        // They should still be valid, because we check the base secret key.
 | 
				
			||||||
		check_cmd(&seed_with_password_and_derivation, &valid_public_hex_with_password, true);
 | 
					        check_cmd(
 | 
				
			||||||
		check_cmd(&seed_with_password_and_derivation, &valid_accountid_with_password, true);
 | 
					            &seed_with_password_and_derivation,
 | 
				
			||||||
 | 
					            &valid_public_hex_with_password,
 | 
				
			||||||
 | 
					            true,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        check_cmd(
 | 
				
			||||||
 | 
					            &seed_with_password_and_derivation,
 | 
				
			||||||
 | 
					            &valid_accountid_with_password,
 | 
				
			||||||
 | 
					            true,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// And these should be invalid.
 | 
					        // And these should be invalid.
 | 
				
			||||||
		check_cmd(&seed_with_password_and_derivation, &valid_public_hex, false);
 | 
					        check_cmd(&seed_with_password_and_derivation, &valid_public_hex, false);
 | 
				
			||||||
		check_cmd(&seed_with_password_and_derivation, &valid_accountid, false);
 | 
					        check_cmd(&seed_with_password_and_derivation, &valid_accountid, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// The public of the derived account should fail.
 | 
					        // The public of the derived account should fail.
 | 
				
			||||||
		check_cmd(
 | 
					        check_cmd(
 | 
				
			||||||
			&seed_with_password_and_derivation,
 | 
					            &seed_with_password_and_derivation,
 | 
				
			||||||
			&valid_public_hex_with_password_and_derivation,
 | 
					            &valid_public_hex_with_password_and_derivation,
 | 
				
			||||||
			false,
 | 
					            false,
 | 
				
			||||||
		);
 | 
					        );
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,40 +1,37 @@
 | 
				
			|||||||
//! Key related CLI utilities
 | 
					//! Key related CLI utilities
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use super::{generate::GenerateCmd, inspect_key::InspectKeyCmd};
 | 
					use super::{generate::GenerateCmd, inspect_key::InspectKeyCmd};
 | 
				
			||||||
use sc_cli::{
 | 
					use sc_cli::{Error, GenerateKeyCmdCommon, InsertKeyCmd, InspectNodeKeyCmd, SubstrateCli};
 | 
				
			||||||
    GenerateKeyCmdCommon, InsertKeyCmd, InspectNodeKeyCmd, Error, 
 | 
					 | 
				
			||||||
    SubstrateCli,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Key utilities for the cli.
 | 
					/// Key utilities for the cli.
 | 
				
			||||||
#[derive(Debug, clap::Subcommand)]
 | 
					#[derive(Debug, clap::Subcommand)]
 | 
				
			||||||
pub enum KeySubcommand {
 | 
					pub enum KeySubcommand {
 | 
				
			||||||
	/// Generate a random node key, write it to a file or stdout and write the
 | 
					    /// Generate a random node key, write it to a file or stdout and write the
 | 
				
			||||||
	/// corresponding peer-id to stderr
 | 
					    /// corresponding peer-id to stderr
 | 
				
			||||||
	GenerateNodeKey(GenerateKeyCmdCommon),
 | 
					    GenerateNodeKey(GenerateKeyCmdCommon),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// Generate a Substrate-based random account
 | 
					    /// Generate a Substrate-based random account
 | 
				
			||||||
	Generate(GenerateCmd),
 | 
					    Generate(GenerateCmd),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// Gets a public key and a SS58 address from the provided Secret URI
 | 
					    /// Gets a public key and a SS58 address from the provided Secret URI
 | 
				
			||||||
	Inspect(InspectKeyCmd),
 | 
					    Inspect(InspectKeyCmd),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// Load a node key from a file or stdin and print the corresponding peer-id
 | 
					    /// Load a node key from a file or stdin and print the corresponding peer-id
 | 
				
			||||||
	InspectNodeKey(InspectNodeKeyCmd),
 | 
					    InspectNodeKey(InspectNodeKeyCmd),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// Insert a key to the keystore of a node.
 | 
					    /// Insert a key to the keystore of a node.
 | 
				
			||||||
	Insert(InsertKeyCmd),
 | 
					    Insert(InsertKeyCmd),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl KeySubcommand {
 | 
					impl KeySubcommand {
 | 
				
			||||||
	/// run the key subcommands
 | 
					    /// run the key subcommands
 | 
				
			||||||
	pub fn run<C: SubstrateCli>(&self, cli: &C) -> Result<(), Error> {
 | 
					    pub fn run<C: SubstrateCli>(&self, cli: &C) -> Result<(), Error> {
 | 
				
			||||||
		match self {
 | 
					        match self {
 | 
				
			||||||
			KeySubcommand::GenerateNodeKey(cmd) => cmd.run(),
 | 
					            KeySubcommand::GenerateNodeKey(cmd) => cmd.run(),
 | 
				
			||||||
			KeySubcommand::Generate(cmd) => cmd.run(),
 | 
					            KeySubcommand::Generate(cmd) => cmd.run(),
 | 
				
			||||||
			KeySubcommand::Inspect(cmd) => cmd.run(),
 | 
					            KeySubcommand::Inspect(cmd) => cmd.run(),
 | 
				
			||||||
			KeySubcommand::Insert(cmd) => cmd.run(cli),
 | 
					            KeySubcommand::Insert(cmd) => cmd.run(cli),
 | 
				
			||||||
			KeySubcommand::InspectNodeKey(cmd) => cmd.run(),
 | 
					            KeySubcommand::InspectNodeKey(cmd) => cmd.run(),
 | 
				
			||||||
		}
 | 
					        }
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,11 +1,13 @@
 | 
				
			|||||||
mod key;
 | 
					 | 
				
			||||||
mod generate;
 | 
					mod generate;
 | 
				
			||||||
mod vanity;
 | 
					 | 
				
			||||||
mod inspect_key;
 | 
					mod inspect_key;
 | 
				
			||||||
 | 
					mod key;
 | 
				
			||||||
mod utils;
 | 
					mod utils;
 | 
				
			||||||
 | 
					mod vanity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub use self::{
 | 
					pub use self::{
 | 
				
			||||||
    key::KeySubcommand, vanity::VanityCmd, inspect_key::InspectKeyCmd,
 | 
					 | 
				
			||||||
    generate::GenerateCmd,
 | 
					    generate::GenerateCmd,
 | 
				
			||||||
    utils::{unwrap_or_default_ss58_name, print_from_uri, print_from_public},
 | 
					    inspect_key::InspectKeyCmd,
 | 
				
			||||||
 | 
					    key::KeySubcommand,
 | 
				
			||||||
 | 
					    utils::{print_from_public, print_from_uri, unwrap_or_default_ss58_name},
 | 
				
			||||||
 | 
					    vanity::VanityCmd,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -1,194 +1,206 @@
 | 
				
			|||||||
use serde_json::json;
 | 
					 | 
				
			||||||
use sc_cli::{
 | 
					use sc_cli::{
 | 
				
			||||||
    OutputType,
 | 
					 | 
				
			||||||
    utils::{PublicFor, SeedFor},
 | 
					    utils::{PublicFor, SeedFor},
 | 
				
			||||||
 | 
					    OutputType,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use sp_runtime::{traits::IdentifyAccount, MultiSigner};
 | 
					use serde_json::json;
 | 
				
			||||||
use sp_core::{
 | 
					use sp_core::{
 | 
				
			||||||
    crypto::{
 | 
					    crypto::{
 | 
				
			||||||
        unwrap_or_default_ss58_version,
 | 
					        unwrap_or_default_ss58_version, ExposeSecret, SecretString, Ss58AddressFormat, Ss58Codec,
 | 
				
			||||||
        Ss58Codec, ExposeSecret, Ss58AddressFormat, SecretString,
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    hexdisplay::HexDisplay,
 | 
					    hexdisplay::HexDisplay,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					use sp_runtime::{traits::IdentifyAccount, MultiSigner};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn print_from_uri<Pair>(
 | 
					pub fn print_from_uri<Pair>(
 | 
				
			||||||
	uri: &str,
 | 
					    uri: &str,
 | 
				
			||||||
	password: Option<SecretString>,
 | 
					    password: Option<SecretString>,
 | 
				
			||||||
	network_override: Option<Ss58AddressFormat>,
 | 
					    network_override: Option<Ss58AddressFormat>,
 | 
				
			||||||
	output: OutputType,
 | 
					    output: OutputType,
 | 
				
			||||||
) where
 | 
					) where
 | 
				
			||||||
	Pair: sp_core::Pair,
 | 
					    Pair: sp_core::Pair,
 | 
				
			||||||
	Pair::Public: Into<MultiSigner>,
 | 
					    Pair::Public: Into<MultiSigner>,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	let password = password.as_ref().map(|s| s.expose_secret().as_str());
 | 
					    let password = password.as_ref().map(|s| s.expose_secret().as_str());
 | 
				
			||||||
	let network_id = unwrap_or_default_ss58_name(network_override);
 | 
					    let network_id = unwrap_or_default_ss58_name(network_override);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if let Ok((pair, seed)) = Pair::from_phrase(uri, password) {
 | 
					    if let Ok((pair, seed)) = Pair::from_phrase(uri, password) {
 | 
				
			||||||
		let public_key = pair.public();
 | 
					        let public_key = pair.public();
 | 
				
			||||||
		let network_override = unwrap_or_default_ss58_version(network_override);
 | 
					        let network_override = unwrap_or_default_ss58_version(network_override);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		match output {
 | 
					        match output {
 | 
				
			||||||
			OutputType::Json => {
 | 
					            OutputType::Json => {
 | 
				
			||||||
				let json = json!({
 | 
					                let json = json!({
 | 
				
			||||||
					"secretPhrase": uri,
 | 
					                    "secretPhrase": uri,
 | 
				
			||||||
					"networkId": network_id,
 | 
					                    "networkId": network_id,
 | 
				
			||||||
					"secretSeed": format_seed::<Pair>(seed),
 | 
					                    "secretSeed": format_seed::<Pair>(seed),
 | 
				
			||||||
					"publicKey": format_public_key::<Pair>(public_key.clone()),
 | 
					                    "publicKey": format_public_key::<Pair>(public_key.clone()),
 | 
				
			||||||
					"ss58PublicKey": public_key.to_ss58check_with_version(network_override),
 | 
					                    "ss58PublicKey": public_key.to_ss58check_with_version(network_override),
 | 
				
			||||||
					"accountId": format_account_id::<Pair>(public_key),
 | 
					                    "accountId": format_account_id::<Pair>(public_key),
 | 
				
			||||||
					"ss58Address": pair.public().into().into_account().to_ss58check_with_version(network_override),
 | 
					                    "ss58Address": pair.public().into().into_account().to_ss58check_with_version(network_override),
 | 
				
			||||||
				});
 | 
					                });
 | 
				
			||||||
				println!(
 | 
					                println!(
 | 
				
			||||||
					"{}",
 | 
					                    "{}",
 | 
				
			||||||
					serde_json::to_string_pretty(&json).expect("Json pretty print failed")
 | 
					                    serde_json::to_string_pretty(&json).expect("Json pretty print failed")
 | 
				
			||||||
				);
 | 
					                );
 | 
				
			||||||
			},
 | 
					            }
 | 
				
			||||||
			OutputType::Text => {
 | 
					            OutputType::Text => {
 | 
				
			||||||
				println!(
 | 
					                println!(
 | 
				
			||||||
					"Secret phrase:       {}\n  \
 | 
					                    "Secret phrase:       {}\n  \
 | 
				
			||||||
					Network ID:        {}\n  \
 | 
										Network ID:        {}\n  \
 | 
				
			||||||
					Secret seed:       {}\n  \
 | 
										Secret seed:       {}\n  \
 | 
				
			||||||
					Public key (hex):  {}\n  \
 | 
										Public key (hex):  {}\n  \
 | 
				
			||||||
					Account ID:        {}\n  \
 | 
										Account ID:        {}\n  \
 | 
				
			||||||
					Public key (SS58): {}\n  \
 | 
										Public key (SS58): {}\n  \
 | 
				
			||||||
					SS58 Address:      {}",
 | 
										SS58 Address:      {}",
 | 
				
			||||||
					uri,
 | 
					                    uri,
 | 
				
			||||||
					network_id,
 | 
					                    network_id,
 | 
				
			||||||
					format_seed::<Pair>(seed),
 | 
					                    format_seed::<Pair>(seed),
 | 
				
			||||||
					format_public_key::<Pair>(public_key.clone()),
 | 
					                    format_public_key::<Pair>(public_key.clone()),
 | 
				
			||||||
					format_account_id::<Pair>(public_key.clone()),
 | 
					                    format_account_id::<Pair>(public_key.clone()),
 | 
				
			||||||
					public_key.to_ss58check_with_version(network_override),
 | 
					                    public_key.to_ss58check_with_version(network_override),
 | 
				
			||||||
					pair.public().into().into_account().to_ss58check_with_version(network_override),
 | 
					                    pair.public()
 | 
				
			||||||
				);
 | 
					                        .into()
 | 
				
			||||||
			},
 | 
					                        .into_account()
 | 
				
			||||||
		}
 | 
					                        .to_ss58check_with_version(network_override),
 | 
				
			||||||
	} else if let Ok((pair, seed)) = Pair::from_string_with_seed(uri, password) {
 | 
					                );
 | 
				
			||||||
		let public_key = pair.public();
 | 
					            }
 | 
				
			||||||
		let network_override = unwrap_or_default_ss58_version(network_override);
 | 
					        }
 | 
				
			||||||
 | 
					    } else if let Ok((pair, seed)) = Pair::from_string_with_seed(uri, password) {
 | 
				
			||||||
 | 
					        let public_key = pair.public();
 | 
				
			||||||
 | 
					        let network_override = unwrap_or_default_ss58_version(network_override);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		match output {
 | 
					        match output {
 | 
				
			||||||
			OutputType::Json => {
 | 
					            OutputType::Json => {
 | 
				
			||||||
				let json = json!({
 | 
					                let json = json!({
 | 
				
			||||||
					"secretKeyUri": uri,
 | 
					                    "secretKeyUri": uri,
 | 
				
			||||||
					"networkId": network_id,
 | 
					                    "networkId": network_id,
 | 
				
			||||||
					"secretSeed": if let Some(seed) = seed { format_seed::<Pair>(seed) } else { "n/a".into() },
 | 
					                    "secretSeed": if let Some(seed) = seed { format_seed::<Pair>(seed) } else { "n/a".into() },
 | 
				
			||||||
					"publicKey": format_public_key::<Pair>(public_key.clone()),
 | 
					                    "publicKey": format_public_key::<Pair>(public_key.clone()),
 | 
				
			||||||
					"ss58PublicKey": public_key.to_ss58check_with_version(network_override),
 | 
					                    "ss58PublicKey": public_key.to_ss58check_with_version(network_override),
 | 
				
			||||||
					"accountId": format_account_id::<Pair>(public_key),
 | 
					                    "accountId": format_account_id::<Pair>(public_key),
 | 
				
			||||||
					"ss58Address": pair.public().into().into_account().to_ss58check_with_version(network_override),
 | 
					                    "ss58Address": pair.public().into().into_account().to_ss58check_with_version(network_override),
 | 
				
			||||||
				});
 | 
					                });
 | 
				
			||||||
				println!(
 | 
					                println!(
 | 
				
			||||||
					"{}",
 | 
					                    "{}",
 | 
				
			||||||
					serde_json::to_string_pretty(&json).expect("Json pretty print failed")
 | 
					                    serde_json::to_string_pretty(&json).expect("Json pretty print failed")
 | 
				
			||||||
				);
 | 
					                );
 | 
				
			||||||
			},
 | 
					            }
 | 
				
			||||||
			OutputType::Text => {
 | 
					            OutputType::Text => {
 | 
				
			||||||
				println!(
 | 
					                println!(
 | 
				
			||||||
					"Secret Key URI `{}` is account:\n  \
 | 
					                    "Secret Key URI `{}` is account:\n  \
 | 
				
			||||||
					Network ID:        {}\n  \
 | 
										Network ID:        {}\n  \
 | 
				
			||||||
					Secret seed:       {}\n  \
 | 
										Secret seed:       {}\n  \
 | 
				
			||||||
					Public key (hex):  {}\n  \
 | 
										Public key (hex):  {}\n  \
 | 
				
			||||||
					Account ID:        {}\n  \
 | 
										Account ID:        {}\n  \
 | 
				
			||||||
					Public key (SS58): {}\n  \
 | 
										Public key (SS58): {}\n  \
 | 
				
			||||||
					SS58 Address:      {}",
 | 
										SS58 Address:      {}",
 | 
				
			||||||
					uri,
 | 
					                    uri,
 | 
				
			||||||
					network_id,
 | 
					                    network_id,
 | 
				
			||||||
					if let Some(seed) = seed { format_seed::<Pair>(seed) } else { "n/a".into() },
 | 
					                    if let Some(seed) = seed {
 | 
				
			||||||
					format_public_key::<Pair>(public_key.clone()),
 | 
					                        format_seed::<Pair>(seed)
 | 
				
			||||||
					format_account_id::<Pair>(public_key.clone()),
 | 
					                    } else {
 | 
				
			||||||
					public_key.to_ss58check_with_version(network_override),
 | 
					                        "n/a".into()
 | 
				
			||||||
					pair.public().into().into_account().to_ss58check_with_version(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 if let Ok((public_key, network)) = Pair::Public::from_string_with_version(uri) {
 | 
					                    pair.public()
 | 
				
			||||||
		let network_override = network_override.unwrap_or(network);
 | 
					                        .into()
 | 
				
			||||||
 | 
					                        .into_account()
 | 
				
			||||||
 | 
					                        .to_ss58check_with_version(network_override),
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } else if let Ok((public_key, network)) = Pair::Public::from_string_with_version(uri) {
 | 
				
			||||||
 | 
					        let network_override = network_override.unwrap_or(network);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		match output {
 | 
					        match output {
 | 
				
			||||||
			OutputType::Json => {
 | 
					            OutputType::Json => {
 | 
				
			||||||
				let json = json!({
 | 
					                let json = json!({
 | 
				
			||||||
					"publicKeyUri": uri,
 | 
					                    "publicKeyUri": uri,
 | 
				
			||||||
					"networkId": String::from(network_override),
 | 
					                    "networkId": String::from(network_override),
 | 
				
			||||||
					"publicKey": format_public_key::<Pair>(public_key.clone()),
 | 
					                    "publicKey": format_public_key::<Pair>(public_key.clone()),
 | 
				
			||||||
					"accountId": format_account_id::<Pair>(public_key.clone()),
 | 
					                    "accountId": format_account_id::<Pair>(public_key.clone()),
 | 
				
			||||||
					"ss58PublicKey": public_key.to_ss58check_with_version(network_override),
 | 
					                    "ss58PublicKey": public_key.to_ss58check_with_version(network_override),
 | 
				
			||||||
					"ss58Address": public_key.to_ss58check_with_version(network_override),
 | 
					                    "ss58Address": public_key.to_ss58check_with_version(network_override),
 | 
				
			||||||
				});
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				println!(
 | 
					                println!(
 | 
				
			||||||
					"{}",
 | 
					                    "{}",
 | 
				
			||||||
					serde_json::to_string_pretty(&json).expect("Json pretty print failed")
 | 
					                    serde_json::to_string_pretty(&json).expect("Json pretty print failed")
 | 
				
			||||||
				);
 | 
					                );
 | 
				
			||||||
			},
 | 
					            }
 | 
				
			||||||
			OutputType::Text => {
 | 
					            OutputType::Text => {
 | 
				
			||||||
				println!(
 | 
					                println!(
 | 
				
			||||||
					"Public Key URI `{}` is account:\n  \
 | 
					                    "Public Key URI `{}` is account:\n  \
 | 
				
			||||||
					 Network ID/Version: {}\n  \
 | 
										 Network ID/Version: {}\n  \
 | 
				
			||||||
					 Public key (hex):   {}\n  \
 | 
										 Public key (hex):   {}\n  \
 | 
				
			||||||
					 Account ID:         {}\n  \
 | 
										 Account ID:         {}\n  \
 | 
				
			||||||
					 Public key (SS58):  {}\n  \
 | 
										 Public key (SS58):  {}\n  \
 | 
				
			||||||
					 SS58 Address:       {}",
 | 
										 SS58 Address:       {}",
 | 
				
			||||||
					uri,
 | 
					                    uri,
 | 
				
			||||||
					String::from(network_override),
 | 
					                    String::from(network_override),
 | 
				
			||||||
					format_public_key::<Pair>(public_key.clone()),
 | 
					                    format_public_key::<Pair>(public_key.clone()),
 | 
				
			||||||
					format_account_id::<Pair>(public_key.clone()),
 | 
					                    format_account_id::<Pair>(public_key.clone()),
 | 
				
			||||||
					public_key.to_ss58check_with_version(network_override),
 | 
					                    public_key.to_ss58check_with_version(network_override),
 | 
				
			||||||
					public_key.to_ss58check_with_version(network_override),
 | 
					                    public_key.to_ss58check_with_version(network_override),
 | 
				
			||||||
				);
 | 
					                );
 | 
				
			||||||
			},
 | 
					            }
 | 
				
			||||||
		}
 | 
					        }
 | 
				
			||||||
	} else {
 | 
					    } else {
 | 
				
			||||||
		println!("Invalid phrase/URI given");
 | 
					        println!("Invalid phrase/URI given");
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Try to parse given `public` as hex encoded public key and print relevant information.
 | 
					/// Try to parse given `public` as hex encoded public key and print relevant information.
 | 
				
			||||||
pub fn print_from_public<Pair>(
 | 
					pub fn print_from_public<Pair>(
 | 
				
			||||||
	public_str: &str,
 | 
					    public_str: &str,
 | 
				
			||||||
	network_override: Option<Ss58AddressFormat>,
 | 
					    network_override: Option<Ss58AddressFormat>,
 | 
				
			||||||
	output: OutputType,
 | 
					    output: OutputType,
 | 
				
			||||||
) -> Result<(), sc_cli::Error>
 | 
					) -> Result<(), sc_cli::Error>
 | 
				
			||||||
where
 | 
					where
 | 
				
			||||||
	Pair: sp_core::Pair,
 | 
					    Pair: sp_core::Pair,
 | 
				
			||||||
	Pair::Public: Into<MultiSigner>,
 | 
					    Pair::Public: Into<MultiSigner>,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	let public = array_bytes::hex2bytes(public_str)?;
 | 
					    let public = array_bytes::hex2bytes(public_str)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let public_key = Pair::Public::try_from(&public)
 | 
					    let public_key = Pair::Public::try_from(&public)
 | 
				
			||||||
		.map_err(|_| "Failed to construct public key from given hex")?;
 | 
					        .map_err(|_| "Failed to construct public key from given hex")?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let network_override = unwrap_or_default_ss58_version(network_override);
 | 
					    let network_override = unwrap_or_default_ss58_version(network_override);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	match output {
 | 
					    match output {
 | 
				
			||||||
		OutputType::Json => {
 | 
					        OutputType::Json => {
 | 
				
			||||||
			let json = json!({
 | 
					            let json = json!({
 | 
				
			||||||
				"networkId": String::from(network_override),
 | 
					                "networkId": String::from(network_override),
 | 
				
			||||||
				"publicKey": format_public_key::<Pair>(public_key.clone()),
 | 
					                "publicKey": format_public_key::<Pair>(public_key.clone()),
 | 
				
			||||||
				"accountId": format_account_id::<Pair>(public_key.clone()),
 | 
					                "accountId": format_account_id::<Pair>(public_key.clone()),
 | 
				
			||||||
				"ss58PublicKey": public_key.to_ss58check_with_version(network_override),
 | 
					                "ss58PublicKey": public_key.to_ss58check_with_version(network_override),
 | 
				
			||||||
				"ss58Address": public_key.to_ss58check_with_version(network_override),
 | 
					                "ss58Address": public_key.to_ss58check_with_version(network_override),
 | 
				
			||||||
			});
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			println!("{}", serde_json::to_string_pretty(&json).expect("Json pretty print failed"));
 | 
					            println!(
 | 
				
			||||||
		},
 | 
					                "{}",
 | 
				
			||||||
		OutputType::Text => {
 | 
					                serde_json::to_string_pretty(&json).expect("Json pretty print failed")
 | 
				
			||||||
			println!(
 | 
					            );
 | 
				
			||||||
				"Network ID/Version: {}\n  \
 | 
					        }
 | 
				
			||||||
 | 
					        OutputType::Text => {
 | 
				
			||||||
 | 
					            println!(
 | 
				
			||||||
 | 
					                "Network ID/Version: {}\n  \
 | 
				
			||||||
				 Public key (hex):   {}\n  \
 | 
									 Public key (hex):   {}\n  \
 | 
				
			||||||
				 Account ID:         {}\n  \
 | 
									 Account ID:         {}\n  \
 | 
				
			||||||
				 Public key (SS58):  {}\n  \
 | 
									 Public key (SS58):  {}\n  \
 | 
				
			||||||
				 SS58 Address:       {}",
 | 
									 SS58 Address:       {}",
 | 
				
			||||||
				String::from(network_override),
 | 
					                String::from(network_override),
 | 
				
			||||||
				format_public_key::<Pair>(public_key.clone()),
 | 
					                format_public_key::<Pair>(public_key.clone()),
 | 
				
			||||||
				format_account_id::<Pair>(public_key.clone()),
 | 
					                format_account_id::<Pair>(public_key.clone()),
 | 
				
			||||||
				public_key.to_ss58check_with_version(network_override),
 | 
					                public_key.to_ss58check_with_version(network_override),
 | 
				
			||||||
				public_key.to_ss58check_with_version(network_override),
 | 
					                public_key.to_ss58check_with_version(network_override),
 | 
				
			||||||
			);
 | 
					            );
 | 
				
			||||||
		},
 | 
					        }
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Ok(())
 | 
					    Ok(())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn unwrap_or_default_ss58_name(x: Option<Ss58AddressFormat>) -> String {
 | 
					pub fn unwrap_or_default_ss58_name(x: Option<Ss58AddressFormat>) -> String {
 | 
				
			||||||
@ -216,5 +228,8 @@ fn format_account_id<P: sp_core::Pair>(public_key: PublicFor<P>) -> String
 | 
				
			|||||||
where
 | 
					where
 | 
				
			||||||
    PublicFor<P>: Into<MultiSigner>,
 | 
					    PublicFor<P>: Into<MultiSigner>,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    format!("0x{}", HexDisplay::from(&public_key.into().into_account().as_ref()))
 | 
					    format!(
 | 
				
			||||||
 | 
					        "0x{}",
 | 
				
			||||||
 | 
					        HexDisplay::from(&public_key.into().into_account().as_ref())
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -2,213 +2,218 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use clap::Parser;
 | 
					use clap::Parser;
 | 
				
			||||||
use rand::{rngs::OsRng, RngCore};
 | 
					use rand::{rngs::OsRng, RngCore};
 | 
				
			||||||
use sp_core::crypto::{
 | 
					use sc_cli::{utils::format_seed, with_crypto_scheme, CryptoSchemeFlag, Error, OutputTypeFlag};
 | 
				
			||||||
    unwrap_or_default_ss58_version, Ss58AddressFormat, Ss58Codec,
 | 
					use sp_core::crypto::{unwrap_or_default_ss58_version, Ss58AddressFormat, Ss58Codec};
 | 
				
			||||||
};
 | 
					 | 
				
			||||||
use sp_runtime::traits::IdentifyAccount;
 | 
					use sp_runtime::traits::IdentifyAccount;
 | 
				
			||||||
use sc_cli::{
 | 
					 | 
				
			||||||
    with_crypto_scheme, Error, OutputTypeFlag, CryptoSchemeFlag,
 | 
					 | 
				
			||||||
    utils::format_seed,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::commands::utils::print_from_uri;
 | 
					use crate::commands::utils::print_from_uri;
 | 
				
			||||||
use crate::params::NetworkSchemeFlag;
 | 
					use crate::params::NetworkSchemeFlag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// The `vanity` command
 | 
					/// The `vanity` command
 | 
				
			||||||
#[derive(Debug, Clone, Parser)]
 | 
					#[derive(Debug, Clone, Parser)]
 | 
				
			||||||
#[command(name = "vanity", about = "Generate a seed that provides a vanity address")]
 | 
					#[command(
 | 
				
			||||||
 | 
					    name = "vanity",
 | 
				
			||||||
 | 
					    about = "Generate a seed that provides a vanity address"
 | 
				
			||||||
 | 
					)]
 | 
				
			||||||
pub struct VanityCmd {
 | 
					pub struct VanityCmd {
 | 
				
			||||||
	/// Desired pattern
 | 
					    /// Desired pattern
 | 
				
			||||||
	#[arg(long, value_parser = assert_non_empty_string)]
 | 
					    #[arg(long, value_parser = assert_non_empty_string)]
 | 
				
			||||||
	pattern: String,
 | 
					    pattern: String,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#[allow(missing_docs)]
 | 
					    #[allow(missing_docs)]
 | 
				
			||||||
	#[clap(flatten)]
 | 
					    #[clap(flatten)]
 | 
				
			||||||
	network_scheme: NetworkSchemeFlag,
 | 
					    network_scheme: NetworkSchemeFlag,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#[allow(missing_docs)]
 | 
					    #[allow(missing_docs)]
 | 
				
			||||||
	#[clap(flatten)]
 | 
					    #[clap(flatten)]
 | 
				
			||||||
	output_scheme: OutputTypeFlag,
 | 
					    output_scheme: OutputTypeFlag,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#[allow(missing_docs)]
 | 
					    #[allow(missing_docs)]
 | 
				
			||||||
	#[clap(flatten)]
 | 
					    #[clap(flatten)]
 | 
				
			||||||
	crypto_scheme: CryptoSchemeFlag,
 | 
					    crypto_scheme: CryptoSchemeFlag,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl VanityCmd {
 | 
					impl VanityCmd {
 | 
				
			||||||
	/// Run the command
 | 
					    /// Run the command
 | 
				
			||||||
	pub fn run(&self) -> Result<(), Error> {
 | 
					    pub fn run(&self) -> Result<(), Error> {
 | 
				
			||||||
		let formated_seed = with_crypto_scheme!(
 | 
					        let formated_seed = with_crypto_scheme!(
 | 
				
			||||||
			self.crypto_scheme.scheme,
 | 
					            self.crypto_scheme.scheme,
 | 
				
			||||||
			generate_key(
 | 
					            generate_key(
 | 
				
			||||||
				&self.pattern,
 | 
					                &self.pattern,
 | 
				
			||||||
				unwrap_or_default_ss58_version(self.network_scheme.network)
 | 
					                unwrap_or_default_ss58_version(self.network_scheme.network)
 | 
				
			||||||
			),
 | 
					            ),
 | 
				
			||||||
		)?;
 | 
					        )?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		with_crypto_scheme!(
 | 
					        with_crypto_scheme!(
 | 
				
			||||||
			self.crypto_scheme.scheme,
 | 
					            self.crypto_scheme.scheme,
 | 
				
			||||||
			print_from_uri(
 | 
					            print_from_uri(
 | 
				
			||||||
				&formated_seed,
 | 
					                &formated_seed,
 | 
				
			||||||
				None,
 | 
					                None,
 | 
				
			||||||
				self.network_scheme.network,
 | 
					                self.network_scheme.network,
 | 
				
			||||||
				self.output_scheme.output_type,
 | 
					                self.output_scheme.output_type,
 | 
				
			||||||
			),
 | 
					            ),
 | 
				
			||||||
		);
 | 
					        );
 | 
				
			||||||
		Ok(())
 | 
					        Ok(())
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// genertae a key based on given pattern
 | 
					/// genertae a key based on given pattern
 | 
				
			||||||
fn generate_key<Pair>(
 | 
					fn generate_key<Pair>(
 | 
				
			||||||
	desired: &str,
 | 
					    desired: &str,
 | 
				
			||||||
	network_override: Ss58AddressFormat,
 | 
					    network_override: Ss58AddressFormat,
 | 
				
			||||||
) -> Result<String, &'static str>
 | 
					) -> Result<String, &'static str>
 | 
				
			||||||
where
 | 
					where
 | 
				
			||||||
	Pair: sp_core::Pair,
 | 
					    Pair: sp_core::Pair,
 | 
				
			||||||
	Pair::Public: IdentifyAccount,
 | 
					    Pair::Public: IdentifyAccount,
 | 
				
			||||||
	<Pair::Public as IdentifyAccount>::AccountId: Ss58Codec,
 | 
					    <Pair::Public as IdentifyAccount>::AccountId: Ss58Codec,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	println!("Generating key containing pattern '{}'", desired);
 | 
					    println!("Generating key containing pattern '{}'", desired);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let top = 45 + (desired.len() * 48);
 | 
					    let top = 45 + (desired.len() * 48);
 | 
				
			||||||
	let mut best = 0;
 | 
					    let mut best = 0;
 | 
				
			||||||
	let mut seed = Pair::Seed::default();
 | 
					    let mut seed = Pair::Seed::default();
 | 
				
			||||||
	let mut done = 0;
 | 
					    let mut done = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	loop {
 | 
					    loop {
 | 
				
			||||||
		if done % 100000 == 0 {
 | 
					        if done % 100000 == 0 {
 | 
				
			||||||
			OsRng.fill_bytes(seed.as_mut());
 | 
					            OsRng.fill_bytes(seed.as_mut());
 | 
				
			||||||
		} else {
 | 
					        } else {
 | 
				
			||||||
			next_seed(seed.as_mut());
 | 
					            next_seed(seed.as_mut());
 | 
				
			||||||
		}
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let p = Pair::from_seed(&seed);
 | 
					        let p = Pair::from_seed(&seed);
 | 
				
			||||||
		let ss58 = p.public().into_account().to_ss58check_with_version(network_override);
 | 
					        let ss58 = p
 | 
				
			||||||
 | 
					            .public()
 | 
				
			||||||
 | 
					            .into_account()
 | 
				
			||||||
 | 
					            .to_ss58check_with_version(network_override);
 | 
				
			||||||
        println!("{:?}", ss58);
 | 
					        println!("{:?}", ss58);
 | 
				
			||||||
		let score = calculate_score(desired, &ss58);
 | 
					        let score = calculate_score(desired, &ss58);
 | 
				
			||||||
		if score > best || desired.len() < 2 {
 | 
					        if score > best || desired.len() < 2 {
 | 
				
			||||||
			best = score;
 | 
					            best = score;
 | 
				
			||||||
			if best >= top {
 | 
					            if best >= top {
 | 
				
			||||||
				println!("best: {} == top: {}", best, top);
 | 
					                println!("best: {} == top: {}", best, top);
 | 
				
			||||||
				return Ok(format_seed::<Pair>(seed.clone()))
 | 
					                return Ok(format_seed::<Pair>(seed.clone()));
 | 
				
			||||||
			}
 | 
					            }
 | 
				
			||||||
		}
 | 
					        }
 | 
				
			||||||
		done += 1;
 | 
					        done += 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if done % good_waypoint(done) == 0 {
 | 
					        if done % good_waypoint(done) == 0 {
 | 
				
			||||||
			println!("{} keys searched; best is {}/{} complete", done, best, top);
 | 
					            println!("{} keys searched; best is {}/{} complete", done, best, top);
 | 
				
			||||||
		}
 | 
					        }
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn good_waypoint(done: u64) -> u64 {
 | 
					fn good_waypoint(done: u64) -> u64 {
 | 
				
			||||||
	match done {
 | 
					    match done {
 | 
				
			||||||
		0..=1_000_000 => 100_000,
 | 
					        0..=1_000_000 => 100_000,
 | 
				
			||||||
		1_000_001..=10_000_000 => 1_000_000,
 | 
					        1_000_001..=10_000_000 => 1_000_000,
 | 
				
			||||||
		10_000_001..=100_000_000 => 10_000_000,
 | 
					        10_000_001..=100_000_000 => 10_000_000,
 | 
				
			||||||
		100_000_001.. => 100_000_000,
 | 
					        100_000_001.. => 100_000_000,
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn next_seed(seed: &mut [u8]) {
 | 
					fn next_seed(seed: &mut [u8]) {
 | 
				
			||||||
	for s in seed {
 | 
					    for s in seed {
 | 
				
			||||||
		match s {
 | 
					        match s {
 | 
				
			||||||
			255 => {
 | 
					            255 => {
 | 
				
			||||||
				*s = 0;
 | 
					                *s = 0;
 | 
				
			||||||
			},
 | 
					            }
 | 
				
			||||||
			_ => {
 | 
					            _ => {
 | 
				
			||||||
				*s += 1;
 | 
					                *s += 1;
 | 
				
			||||||
				break
 | 
					                break;
 | 
				
			||||||
			},
 | 
					            }
 | 
				
			||||||
		}
 | 
					        }
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Calculate the score of a key based on the desired
 | 
					/// Calculate the score of a key based on the desired
 | 
				
			||||||
/// input.
 | 
					/// input.
 | 
				
			||||||
fn calculate_score(_desired: &str, key: &str) -> usize {
 | 
					fn calculate_score(_desired: &str, key: &str) -> usize {
 | 
				
			||||||
	for truncate in 0.._desired.len() {
 | 
					    for truncate in 0.._desired.len() {
 | 
				
			||||||
		let snip_size = _desired.len() - truncate;
 | 
					        let snip_size = _desired.len() - truncate;
 | 
				
			||||||
		let truncated = &_desired[0..snip_size];
 | 
					        let truncated = &_desired[0..snip_size];
 | 
				
			||||||
		if let Some(pos) = key.find(truncated) {
 | 
					        if let Some(pos) = key.find(truncated) {
 | 
				
			||||||
			return (47 - pos) + (snip_size * 48)
 | 
					            return (47 - pos) + (snip_size * 48);
 | 
				
			||||||
		}
 | 
					        }
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
	0
 | 
					    0
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// checks that `pattern` is non-empty
 | 
					/// checks that `pattern` is non-empty
 | 
				
			||||||
fn assert_non_empty_string(pattern: &str) -> Result<String, &'static str> {
 | 
					fn assert_non_empty_string(pattern: &str) -> Result<String, &'static str> {
 | 
				
			||||||
	if pattern.is_empty() {
 | 
					    if pattern.is_empty() {
 | 
				
			||||||
		Err("Pattern must not be empty")
 | 
					        Err("Pattern must not be empty")
 | 
				
			||||||
	} else {
 | 
					    } else {
 | 
				
			||||||
		Ok(pattern.to_string())
 | 
					        Ok(pattern.to_string())
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[cfg(test)]
 | 
					#[cfg(test)]
 | 
				
			||||||
mod tests {
 | 
					mod tests {
 | 
				
			||||||
	use super::*;
 | 
					    use super::*;
 | 
				
			||||||
	use sp_core::{
 | 
					    use sp_core::{
 | 
				
			||||||
		crypto::{default_ss58_version, Ss58AddressFormatRegistry, Ss58Codec},
 | 
					        crypto::{default_ss58_version, Ss58AddressFormatRegistry, Ss58Codec},
 | 
				
			||||||
		sr25519, Pair,
 | 
					        sr25519, Pair,
 | 
				
			||||||
	};
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#[test]
 | 
					    #[test]
 | 
				
			||||||
	fn vanity() {
 | 
					    fn vanity() {
 | 
				
			||||||
		let vanity = VanityCmd::parse_from(&["vanity", "--pattern", "j"]);
 | 
					        let vanity = VanityCmd::parse_from(&["vanity", "--pattern", "j"]);
 | 
				
			||||||
		assert!(vanity.run().is_ok());
 | 
					        assert!(vanity.run().is_ok());
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#[test]
 | 
					    #[test]
 | 
				
			||||||
	fn test_generation_with_single_char() {
 | 
					    fn test_generation_with_single_char() {
 | 
				
			||||||
		let seed = generate_key::<sr25519::Pair>("ab", default_ss58_version()).unwrap();
 | 
					        let seed = generate_key::<sr25519::Pair>("ab", default_ss58_version()).unwrap();
 | 
				
			||||||
		assert!(sr25519::Pair::from_seed_slice(&array_bytes::hex2bytes_unchecked(&seed))
 | 
					        assert!(
 | 
				
			||||||
			.unwrap()
 | 
					            sr25519::Pair::from_seed_slice(&array_bytes::hex2bytes_unchecked(&seed))
 | 
				
			||||||
			.public()
 | 
					                .unwrap()
 | 
				
			||||||
			.to_ss58check()
 | 
					                .public()
 | 
				
			||||||
			.contains("ab"));
 | 
					                .to_ss58check()
 | 
				
			||||||
	}
 | 
					                .contains("ab")
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#[test]
 | 
					    #[test]
 | 
				
			||||||
	fn generate_key_respects_network_override() {
 | 
					    fn generate_key_respects_network_override() {
 | 
				
			||||||
		let seed =
 | 
					        let seed =
 | 
				
			||||||
			generate_key::<sr25519::Pair>("ab", Ss58AddressFormatRegistry::PolkadotAccount.into())
 | 
					            generate_key::<sr25519::Pair>("ab", Ss58AddressFormatRegistry::PolkadotAccount.into())
 | 
				
			||||||
				.unwrap();
 | 
					                .unwrap();
 | 
				
			||||||
		assert!(sr25519::Pair::from_seed_slice(&array_bytes::hex2bytes_unchecked(&seed))
 | 
					        assert!(
 | 
				
			||||||
			.unwrap()
 | 
					            sr25519::Pair::from_seed_slice(&array_bytes::hex2bytes_unchecked(&seed))
 | 
				
			||||||
			.public()
 | 
					                .unwrap()
 | 
				
			||||||
			.to_ss58check_with_version(Ss58AddressFormatRegistry::PolkadotAccount.into())
 | 
					                .public()
 | 
				
			||||||
			.contains("ab"));
 | 
					                .to_ss58check_with_version(Ss58AddressFormatRegistry::PolkadotAccount.into())
 | 
				
			||||||
	}
 | 
					                .contains("ab")
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#[test]
 | 
					    #[test]
 | 
				
			||||||
	fn test_score_1_char_100() {
 | 
					    fn test_score_1_char_100() {
 | 
				
			||||||
		let score = calculate_score("j", "sYrjWiZkEP1PQe2kKEZiC1Bi9L8yFSsB5RPEkzEPd5NThsB5H");
 | 
					        let score = calculate_score("j", "sYrjWiZkEP1PQe2kKEZiC1Bi9L8yFSsB5RPEkzEPd5NThsB5H");
 | 
				
			||||||
		assert_eq!(score, 96);
 | 
					        assert_eq!(score, 96);
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#[test]
 | 
					    #[test]
 | 
				
			||||||
	fn test_score_100() {
 | 
					    fn test_score_100() {
 | 
				
			||||||
		let score = calculate_score("ghst", "sYsghstuhYd9p6unUC3kPxjD2gv2zRCztYQaEDCMJpYrPTqTG");
 | 
					        let score = calculate_score("ghst", "sYsghstuhYd9p6unUC3kPxjD2gv2zRCztYQaEDCMJpYrPTqTG");
 | 
				
			||||||
		assert_eq!(score, 246);
 | 
					        assert_eq!(score, 246);
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#[test]
 | 
					    #[test]
 | 
				
			||||||
	fn test_score_50_2() {
 | 
					    fn test_score_50_2() {
 | 
				
			||||||
		// 50% for the position + 50% for the size
 | 
					        // 50% for the position + 50% for the size
 | 
				
			||||||
		assert_eq!(
 | 
					        assert_eq!(
 | 
				
			||||||
			calculate_score("ghst", "sYsghXXuhYd9p6unUC3kPxjD2gv2zRCztYQaEDCMJpYrPTqTG"),
 | 
					            calculate_score("ghst", "sYsghXXuhYd9p6unUC3kPxjD2gv2zRCztYQaEDCMJpYrPTqTG"),
 | 
				
			||||||
			146
 | 
					            146
 | 
				
			||||||
		);
 | 
					        );
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#[test]
 | 
					    #[test]
 | 
				
			||||||
	fn test_score_0() {
 | 
					    fn test_score_0() {
 | 
				
			||||||
		assert_eq!(
 | 
					        assert_eq!(
 | 
				
			||||||
			calculate_score("ghst", "sYrjWiZkEP1PQe2kKEZiC1Bi9L8yFSsB5RPEkzEPd5NThsB5H"),
 | 
					            calculate_score("ghst", "sYrjWiZkEP1PQe2kKEZiC1Bi9L8yFSsB5RPEkzEPd5NThsB5H"),
 | 
				
			||||||
			0
 | 
					            0
 | 
				
			||||||
		);
 | 
					        );
 | 
				
			||||||
	}
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
pub mod params;
 | 
					 | 
				
			||||||
pub mod commands;
 | 
					pub mod commands;
 | 
				
			||||||
 | 
					pub mod params;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub use commands::KeySubcommand;
 | 
					pub use commands::KeySubcommand;
 | 
				
			||||||
pub use commands::VanityCmd;
 | 
					pub use commands::VanityCmd;
 | 
				
			||||||
 | 
				
			|||||||
@ -21,19 +21,25 @@ pub struct InnerSs58AddressFormat(Ss58AddressFormat);
 | 
				
			|||||||
impl InnerSs58AddressFormat {
 | 
					impl InnerSs58AddressFormat {
 | 
				
			||||||
    #[inline]
 | 
					    #[inline]
 | 
				
			||||||
    pub fn custom(prefix: u16) -> Self {
 | 
					    pub fn custom(prefix: u16) -> Self {
 | 
				
			||||||
        Self { 0: Ss58AddressFormat::custom(prefix) }
 | 
					        Self {
 | 
				
			||||||
 | 
					            0: Ss58AddressFormat::custom(prefix),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl std::fmt::Display for InnerSs58AddressFormat {
 | 
					impl std::fmt::Display for InnerSs58AddressFormat {
 | 
				
			||||||
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
 | 
					    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
 | 
				
			||||||
        write!(f, "{} network", ALL_POSSIBLE_IDS
 | 
					        write!(
 | 
				
			||||||
            .binary_search(&u16::from(self.0))
 | 
					            f,
 | 
				
			||||||
            .expect("always be found"))
 | 
					            "{} network",
 | 
				
			||||||
 | 
					            ALL_POSSIBLE_IDS
 | 
				
			||||||
 | 
					                .binary_search(&u16::from(self.0))
 | 
				
			||||||
 | 
					                .expect("always be found")
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'a>TryFrom<&'a str> for InnerSs58AddressFormat {
 | 
					impl<'a> TryFrom<&'a str> for InnerSs58AddressFormat {
 | 
				
			||||||
    type Error = ParseError;
 | 
					    type Error = ParseError;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn try_from(x: &'a str) -> Result<Self, Self::Error> {
 | 
					    fn try_from(x: &'a str) -> Result<Self, Self::Error> {
 | 
				
			||||||
@ -44,13 +50,13 @@ impl<'a>TryFrom<&'a str> for InnerSs58AddressFormat {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn parse_s58_prefix_address_format(x: &str,) -> Result<Ss58AddressFormat, String> {
 | 
					pub fn parse_s58_prefix_address_format(x: &str) -> Result<Ss58AddressFormat, String> {
 | 
				
			||||||
    match InnerSs58AddressFormat::try_from(x) {
 | 
					    match InnerSs58AddressFormat::try_from(x) {
 | 
				
			||||||
        Ok(format_registry) => Ok(format_registry.0.into()),
 | 
					        Ok(format_registry) => Ok(format_registry.0.into()),
 | 
				
			||||||
        Err(_) => Err(format!(
 | 
					        Err(_) => Err(format!(
 | 
				
			||||||
            "Unable to parse variant. Known variants: {:?}",
 | 
					            "Unable to parse variant. Known variants: {:?}",
 | 
				
			||||||
            &ALL_POSSIBLE_NAMES
 | 
					            &ALL_POSSIBLE_NAMES
 | 
				
			||||||
        ))
 | 
					        )),
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user