From 52f37e1e07c4604f1fa4bb99fb9b47cdbb7bada7 Mon Sep 17 00:00:00 2001
From: Anthony Graignic <anthony.graignic@uca.fr>
Date: Thu, 11 Jan 2024 10:47:35 +0100
Subject: [PATCH] Update sending tx from csv file

Rename to send for clarity
Add rpc call to ots_accounts
---
 src/main.rs | 83 ++++++++++++++++++++++++++++-------------------------
 1 file changed, 44 insertions(+), 39 deletions(-)

diff --git a/src/main.rs b/src/main.rs
index a6597be..60631a5 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,9 +1,9 @@
 use ecomobicoin_jsonrpc::types::{Behavior, Block};
 use ethereum_types::U64;
-use ethers::{prelude::*, signers::coins_bip39::English};
+use ethers::{prelude::{*, rand::Rng}, signers::coins_bip39::English};
 use futures::executor::block_on;
 use testnet_injector::utils::miner::get_miner_behavior;
-use std::{process, time::Duration, ops::Div};
+use std::{process, time::Duration};
 use testnet_injector::{
     utils::{mobility_data::*, txbx},
 };
@@ -28,8 +28,8 @@ enum Commands {
     Send(SendParams),
     /// Simulate behaviors from csv dataset and send them to the node
     SimulateBxFromCsv(SimulateBxFromCsv),
-    /// Simulate transactions from derived accounts from csv dataset and send them to the node
-    SimulateTxFromCsv(SimulateTxFromCsv),
+    /// Send transactions from derived accounts from csv dataset
+    SendTxFromCsv(SendTxFromCsv),
     /// Mine a block
     Mine(MineParams),
 }
@@ -58,13 +58,13 @@ struct SimulateBxFromCsv {
     chain_id: Option<u64>
 }
 #[derive(Args)]
-struct SimulateTxFromCsv {
+struct SendTxFromCsv {
     /// Path to CSV file
     file: String,
     /// Block time in seconds, will send 1 tx every block
     block_time: u64,
-    /// Send tx to random addresses
-    random_addr: Option<bool>,
+    /// Send tx to unknown addresses
+    unknown_addr: Option<bool>,
     // Node RPC URL
     rpc_url: Option<String>,
     // Chain ID
@@ -265,8 +265,8 @@ async fn main() -> Result<(), anyhow::Error> {
                 block_on(handle).unwrap();
             }
         },
-        Some(Commands::SimulateTxFromCsv(params)) => {
-            info!("Simulating tx from {:?} every {:?} secs",params.file.clone(), params.block_time.clone());
+        Some(Commands::SendTxFromCsv(params)) => {
+            info!("Sending tx from {:?} every {:?} secs with unknown address={:?}", params.file, params.block_time, params.unknown_addr);
             // Override env vars if specified in CLI
             if params.rpc_url.clone().is_some(){
                 rpc_url = params.rpc_url.clone().unwrap();
@@ -283,13 +283,7 @@ async fn main() -> Result<(), anyhow::Error> {
 
             let mobility_records = generate_behaviors_from_records(records.clone());
 
-            let dataset_max_relative_time = mobility_records
-                .iter()
-                .max_by(|x, y| x.relative_start_time.cmp(&y.relative_start_time))
-                .unwrap()
-                .relative_start_time;
-
-            let is_addr_random = params.random_addr.unwrap_or(false);
+            let is_addr_unknown = params.unknown_addr.unwrap_or(false);
             let block_time = if params.block_time > 0 {
                 params.block_time
             } else {
@@ -297,10 +291,8 @@ async fn main() -> Result<(), anyhow::Error> {
             };
 
             info!(
-                "Simulation of {:?} records every {:?} secs with random addr {:?}",
-                mobility_records.len(),
-                block_time,
-                is_addr_random
+                "Simulation of {:?} records",
+                mobility_records.len()
             );
 
             // ----------------
@@ -322,46 +314,59 @@ async fn main() -> Result<(), anyhow::Error> {
 
                             // Wallet is derived from mnemomic with user_id to ensure each user have the same wallet for the simulation.
                             let mnemonic = std::env::var("MNEMONIC").unwrap_or("abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about".to_string());
+                            let user_id = simulation_behavior.mobility_record.user_id as u32;
                             let wallet = MnemonicBuilder::<English>::default()
                                 .phrase(PathOrString::String(mnemonic.clone()))
-                                .index(simulation_behavior.mobility_record.user_id as u32)
+                                .index(user_id)
                                 .unwrap()
                                 .build()
                                 .unwrap()
                                 .with_chain_id(chain_id);
 
-                            // Get random addr
-                            //TODO call rpc
-                            let to_addr = if is_addr_random{ Address::random()} else {
-                                Address::zero()
-                            };
+                            let signer = SignerMiddleware::new(provider.clone(), wallet.clone());
+                            let addr = signer.clone().address();
+                            let nonce_manager = signer.nonce_manager(addr);
 
-                            let from_balance = provider.get_balance(wallet.address(),None).await.unwrap();
+                            // List of active accounts from node
+                            let accounts = provider.request::<[Behavior;0], Vec<(Address, U256)>>("ots_getAccountWithBalance", []).await.unwrap();
 
-                            if from_balance.is_zero() {
-                                warn!("Attempted to send a tx from an empty account {:?}, user_id {:?}", wallet.address(),simulation_behavior.mobility_record.user_id);
+                            let to_addr = if is_addr_unknown { 
+                                Address::random()
                             } else {
-                                // Temporary value
-                                let value = from_balance.div(2) + 1 ;
+                                let mut rng = rand::thread_rng();
+                                let rnd = rng.gen_range(0..accounts.len());
+                                accounts[rnd].0
+                            };
+
+                            let from_balance = provider.get_balance(wallet.address(),None).await.unwrap();
 
+                            // Temporary value close to min
+                            let tx_value= U256::from(210000);
+                            
+                            if from_balance.gt(&tx_value) {
+                                let tx = TransactionRequest::new()
+                                .to(to_addr)
+                                .value(tx_value)
+                                .chain_id(chain_id);
+                            
                                 info!(
                                     "Sending tx from: {:?} (user_id: {:?}),to {:?} value {:?} ",
-                                    wallet.address(),
-                                    simulation_behavior.mobility_record.user_id,
+                                    addr,
+                                    user_id,
                                     to_addr,
-                                    value
+                                    tx_value
                                 );
-
-                                let client = SignerMiddleware::new(provider.clone(), wallet.clone());
-
-                                let tx_hash = txbx::send_transaction(client.clone(), chain_id, to_addr, value).await;
+                        
+                                let tx_hash = nonce_manager.send_transaction(tx, None).await;
                                 info!("Sent tx {:?}", tx_hash);
+                            } else {
+                                warn!("Didn't send tx for {:?}, balance too low ({:?}<210000)", addr, from_balance);
                             }
                         }
                         }))
             }
 
-            info!("Scheduling done, waiting for bx & tx threads...");
+            info!("Scheduling done, waiting for tx threads...");
 
             // Wait for all of them to complete.
             for handle in handles {
-- 
GitLab