-
Notifications
You must be signed in to change notification settings - Fork 71
feat: Initial version of a key generation utility for ream #757
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
7978ad0
dcf8b61
6771ad2
9021822
c3712de
259be58
2737548
d18c60c
cdbaba7
4ba922c
1731b6d
dc65161
193b96c
424a8ff
9660a93
949091e
75a18f1
5f4321b
638959f
4aa6fe9
54b3a14
861c390
d43a7b4
f12db7b
6da008b
9ef714f
7c03e53
bfe8f5e
4c07a12
2269d17
a2e260d
7c307b9
3f513b7
eb82dd9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,7 @@ | ||
| use anyhow::ensure; | ||
| use bip39::Mnemonic; | ||
| use clap::Parser; | ||
| use tracing::info; | ||
|
|
||
| const MIN_CHUNK_SIZE: u64 = 4; | ||
| const MIN_LIFETIME: u64 = 18; | ||
|
|
@@ -31,6 +33,14 @@ pub struct AccountManagerConfig { | |
| /// Number of active epochs | ||
| #[arg(long, default_value_t = DEFAULT_NUM_ACTIVE_EPOCHS)] | ||
| pub num_active_epochs: usize, | ||
|
|
||
| /// Path for keystore file | ||
ch4r10t33r marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| #[arg(long, default_value = "./.keystore/")] | ||
|
||
| pub path: Option<String>, | ||
ch4r10t33r marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| /// Import existing keystore | ||
| #[arg(long)] | ||
| pub import_keystore: Option<String>, | ||
ch4r10t33r marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| impl Default for AccountManagerConfig { | ||
|
|
@@ -42,6 +52,8 @@ impl Default for AccountManagerConfig { | |
| seed_phrase: None, | ||
| activation_epoch: DEFAULT_ACTIVATION_EPOCH, | ||
| num_active_epochs: DEFAULT_NUM_ACTIVE_EPOCHS, | ||
| path: Some("./.keystore/".to_string()), | ||
| import_keystore: None, | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -60,14 +72,26 @@ impl AccountManagerConfig { | |
| self.lifetime >= MIN_LIFETIME, | ||
| "Lifetime must be at least {MIN_LIFETIME}" | ||
| ); | ||
|
|
||
| // Ensure that if import-keystore is provided, seed-phrase is not provided | ||
| ensure!( | ||
| !(self.import_keystore.is_some() && self.seed_phrase.is_some()), | ||
| "Cannot provide both --seed-phrase and --import-keystore. Use one or the other." | ||
| ); | ||
ch4r10t33r marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| Ok(()) | ||
| } | ||
|
|
||
| pub fn get_seed_phrase(&self) -> String { | ||
| if let Some(phrase) = &self.seed_phrase { | ||
| phrase.clone() | ||
| } else { | ||
| "default_seed_phrase".to_string() | ||
| // Generate a new BIP39 mnemonic with 24 words (256 bits of entropy) | ||
| let entropy: [u8; 32] = rand::random(); | ||
| let mnemonic = Mnemonic::from_entropy_in(bip39::Language::English, &entropy).unwrap(); | ||
syjn99 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| let phrase = mnemonic.words().collect::<Vec<_>>().join(" "); | ||
| info!("Generated new seed phrase (KEEP SAFELY): {}", phrase); | ||
| phrase | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,12 +1,14 @@ | ||||||
| use std::{ | ||||||
| env, | ||||||
| env, fs, | ||||||
| net::SocketAddr, | ||||||
| path::Path, | ||||||
| process, | ||||||
| sync::Arc, | ||||||
| time::{Duration, SystemTime, UNIX_EPOCH}, | ||||||
| }; | ||||||
|
|
||||||
| use clap::Parser; | ||||||
| use rayon::prelude::*; | ||||||
ch4r10t33r marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
| use ream::cli::{ | ||||||
| Cli, Commands, | ||||||
| account_manager::AccountManagerConfig, | ||||||
|
|
@@ -16,6 +18,7 @@ use ream::cli::{ | |||||
| validator_node::ValidatorNodeConfig, | ||||||
| voluntary_exit::VoluntaryExitConfig, | ||||||
| }; | ||||||
| use ream_account_manager::message_types::MessageType; | ||||||
| use ream_api_types_beacon::id::{ID, ValidatorID}; | ||||||
| use ream_chain_lean::{ | ||||||
| genesis as lean_genesis, lean_chain::LeanChain, messages::LeanChainServiceMessage, | ||||||
|
|
@@ -53,9 +56,24 @@ use ream_validator_beacon::{ | |||||
| use ream_validator_lean::{ | ||||||
| registry::load_validator_registry, service::ValidatorService as LeanValidatorService, | ||||||
| }; | ||||||
| use serde::{Deserialize, Serialize}; | ||||||
| use tokio::{sync::mpsc, time::Instant}; | ||||||
| use tracing::{error, info}; | ||||||
| use tracing_subscriber::EnvFilter; | ||||||
| use uuid::Uuid; | ||||||
|
|
||||||
| // Keystore structure for storing generated keys | ||||||
| #[derive(Serialize, Deserialize, Debug)] | ||||||
| struct KeystoreFile { | ||||||
| version: u32, | ||||||
| id: String, | ||||||
| description: String, | ||||||
| seed_phrase: String, | ||||||
| activation_epoch: usize, | ||||||
| num_active_epochs: usize, | ||||||
| public_key: String, | ||||||
| created: String, | ||||||
| } | ||||||
|
|
||||||
| pub const APP_NAME: &str = "ream"; | ||||||
|
|
||||||
|
|
@@ -380,13 +398,55 @@ pub async fn run_account_manager(mut config: AccountManagerConfig) { | |||||
|
|
||||||
| let seed_phrase = config.get_seed_phrase(); | ||||||
|
|
||||||
| // Create keystore directory if it doesn't exist | ||||||
| let default_path = "./.keystore/".to_string(); | ||||||
| let keystore_path = config.path.as_ref().unwrap_or(&default_path); | ||||||
| let keystore_dir = Path::new(keystore_path); | ||||||
| if !keystore_dir.exists() { | ||||||
| fs::create_dir_all(keystore_dir).expect("Failed to create keystore directory"); | ||||||
| info!("Created keystore directory: {:?}", keystore_dir); | ||||||
ch4r10t33r marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
| } | ||||||
|
|
||||||
| // Measure key generation time | ||||||
| let start_time = Instant::now(); | ||||||
| let (_public_key, _private_key) = ream_account_manager::generate_keys( | ||||||
| &seed_phrase, | ||||||
| config.activation_epoch, | ||||||
| config.num_active_epochs, | ||||||
| ); | ||||||
|
|
||||||
| // Parallelize key generation for each message type | ||||||
| let message_types: Vec<MessageType> = MessageType::iter().collect(); | ||||||
|
|
||||||
| message_types | ||||||
|
||||||
| message_types | |
| MessageType::iter().collect() |
We might inline this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
ch4r10t33r marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can just implement std::fmt::Display trait to MessageType so that not using Debug trait here.
Uh oh!
There was an error while loading. Please reload this page.