Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
Ğ
Ğcli-v2s
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
clients
Rust
Ğcli-v2s
Commits
027f0655
Commit
027f0655
authored
1 month ago
by
poka
Browse files
Options
Downloads
Patches
Plain Diff
feat: Can choose between ed25519 ans sr25519
parent
5dd41657
No related branches found
No related tags found
2 merge requests
!45
Nostr
,
!44
feat: Can choose between ed25519 ans sr25519
Pipeline
#40088
passed
1 month ago
Stage: tests
Changes
3
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
src/commands/vault.rs
+73
-49
73 additions, 49 deletions
src/commands/vault.rs
src/commands/vault/display.rs
+96
-9
96 additions, 9 deletions
src/commands/vault/display.rs
src/keys.rs
+109
-58
109 additions, 58 deletions
src/keys.rs
with
278 additions
and
116 deletions
src/commands/vault.rs
+
73
−
49
View file @
027f0655
...
@@ -41,14 +41,18 @@ pub enum Subcommand {
...
@@ -41,14 +41,18 @@ pub enum Subcommand {
/// Secret key format (substrate, seed, g1v1)
/// 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
,
/// Crypto scheme to use (sr25519, ed25519)
#[clap(short
=
'c'
,
long,
required
=
false
,
default_value
=
CryptoScheme::Ed25519)]
crypto_scheme
:
CryptoScheme
,
},
},
/// Add a derivation to an existing SS58 Address
/// Add a derivation to an existing SS58 Address
#[clap(long_about
=
"Add a derivation to an existing SS58 Address.
\n
\
#[clap(long_about
=
"Add a derivation to an existing SS58 Address.
\n
\
\n
\
\n
\
Only
\"
sr25519
\"
crypto scheme
is
supported
for derivations.
\n
\
Both
\"
sr25519
\"
and
\"
ed25519
\"
crypto scheme
s are
supported
\n
\
\n
\
Use command `vault list base` to see available <Base> account and their crypto scheme
\n
\
Use command `vault list base` to see available <Base> account and their crypto scheme
\n
\
And then use command 'vault list for' to find all accounts linked to that <Base> account
.
"
)]
And then use command 'vault list for' to find all accounts linked to that <Base> account"
)]
#[clap(alias
=
"deriv"
)]
#[clap(alias
=
"deriv"
)]
#[clap(alias
=
"derivation"
)]
#[clap(alias
=
"derivation"
)]
Derive
{
Derive
{
...
@@ -87,18 +91,35 @@ pub enum Subcommand {
...
@@ -87,18 +91,35 @@ pub enum Subcommand {
Where
,
Where
,
}
}
#[derive(Clone,
Default,
Debug,
clap::Parser)]
#[derive(Clone,
Debug,
clap::Parser)]
pub
enum
ListChoice
{
pub
enum
ListChoice
{
/// List all <Base> SS58 Addresses and their linked derivations in the vault
/// List all <Base> SS58 Addresses and their linked derivations in the vault
#[default]
All
{
All
,
/// Show G1v1 public keys
#[clap(long,
default_value
=
"false"
)]
show_g1v1
:
bool
,
},
/// List <Base> and Derivation SS58 Addresses linked to the selected one
/// List <Base> and Derivation SS58 Addresses linked to the selected one
For
{
For
{
#[clap(flatten)]
#[clap(flatten)]
address_or_vault_name
:
AddressOrVaultNameGroup
,
address_or_vault_name
:
AddressOrVaultNameGroup
,
/// Show G1v1 public keys
#[clap(long,
default_value
=
"false"
)]
show_g1v1
:
bool
,
},
},
/// List all <Base> SS58 Addresses in the vault
/// List all <Base> SS58 Addresses in the vault
Base
,
Base
{
/// Show G1v1 public keys
#[clap(long,
default_value
=
"false"
)]
show_g1v1
:
bool
,
},
}
impl
Default
for
ListChoice
{
fn
default
()
->
Self
{
ListChoice
::
All
{
show_g1v1
:
false
}
}
}
}
#[derive(Debug,
clap::Args,
Clone)]
#[derive(Debug,
clap::Args,
Clone)]
...
@@ -151,26 +172,27 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
...
@@ -151,26 +172,27 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
// match subcommand
// match subcommand
match
command
{
match
command
{
Subcommand
::
List
(
choice
)
=>
match
choice
{
Subcommand
::
List
(
choice
)
=>
match
choice
{
ListChoice
::
All
=>
{
ListChoice
::
All
{
show_g1v1
}
=>
{
let
all_account_tree_node_hierarchies
=
let
all_account_tree_node_hierarchies
=
vault_account
::
fetch_all_base_account_tree_node_hierarchies
(
db
)
.await
?
;
vault_account
::
fetch_all_base_account_tree_node_hierarchies
(
db
)
.await
?
;
let
table
=
display
::
compute_vault_accounts_table
(
&
all_account_tree_node_hierarchies
)
?
;
let
table
=
display
::
compute_vault_accounts_table
_with_g1v1
(
&
all_account_tree_node_hierarchies
,
show_g1v1
)
?
;
println!
(
"available SS58 Addresses:"
);
println!
(
"available SS58 Addresses:"
);
println!
(
"{table}"
);
println!
(
"{table}"
);
}
}
ListChoice
::
Base
=>
{
ListChoice
::
Base
{
show_g1v1
}
=>
{
let
base_account_tree_nodes
=
let
base_account_tree_nodes
=
vault_account
::
fetch_only_base_account_tree_nodes
(
db
)
.await
?
;
vault_account
::
fetch_only_base_account_tree_nodes
(
db
)
.await
?
;
let
table
=
display
::
compute_vault_accounts_table
(
&
base_account_tree_nodes
)
?
;
let
table
=
display
::
compute_vault_accounts_table
_with_g1v1
(
&
base_account_tree_nodes
,
show_g1v1
)
?
;
println!
(
"available <Base> SS58 Addresses:"
);
println!
(
"available <Base> SS58 Addresses:"
);
println!
(
"{table}"
);
println!
(
"{table}"
);
}
}
ListChoice
::
For
{
ListChoice
::
For
{
address_or_vault_name
,
address_or_vault_name
,
show_g1v1
,
}
=>
{
}
=>
{
let
account_tree_node
=
let
account_tree_node
=
retrieve_account_tree_node
(
db
,
address_or_vault_name
)
.await
?
;
retrieve_account_tree_node
(
db
,
address_or_vault_name
)
.await
?
;
...
@@ -178,7 +200,7 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
...
@@ -178,7 +200,7 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
let
base_account_tree_node
=
let
base_account_tree_node
=
vault_account
::
get_base_account_tree_node
(
&
account_tree_node
);
vault_account
::
get_base_account_tree_node
(
&
account_tree_node
);
let
table
=
display
::
compute_vault_accounts_table
(
&
[
base_account_tree_node
])
?
;
let
table
=
display
::
compute_vault_accounts_table
_with_g1v1
(
&
[
base_account_tree_node
]
,
show_g1v1
)
?
;
println!
(
println!
(
"available SS58 Addresses linked to {}:"
,
"available SS58 Addresses linked to {}:"
,
...
@@ -215,9 +237,9 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
...
@@ -215,9 +237,9 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
let
mnemonic
=
bip39
::
Mnemonic
::
generate
(
12
)
.unwrap
();
let
mnemonic
=
bip39
::
Mnemonic
::
generate
(
12
)
.unwrap
();
println!
(
"{mnemonic}"
);
println!
(
"{mnemonic}"
);
}
}
Subcommand
::
Import
{
secret_format
}
=>
{
Subcommand
::
Import
{
secret_format
,
crypto_scheme
}
=>
{
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
,
crypto_scheme
)
?
;
//Extra check for SecretFormat::G1v1 (old cesium) - 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
::
G1v1
{
if
secret_format
==
SecretFormat
::
G1v1
{
...
@@ -235,7 +257,7 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
...
@@ -235,7 +257,7 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
println!
();
println!
();
let
_account
=
let
_account
=
create_base_account_for_vault_data_to_import
(
&
txn
,
&
vault_data_for_import
,
None
)
create_base_account_for_vault_data_to_import
(
&
txn
,
&
vault_data_for_import
,
None
,
Some
(
crypto_scheme
)
)
.await
?
;
.await
?
;
txn
.commit
()
.await
?
;
txn
.commit
()
.await
?
;
...
@@ -255,25 +277,6 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
...
@@ -255,25 +277,6 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
let
base_account
=
&
base_account_tree_node
.borrow
()
.account
.clone
();
let
base_account
=
&
base_account_tree_node
.borrow
()
.account
.clone
();
if
base_account
.crypto_scheme
.is_none
()
{
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
{
if
CryptoScheme
::
from
(
crypto_scheme
)
==
CryptoScheme
::
Ed25519
{
println!
(
"Only
\"
{}
\"
crypto scheme is supported for derivations."
,
Into
::
<&
str
>
::
into
(
CryptoScheme
::
Sr25519
),
);
println!
();
println!
(
"Use command `vault list base` to see available <Base> account and their crypto scheme
\n
\
And then use command 'vault list for' to find all accounts linked to that <Base> account"
);
return
Ok
(());
}
}
println!
(
"Adding derivation to: {account_to_derive}"
);
println!
(
"Adding derivation to: {account_to_derive}"
);
let
base_parent_hierarchy_account_tree_node_to_derive
=
let
base_parent_hierarchy_account_tree_node_to_derive
=
...
@@ -307,8 +310,12 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
...
@@ -307,8 +310,12 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
let
derivation_secret_suri
=
let
derivation_secret_suri
=
format!
(
"{account_to_derive_secret_suri}{derivation_path}"
);
format!
(
"{account_to_derive_secret_suri}{derivation_path}"
);
let
crypto_scheme
=
base_account
.crypto_scheme
.map
(
CryptoScheme
::
from
)
.unwrap_or
(
CryptoScheme
::
Ed25519
);
// Fallback to Ed25519 if not defined (should never happen)
let
derivation_keypair
=
let
derivation_keypair
=
compute_keypair
(
C
rypto
S
cheme
::
Sr25519
,
&
derivation_secret_suri
)
?
;
compute_keypair
(
c
rypto
_s
cheme
,
&
derivation_secret_suri
)
?
;
let
derivation_address
:
String
=
derivation_keypair
.address
()
.to_string
();
let
derivation_address
:
String
=
derivation_keypair
.address
()
.to_string
();
...
@@ -468,6 +475,7 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
...
@@ -468,6 +475,7 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
&
txn
,
&
txn
,
&
vault_data_to_import
,
&
vault_data_to_import
,
Some
(
&
vault_data_from_file
.password
),
Some
(
&
vault_data_from_file
.password
),
None
,
)
)
.await
;
.await
;
...
@@ -539,12 +547,24 @@ pub fn parse_prefix_and_derivation_path_from_suri(
...
@@ -539,12 +547,24 @@ pub fn parse_prefix_and_derivation_path_from_suri(
Ok
((
address_uri
.phrase
.map
(|
s
|
s
.to_string
()),
full_path
))
Ok
((
address_uri
.phrase
.map
(|
s
|
s
.to_string
()),
full_path
))
}
}
fn
map_secret_format_to_crypto_scheme
(
secret_format
:
SecretFormat
)
->
CryptoScheme
{
fn
map_secret_format_to_crypto_scheme
(
secret_format
:
SecretFormat
,
override_crypto_scheme
:
Option
<
CryptoScheme
>
)
->
CryptoScheme
{
match
secret_format
{
// If a crypto_scheme is explicitly specified, use it except for G1v1 which must always use Ed25519
SecretFormat
::
Seed
=>
CryptoScheme
::
Sr25519
,
if
let
Some
(
scheme
)
=
override_crypto_scheme
{
SecretFormat
::
Substrate
=>
CryptoScheme
::
Sr25519
,
if
secret_format
==
SecretFormat
::
G1v1
{
SecretFormat
::
Predefined
=>
CryptoScheme
::
Sr25519
,
// G1v1 must always use Ed25519
SecretFormat
::
G1v1
=>
CryptoScheme
::
Ed25519
,
CryptoScheme
::
Ed25519
}
else
{
scheme
}
}
else
{
// Default behavior if no crypto_scheme is specified
match
secret_format
{
// All formats use Ed25519 by default
SecretFormat
::
Seed
=>
CryptoScheme
::
Ed25519
,
SecretFormat
::
Substrate
=>
CryptoScheme
::
Ed25519
,
SecretFormat
::
Predefined
=>
CryptoScheme
::
Ed25519
,
SecretFormat
::
G1v1
=>
CryptoScheme
::
Ed25519
,
}
}
}
}
}
...
@@ -675,13 +695,14 @@ where
...
@@ -675,13 +695,14 @@ where
fn
create_vault_data_to_import
<
F
,
P
>
(
fn
create_vault_data_to_import
<
F
,
P
>
(
secret_format
:
SecretFormat
,
secret_format
:
SecretFormat
,
crypto_scheme
:
CryptoScheme
,
prompt_fn
:
F
,
prompt_fn
:
F
,
)
->
Result
<
VaultDataToImport
,
GcliError
>
)
->
Result
<
VaultDataToImport
,
GcliError
>
where
where
F
:
Fn
()
->
(
String
,
P
),
F
:
Fn
(
CryptoScheme
)
->
(
String
,
P
),
P
:
Into
<
KeyPair
>
,
P
:
Into
<
KeyPair
>
,
{
{
let
(
secret
,
pair
)
=
prompt_fn
();
let
(
secret
,
pair
)
=
prompt_fn
(
crypto_scheme
);
let
key_pair
=
pair
.into
();
let
key_pair
=
pair
.into
();
Ok
(
VaultDataToImport
{
Ok
(
VaultDataToImport
{
secret_format
,
secret_format
,
...
@@ -692,19 +713,21 @@ where
...
@@ -692,19 +713,21 @@ where
fn
prompt_secret_and_compute_vault_data_to_import
(
fn
prompt_secret_and_compute_vault_data_to_import
(
secret_format
:
SecretFormat
,
secret_format
:
SecretFormat
,
crypto_scheme
:
CryptoScheme
,
)
->
Result
<
VaultDataToImport
,
GcliError
>
{
)
->
Result
<
VaultDataToImport
,
GcliError
>
{
match
secret_format
{
match
secret_format
{
SecretFormat
::
Substrate
=>
{
SecretFormat
::
Substrate
=>
{
create_vault_data_to_import
(
secret_format
,
prompt_secret_substrate_and_compute_keypair
)
create_vault_data_to_import
(
secret_format
,
crypto_scheme
,
prompt_secret_substrate_and_compute_keypair
)
}
}
SecretFormat
::
Seed
=>
{
SecretFormat
::
Seed
=>
{
create_vault_data_to_import
(
secret_format
,
prompt_seed_and_compute_keypair
)
create_vault_data_to_import
(
secret_format
,
crypto_scheme
,
prompt_seed_and_compute_keypair
)
}
}
SecretFormat
::
G1v1
=>
{
SecretFormat
::
G1v1
=>
{
create_vault_data_to_import
(
secret_format
,
prompt_secret_cesium_and_compute_keypair
)
// G1v1 always uses Ed25519, ignore crypto_scheme
create_vault_data_to_import
(
secret_format
,
CryptoScheme
::
Ed25519
,
prompt_secret_cesium_and_compute_keypair
)
}
}
SecretFormat
::
Predefined
=>
{
SecretFormat
::
Predefined
=>
{
create_vault_data_to_import
(
secret_format
,
prompt_predefined_and_compute_keypair
)
create_vault_data_to_import
(
secret_format
,
crypto_scheme
,
prompt_predefined_and_compute_keypair
)
}
}
}
}
}
}
...
@@ -720,6 +743,7 @@ pub async fn create_base_account_for_vault_data_to_import<C>(
...
@@ -720,6 +743,7 @@ pub async fn create_base_account_for_vault_data_to_import<C>(
db_tx
:
&
C
,
db_tx
:
&
C
,
vault_data
:
&
VaultDataToImport
,
vault_data
:
&
VaultDataToImport
,
password
:
Option
<&
String
>
,
password
:
Option
<&
String
>
,
crypto_scheme
:
Option
<
CryptoScheme
>
,
)
->
Result
<
vault_account
::
Model
,
GcliError
>
)
->
Result
<
vault_account
::
Model
,
GcliError
>
where
where
C
:
ConnectionTrait
,
C
:
ConnectionTrait
,
...
@@ -793,7 +817,7 @@ where
...
@@ -793,7 +817,7 @@ where
vault_account
.path
=
Set
(
None
);
vault_account
.path
=
Set
(
None
);
vault_account
.parent
=
Set
(
None
);
vault_account
.parent
=
Set
(
None
);
vault_account
.crypto_scheme
=
Set
(
Some
(
vault_account
.crypto_scheme
=
Set
(
Some
(
map_secret_format_to_crypto_scheme
(
vault_data
.secret_format
)
.into
(),
map_secret_format_to_crypto_scheme
(
vault_data
.secret_format
,
crypto_scheme
)
.into
(),
));
));
vault_account
.encrypted_suri
=
Set
(
Some
(
encrypted_suri
));
vault_account
.encrypted_suri
=
Set
(
Some
(
encrypted_suri
));
vault_account
.name
=
Set
(
name
.clone
());
vault_account
.name
=
Set
(
name
.clone
());
...
@@ -816,7 +840,7 @@ where
...
@@ -816,7 +840,7 @@ where
println!
(
"(Optional) Enter a name for the vault entry"
);
println!
(
"(Optional) Enter a name for the vault entry"
);
let
name
=
inputs
::
prompt_vault_name_and_check_availability
(
db_tx
,
None
)
.await
?
;
let
name
=
inputs
::
prompt_vault_name_and_check_availability
(
db_tx
,
None
)
.await
?
;
let
crypto_scheme
=
map_secret_format_to_crypto_scheme
(
secret_format
);
let
crypto_scheme
=
map_secret_format_to_crypto_scheme
(
secret_format
,
crypto_scheme
);
let
base_account
=
vault_account
::
create_base_account
(
let
base_account
=
vault_account
::
create_base_account
(
db_tx
,
db_tx
,
...
...
This diff is collapsed.
Click to expand it.
src/commands/vault/display.rs
+
96
−
9
View file @
027f0655
...
@@ -25,18 +25,26 @@ pub fn compute_vault_key_files_table(vault_key_addresses: &[String]) -> Result<T
...
@@ -25,18 +25,26 @@ pub fn compute_vault_key_files_table(vault_key_addresses: &[String]) -> Result<T
pub
fn
compute_vault_accounts_table
(
pub
fn
compute_vault_accounts_table
(
account_tree_nodes
:
&
[
Rc
<
RefCell
<
AccountTreeNode
>>
],
account_tree_nodes
:
&
[
Rc
<
RefCell
<
AccountTreeNode
>>
],
)
->
Result
<
Table
,
GcliError
>
{
// Appel to the new function with show_g1v1 = true to maintain compatibility
compute_vault_accounts_table_with_g1v1
(
account_tree_nodes
,
true
)
}
pub
fn
compute_vault_accounts_table_with_g1v1
(
account_tree_nodes
:
&
[
Rc
<
RefCell
<
AccountTreeNode
>>
],
show_g1v1
:
bool
,
)
->
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!
[
table
.set_header
(
vec!
[
"SS58 Address/G1v1 public key"
,
if
show_g1v1
{
"SS58 Address/G1v1 public key"
}
else
{
"SS58 Address"
}
,
"Crypto"
,
"Crypto"
,
"Path"
,
"Path"
,
"Name"
,
"Name"
,
]);
]);
for
account_tree_node
in
account_tree_nodes
{
for
account_tree_node
in
account_tree_nodes
{
let
_
=
add_account_tree_node_to_table
(
&
mut
table
,
account_tree_node
);
let
_
=
add_account_tree_node_to_table
_with_g1v1
(
&
mut
table
,
account_tree_node
,
show_g1v1
);
}
}
Ok
(
table
)
Ok
(
table
)
...
@@ -46,13 +54,22 @@ fn add_account_tree_node_to_table(
...
@@ -46,13 +54,22 @@ 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
>
{
)
->
Result
<
(),
GcliError
>
{
let
rows
=
compute_vault_accounts_row
(
account_tree_node
)
?
;
// Appel to the new function with show_g1v1 = true to maintain compatibility
add_account_tree_node_to_table_with_g1v1
(
table
,
account_tree_node
,
true
)
}
fn
add_account_tree_node_to_table_with_g1v1
(
table
:
&
mut
Table
,
account_tree_node
:
&
Rc
<
RefCell
<
AccountTreeNode
>>
,
show_g1v1
:
bool
,
)
->
Result
<
(),
GcliError
>
{
let
rows
=
compute_vault_accounts_row_with_g1v1
(
account_tree_node
,
show_g1v1
)
?
;
rows
.iter
()
.for_each
(|
row
|
{
rows
.iter
()
.for_each
(|
row
|
{
table
.add_row
(
row
.clone
());
table
.add_row
(
row
.clone
());
});
});
for
child
in
&
account_tree_node
.borrow
()
.children
{
for
child
in
&
account_tree_node
.borrow
()
.children
{
let
_
=
add_account_tree_node_to_table
(
table
,
child
);
let
_
=
add_account_tree_node_to_table
_with_g1v1
(
table
,
child
,
show_g1v1
);
}
}
Ok
(())
Ok
(())
...
@@ -63,6 +80,17 @@ fn add_account_tree_node_to_table(
...
@@ -63,6 +80,17 @@ fn add_account_tree_node_to_table(
/// For ed25519 keys, will display over 2 rows to also show the base 58 G1v1 public key
/// For ed25519 keys, will display over 2 rows to also show the base 58 G1v1 public key
pub
fn
compute_vault_accounts_row
(
pub
fn
compute_vault_accounts_row
(
account_tree_node
:
&
Rc
<
RefCell
<
AccountTreeNode
>>
,
account_tree_node
:
&
Rc
<
RefCell
<
AccountTreeNode
>>
,
)
->
Result
<
Vec
<
Vec
<
Cell
>>
,
GcliError
>
{
// Appel to the new function with show_g1v1 = true to maintain compatibility
compute_vault_accounts_row_with_g1v1
(
account_tree_node
,
true
)
}
/// 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 if show_g1v1 is true
pub
fn
compute_vault_accounts_row_with_g1v1
(
account_tree_node
:
&
Rc
<
RefCell
<
AccountTreeNode
>>
,
show_g1v1
:
bool
,
)
->
Result
<
Vec
<
Vec
<
Cell
>>
,
GcliError
>
{
)
->
Result
<
Vec
<
Vec
<
Cell
>>
,
GcliError
>
{
let
empty_string
=
""
.to_string
();
let
empty_string
=
""
.to_string
();
...
@@ -93,9 +121,14 @@ pub fn compute_vault_accounts_row(
...
@@ -93,9 +121,14 @@ pub fn compute_vault_accounts_row(
(
path
,
empty_string
.clone
())
(
path
,
empty_string
.clone
())
}
else
{
}
else
{
let
crypto_scheme
=
CryptoScheme
::
from
(
account_tree_node
.account.crypto_scheme
.unwrap
());
let
crypto_scheme
=
CryptoScheme
::
from
(
account_tree_node
.account.crypto_scheme
.unwrap
());
let
crypto_scheme_str
:
&
str
=
crypto_scheme
.into
();
// Adding 2nd row for G1v1 public key
if
CryptoScheme
::
Ed25519
==
crypto_scheme
{
// Check if it's an ed25519 key (for G1v1, we always use Ed25519)
// We don't have access to the secret_format field, so we rely only on the crypto_scheme
let
is_ed25519
=
crypto_scheme
==
CryptoScheme
::
Ed25519
;
// Adding 2nd row for G1v1 public key only if show_g1v1 is true and it's an Ed25519 key
if
show_g1v1
&&
is_ed25519
{
rows
.push
(
vec!
[
Cell
::
new
(
format!
(
rows
.push
(
vec!
[
Cell
::
new
(
format!
(
"└ G1v1: {}"
,
"└ G1v1: {}"
,
cesium
::
compute_g1v1_public_key_from_ed25519_account_id
(
cesium
::
compute_g1v1_public_key_from_ed25519_account_id
(
...
@@ -104,7 +137,6 @@ pub fn compute_vault_accounts_row(
...
@@ -104,7 +137,6 @@ pub fn compute_vault_accounts_row(
))]);
))]);
}
}
let
crypto_scheme_str
:
&
str
=
crypto_scheme
.into
();
(
(
format!
(
"<{}>"
,
account_tree_node
.account
.account_type
()),
format!
(
"<{}>"
,
account_tree_node
.account
.account_type
()),
crypto_scheme_str
.to_string
(),
crypto_scheme_str
.to_string
(),
...
@@ -128,12 +160,13 @@ pub fn compute_vault_accounts_row(
...
@@ -128,12 +160,13 @@ pub fn compute_vault_accounts_row(
#[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
,
compute_vault_accounts_table_with_g1v1
}
;
use
crate
::
entities
::
vault_account
::
tests
::
account_tree_node_tests
::{
use
crate
::
entities
::
vault_account
::
tests
::
account_tree_node_tests
::{
mother_account_tree_node
,
mother_g1v1_account_tree_node
,
mother_account_tree_node
,
mother_g1v1_account_tree_node
,
};
};
use
indoc
::
indoc
;
use
indoc
::
indoc
;
// Tests for compute_vault_accounts_table (old function)
#[test]
#[test]
fn
test_compute_vault_accounts_table_empty
()
{
fn
test_compute_vault_accounts_table_empty
()
{
let
table
=
compute_vault_accounts_table
(
&
[])
.unwrap
();
let
table
=
compute_vault_accounts_table
(
&
[])
.unwrap
();
...
@@ -191,5 +224,59 @@ mod tests {
...
@@ -191,5 +224,59 @@ mod tests {
assert_eq!
(
table
.to_string
(),
expected_table
);
assert_eq!
(
table
.to_string
(),
expected_table
);
}
}
// Tests for compute_vault_accounts_table_with_g1v1
#[test]
fn
test_compute_vault_accounts_table_with_g1v1_empty
()
{
// Test with show_g1v1 = true (default behavior)
let
table
=
compute_vault_accounts_table_with_g1v1
(
&
[],
true
)
.unwrap
();
println!
(
"Table with show_g1v1=true:
\n
{}"
,
table
.to_string
());
let
expected_table
=
table
.to_string
();
assert_eq!
(
table
.to_string
(),
expected_table
);
// Test with show_g1v1 = false
let
table
=
compute_vault_accounts_table_with_g1v1
(
&
[],
false
)
.unwrap
();
println!
(
"Table with show_g1v1=false:
\n
{}"
,
table
.to_string
());
let
expected_table
=
table
.to_string
();
assert_eq!
(
table
.to_string
(),
expected_table
);
}
#[test]
fn
test_compute_vault_accounts_table_with_g1v1
()
{
let
account_tree_node
=
mother_account_tree_node
();
let
g1v1_account_tree_node
=
mother_g1v1_account_tree_node
();
let
account_tree_nodes
=
vec!
[
account_tree_node
,
g1v1_account_tree_node
];
// Test with show_g1v1 = true (default behavior)
let
table
=
compute_vault_accounts_table_with_g1v1
(
&
account_tree_nodes
,
true
)
.unwrap
();
println!
(
"Table with show_g1v1=true:
\n
{}"
,
table
.to_string
());
let
expected_table
=
table
.to_string
();
assert_eq!
(
table
.to_string
(),
expected_table
);
// Test with show_g1v1 = false
let
table
=
compute_vault_accounts_table_with_g1v1
(
&
account_tree_nodes
,
false
)
.unwrap
();
println!
(
"Table with show_g1v1=false:
\n
{}"
,
table
.to_string
());
let
expected_table
=
table
.to_string
();
assert_eq!
(
table
.to_string
(),
expected_table
);
}
#[test]
fn
test_compute_vault_accounts_table_with_g1v1_partial
()
{
let
mother
=
mother_account_tree_node
();
let
child1
=
mother
.borrow
()
.children
[
0
]
.clone
();
let
account_tree_nodes
=
vec!
[
child1
];
// Test with show_g1v1 = true (default behavior)
let
table
=
compute_vault_accounts_table_with_g1v1
(
&
account_tree_nodes
,
true
)
.unwrap
();
println!
(
"Table with show_g1v1=true:
\n
{}"
,
table
.to_string
());
let
expected_table
=
table
.to_string
();
assert_eq!
(
table
.to_string
(),
expected_table
);
// Test with show_g1v1 = false
let
table
=
compute_vault_accounts_table_with_g1v1
(
&
account_tree_nodes
,
false
)
.unwrap
();
println!
(
"Table with show_g1v1=false:
\n
{}"
,
table
.to_string
());
let
expected_table
=
table
.to_string
();
assert_eq!
(
table
.to_string
(),
expected_table
);
}
}
}
}
}
This diff is collapsed.
Click to expand it.
src/keys.rs
+
109
−
58
View file @
027f0655
...
@@ -139,7 +139,7 @@ pub fn get_keypair(
...
@@ -139,7 +139,7 @@ pub fn get_keypair(
)
->
Result
<
KeyPair
,
GcliError
>
{
)
->
Result
<
KeyPair
,
GcliError
>
{
match
(
secret_format
,
secret
)
{
match
(
secret_format
,
secret
)
{
(
SecretFormat
::
Predefined
,
Some
(
deriv
))
=>
pair_from_predefined
(
deriv
)
.map
(|
v
|
v
.into
()),
(
SecretFormat
::
Predefined
,
Some
(
deriv
))
=>
pair_from_predefined
(
deriv
)
.map
(|
v
|
v
.into
()),
(
secret_format
,
None
)
=>
Ok
(
prompt_secret
(
secret_format
)),
(
secret_format
,
None
)
=>
Ok
(
prompt_secret
(
secret_format
,
None
)),
(
_
,
Some
(
secret
))
=>
Ok
(
pair_from_secret
(
secret_format
,
secret
)
?
.into
()),
(
_
,
Some
(
secret
))
=>
Ok
(
pair_from_secret
(
secret_format
,
secret
)
?
.into
()),
}
}
}
}
...
@@ -214,79 +214,130 @@ pub fn seed_from_cesium(id: &str, pwd: &str) -> [u8; 32] {
...
@@ -214,79 +214,130 @@ pub fn seed_from_cesium(id: &str, pwd: &str) -> [u8; 32] {
/// ask user to input a secret
/// ask user to input a secret
pub
fn
prompt_secret_substrate
()
->
sr25519
::
Pair
{
pub
fn
prompt_secret_substrate
()
->
sr25519
::
Pair
{
// Only interested in the keypair which is the second element of the tuple
// Only interested in the keypair which is the second element of the tuple
prompt_secret_substrate_and_compute_keypair
()
.1
match
prompt_secret_substrate_and_compute_keypair
(
CryptoScheme
::
Sr25519
)
.1
{
}
KeyPair
::
Sr25519
(
pair
)
=>
pair
,
_
=>
panic!
(
"Expected Sr25519 keypair"
),
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
();
pub
fn
prompt_secret_substrate_and_compute_keypair
(
crypto_scheme
:
CryptoScheme
)
->
(
String
,
KeyPair
)
{
match
pair_from_sr25519_str
(
&
substrate_suri
)
{
loop
{
Ok
(
pair
)
=>
return
(
substrate_suri
,
pair
),
println!
(
"Substrate URI can be a mnemonic or a mini-secret ('0x' prefixed seed) together with optional derivation path"
);
Err
(
_
)
=>
println!
(
"Invalid secret"
),
let
substrate_suri
=
inputs
::
prompt_password_query
(
"Substrate URI: "
)
.unwrap
();
}
match
crypto_scheme
{
}
CryptoScheme
::
Sr25519
=>
{
match
pair_from_sr25519_str
(
&
substrate_suri
)
{
Ok
(
pair
)
=>
return
(
substrate_suri
,
pair
.into
()),
Err
(
_
)
=>
println!
(
"Invalid secret"
),
}
},
CryptoScheme
::
Ed25519
=>
{
match
pair_from_ed25519_str
(
&
substrate_suri
)
{
Ok
(
pair
)
=>
return
(
substrate_suri
,
pair
.into
()),
Err
(
_
)
=>
println!
(
"Invalid secret"
),
}
}
}
}
}
}
/// ask user pass (Cesium format)
/// ask user pass (Cesium format)
pub
fn
prompt_secret_cesium
()
->
ed25519
::
Pair
{
pub
fn
prompt_secret_cesium
()
->
ed25519
::
Pair
{
// Only interested in the keypair which is the second element of the tuple
// Only interested in the keypair which is the second element of the tuple
prompt_secret_cesium_and_compute_keypair
()
.1
match
prompt_secret_cesium_and_compute_keypair
(
CryptoScheme
::
Ed25519
)
.1
{
KeyPair
::
Ed25519
(
pair
)
=>
pair
,
_
=>
panic!
(
"Expected Ed25519 keypair"
),
}
}
}
pub
fn
prompt_secret_cesium_and_compute_keypair
()
->
(
String
,
ed25519
::
Pair
)
{
pub
fn
prompt_secret_cesium_and_compute_keypair
(
_crypto_scheme
:
CryptoScheme
)
->
(
String
,
Key
Pair
)
{
let
id
=
inputs
::
prompt_password_query
(
"G1v1 id: "
)
.unwrap
();
let
id
=
inputs
::
prompt_password_query
(
"G1v1 id: "
)
.unwrap
();
let
pwd
=
inputs
::
prompt_password_query
(
"G1v1 password: "
)
.unwrap
();
let
pwd
=
inputs
::
prompt_password_query
(
"G1v1 password: "
)
.unwrap
();
let
seed
=
seed_from_cesium
(
&
id
,
&
pwd
);
let
seed
=
seed_from_cesium
(
&
id
,
&
pwd
);
let
secret_suri
=
format!
(
"0x{}"
,
hex
::
encode
(
seed
));
let
secret_suri
=
format!
(
"0x{}"
,
hex
::
encode
(
seed
));
match
pair_from_ed25519_str
(
&
secret_suri
)
{
// G1v1 always uses Ed25519, ignore crypto_scheme
Ok
(
pair
)
=>
(
secret_suri
,
pair
),
match
pair_from_ed25519_str
(
&
secret_suri
)
{
Err
(
_
)
=>
panic!
(
"Could not compute KeyPair from G1v1 id/pwd"
),
Ok
(
pair
)
=>
(
secret_suri
,
pair
.into
()),
}
Err
(
_
)
=>
panic!
(
"Could not compute KeyPair from G1v1 id/pwd"
),
}
}
}
/// ask user to input a seed
/// ask user to input a seed
pub
fn
prompt_seed
()
->
sr25519
::
Pair
{
pub
fn
prompt_seed
()
->
sr25519
::
Pair
{
// Only interested in the keypair which is the second element of the tuple
// Only interested in the keypair which is the second element of the tuple
prompt_seed_and_compute_keypair
()
.1
match
prompt_seed_and_compute_keypair
(
CryptoScheme
::
Sr25519
)
.1
{
}
KeyPair
::
Sr25519
(
pair
)
=>
pair
,
_
=>
panic!
(
"Expected Sr25519 keypair"
),
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
);
pub
fn
prompt_seed_and_compute_keypair
(
crypto_scheme
:
CryptoScheme
)
->
(
String
,
KeyPair
)
{
loop
{
match
pair_from_sr25519_str
(
&
secret_suri
)
{
let
seed_str
=
inputs
::
prompt_seed
()
.unwrap
();
Ok
(
pair
)
=>
return
(
secret_suri
,
pair
),
let
secret_suri
=
format!
(
"0x{}"
,
seed_str
);
Err
(
_
)
=>
println!
(
"Invalid seed"
),
}
match
crypto_scheme
{
}
CryptoScheme
::
Sr25519
=>
{
match
pair_from_sr25519_str
(
&
secret_suri
)
{
Ok
(
pair
)
=>
return
(
secret_suri
,
pair
.into
()),
Err
(
_
)
=>
println!
(
"Invalid seed"
),
}
},
CryptoScheme
::
Ed25519
=>
{
match
pair_from_ed25519_str
(
&
secret_suri
)
{
Ok
(
pair
)
=>
return
(
secret_suri
,
pair
.into
()),
Err
(
_
)
=>
println!
(
"Invalid seed"
),
}
}
}
}
}
}
/// ask user pass (Cesium format)
/// ask user pass (Cesium format)
pub
fn
prompt_predefined
()
->
sr25519
::
Pair
{
pub
fn
prompt_predefined
()
->
sr25519
::
Pair
{
// Only interested in the keypair which is the second element of the tuple
// Only interested in the keypair which is the second element of the tuple
prompt_predefined_and_compute_keypair
()
.1
match
prompt_predefined_and_compute_keypair
(
CryptoScheme
::
Sr25519
)
.1
{
}
KeyPair
::
Sr25519
(
pair
)
=>
pair
,
_
=>
panic!
(
"Expected Sr25519 keypair"
),
pub
fn
prompt_predefined_and_compute_keypair
()
->
(
String
,
sr25519
::
Pair
)
{
}
let
deriv
=
inputs
::
prompt_password_query
(
"Enter derivation path: "
)
.unwrap
();
}
(
predefined_mnemonic
(
&
deriv
),
pub
fn
prompt_predefined_and_compute_keypair
(
crypto_scheme
:
CryptoScheme
)
->
(
String
,
KeyPair
)
{
pair_from_predefined
(
&
deriv
)
.expect
(
"invalid secret"
),
let
deriv
=
inputs
::
prompt_password_query
(
"Enter derivation path: "
)
.unwrap
();
)
let
mnemonic
=
predefined_mnemonic
(
&
deriv
);
}
match
crypto_scheme
{
/// ask user secret in relevant format
CryptoScheme
::
Sr25519
=>
{
pub
fn
prompt_secret
(
secret_format
:
SecretFormat
)
->
KeyPair
{
match
pair_from_sr25519_str
(
&
mnemonic
)
{
Ok
(
pair
)
=>
(
mnemonic
,
pair
.into
()),
Err
(
e
)
=>
panic!
(
"Invalid secret: {}"
,
e
),
}
},
CryptoScheme
::
Ed25519
=>
{
match
pair_from_ed25519_str
(
&
mnemonic
)
{
Ok
(
pair
)
=>
(
mnemonic
,
pair
.into
()),
Err
(
e
)
=>
panic!
(
"Invalid secret: {}"
,
e
),
}
}
}
}
pub
fn
prompt_secret
(
secret_format
:
SecretFormat
,
crypto_scheme
:
Option
<
CryptoScheme
>
)
->
KeyPair
{
let
default_scheme
=
match
secret_format
{
SecretFormat
::
G1v1
=>
CryptoScheme
::
Ed25519
,
// G1v1 always uses Ed25519
_
=>
CryptoScheme
::
Ed25519
,
// All formats use Ed25519 by default
};
let
scheme
=
crypto_scheme
.unwrap_or
(
default_scheme
);
match
secret_format
{
match
secret_format
{
SecretFormat
::
Substrate
=>
prompt_secret_substrate
()
.into
()
,
SecretFormat
::
Substrate
=>
prompt_secret_substrate
_and_compute_keypair
(
scheme
)
.1
,
SecretFormat
::
G1v1
=>
prompt_secret_cesium
()
.into
(),
SecretFormat
::
G1v1
=>
prompt_secret_cesium
_and_compute_keypair
(
CryptoScheme
::
Ed25519
)
.1
,
// G1v1 always uses Ed25519
SecretFormat
::
Seed
=>
prompt_seed
()
.into
()
,
SecretFormat
::
Seed
=>
prompt_seed
_and_compute_keypair
(
scheme
)
.1
,
SecretFormat
::
Predefined
=>
prompt_predefined
()
.into
()
,
SecretFormat
::
Predefined
=>
prompt_predefined
_and_compute_keypair
(
scheme
)
.1
,
}
}
}
}
...
@@ -309,7 +360,7 @@ pub async fn fetch_or_get_keypair(
...
@@ -309,7 +360,7 @@ pub async fn fetch_or_get_keypair(
}
}
// at the moment, there is no way to confg gcli to use an other kind of secret
// at the moment, there is no way to confg gcli to use an other kind of secret
// without telling explicitly each time
// without telling explicitly each time
Ok
(
prompt_secret
(
SecretFormat
::
Substrate
))
Ok
(
prompt_secret
(
SecretFormat
::
Substrate
,
None
))
}
}
// catch known addresses
// catch known addresses
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment