From dae79860bd6f7d839a1263959be107e2261f12fd Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Tue, 21 Oct 2025 16:25:38 -0300 Subject: [PATCH] wip --- wallet/Cargo.toml | 4 ++ wallet/src/cli/mod.rs | 1 + wallet/src/cli/stress_tests.rs | 118 +++++++++++++++++++++++++++++++++ wallet/src/lib.rs | 8 ++- 4 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 wallet/src/cli/stress_tests.rs diff --git a/wallet/Cargo.toml b/wallet/Cargo.toml index 48d79e2f..d75ef167 100644 --- a/wallet/Cargo.toml +++ b/wallet/Cargo.toml @@ -27,3 +27,7 @@ path = "../nssa" [dependencies.common] path = "../common" + +[dependencies.sequencer_core] +path = "../sequencer_core" + diff --git a/wallet/src/cli/mod.rs b/wallet/src/cli/mod.rs index 3aa1b7f7..12b63cbe 100644 --- a/wallet/src/cli/mod.rs +++ b/wallet/src/cli/mod.rs @@ -7,6 +7,7 @@ pub mod chain; pub mod native_token_transfer_program; pub mod pinata_program; pub mod token_program; +pub mod stress_tests; pub(crate) trait WalletSubcommand { async fn handle_subcommand(self, wallet_core: &mut WalletCore) diff --git a/wallet/src/cli/stress_tests.rs b/wallet/src/cli/stress_tests.rs new file mode 100644 index 00000000..f55ea406 --- /dev/null +++ b/wallet/src/cli/stress_tests.rs @@ -0,0 +1,118 @@ +use std::fs::File; + +use anyhow::Result; +use clap::Subcommand; +use nssa::{ + Address, PrivateKey, PublicKey, PublicTransaction, program::Program, + public_transaction::Message, +}; +use sequencer_core::config::{AccountInitialData, SequencerConfig}; + +use crate::{SubcommandReturnValue, WalletCore, cli::WalletSubcommand}; + +///Represents generic chain CLI subcommand +#[derive(Subcommand, Debug, Clone)] +pub enum StressTestSubcommand { + Run, + GenerateConfig, +} + +impl WalletSubcommand for StressTestSubcommand { + async fn handle_subcommand( + self, + wallet_core: &mut WalletCore, + ) -> Result { + match self { + StressTestSubcommand::Run => { + println!("Stress test begin"); + let txs = build_txs(); + for (i, tx) in txs.into_iter().enumerate() { + wallet_core.sequencer_client.send_tx_public(tx).await; + println!("Sent tx: {}", i); + } + + println!("Stress test end"); + } + StressTestSubcommand::GenerateConfig => { + println!("Generating config"); + let config = generate_stress_test_config(); + let file = File::create("config.json")?; // crea/trunca el archivo + serde_json::to_writer_pretty(file, &config).unwrap(); // escribe JSON formateado + println!("Done"); + } + } + Ok(SubcommandReturnValue::Empty) + } +} + +fn generate_stress_test_config() -> SequencerConfig { + // Create public public keypairs + let public_keypairs = generate_public_keypairs(); + let initial_public_accounts = public_keypairs + .iter() + .map(|(_, addr)| AccountInitialData { + addr: addr.to_string(), + balance: 10000, + }) + .collect(); + + SequencerConfig { + home: ".".into(), + override_rust_log: None, + genesis_id: 1, + is_genesis_random: true, + max_num_tx_in_block: 20, + block_create_timeout_millis: 10000, + port: 3040, + initial_accounts: initial_public_accounts, + initial_commitments: vec![], + signing_key: [37; 32], + } +} + +pub fn generate_public_keypairs() -> Vec<(PrivateKey, Address)> { + const N_PUBLIC_ACCOUNTS_WITH_BALANCE: usize = 100000; + + (1..(N_PUBLIC_ACCOUNTS_WITH_BALANCE + 1)) + .map(|i| { + let mut private_key_bytes = [0u8; 32]; + private_key_bytes[..8].copy_from_slice(&i.to_le_bytes()); + let private_key = PrivateKey::try_new(private_key_bytes).unwrap(); + let public_key = PublicKey::new_from_private_key(&private_key); + let address = Address::from(&public_key); + (private_key, address) + }) + .collect::>() +} + +pub fn build_txs() -> Vec { + // Create public public keypairs + let public_keypairs = generate_public_keypairs(); + + // Create random private keychains + // TODO + + // Create valid public transactions + let program = Program::authenticated_transfer_program(); + let public_txs: Vec = public_keypairs + .windows(2) + .map(|pair| { + let amount: u128 = 1; + let message = Message::try_new( + program.id(), + [pair[0].1, pair[1].1].to_vec(), + [0u128].to_vec(), + amount, + ) + .unwrap(); + let witness_set = + nssa::public_transaction::WitnessSet::for_message(&message, &[&pair[0].0]); + PublicTransaction::new(message, witness_set) + }) + .collect(); + + public_txs + + // Create valid private transactions + // TODO +} diff --git a/wallet/src/lib.rs b/wallet/src/lib.rs index 5adfa39c..70048aa6 100644 --- a/wallet/src/lib.rs +++ b/wallet/src/lib.rs @@ -23,7 +23,7 @@ use tokio::io::AsyncWriteExt; use crate::cli::{ WalletSubcommand, account::AccountSubcommand, chain::ChainSubcommand, native_token_transfer_program::NativeTokenTransferProgramSubcommand, - pinata_program::PinataProgramSubcommand, + pinata_program::PinataProgramSubcommand, stress_tests::StressTestSubcommand, }; use crate::{ cli::token_program::TokenProgramSubcommand, @@ -209,6 +209,9 @@ pub enum Command { // Check the wallet can connect to the node and builtin local programs // match the remote versions CheckHealth {}, + + #[command(subcommand)] + StressTest(StressTestSubcommand), } ///To execute commands, env var NSSA_WALLET_HOME_DIR must be set into directory with config @@ -306,6 +309,9 @@ pub async fn execute_subcommand(command: Command) -> Result { token_subcommand.handle_subcommand(&mut wallet_core).await? } + Command::StressTest(stress_test_subcommand) => { + stress_test_subcommand.handle_subcommand(&mut wallet_core).await? + } }; Ok(subcommand_ret)