diff --git a/src/main.rs b/src/main.rs index cff2cb7d83d5fa070958c9471311b281069cdff1..b59a2819d57c4ca802167bb87876bbd96bdc725f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,14 @@ use ecomobicoin_jsonrpc::types::{Behavior, Block}; use ethereum_types::U64; +use ethers::prelude::rand::Rng; +use ethers::types::transaction::ecomobicoin_behavior::EcoMobiCoinBehaviorTransactionRequest; use ethers::{prelude::*, signers::coins_bip39::English}; use futures::executor::block_on; -use testnet_injector::utils::miner::get_miner_behavior; -use std::{process, time::Duration}; +use std::str::FromStr; use std::time::{SystemTime, UNIX_EPOCH}; -use testnet_injector::{ - utils::{mobility_data::*, txbx}, -}; +use std::{process, time::Duration}; +use testnet_injector::utils::miner::get_miner_behavior; +use testnet_injector::utils::{mobility_data::*, txbx}; use tracing::{debug, error, info, Level}; use ::clap::{Args, Parser, Subcommand}; @@ -39,10 +40,14 @@ struct SendParams { txs: u64, /// Number of behaviors to send bxs: u64, + // Index of account in HD wallet + hd_index: Option<u32>, + // Waiting period between each tx/bx + wait: Option<u64>, // Node RPC URL rpc_url: Option<String>, // Chain ID - chain_id: Option<u64> + chain_id: Option<u64>, } #[derive(Args)] @@ -54,7 +59,7 @@ struct SimulateBxFromCsv { // Node RPC URL rpc_url: Option<String>, // Chain ID - chain_id: Option<u64> + chain_id: Option<u64>, } #[derive(Args)] @@ -62,7 +67,7 @@ struct MineParams { // Node RPC URL rpc_url: Option<String>, // Chain ID - chain_id: Option<u64> + chain_id: Option<u64>, } async fn init() -> (u64, String) { @@ -111,51 +116,91 @@ async fn main() -> Result<(), anyhow::Error> { Some(Commands::Send(params)) => { info!("Sending {:?} tx and {:?} bx ...", params.txs, params.bxs); // Override env vars if specified in CLI - if params.rpc_url.clone().is_some(){ + if params.rpc_url.clone().is_some() { rpc_url = params.rpc_url.clone().unwrap(); } - if params.chain_id.clone().is_some(){ + if params.chain_id.clone().is_some() { chain_id = params.chain_id.clone().unwrap(); } let max = std::cmp::max(params.txs, params.bxs); - for i in 0..max { - let mnemonic = std::env::var("MNEMONIC").unwrap_or("abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about".to_string()); - let wallet = MnemonicBuilder::<English>::default() + let hd_index: u32 = if params.hd_index.is_some() { + params.hd_index.unwrap() + } else { + let mut rng = rand::thread_rng(); + rng.gen() + }; + + let mnemonic = std::env::var("MNEMONIC").unwrap_or("abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about".to_string()); + let wallet = MnemonicBuilder::<English>::default() .phrase(PathOrString::String(mnemonic.clone())) - .index(i as u32) + .index(hd_index) .unwrap() .build() .unwrap() .with_chain_id(chain_id); - let provider = Provider::<Http>::try_from(rpc_url.clone()).unwrap(); - let client = SignerMiddleware::new(provider.clone(), wallet.clone()); + let provider = Provider::<Http>::try_from(rpc_url.clone()).unwrap(); + let signer = SignerMiddleware::new(provider.clone(), wallet.clone()); + let addr = signer.clone().address(); + + let nonce_manager = signer.nonce_manager(addr); + + for i in 0..max { + //FIXME nonce doesn't update locally + let curr_nonce = nonce_manager + .get_transaction_count(addr, None) + .await + .unwrap() + .as_u64(); + + info!("Signer: 0x{:02x}, nonce: {:?}", addr, curr_nonce); if i < params.bxs { - let bx_hash = txbx::send_default_bx( - client.clone(), - chain_id, - ).await; + let now = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap() + .as_secs(); + let data = Bytes::from_str("0x015d8eb90000000000000000000000000000000000000000000000000000000000878c1c00000000000000000000000000000000000000000000000000000000644662bc0000000000000000000000000000000000000000000000000000001ee24fba17b7e19cc10812911dfa8a438e0a81a9933f843aa5b528899b8d9e221b649ae0df00000000000000000000000000000000000000000000000000000000000000060000000000000000000000007431310e026b69bfc676c0013e12a1a11411eec9000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240").unwrap(); + + let bx: EcoMobiCoinBehaviorTransactionRequest = + EcoMobiCoinBehaviorTransactionRequest::new( + TransactionRequest::new() + // .to(signer.address()) + .value(U256::from(210000)) + .chain_id(chain_id) + .data(data.0.clone()), + Some(U64::from(now)), + ); + + let bx_hash = nonce_manager.send_transaction(bx, None).await; info!("Sent default bx {:?}", bx_hash); } if i < params.txs { - let tx_hash = txbx::send_default_tx( - client.clone(), - chain_id, - ).await; + let tx = TransactionRequest::new() + .to(Address::random()) + .value(U256::from(210000)) + .chain_id(chain_id); + let tx_hash = nonce_manager.send_transaction(tx, None).await; info!("Sent default tx {:?}", tx_hash); } + if params.wait.is_some() { + tokio::time::sleep(Duration::from_secs(params.wait.unwrap())).await; + } } } Some(Commands::SimulateBxFromCsv(params)) => { - info!("Simulating file {:?} for a total time of {:?} secs",params.file.clone(), params.total_simulation_duration.clone()); + info!( + "Simulating file {:?} for a total time of {:?} secs", + params.file.clone(), + params.total_simulation_duration.clone() + ); // Override env vars if specified in CLI - if params.rpc_url.clone().is_some(){ + if params.rpc_url.clone().is_some() { rpc_url = params.rpc_url.clone().unwrap(); } - if params.chain_id.clone().is_some(){ + if params.chain_id.clone().is_some() { chain_id = params.chain_id.clone().unwrap(); } // println!("Processing {:?}", params.file); @@ -188,11 +233,16 @@ async fn main() -> Result<(), anyhow::Error> { Duration::from_millis(dataset_max_relative_time as u64) ); - let mobility_records_times: Vec<Duration> = mobility_records.iter().map(|r| compute_stretched_relative_start_time( - r.relative_start_time as u64, - total_simulation_duration, - dataset_max_relative_time as u64, - )).collect(); + let mobility_records_times: Vec<Duration> = mobility_records + .iter() + .map(|r| { + compute_stretched_relative_start_time( + r.relative_start_time as u64, + total_simulation_duration, + dataset_max_relative_time as u64, + ) + }) + .collect(); // ---------------- // Sending queue @@ -200,7 +250,10 @@ async fn main() -> Result<(), anyhow::Error> { let mut handles = Vec::with_capacity(mobility_records.len()); for i in 0..mobility_records.len() { - let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs(); + let now = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs(); let simulation_behavior = mobility_records[i].clone(); let relative_start_duration = mobility_records_times[i].clone(); let rpc_url = rpc_url.clone(); @@ -252,32 +305,38 @@ async fn main() -> Result<(), anyhow::Error> { for handle in handles { block_on(handle).unwrap(); } - }, + } Some(Commands::Mine(params)) => { - // Override env vars if specified in CLI - if params.rpc_url.clone().is_some(){ + if params.rpc_url.clone().is_some() { rpc_url = params.rpc_url.clone().unwrap(); } - if params.chain_id.clone().is_some(){ + if params.chain_id.clone().is_some() { chain_id = params.chain_id.clone().unwrap(); } // Wallet is derived from mnemomic with user_id to ensure each user have the same wallet for the simulation. - let miner_signing_key = std::env::var("MINER_SIGNING_KEY").expect("Must specify a miner private key"); + let miner_signing_key = + std::env::var("MINER_SIGNING_KEY").expect("Must specify a miner private key"); let wallet: LocalWallet = miner_signing_key.parse::<LocalWallet>().unwrap(); let miner_addr = wallet.address(); - info!("Mining with 0x{:02x} ...",miner_addr); + info!("Mining with 0x{:02x} ...", miner_addr); let behavior = get_miner_behavior(wallet, chain_id, miner_addr); // SEND IT let provider = Provider::<Http>::try_from(rpc_url.clone()).unwrap(); - debug!("Miner behavior: {:?}",serde_json::to_string(&behavior.clone())); - let block = provider.request::<[Behavior;1], Block>("emc_mine", [behavior]).await.unwrap(); + debug!( + "Miner behavior: {:?}", + serde_json::to_string(&behavior.clone()) + ); + let block = provider + .request::<[Behavior; 1], Block>("emc_mine", [behavior]) + .await + .unwrap(); debug!("Mining response: {:?}", block); info!("Mined block {:?}", block.number.unwrap()) - }, + } None => {} } Ok(())