diff --git a/src/commands/cesium.rs b/src/commands/cesium.rs index 960db3478062f9e8ab6d009d549f61ec403437d9..dee9515d5cb0dc7b188db195d1da8e589257a513 100644 --- a/src/commands/cesium.rs +++ b/src/commands/cesium.rs @@ -1,6 +1,6 @@ use crate::*; use bs58; -use sp_core::ed25519::Pair as Ed25519Pair; +use sp_core::ed25519; /// define cesium subcommands #[derive(Clone, Default, Debug, clap::Parser)] @@ -58,7 +58,7 @@ pub fn compute_g1v1_public_key(key_pair: &KeyPair) -> Result<String, GcliError> /// Computes G1v1 public key from an ed25519 Pair pub fn compute_g1v1_public_key_from_ed25519_pair( - ed25519_key_pair: &Ed25519Pair, + ed25519_key_pair: &ed25519::Pair, ) -> Result<String, GcliError> { Ok(bs58::encode(ed25519_key_pair.public()).into_string()) } diff --git a/src/commands/vault.rs b/src/commands/vault.rs index 58821ddc074b0880e16179962212c4b19d599777..ee5b2352680ca0e4ce3509668426018587e2ce84 100644 --- a/src/commands/vault.rs +++ b/src/commands/vault.rs @@ -5,8 +5,8 @@ use crate::*; use age::secrecy::Secret; use comfy_table::{Cell, Table}; use sea_orm::ActiveValue::Set; -use sea_orm::ModelTrait; use sea_orm::{ConnectionTrait, TransactionTrait}; +use sea_orm::{DbErr, ModelTrait}; use sp_core::crypto::AddressUri; use std::cell::RefCell; use std::io::{Read, Write}; @@ -59,7 +59,7 @@ pub enum Subcommand { /// SS58 Address address: AccountId, }, - /// Remove an SS58 Address from the vault together with it's linked derivations + /// Remove an SS58 Address from the vault together with its linked derivations #[clap(long_about = "Remove an SS58 Address from the vault\n\ \n\ If a <Base> Address is given it will also remove the saved key")] @@ -72,9 +72,15 @@ pub enum Subcommand { #[clap(flatten)] address_or_vault_name: AddressOrVaultNameGroup, }, - /// (deprecated)List available key files (needs to be migrated with command `vault migrate` in order to use them) + /// (deprecated) List available key files (needs to be migrated with command `vault migrate` in order to use them) + #[deprecated( + note = "Should be removed in a future version when db persistence of vault is present for a while" + )] ListFiles, - /// (deprecated)Migrate old key files into db (will have to provide password for each key) + /// (deprecated) Migrate old key files into db (will have to provide password for each key) + #[deprecated( + note = "Should be removed in a future version when db persistence of vault is present for a while" + )] Migrate, /// Show where vault db (or old keys) is stored Where, @@ -248,7 +254,7 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE let base_account = &base_account_tree_node.borrow().account.clone(); if base_account.crypto_scheme.is_none() { - panic!("Crypto scheme is not set for the base account:{base_account} - should not happen"); + return Err(GcliError::DatabaseError(DbErr::Custom(format!("Crypto scheme is not set for the base account:{base_account} - should never happen")))); } if let Some(crypto_scheme) = base_account.crypto_scheme { @@ -483,19 +489,20 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE Ok(()) } -/// Method used to separate `name` part from optional `derivation` part in computed names -fn parse_prefix_and_derivation_path_from_string_for_vault_name( - raw_string: String, +/// Method used to separate vault `name` part from optional `derivation` part in computed names that can be provided by users in the different `vault` commands using `AddressOrVaultNameGroup` +fn parse_vault_name_and_derivation_path_from_user_input( + user_input_name: String, ) -> Result<(String, Option<String>), GcliError> { - if raw_string.contains("/") { - raw_string - .find("/") - .map_or(Err(GcliError::Input("Invalid format".to_string())), |idx| { - let (prefix, derivation_path) = raw_string.split_at(idx); + if user_input_name.contains("/") { + user_input_name.find("/").map_or( + Err(GcliError::Input("Invalid format".to_string())), + |idx| { + let (prefix, derivation_path) = user_input_name.split_at(idx); Ok((prefix.to_string(), Some(derivation_path.to_string()))) - }) + }, + ) } else { - Ok((raw_string, None)) + Ok((user_input_name, None)) } } @@ -522,14 +529,7 @@ pub fn parse_prefix_and_derivation_path_from_suri( let full_path = if address_uri.paths.is_empty() { None } else { - Some( - address_uri - .paths - .iter() - .map(|s| "/".to_string() + s) - .collect::<Vec<_>>() - .join(""), - ) + Some("/".to_owned() + &address_uri.paths.into_iter().collect::<Vec<_>>().join("/")) }; Ok((address_uri.phrase.map(|s| s.to_string()), full_path)) @@ -545,6 +545,9 @@ fn map_secret_format_to_crypto_scheme(secret_format: SecretFormat) -> CryptoSche } /// This method will scan files in the data directory and return the addresses of the vault keys found +#[deprecated( + note = "Should be removed in a future version when db persistence of vault is present for a while" +)] async fn fetch_vault_key_addresses(data: &Data) -> Result<Vec<String>, GcliError> { let mut entries = std::fs::read_dir(data.project_dir.data_dir())? .map(|res| res.map(|e| e.path())) @@ -556,17 +559,18 @@ async fn fetch_vault_key_addresses(data: &Data) -> Result<Vec<String>, GcliError let mut vault_key_addresses: Vec<String> = vec![]; entries.iter().for_each(|dir_path| { let filename = dir_path.file_name().unwrap().to_str().unwrap(); - // To only keep the address part of the filename for names like "<ss58 address>-<secret_format>" - let potential_address = filename.split("-").next().unwrap(); // If potential_address is a valid AccountId - if AccountId::from_str(potential_address).is_ok() { - vault_key_addresses.push(potential_address.to_string()); + if AccountId::from_str(filename).is_ok() { + vault_key_addresses.push(filename.to_string()); } }); Ok(vault_key_addresses) } +#[deprecated( + note = "Should be removed in a future version when db persistence of vault is present for a while" +)] async fn compute_vault_key_files_table(vault_key_addresses: &[String]) -> Result<Table, GcliError> { let mut table = Table::new(); table.load_preset(comfy_table::presets::UTF8_BORDERS_ONLY); @@ -703,7 +707,7 @@ where C: ConnectionTrait, { let (name, derivation_path_opt) = - parse_prefix_and_derivation_path_from_string_for_vault_name(name_input.to_string())?; + parse_vault_name_and_derivation_path_from_user_input(name_input.to_string())?; let account_for_name = vault_account::find_by_name(db, &name).await?; @@ -844,7 +848,7 @@ where existing_vault_account.parent.clone().unwrap() ); println!(); - println!("It's parent hierarchy is this:"); + println!("Its parent hierarchy is this:"); println!("{parent_hierarchy_table}"); println!(); println!("Do you want to:"); @@ -976,7 +980,7 @@ where ); println!(); - println!("It's parent hierarchy is this:"); + println!("Its parent hierarchy is this:"); println!("{parent_hierarchy_table_existing_account}"); println!(); println!("Do you want to:"); @@ -1126,6 +1130,9 @@ pub struct VaultDataFromFile { } /// try to get secret in keystore, prompt for the password and compute the keypair +#[deprecated( + note = "Should be removed in a future version when db persistence of vault is present for a while" +)] pub fn try_fetch_vault_data_from_file( data: &Data, address: &str, diff --git a/src/entities/vault_account.rs b/src/entities/vault_account.rs index 797a50e4bad9bd368de882d6783e55bd368895b9..1a31f4af9fe55e5305f9d220074741a8edb20e48 100644 --- a/src/entities/vault_account.rs +++ b/src/entities/vault_account.rs @@ -417,7 +417,7 @@ pub fn get_account_tree_node_for_address( Rc::clone(&account_tree_node_for_address) } -/// Returns a new (limited) `AccountTreeNode` hierarchy including the selected account_tree_node and all it's parents. +/// Returns a new (limited) `AccountTreeNode` hierarchy including the selected account_tree_node and all its parents. /// /// The base of the new hierarchy will be returned pub fn get_base_parent_hierarchy_account_tree_node( diff --git a/src/keys.rs b/src/keys.rs index 63ffbbf0dec322423ef629c563dad77be4e296fd..ad03260a9a5b2a16be9d14873b2eca323fef3843 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -1,7 +1,7 @@ +use crate::commands::vault; use crate::*; use sp_core::ed25519; -use sp_core::ed25519::Pair as Ed25519Pair; -use sp_core::sr25519::Pair as Sr25519Pair; +use sp_core::sr25519; pub const SUBSTRATE_MNEMONIC: &str = "bottom drive obey lake curtain smoke basket hold race lonely fit walk"; @@ -74,8 +74,8 @@ pub enum CryptoScheme { // /home/valpha/.cargo/git/checkouts/duniter-polkadot-sdk-0889f590ced4a269/bcc60f3/substrate/primitives/core/src/crypto.rs:1012 #[allow(clippy::large_enum_variant)] pub enum KeyPair { - Sr25519(Sr25519Pair), - Ed25519(Ed25519Pair), + Sr25519(sr25519::Pair), + Ed25519(ed25519::Pair), } impl KeyPair { pub fn address(&self) -> AccountId { @@ -94,13 +94,13 @@ impl Clone for KeyPair { } } } -impl From<Sr25519Pair> for KeyPair { - fn from(pair: Sr25519Pair) -> KeyPair { +impl From<sr25519::Pair> for KeyPair { + fn from(pair: sr25519::Pair) -> KeyPair { KeyPair::Sr25519(pair) } } -impl From<Ed25519Pair> for KeyPair { - fn from(pair: Ed25519Pair) -> KeyPair { +impl From<ed25519::Pair> for KeyPair { + fn from(pair: ed25519::Pair) -> KeyPair { KeyPair::Ed25519(pair) } } @@ -127,7 +127,7 @@ pub fn get_keypair( pub fn pair_from_secret( secret_format: SecretFormat, secret: &str, -) -> Result<Sr25519Pair, GcliError> { +) -> Result<sr25519::Pair, GcliError> { match secret_format { SecretFormat::Substrate => pair_from_sr25519_str(secret), SecretFormat::Predefined => pair_from_sr25519_str(secret), /* if predefined, secret arg is replaced in config */ @@ -139,35 +139,36 @@ pub fn pair_from_secret( } /// get keypair from given string secret -pub fn pair_from_sr25519_str(secret: &str) -> Result<Sr25519Pair, GcliError> { - Sr25519Pair::from_string(secret, None) +pub fn pair_from_sr25519_str(secret: &str) -> Result<sr25519::Pair, GcliError> { + let _validation_only = vault::parse_prefix_and_derivation_path_from_suri(secret.to_string())?; + sr25519::Pair::from_string(secret, None) .map_err(|_| GcliError::Input("Invalid secret".to_string())) } /// get keypair from given seed -// note: Sr25519Pair::from_string does exactly that when seed is 0x prefixed +// note: sr25519::Pair::from_string does exactly that when seed is 0x prefixed // (see from_string_with_seed method in crypto core) -pub fn pair_from_sr25519_seed(secret: &str) -> Result<Sr25519Pair, GcliError> { +pub fn pair_from_sr25519_seed(secret: &str) -> Result<sr25519::Pair, GcliError> { let mut seed = [0; 32]; hex::decode_to_slice(secret, &mut seed) .map_err(|_| GcliError::Input("Invalid secret".to_string()))?; - let pair = Sr25519Pair::from_seed(&seed); + let pair = sr25519::Pair::from_seed(&seed); Ok(pair) } /// get keypair from given ed25519 string secret (used for cesium) -pub fn pair_from_ed25519_str(secret: &str) -> Result<Ed25519Pair, GcliError> { - Ed25519Pair::from_string(secret, None) +pub fn pair_from_ed25519_str(secret: &str) -> Result<ed25519::Pair, GcliError> { + ed25519::Pair::from_string(secret, None) .map_err(|_| GcliError::Input("Invalid secret".to_string())) } /// get keypair from given ed25519 seed (used for cesium) #[allow(unused)] -pub fn pair_from_ed25519_seed(secret: &str) -> Result<Ed25519Pair, GcliError> { +pub fn pair_from_ed25519_seed(secret: &str) -> Result<ed25519::Pair, GcliError> { let mut seed = [0; 32]; hex::decode_to_slice(secret, &mut seed) .map_err(|_| GcliError::Input("Invalid secret".to_string()))?; - let pair = Ed25519Pair::from_seed(&seed); + let pair = ed25519::Pair::from_seed(&seed); Ok(pair) } @@ -177,7 +178,7 @@ pub fn predefined_mnemonic(deriv: &str) -> String { } /// get keypair from predefined secret -pub fn pair_from_predefined(deriv: &str) -> Result<Sr25519Pair, GcliError> { +pub fn pair_from_predefined(deriv: &str) -> Result<sr25519::Pair, GcliError> { pair_from_sr25519_str(&predefined_mnemonic(deriv)) } @@ -190,12 +191,12 @@ fn seed_from_cesium(id: &str, pwd: &str) -> [u8; 32] { } /// ask user to input a secret -pub fn prompt_secret_substrate() -> Sr25519Pair { +pub fn prompt_secret_substrate() -> sr25519::Pair { // Only interested in the keypair which is the second element of the tuple prompt_secret_substrate_and_compute_keypair().1 } -pub fn prompt_secret_substrate_and_compute_keypair() -> (String, Sr25519Pair) { +pub fn prompt_secret_substrate_and_compute_keypair() -> (String, sr25519::Pair) { loop { println!("Substrate URI can be a mnemonic or a mini-secret ('0x' prefixed seed) together with optional derivation path"); let substrate_suri = inputs::prompt_password_query("Substrate URI: ").unwrap(); @@ -207,12 +208,12 @@ pub fn prompt_secret_substrate_and_compute_keypair() -> (String, Sr25519Pair) { } /// ask user pass (Cesium format) -pub fn prompt_secret_cesium() -> Ed25519Pair { +pub fn prompt_secret_cesium() -> ed25519::Pair { // Only interested in the keypair which is the second element of the tuple prompt_secret_cesium_and_compute_keypair().1 } -pub fn prompt_secret_cesium_and_compute_keypair() -> (String, Ed25519Pair) { +pub fn prompt_secret_cesium_and_compute_keypair() -> (String, ed25519::Pair) { let id = inputs::prompt_password_query("Cesium id: ").unwrap(); let pwd = inputs::prompt_password_query("Cesium password: ").unwrap(); @@ -226,12 +227,12 @@ pub fn prompt_secret_cesium_and_compute_keypair() -> (String, Ed25519Pair) { } /// ask user to input a seed -pub fn prompt_seed() -> Sr25519Pair { +pub fn prompt_seed() -> sr25519::Pair { // Only interested in the keypair which is the second element of the tuple prompt_seed_and_compute_keypair().1 } -pub fn prompt_seed_and_compute_keypair() -> (String, Sr25519Pair) { +pub fn prompt_seed_and_compute_keypair() -> (String, sr25519::Pair) { loop { let seed_str = inputs::prompt_seed().unwrap(); let secret_suri = format!("0x{}", seed_str); @@ -244,12 +245,12 @@ pub fn prompt_seed_and_compute_keypair() -> (String, Sr25519Pair) { } /// ask user pass (Cesium format) -pub fn prompt_predefined() -> Sr25519Pair { +pub fn prompt_predefined() -> sr25519::Pair { // Only interested in the keypair which is the second element of the tuple prompt_predefined_and_compute_keypair().1 } -pub fn prompt_predefined_and_compute_keypair() -> (String, Sr25519Pair) { +pub fn prompt_predefined_and_compute_keypair() -> (String, sr25519::Pair) { let deriv = inputs::prompt_password_query("Enter derivation path: ").unwrap(); ( predefined_mnemonic(&deriv),