Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
7978ad0
Feat: Adding message_types.rs
ch4r10t33r Aug 31, 2025
dcf8b61
feat: parallelise key generation
ch4r10t33r Aug 31, 2025
6771ad2
feat: amended generate_keys function to create multiple keys based on…
ch4r10t33r Aug 31, 2025
9021822
fix: resolved udeps error
ch4r10t33r Aug 31, 2025
c3712de
feat: Added struct definitions for post quantum keystore
ch4r10t33r Sep 1, 2025
259be58
feat: Saving to QsKeystore
ch4r10t33r Sep 1, 2025
2737548
feat: Added passphrase parameter to account_manager command
ch4r10t33r Sep 2, 2025
d18c60c
Merge branch 'master' into account_manager
ch4r10t33r Sep 14, 2025
cdbaba7
fix: review comments
ch4r10t33r Sep 14, 2025
4ba922c
fix: fixed cargo fmt issue
ch4r10t33r Sep 14, 2025
1731b6d
fix: removed ascii art
ch4r10t33r Sep 17, 2025
dc65161
fix: fixed review comments
ch4r10t33r Sep 17, 2025
193b96c
Merge branch 'master' into account_manager
ch4r10t33r Sep 17, 2025
424a8ff
Fix: addressed review comments.
ch4r10t33r Sep 17, 2025
9660a93
Fix: review comment fixes
ch4r10t33r Sep 17, 2025
949091e
fix: linting errors
ch4r10t33r Sep 17, 2025
75a18f1
Fix: Update bin/ream/src/main.rs
ch4r10t33r Sep 17, 2025
5f4321b
Fix: Update crates/common/account_manager/src/keystore.rs
ch4r10t33r Sep 17, 2025
638959f
Fix: Update crates/common/account_manager/src/keystore.rs
ch4r10t33r Sep 17, 2025
4aa6fe9
Fix: review comment fixes
ch4r10t33r Sep 17, 2025
54b3a14
Merge branch 'account_manager' of https://github.com/ch4r10t33r/ream …
ch4r10t33r Sep 17, 2025
861c390
fix: fixed issues with build and removed redundant code
ch4r10t33r Sep 17, 2025
d43a7b4
Fix: review comment fixes
ch4r10t33r Sep 17, 2025
f12db7b
fix: Update bin/ream/src/cli/account_manager.rs
ch4r10t33r Sep 17, 2025
6da008b
Fix: Update bin/ream/src/cli/account_manager.rs
ch4r10t33r Sep 17, 2025
9ef714f
fix: Update crates/common/account_manager/src/lib.rs
ch4r10t33r Sep 17, 2025
7c03e53
Fix: Update crates/common/account_manager/src/message_types.rs
ch4r10t33r Sep 17, 2025
bfe8f5e
Fix: updated code to address comments
ch4r10t33r Sep 17, 2025
4c07a12
fix: review comment fixes
ch4r10t33r Sep 17, 2025
2269d17
fix: Removed parallel processing.
ch4r10t33r Sep 19, 2025
a2e260d
Fix: Removed rayon from Cargo.toml
ch4r10t33r Sep 19, 2025
7c307b9
Fix: addressed review comments
ch4r10t33r Sep 19, 2025
3f513b7
fix: renamed functions
ch4r10t33r Sep 19, 2025
eb82dd9
fix: changed the default keystore path
ch4r10t33r Sep 19, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 51 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ alloy-rpc-types-beacon = "1.0.8"
alloy-rpc-types-eth = "1.0.7"
anyhow = "1.0"
async-trait = "0.1.86"
bip32 = "0.5.3"
bip39 = "2.0.0"
chrono = { version = "0.4", features = ["serde"] }
clap = "4"
delay_map = "0.4.1"
directories = { version = "6.0.0" }
Expand All @@ -84,6 +85,7 @@ eventsource-client = "0.15.0"
futures = "0.3"
hashbrown = "0.15.3"
hashsig = { git = "https://github.com/b-wagn/hash-sig", rev = "287517a763edba7e518b0c1ee5beb868f26f1f66" }
hex = "0.4"
itertools = "0.14"
jsonwebtoken = "9.3.1"
kzg = { git = "https://github.com/grandinetech/rust-kzg" }
Expand All @@ -96,6 +98,7 @@ parking_lot = "0.12.3"
prometheus_exporter = "0.8.5"
rand = "0.9"
rand_chacha = "0.9"
rayon = "1.11.0"
redb = { version = "2.4.0" }
reqwest = { version = "0.12", features = ["json"] }
rstest = "0.25"
Expand All @@ -104,6 +107,7 @@ serde = { version = '1.0', features = ['derive', "rc"] }
serde_json = "1.0.139"
serde_yaml = "0.9"
sha2 = "0.10"
sha3 = "0.10.8"
snap = "1.1"
ssz_types = { git = "https://github.com/ReamLabs/ssz_types", branch = "removable-variable-list" }
tempdir = "0.3.7"
Expand All @@ -118,6 +122,7 @@ tree_hash = "0.10"
tree_hash_derive = "0.10"
unicode-normalization = "0.1.24"
url = "2.5"
uuid = "1.0"

# ream dependencies
ream-account-manager = { path = "crates/common/account_manager" }
Expand Down
6 changes: 6 additions & 0 deletions bin/ream/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,23 @@ path = "src/main.rs"
[dependencies]
alloy-primitives.workspace = true
anyhow.workspace = true
bip39.workspace = true
chrono.workspace = true
clap = { workspace = true, features = ["derive", "env"] }
discv5.workspace = true
hashbrown.workspace = true
prometheus_exporter.workspace = true
rand.workspace = true
rand_chacha.workspace = true
rayon.workspace = true
serde.workspace = true
serde_json.workspace = true
tokio.workspace = true
tracing = { workspace = true, features = ["log"] }
tracing-subscriber = { workspace = true, features = ["env-filter"] }
unicode-normalization.workspace = true
url.workspace = true
uuid.workspace = true

# ream dependencies
ream-account-manager.workspace = true
Expand Down
26 changes: 25 additions & 1 deletion bin/ream/src/cli/account_manager.rs
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;
Expand Down Expand Up @@ -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
#[arg(long, default_value = "./.keystore/")]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think ./.keystore/ should be a constant so that it can be referenced in main.rs also.

pub path: Option<String>,

/// Import existing keystore
#[arg(long)]
pub import_keystore: Option<String>,
}

impl Default for AccountManagerConfig {
Expand All @@ -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,
}
}
}
Expand All @@ -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."
);

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();
let phrase = mnemonic.words().collect::<Vec<_>>().join(" ");
info!("Generated new seed phrase (KEEP SAFELY): {}", phrase);
phrase
}
}
}
72 changes: 66 additions & 6 deletions bin/ream/src/main.rs
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::*;
use ream::cli::{
Cli, Commands,
account_manager::AccountManagerConfig,
Expand All @@ -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,
Expand Down Expand Up @@ -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";

Expand Down Expand Up @@ -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);
}

// 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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
message_types
MessageType::iter().collect()

We might inline this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

.par_iter()
.enumerate()
.for_each(|(index, &message_type)| {
let (_public_key, _private_key) = ream_account_manager::generate_keys(
&seed_phrase,
index as u32,
config.activation_epoch,
config.num_active_epochs,
);

// Create keystore file
let keystore = KeystoreFile {
version: 1,
id: Uuid::new_v4().to_string(),
description: format!("Ream validator keystore for {:?}", message_type),
seed_phrase: seed_phrase.clone(),
activation_epoch: config.activation_epoch,
num_active_epochs: config.num_active_epochs,
public_key: "Public key generated successfully".to_string(),
created: chrono::Utc::now().to_rfc3339(),
};

// Write keystore to file with enum name
let filename = format!("{:?}.json", message_type);
Copy link
Member

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.

let keystore_file_path = keystore_dir.join(filename);
let keystore_json =
serde_json::to_string_pretty(&keystore).expect("Failed to serialize keystore");

fs::write(&keystore_file_path, keystore_json).expect("Failed to write keystore file");

info!("Keystore written to: {:?}", keystore_file_path);
// info!("Public key for {:?}: {:?}", message_type, public_key.inner.to_string());
});
let duration = start_time.elapsed();
info!("Key generation complete, took {:?}", duration);

Expand Down
Loading
Loading