Skip to content
Snippets Groups Projects
Commit 66c7c2a8 authored by Nicolas80's avatar Nicolas80
Browse files

* Added support to show g1v1 base58 public key from (ed25519) ss58 address,...

* Added support to show g1v1 base58 public key from (ed25519) ss58 address, AccountId, ed25519::Public with tests for those
* Renamed SecretFormat.Cesium to SecretFormat.G1v1
   * Adapted `clap` display help to reflect the change
   * Still supporting using "cesium" as "-S" secret format argument and mapping it to SecretFormat.G1v1
* Adapted display of vault
   * Changed column "Format" into "Crypto", showing either "ed25519" or "sr25519" instead of "cesium" or "substrate"
   * Adapted 1st row header to "SS58 Address/G1v1 public key"
   * For "ed25519" account, showing a 2nd row just below containing "└ G1v1: <base58 public key value>"
   * Adapted test cases and added a G1v1 account example
* Adapted (String) Display of vault_account to include "g1v1_pub_key" value when crypto_scheme is Ed25519
parent f70f165b
No related branches found
No related tags found
1 merge request!41Adding db persistence for all SecretFormat of vault keys as well as supporting derivations
use crate::*; use crate::data::Data;
use crate::keys;
use crate::keys::KeyPair;
use crate::runtime_config::AccountId;
use crate::utils::GcliError;
use bs58; use bs58;
use sp_core::ed25519; use sp_core::{ed25519, Pair};
use std::str::FromStr;
/// define cesium subcommands /// define cesium subcommands
#[derive(Clone, Default, Debug, clap::Parser)] #[derive(Clone, Default, Debug, clap::Parser)]
...@@ -34,10 +39,10 @@ pub async fn handle_command(_data: Data, command: Subcommand) -> Result<(), Gcli ...@@ -34,10 +39,10 @@ pub async fn handle_command(_data: Data, command: Subcommand) -> Result<(), Gcli
println!("Address (SS58): {}", address); println!("Address (SS58): {}", address);
} }
Subcommand::Prompt => { Subcommand::Prompt => {
let pair = prompt_secret_cesium(); let pair = keys::prompt_secret_cesium();
println!( println!(
"Pubkey: {}", "Pubkey: {}",
compute_g1v1_public_key_from_ed25519_pair(&pair)? compute_g1v1_public_key_from_ed25519_pair(&pair)
); );
let address: AccountId = pair.public().into(); let address: AccountId = pair.public().into();
println!("Address: {}", address); println!("Address: {}", address);
...@@ -52,13 +57,91 @@ pub fn compute_g1v1_public_key(key_pair: &KeyPair) -> Result<String, GcliError> ...@@ -52,13 +57,91 @@ pub fn compute_g1v1_public_key(key_pair: &KeyPair) -> Result<String, GcliError>
KeyPair::Sr25519(_) => Err(GcliError::Logic( KeyPair::Sr25519(_) => Err(GcliError::Logic(
"key pair is not of type ed25519".to_string(), "key pair is not of type ed25519".to_string(),
)), )),
KeyPair::Ed25519(key_pair) => Ok(compute_g1v1_public_key_from_ed25519_pair(key_pair)?), KeyPair::Ed25519(key_pair) => Ok(compute_g1v1_public_key_from_ed25519_pair(key_pair)),
} }
} }
/// Computes G1v1 public key from an ed25519 Pair /// Computes G1v1 public key from an ed25519 Pair
pub fn compute_g1v1_public_key_from_ed25519_pair( pub fn compute_g1v1_public_key_from_ed25519_pair(ed25519_key_pair: &ed25519::Pair) -> String {
ed25519_key_pair: &ed25519::Pair, compute_g1v1_public_key_from_ed25519_public(&ed25519_key_pair.public())
}
/// Computes G1v1 public key from an ed25519 Public
pub fn compute_g1v1_public_key_from_ed25519_public(ed25519_public: &ed25519::Public) -> String {
bs58::encode(ed25519_public).into_string()
}
/// Computes G1v1 public key from an ed25519 AccountId
pub fn compute_g1v1_public_key_from_ed25519_account_id(ed25519_account_id: &AccountId) -> String {
let ed25519_public: ed25519::Public = ed25519::Public::from(ed25519_account_id.0);
bs58::encode(ed25519_public).into_string()
}
/// Computes G1v1 public key from an ed25519 SS58 Address
#[allow(unused)]
pub fn compute_g1v1_public_key_from_ed25519_ss58_address(
ed25519_ss58_address: &str,
) -> Result<String, GcliError> { ) -> Result<String, GcliError> {
Ok(bs58::encode(ed25519_key_pair.public()).into_string()) Ok(compute_g1v1_public_key_from_ed25519_account_id(
&AccountId::from_str(ed25519_ss58_address).map_err(|e| GcliError::Input(e.to_string()))?,
))
}
// Unit tests
#[cfg(test)]
mod tests {
use super::*;
/// Test data:
/// cesium_id = "test_cesium_id"
/// cesium_pwd = "test_cesium_pwd"
///
/// G1v1 base58 public key: 86pW1doyJPVH3jeDPZNQa1UZFBo5zcdvHERcaeE758W7
///
/// ```
/// subkey inspect --scheme ed25519
/// URI:
/// Secret Key URI `0x2101d2bc68de9ad149c06293bfe489c8608de576c88927aa5439a81be17aae84` is account:
/// Network ID: substrate
/// Secret seed: 0x2101d2bc68de9ad149c06293bfe489c8608de576c88927aa5439a81be17aae84
/// Public key (hex): 0x697f6bd16ddebf142384e503fd3f3efc39fe5c7be7c693bd98d982403bb6eb74
/// Account ID: 0x697f6bd16ddebf142384e503fd3f3efc39fe5c7be7c693bd98d982403bb6eb74
/// Public key (SS58): 5ET2jhgJFoNQUpgfdSkdwftK8DKWdqZ1FKm5GKWdPfMWhPr4
/// SS58 Address: 5ET2jhgJFoNQUpgfdSkdwftK8DKWdqZ1FKm5GKWdPfMWhPr4
/// ```
#[test]
fn test_compute_g1v1_public_key() {
let expected_base58_public_key = "86pW1doyJPVH3jeDPZNQa1UZFBo5zcdvHERcaeE758W7";
let ss58_address = "5ET2jhgJFoNQUpgfdSkdwftK8DKWdqZ1FKm5GKWdPfMWhPr4";
assert_eq!(
expected_base58_public_key,
compute_g1v1_public_key_from_ed25519_ss58_address(ss58_address).unwrap()
);
let account_id = AccountId::from_str(ss58_address).unwrap();
assert_eq!(
expected_base58_public_key,
compute_g1v1_public_key_from_ed25519_account_id(&account_id)
);
let ed25519_public = ed25519::Public::from(account_id.0);
assert_eq!(
expected_base58_public_key,
compute_g1v1_public_key_from_ed25519_public(&ed25519_public)
);
let cesium_id = "test_cesium_id".to_string();
let cesium_pwd = "test_cesium_pwd".to_string();
let seed = keys::seed_from_cesium(&cesium_id, &cesium_pwd);
let ed25519_pair_from_seed = ed25519::Pair::from_seed(&seed);
assert_eq!(
expected_base58_public_key,
compute_g1v1_public_key_from_ed25519_pair(&ed25519_pair_from_seed)
);
}
} }
...@@ -38,7 +38,7 @@ pub enum Subcommand { ...@@ -38,7 +38,7 @@ pub enum Subcommand {
in the substrate uri value." in the substrate uri value."
)] )]
Import { Import {
/// Secret key format (substrate, seed, cesium) /// Secret key format (substrate, seed, g1v1)
#[clap(short = 'S', long, required = false, default_value = SecretFormat::Substrate)] #[clap(short = 'S', long, required = false, default_value = SecretFormat::Substrate)]
secret_format: SecretFormat, secret_format: SecretFormat,
}, },
...@@ -219,8 +219,8 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE ...@@ -219,8 +219,8 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
let vault_data_for_import = let vault_data_for_import =
prompt_secret_and_compute_vault_data_to_import(secret_format)?; prompt_secret_and_compute_vault_data_to_import(secret_format)?;
//Extra check for SecretFormat::Cesium / G1v1Seed - showing the G1v1 cesium public key for confirmation //Extra check for SecretFormat::G1v1 (old cesium) - showing the G1v1 cesium public key for confirmation
if secret_format == SecretFormat::Cesium { if secret_format == SecretFormat::G1v1 {
println!( println!(
"The G1v1 public key for the provided secret is: '{}'", "The G1v1 public key for the provided secret is: '{}'",
compute_g1v1_public_key(&vault_data_for_import.key_pair)? compute_g1v1_public_key(&vault_data_for_import.key_pair)?
...@@ -545,7 +545,7 @@ fn map_secret_format_to_crypto_scheme(secret_format: SecretFormat) -> CryptoSche ...@@ -545,7 +545,7 @@ fn map_secret_format_to_crypto_scheme(secret_format: SecretFormat) -> CryptoSche
SecretFormat::Seed => CryptoScheme::Sr25519, SecretFormat::Seed => CryptoScheme::Sr25519,
SecretFormat::Substrate => CryptoScheme::Sr25519, SecretFormat::Substrate => CryptoScheme::Sr25519,
SecretFormat::Predefined => CryptoScheme::Sr25519, SecretFormat::Predefined => CryptoScheme::Sr25519,
SecretFormat::Cesium => CryptoScheme::Ed25519, SecretFormat::G1v1 => CryptoScheme::Ed25519,
} }
} }
...@@ -701,7 +701,7 @@ fn prompt_secret_and_compute_vault_data_to_import( ...@@ -701,7 +701,7 @@ fn prompt_secret_and_compute_vault_data_to_import(
SecretFormat::Seed => { SecretFormat::Seed => {
create_vault_data_to_import(secret_format, prompt_seed_and_compute_keypair) create_vault_data_to_import(secret_format, prompt_seed_and_compute_keypair)
} }
SecretFormat::Cesium => { SecretFormat::G1v1 => {
create_vault_data_to_import(secret_format, prompt_secret_cesium_and_compute_keypair) create_vault_data_to_import(secret_format, prompt_secret_cesium_and_compute_keypair)
} }
SecretFormat::Predefined => { SecretFormat::Predefined => {
......
use crate::commands::cesium;
use crate::entities::vault_account; use crate::entities::vault_account;
use crate::entities::vault_account::AccountTreeNode; use crate::entities::vault_account::AccountTreeNode;
use crate::keys::{CryptoScheme, SecretFormat}; use crate::keys::CryptoScheme;
use crate::utils::GcliError; use crate::utils::GcliError;
use comfy_table::{Cell, Table}; use comfy_table::{Cell, Table};
use std::cell::RefCell; use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;
use std::str;
#[deprecated( #[deprecated(
note = "Should be removed in a future version when db persistence of vault is present for a while" note = "Should be removed in a future version when db persistence of vault is present for a while"
...@@ -26,10 +28,15 @@ pub fn compute_vault_accounts_table( ...@@ -26,10 +28,15 @@ pub fn compute_vault_accounts_table(
) -> Result<Table, GcliError> { ) -> Result<Table, GcliError> {
let mut table = Table::new(); let mut table = Table::new();
table.load_preset(comfy_table::presets::UTF8_BORDERS_ONLY); table.load_preset(comfy_table::presets::UTF8_BORDERS_ONLY);
table.set_header(vec!["SS58 Address", "Format", "Account/Path", "Name"]); table.set_header(vec![
"SS58 Address/G1v1 public key",
"Crypto",
"Path",
"Name",
]);
for account_tree_node in account_tree_nodes { for account_tree_node in account_tree_nodes {
add_account_tree_node_to_table(&mut table, account_tree_node); let _ = add_account_tree_node_to_table(&mut table, account_tree_node);
} }
Ok(table) Ok(table)
...@@ -38,16 +45,25 @@ pub fn compute_vault_accounts_table( ...@@ -38,16 +45,25 @@ pub fn compute_vault_accounts_table(
fn add_account_tree_node_to_table( fn add_account_tree_node_to_table(
table: &mut Table, table: &mut Table,
account_tree_node: &Rc<RefCell<AccountTreeNode>>, account_tree_node: &Rc<RefCell<AccountTreeNode>>,
) { ) -> Result<(), GcliError> {
let row = compute_vault_accounts_row(account_tree_node); let rows = compute_vault_accounts_row(account_tree_node)?;
table.add_row(row); rows.iter().for_each(|row| {
table.add_row(row.clone());
});
for child in &account_tree_node.borrow().children { for child in &account_tree_node.borrow().children {
add_account_tree_node_to_table(table, child); let _ = add_account_tree_node_to_table(table, child);
} }
Ok(())
} }
pub fn compute_vault_accounts_row(account_tree_node: &Rc<RefCell<AccountTreeNode>>) -> Vec<Cell> { /// Computes one or more row of the table for selected account_tree_node
///
/// For ed25519 keys, will display over 2 rows to also show the base 58 G1v1 public key
pub fn compute_vault_accounts_row(
account_tree_node: &Rc<RefCell<AccountTreeNode>>,
) -> Result<Vec<Vec<Cell>>, GcliError> {
let empty_string = "".to_string(); let empty_string = "".to_string();
let depth_account_tree_node = vault_account::count_depth_account_tree_node(account_tree_node); let depth_account_tree_node = vault_account::count_depth_account_tree_node(account_tree_node);
...@@ -71,33 +87,51 @@ pub fn compute_vault_accounts_row(account_tree_node: &Rc<RefCell<AccountTreeNode ...@@ -71,33 +87,51 @@ pub fn compute_vault_accounts_row(account_tree_node: &Rc<RefCell<AccountTreeNode
account_tree_node.account.address.to_string() account_tree_node.account.address.to_string()
}; };
let (path, format) = if let Some(path) = account_tree_node.account.path.clone() { let mut rows: Vec<Vec<Cell>> = vec![];
let (path, crypto) = if let Some(path) = account_tree_node.account.path.clone() {
(path, empty_string.clone()) (path, empty_string.clone())
} else { } else {
let secret_format = match account_tree_node.account.crypto_scheme.unwrap().into() { let crypto_scheme = CryptoScheme::from(account_tree_node.account.crypto_scheme.unwrap());
CryptoScheme::Sr25519 => SecretFormat::Substrate,
CryptoScheme::Ed25519 => SecretFormat::Cesium, // Adding 2nd row for G1v1 public key
}; if CryptoScheme::Ed25519 == crypto_scheme {
let secret_format_str: &str = secret_format.into(); rows.push(vec![Cell::new(format!(
"└ G1v1: {}",
cesium::compute_g1v1_public_key_from_ed25519_account_id(
&account_tree_node.account.address.0
)
))]);
}
let crypto_scheme_str: &str = crypto_scheme.into();
( (
format!("<{}>", account_tree_node.account.account_type()), format!("<{}>", account_tree_node.account.account_type()),
secret_format_str.to_string(), crypto_scheme_str.to_string(),
) )
}; };
// Adding 1st row
rows.insert(
0,
vec![ vec![
Cell::new(&address), Cell::new(&address),
Cell::new(format), Cell::new(crypto),
Cell::new(&path), Cell::new(&path),
Cell::new(&name), Cell::new(&name),
] ],
);
Ok(rows)
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
mod vault_accounts_table_tests { mod vault_accounts_table_tests {
use crate::commands::vault::display::compute_vault_accounts_table; use crate::commands::vault::display::compute_vault_accounts_table;
use crate::entities::vault_account::tests::account_tree_node_tests::mother_account_tree_node; use crate::entities::vault_account::tests::account_tree_node_tests::{
mother_account_tree_node, mother_g1v1_account_tree_node,
};
use indoc::indoc; use indoc::indoc;
#[test] #[test]
...@@ -105,10 +139,10 @@ mod tests { ...@@ -105,10 +139,10 @@ mod tests {
let table = compute_vault_accounts_table(&[]).unwrap(); let table = compute_vault_accounts_table(&[]).unwrap();
let expected_table = indoc! {r#" let expected_table = indoc! {r#"
┌─────────────────────────────────────────────┐ ┌─────────────────────────────────────────────────────
│ SS58 Address Format Account/Path Name │ │ SS58 Address/G1v1 public key Crypto Path Name │
╞═════════════════════════════════════════════╡ ╞═════════════════════════════════════════════════════
└─────────────────────────────────────────────┘"# └─────────────────────────────────────────────────────┘"#
}; };
assert_eq!(table.to_string(), expected_table); assert_eq!(table.to_string(), expected_table);
...@@ -117,19 +151,23 @@ mod tests { ...@@ -117,19 +151,23 @@ mod tests {
#[test] #[test]
fn test_compute_vault_accounts_table() { fn test_compute_vault_accounts_table() {
let account_tree_node = mother_account_tree_node(); let account_tree_node = mother_account_tree_node();
let g1v1_account_tree_node = mother_g1v1_account_tree_node();
let table = compute_vault_accounts_table(&[account_tree_node]).unwrap(); let table =
compute_vault_accounts_table(&[account_tree_node, g1v1_account_tree_node]).unwrap();
let expected_table = indoc! {r#" let expected_table = indoc! {r#"
┌────────────────────────────────────────────────────────────────────────────────────────────────── ┌──────────────────────────────────────────────────────────────────────────────────────────┐
│ SS58 Address Format Account/Path Name │ │ SS58 Address/G1v1 public key Crypto Path Name │
╞══════════════════════════════════════════════════════════════════════════════════════════════════ ╞══════════════════════════════════════════════════════════════════════════════════════════╡
│ 5DfhGyQdFobKM8NsWvEeAKk5EQQgYe9AydgJ7rMB6E1EqRzV substrate <Base> Mother │ │ 5DfhGyQdFobKM8NsWvEeAKk5EQQgYe9AydgJ7rMB6E1EqRzV sr25519 <Base> Mother │
│ ├─5D34dL5prEUaGNQtPPZ3yN5Y6BnkfXunKXXz6fo7ZJbLwRRH //0 Child 1 │ │ ├─5D34dL5prEUaGNQtPPZ3yN5Y6BnkfXunKXXz6fo7ZJbLwRRH //0 Child 1 │
│ │ ├─5Fh5PLQNt1xuEXm71dfDtQdnwceSew4oHewWBLsWAkKspV7d //0 Grandchild 1 │ │ │ ├─5Fh5PLQNt1xuEXm71dfDtQdnwceSew4oHewWBLsWAkKspV7d //0 Grandchild 1 │
│ ├─5GBNeWRhZc2jXu7D55rBimKYDk8PGk8itRYFTPfC8RJLKG5o //1 <Mother//1> │ │ ├─5GBNeWRhZc2jXu7D55rBimKYDk8PGk8itRYFTPfC8RJLKG5o //1 <Mother//1> │
│ │ ├─5CvdJuB9HLXSi5FS9LW57cyHF13iCv5HDimo2C45KxnxriCT //1 <Mother//1//1> │ │ │ ├─5CvdJuB9HLXSi5FS9LW57cyHF13iCv5HDimo2C45KxnxriCT //1 <Mother//1//1> │
└──────────────────────────────────────────────────────────────────────────────────────────────────┘"# │ 5ET2jhgJFoNQUpgfdSkdwftK8DKWdqZ1FKm5GKWdPfMWhPr4 ed25519 <Base> MotherG1v1 │
│ └ G1v1: 86pW1doyJPVH3jeDPZNQa1UZFBo5zcdvHERcaeE758W7 │
└──────────────────────────────────────────────────────────────────────────────────────────┘"#
}; };
assert_eq!(table.to_string(), expected_table); assert_eq!(table.to_string(), expected_table);
...@@ -143,12 +181,12 @@ mod tests { ...@@ -143,12 +181,12 @@ mod tests {
let table = compute_vault_accounts_table(&[child1]).unwrap(); let table = compute_vault_accounts_table(&[child1]).unwrap();
let expected_table = indoc! {r#" let expected_table = indoc! {r#"
┌───────────────────────────────────────────────────────────────────────────────────────────── ┌─────────────────────────────────────────────────────────────────────────────────────┐
│ SS58 Address Format Account/Path Name │ │ SS58 Address/G1v1 public key Crypto Path Name │
╞═════════════════════════════════════════════════════════════════════════════════════════════ ╞═════════════════════════════════════════════════════════════════════════════════════╡
│ ├─5D34dL5prEUaGNQtPPZ3yN5Y6BnkfXunKXXz6fo7ZJbLwRRH //0 Child 1 │ │ ├─5D34dL5prEUaGNQtPPZ3yN5Y6BnkfXunKXXz6fo7ZJbLwRRH //0 Child 1 │
│ │ ├─5Fh5PLQNt1xuEXm71dfDtQdnwceSew4oHewWBLsWAkKspV7d //0 Grandchild 1 │ │ │ ├─5Fh5PLQNt1xuEXm71dfDtQdnwceSew4oHewWBLsWAkKspV7d //0 Grandchild 1 │
└─────────────────────────────────────────────────────────────────────────────────────────────┘"# └─────────────────────────────────────────────────────────────────────────────────────┘"#
}; };
assert_eq!(table.to_string(), expected_table); assert_eq!(table.to_string(), expected_table);
......
use crate::commands::vault; use crate::commands::{cesium, vault};
use crate::runtime_config::AccountId;
use crate::utils::GcliError; use crate::utils::GcliError;
use anyhow::anyhow; use anyhow::anyhow;
use sea_orm::prelude::async_trait::async_trait; use sea_orm::prelude::async_trait::async_trait;
...@@ -20,7 +21,6 @@ use std::future::Future; ...@@ -20,7 +21,6 @@ use std::future::Future;
use std::pin::Pin; use std::pin::Pin;
use std::rc::Rc; use std::rc::Rc;
use std::str::FromStr; use std::str::FromStr;
use subxt::utils::AccountId32;
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)] #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "vault_account")] #[sea_orm(table_name = "vault_account")]
...@@ -63,6 +63,23 @@ impl Model { ...@@ -63,6 +63,23 @@ impl Model {
impl Display for Model { impl Display for Model {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.is_base_account() { if self.is_base_account() {
match self.crypto_scheme {
None => {
unreachable!()
}
Some(DbCryptoScheme::Ed25519) => {
// Also showing G1v1 public key for Ed25519 (base) accounts
write!(
f,
"{}[address:{}, g1v1_pub_key:{}, name:{:?}, crypto_scheme:{:?}]",
self.account_type(),
self.address,
cesium::compute_g1v1_public_key_from_ed25519_account_id(&self.address.0),
self.name,
self.crypto_scheme
)
}
Some(DbCryptoScheme::Sr25519) => {
write!( write!(
f, f,
"{}[address:{}, name:{:?}, crypto_scheme:{:?}]", "{}[address:{}, name:{:?}, crypto_scheme:{:?}]",
...@@ -71,6 +88,8 @@ impl Display for Model { ...@@ -71,6 +88,8 @@ impl Display for Model {
self.name, self.name,
self.crypto_scheme self.crypto_scheme
) )
}
}
} else { } else {
fn get_parent_name(parent: &Option<DbAccountId>) -> String { fn get_parent_name(parent: &Option<DbAccountId>) -> String {
if let Some(parent) = parent { if let Some(parent) = parent {
...@@ -95,15 +114,15 @@ impl Display for Model { ...@@ -95,15 +114,15 @@ impl Display for Model {
/// Necessary to create a wrapper over AccountId32 to implement sea-orm traits /// Necessary to create a wrapper over AccountId32 to implement sea-orm traits
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, FromJsonQueryResult)] #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, FromJsonQueryResult)]
pub struct DbAccountId(pub AccountId32); pub struct DbAccountId(pub AccountId);
impl FromStr for DbAccountId { impl FromStr for DbAccountId {
type Err = GcliError; type Err = GcliError;
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
AccountId32::from_str(s) AccountId::from_str(s)
.map(DbAccountId) .map(DbAccountId)
.map_err(|_| GcliError::Input("Invalid AccountId32 format".to_string())) .map_err(|_| GcliError::Input("Invalid AccountId format".to_string()))
} }
} }
...@@ -113,13 +132,13 @@ impl Display for DbAccountId { ...@@ -113,13 +132,13 @@ impl Display for DbAccountId {
} }
} }
impl From<AccountId32> for DbAccountId { impl From<AccountId> for DbAccountId {
fn from(account_id32: AccountId32) -> Self { fn from(account_id: AccountId) -> Self {
DbAccountId(account_id32) DbAccountId(account_id)
} }
} }
impl From<DbAccountId> for AccountId32 { impl From<DbAccountId> for AccountId {
fn from(db_account_id: DbAccountId) -> Self { fn from(db_account_id: DbAccountId) -> Self {
db_account_id.0 db_account_id.0
} }
...@@ -127,7 +146,7 @@ impl From<DbAccountId> for AccountId32 { ...@@ -127,7 +146,7 @@ impl From<DbAccountId> for AccountId32 {
impl From<String> for DbAccountId { impl From<String> for DbAccountId {
fn from(s: String) -> Self { fn from(s: String) -> Self {
DbAccountId(AccountId32::from_str(&s).expect("Invalid AccountId32 format")) DbAccountId(AccountId::from_str(&s).expect("Invalid AccountId format"))
} }
} }
...@@ -888,6 +907,7 @@ pub mod tests { ...@@ -888,6 +907,7 @@ pub mod tests {
pub mod account_tree_node_tests { pub mod account_tree_node_tests {
use super::*; use super::*;
use crate::commands::vault; use crate::commands::vault;
use crate::keys;
use crate::keys::SUBSTRATE_MNEMONIC; use crate::keys::SUBSTRATE_MNEMONIC;
pub fn mother_account_tree_node() -> Rc<RefCell<AccountTreeNode>> { pub fn mother_account_tree_node() -> Rc<RefCell<AccountTreeNode>> {
...@@ -980,6 +1000,34 @@ pub mod tests { ...@@ -980,6 +1000,34 @@ pub mod tests {
mother mother
} }
pub fn mother_g1v1_account_tree_node() -> Rc<RefCell<AccountTreeNode>> {
let mother_address =
DbAccountId::from_str("5ET2jhgJFoNQUpgfdSkdwftK8DKWdqZ1FKm5GKWdPfMWhPr4").unwrap();
let cesium_id = "test_cesium_id".to_string();
let cesium_pwd = "test_cesium_pwd".to_string();
let seed = keys::seed_from_cesium(&cesium_id, &cesium_pwd);
let secret_suri = format!("0x{}", hex::encode(seed));
let mother_g1v1 = Rc::new(RefCell::new(AccountTreeNode {
account: Model {
address: mother_address.clone(),
name: Some("MotherG1v1".to_string()),
path: None,
crypto_scheme: Some(DbCryptoScheme::Ed25519),
encrypted_suri: Some(
vault::encrypt(secret_suri.as_bytes(), "".to_string()).unwrap(),
),
parent: None,
},
children: vec![],
parent: None,
}));
mother_g1v1
}
#[test] #[test]
fn test_count_depth_account_tree_node() { fn test_count_depth_account_tree_node() {
let mother = mother_account_tree_node(); let mother = mother_account_tree_node();
......
...@@ -16,8 +16,8 @@ pub enum SecretFormat { ...@@ -16,8 +16,8 @@ pub enum SecretFormat {
Substrate, Substrate,
/// Predefined (Alice, Bob, ...) /// Predefined (Alice, Bob, ...)
Predefined, Predefined,
/// Cesium (scrypt + nacl) /// G1v1 id+secret using (scrypt + ed25519)
Cesium, G1v1,
} }
impl FromStr for SecretFormat { impl FromStr for SecretFormat {
...@@ -28,7 +28,9 @@ impl FromStr for SecretFormat { ...@@ -28,7 +28,9 @@ impl FromStr for SecretFormat {
"seed" => Ok(SecretFormat::Seed), "seed" => Ok(SecretFormat::Seed),
"substrate" => Ok(SecretFormat::Substrate), "substrate" => Ok(SecretFormat::Substrate),
"predefined" => Ok(SecretFormat::Predefined), "predefined" => Ok(SecretFormat::Predefined),
"cesium" => Ok(SecretFormat::Cesium), "g1v1" => Ok(SecretFormat::G1v1),
//Still support "cesium" input as well for backward compatibility
"cesium" => Ok(SecretFormat::G1v1),
_ => Err(std::io::Error::from(std::io::ErrorKind::InvalidInput)), _ => Err(std::io::Error::from(std::io::ErrorKind::InvalidInput)),
} }
} }
...@@ -39,7 +41,7 @@ impl From<SecretFormat> for &'static str { ...@@ -39,7 +41,7 @@ impl From<SecretFormat> for &'static str {
SecretFormat::Seed => "seed", SecretFormat::Seed => "seed",
SecretFormat::Substrate => "substrate", SecretFormat::Substrate => "substrate",
SecretFormat::Predefined => "predefined", SecretFormat::Predefined => "predefined",
SecretFormat::Cesium => "cesium", SecretFormat::G1v1 => "g1v1",
} }
} }
} }
...@@ -60,18 +62,38 @@ pub enum CryptoScheme { ...@@ -60,18 +62,38 @@ pub enum CryptoScheme {
Sr25519, Sr25519,
} }
impl FromStr for CryptoScheme {
type Err = std::io::Error;
fn from_str(s: &str) -> std::io::Result<Self> {
match s {
"ed25519" => Ok(CryptoScheme::Ed25519),
"sr25519" => Ok(CryptoScheme::Sr25519),
_ => Err(std::io::Error::from(std::io::ErrorKind::InvalidInput)),
}
}
}
impl From<CryptoScheme> for &'static str {
fn from(val: CryptoScheme) -> &'static str {
match val {
CryptoScheme::Ed25519 => "ed25519",
CryptoScheme::Sr25519 => "sr25519",
}
}
}
impl From<CryptoScheme> for OsStr {
fn from(val: CryptoScheme) -> OsStr {
OsStr::from(Into::<&str>::into(val))
}
}
/// wrapper type for keys + signature /// wrapper type for keys + signature
//FIXME check if it's ok to keep large enum variant //FIXME check if it's ok to keep large enum variant
// Sr25519 second-largest variant contains at least 256 bytes // Sr25519 second-largest variant contains at least 256 bytes
// Ed25519 largest variant contains at least 480 bytes // Ed25519 largest variant contains at least 480 bytes
//FIXME //FIXME
// Replace by CryptoScheme from sc_cli?? or CryptoType from sp-core ? // Replace by CryptoType from sp-core ?
// sc_cli::arg_enums::CryptoScheme (enum)
// CryptoScheme::Ed25519
// CryptoScheme::Sr25519
// CryptoScheme::Ecdsa
// sp_core::crypto::CryptoType (trait) // sp_core::crypto::CryptoType (trait)
// /home/valpha/.cargo/git/checkouts/duniter-polkadot-sdk-0889f590ced4a269/bcc60f3/substrate/primitives/core/src/crypto.rs:1012
#[allow(clippy::large_enum_variant)] #[allow(clippy::large_enum_variant)]
pub enum KeyPair { pub enum KeyPair {
Sr25519(sr25519::Pair), Sr25519(sr25519::Pair),
...@@ -132,8 +154,8 @@ pub fn pair_from_secret( ...@@ -132,8 +154,8 @@ pub fn pair_from_secret(
SecretFormat::Substrate => pair_from_sr25519_str(secret), SecretFormat::Substrate => pair_from_sr25519_str(secret),
SecretFormat::Predefined => pair_from_sr25519_str(secret), /* if predefined, secret arg is replaced in config */ SecretFormat::Predefined => pair_from_sr25519_str(secret), /* if predefined, secret arg is replaced in config */
SecretFormat::Seed => pair_from_sr25519_seed(secret), SecretFormat::Seed => pair_from_sr25519_seed(secret),
SecretFormat::Cesium => Err(GcliError::Logic( SecretFormat::G1v1 => Err(GcliError::Logic(
"cesium format incompatible with single secret".to_string(), "G1v1 format incompatible with single secret".to_string(),
)), )),
} }
} }
...@@ -183,7 +205,7 @@ pub fn pair_from_predefined(deriv: &str) -> Result<sr25519::Pair, GcliError> { ...@@ -183,7 +205,7 @@ pub fn pair_from_predefined(deriv: &str) -> Result<sr25519::Pair, GcliError> {
} }
/// get seed from Cesium id/pwd /// get seed from Cesium id/pwd
fn seed_from_cesium(id: &str, pwd: &str) -> [u8; 32] { pub fn seed_from_cesium(id: &str, pwd: &str) -> [u8; 32] {
let params = scrypt::Params::new(12u8, 16u32, 1u32, 32).unwrap(); let params = scrypt::Params::new(12u8, 16u32, 1u32, 32).unwrap();
let mut seed = [0u8; 32]; let mut seed = [0u8; 32];
scrypt::scrypt(pwd.as_bytes(), id.as_bytes(), &params, &mut seed).unwrap(); scrypt::scrypt(pwd.as_bytes(), id.as_bytes(), &params, &mut seed).unwrap();
...@@ -262,7 +284,7 @@ pub fn prompt_predefined_and_compute_keypair() -> (String, sr25519::Pair) { ...@@ -262,7 +284,7 @@ pub fn prompt_predefined_and_compute_keypair() -> (String, sr25519::Pair) {
pub fn prompt_secret(secret_format: SecretFormat) -> KeyPair { pub fn prompt_secret(secret_format: SecretFormat) -> KeyPair {
match secret_format { match secret_format {
SecretFormat::Substrate => prompt_secret_substrate().into(), SecretFormat::Substrate => prompt_secret_substrate().into(),
SecretFormat::Cesium => prompt_secret_cesium().into(), SecretFormat::G1v1 => prompt_secret_cesium().into(),
SecretFormat::Seed => prompt_seed().into(), SecretFormat::Seed => prompt_seed().into(),
SecretFormat::Predefined => prompt_predefined().into(), SecretFormat::Predefined => prompt_predefined().into(),
} }
...@@ -388,7 +410,7 @@ mod tests { ...@@ -388,7 +410,7 @@ mod tests {
/// formats public key as hex /// formats public key as hex
fn format_public_key<P: sp_core::Pair>(public_key: PublicFor<P>) -> String { fn format_public_key<P: sp_core::Pair>(public_key: PublicFor<P>) -> String {
format!("0x{}", hex::encode((&public_key.as_ref()))) format!("0x{}", hex::encode(&public_key.as_ref()))
} }
/// formats public key as accountId as hex /// formats public key as accountId as hex
......
...@@ -50,7 +50,7 @@ pub struct Args { ...@@ -50,7 +50,7 @@ pub struct Args {
/// (eventually followed by derivation path) /// (eventually followed by derivation path)
#[clap(short, long)] #[clap(short, long)]
secret: Option<String>, secret: Option<String>,
/// Secret key format (seed, substrate, cesium) /// Secret key format (seed, substrate, g1v1)
#[clap(short = 'S', long)] #[clap(short = 'S', long)]
secret_format: Option<SecretFormat>, secret_format: Option<SecretFormat>,
/// SS58 Address /// SS58 Address
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment