From b4b4020e819a580f2fcc9c4266cab1d93876c3b7 Mon Sep 17 00:00:00 2001 From: Icarus131 Date: Thu, 16 Jan 2025 20:48:34 +0530 Subject: [PATCH 01/13] feat: first draft ggp fund e2e test --- .../movement-client/src/bin/e2e/ggp_fund.rs | 106 ++++++++++++++++++ .../process-compose.test-ggp-gas-fund-fee.yml | 13 +++ 2 files changed, 119 insertions(+) create mode 100644 networks/movement/movement-client/src/bin/e2e/ggp_fund.rs create mode 100644 process-compose/movement-full-node/process-compose.test-ggp-gas-fund-fee.yml diff --git a/networks/movement/movement-client/src/bin/e2e/ggp_fund.rs b/networks/movement/movement-client/src/bin/e2e/ggp_fund.rs new file mode 100644 index 000000000..2e813806b --- /dev/null +++ b/networks/movement/movement-client/src/bin/e2e/ggp_fund.rs @@ -0,0 +1,106 @@ +use anyhow::Context; +use aptos_sdk::rest_client::{ + aptos_api_types::{Address, EntryFunctionId, IdentifierWrapper, MoveModuleId, ViewRequest}, + Response, +}; +use aptos_sdk::types::account_address::AccountAddress; +use movement_client::{ + coin_client::CoinClient, + rest_client::{Client, FaucetClient}, + types::LocalAccount, +}; +use once_cell::sync::Lazy; +use std::str::FromStr; +use tracing; +use url::Url; + +#[tokio::main] +async fn main() -> Result<(), anyhow::Error> { + let rest_client = Client::new(NODE_URL.clone()); + let faucet_client = FaucetClient::new(FAUCET_URL.clone(), NODE_URL.clone()); + let coin_client = CoinClient::new(&rest_client); + + // Create a gas payer account (to fund the pool) and beneficiary account + let mut gas_payer = LocalAccount::generate(&mut rand::rngs::OsRng); + let beneficiary = LocalAccount::generate(&mut rand::rngs::OsRng); + + tracing::info!("Created test accounts"); + tracing::debug!( + "Gas payer address: {}, Beneficiary address: {}", + gas_payer.address(), + beneficiary.address() + ); + + // Fund the gas payer account + faucet_client + .fund(gas_payer.address(), 1_000_000) + .await + .context("Failed to fund gas payer account")?; + + // Create and register the beneficiary account for APT + faucet_client + .create_account(beneficiary.address()) + .await + .context("Failed to create beneficiary account")?; + + // Get the governed gas pool address + let view_req = ViewRequest { + function: EntryFunctionId { + module: MoveModuleId { + address: Address::from_str("0x1").unwrap(), + name: IdentifierWrapper::from_str("governed_gas_pool").unwrap(), + }, + name: IdentifierWrapper::from_str("governed_gas_pool_address").unwrap(), + }, + type_arguments: vec![], + arguments: vec![], + }; + + let view_res: Response> = rest_client + .view(&view_req, None) + .await + .context("Failed to get governed gas pool address")?; + + let inner_value = serde_json::to_value(view_res.inner()) + .context("Failed to convert response inner to serde_json::Value")?; + + let ggp_address: Vec = + serde_json::from_value(inner_value).context("Failed to deserialize AddressResponse")?; + + let ggp_account_address = + AccountAddress::from_str(&ggp_address[0]).expect("Failed to parse address"); + + // Make a transaction to generate gas fees that will go to the pool + let txn_hash = coin_client + .transfer(&mut gas_payer, beneficiary.address(), 1_000, None) + .await + .context("Failed to submit transfer transaction")?; + + rest_client + .wait_for_transaction(&txn_hash) + .await + .context("Failed when waiting for transfer transaction")?; + + // Get initial balances before fund distribution + let initial_pool_balance = coin_client + .get_account_balance(&ggp_account_address) + .await + .context("Failed to get initial gas pool balance")?; + + let initial_beneficiary_balance = coin_client + .get_account_balance(&beneficiary.address()) + .await + .context("Failed to get initial beneficiary balance")?; + + tracing::info!("Initial gas pool balance: {}", initial_pool_balance); + tracing::info!("Initial beneficiary balance: {}", initial_beneficiary_balance); + + let final_pool_balance = coin_client + .get_account_balance(&ggp_account_address) + .await + .context("Failed to get final gas pool balance")?; + + assert!(final_pool_balance > initial_pool_balance, "Gas fees were not collected by the pool"); + + Ok(()) +} diff --git a/process-compose/movement-full-node/process-compose.test-ggp-gas-fund-fee.yml b/process-compose/movement-full-node/process-compose.test-ggp-gas-fund-fee.yml new file mode 100644 index 000000000..316fc81f0 --- /dev/null +++ b/process-compose/movement-full-node/process-compose.test-ggp-gas-fund-fee.yml @@ -0,0 +1,13 @@ +version: "3" + +environment: + +processes: + test-ggp-gas-fund-fee: + command: | + cargo run --bin movement-tests-e2e-ggp-gas-fund-fee + depends_on: + movement-full-node: + condition: process_healthy + movement-faucet: + condition: process_healthy From 6034462de84babbdcc91f708b5282f2e78920afb Mon Sep 17 00:00:00 2001 From: Icarus131 Date: Thu, 16 Jan 2025 21:55:47 +0530 Subject: [PATCH 02/13] chore: add test as mod --- networks/movement/movement-client/Cargo.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/networks/movement/movement-client/Cargo.toml b/networks/movement/movement-client/Cargo.toml index 5680c517d..61414bff0 100644 --- a/networks/movement/movement-client/Cargo.toml +++ b/networks/movement/movement-client/Cargo.toml @@ -40,6 +40,10 @@ name = "movement-tests-e2e-ggp-gas-fee" path = "src/bin/e2e/ggp_gas_fee.rs" +[[bin]] +name = "movement-tests-e2e-ggp-fund-fee" +path = "src/bin/e2e/ggp_fund_fee.rs" + [dependencies] aptos-sdk = { workspace = true } aptos-types = { workspace = true } From 2c84414765f0fa62f69036bf9875093a227490e3 Mon Sep 17 00:00:00 2001 From: Icarus131 Date: Thu, 16 Jan 2025 22:02:35 +0530 Subject: [PATCH 03/13] fix: modify erroneous test name in process compose file --- .../process-compose.test-ggp-gas-fund-fee.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/process-compose/movement-full-node/process-compose.test-ggp-gas-fund-fee.yml b/process-compose/movement-full-node/process-compose.test-ggp-gas-fund-fee.yml index 316fc81f0..ce33d4382 100644 --- a/process-compose/movement-full-node/process-compose.test-ggp-gas-fund-fee.yml +++ b/process-compose/movement-full-node/process-compose.test-ggp-gas-fund-fee.yml @@ -5,7 +5,7 @@ environment: processes: test-ggp-gas-fund-fee: command: | - cargo run --bin movement-tests-e2e-ggp-gas-fund-fee + cargo run --bin movement-tests-e2e-ggp-fund-fee depends_on: movement-full-node: condition: process_healthy From beef7f8c72a67449185c813734cf5fe0939cec06 Mon Sep 17 00:00:00 2001 From: Icarus131 Date: Thu, 16 Jan 2025 22:07:01 +0530 Subject: [PATCH 04/13] chore: change test name in cargo mod --- networks/movement/movement-client/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/networks/movement/movement-client/Cargo.toml b/networks/movement/movement-client/Cargo.toml index 61414bff0..a462d5abb 100644 --- a/networks/movement/movement-client/Cargo.toml +++ b/networks/movement/movement-client/Cargo.toml @@ -42,7 +42,7 @@ path = "src/bin/e2e/ggp_gas_fee.rs" [[bin]] name = "movement-tests-e2e-ggp-fund-fee" -path = "src/bin/e2e/ggp_fund_fee.rs" +path = "src/bin/e2e/ggp_fund.rs" [dependencies] aptos-sdk = { workspace = true } From 59caa87bedc97425f52d4155a56045fb88dee30c Mon Sep 17 00:00:00 2001 From: Icarus131 Date: Mon, 20 Jan 2025 10:45:31 +0530 Subject: [PATCH 05/13] fix: add node and faucet url --- .../movement-client/src/bin/e2e/ggp_fund.rs | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/networks/movement/movement-client/src/bin/e2e/ggp_fund.rs b/networks/movement/movement-client/src/bin/e2e/ggp_fund.rs index 2e813806b..e9d76cdc6 100644 --- a/networks/movement/movement-client/src/bin/e2e/ggp_fund.rs +++ b/networks/movement/movement-client/src/bin/e2e/ggp_fund.rs @@ -14,6 +14,47 @@ use std::str::FromStr; use tracing; use url::Url; +static SUZUKA_CONFIG: Lazy = Lazy::new(|| { + let dot_movement = dot_movement::DotMovement::try_from_env().unwrap(); + let config = dot_movement.try_get_config_from_json::().unwrap(); + config +}); + +static NODE_URL: Lazy = Lazy::new(|| { + let node_connection_address = SUZUKA_CONFIG + .execution_config + .maptos_config + .client + .maptos_rest_connection_hostname + .clone(); + let node_connection_port = SUZUKA_CONFIG + .execution_config + .maptos_config + .client + .maptos_rest_connection_port + .clone(); + let node_connection_url = + format!("http://{}:{}", node_connection_address, node_connection_port); + Url::from_str(node_connection_url.as_str()).unwrap() +}); + +static FAUCET_URL: Lazy = Lazy::new(|| { + let faucet_listen_address = SUZUKA_CONFIG + .execution_config + .maptos_config + .client + .maptos_faucet_rest_connection_hostname + .clone(); + let faucet_listen_port = SUZUKA_CONFIG + .execution_config + .maptos_config + .client + .maptos_faucet_rest_connection_port + .clone(); + let faucet_listen_url = format!("http://{}:{}", faucet_listen_address, faucet_listen_port); + Url::from_str(faucet_listen_url.as_str()).unwrap() +}); + #[tokio::main] async fn main() -> Result<(), anyhow::Error> { let rest_client = Client::new(NODE_URL.clone()); From 645bcba26f9c41d635dfc96ac90b06e8df32899f Mon Sep 17 00:00:00 2001 From: Icarus131 Date: Tue, 21 Jan 2025 22:35:20 +0530 Subject: [PATCH 06/13] feat: modify logic for checking fee --- .../movement-client/src/bin/e2e/ggp_fund.rs | 76 +++++++++++++++---- 1 file changed, 62 insertions(+), 14 deletions(-) diff --git a/networks/movement/movement-client/src/bin/e2e/ggp_fund.rs b/networks/movement/movement-client/src/bin/e2e/ggp_fund.rs index e9d76cdc6..3a47f339c 100644 --- a/networks/movement/movement-client/src/bin/e2e/ggp_fund.rs +++ b/networks/movement/movement-client/src/bin/e2e/ggp_fund.rs @@ -61,7 +61,7 @@ async fn main() -> Result<(), anyhow::Error> { let faucet_client = FaucetClient::new(FAUCET_URL.clone(), NODE_URL.clone()); let coin_client = CoinClient::new(&rest_client); - // Create a gas payer account (to fund the pool) and beneficiary account + // Create accounts let mut gas_payer = LocalAccount::generate(&mut rand::rngs::OsRng); let beneficiary = LocalAccount::generate(&mut rand::rngs::OsRng); @@ -72,18 +72,31 @@ async fn main() -> Result<(), anyhow::Error> { beneficiary.address() ); - // Fund the gas payer account + // Fund gas payer and get initial balance faucet_client .fund(gas_payer.address(), 1_000_000) .await .context("Failed to fund gas payer account")?; - // Create and register the beneficiary account for APT + let initial_gas_payer_balance = coin_client + .get_account_balance(&gas_payer.address()) + .await + .context("Failed to get initial gas payer balance")?; + tracing::info!("Initial gas payer balance: {}", initial_gas_payer_balance); + + // Fund beneficiary account faucet_client .create_account(beneficiary.address()) .await .context("Failed to create beneficiary account")?; + // Get initial beneficiary balance + let initial_beneficiary_balance = coin_client + .get_account_balance(&beneficiary.address()) + .await + .context("Failed to get initial beneficiary balance")?; + tracing::info!("Initial beneficiary balance: {}", initial_beneficiary_balance); + // Get the governed gas pool address let view_req = ViewRequest { function: EntryFunctionId { @@ -111,37 +124,72 @@ async fn main() -> Result<(), anyhow::Error> { let ggp_account_address = AccountAddress::from_str(&ggp_address[0]).expect("Failed to parse address"); - // Make a transaction to generate gas fees that will go to the pool + // Get initial gas pool balance + let initial_pool_balance = coin_client + .get_account_balance(&ggp_account_address) + .await + .context("Failed to get initial gas pool balance")?; + tracing::info!("Initial gas pool balance: {}", initial_pool_balance); + + // Get gas payer balance before transfer + let pre_transfer_gas_payer_balance = coin_client + .get_account_balance(&gas_payer.address()) + .await + .context("Failed to get pre-transfer gas payer balance")?; + tracing::info!("Gas payer balance before transfer: {}", pre_transfer_gas_payer_balance); + + // Make the transfer let txn_hash = coin_client .transfer(&mut gas_payer, beneficiary.address(), 1_000, None) .await .context("Failed to submit transfer transaction")?; + // Wait for transaction and get detailed info rest_client .wait_for_transaction(&txn_hash) .await .context("Failed when waiting for transfer transaction")?; - // Get initial balances before fund distribution - let initial_pool_balance = coin_client - .get_account_balance(&ggp_account_address) + // Get all final balances + let final_gas_payer_balance = coin_client + .get_account_balance(&gas_payer.address()) .await - .context("Failed to get initial gas pool balance")?; + .context("Failed to get final gas payer balance")?; - let initial_beneficiary_balance = coin_client + let final_beneficiary_balance = coin_client .get_account_balance(&beneficiary.address()) .await - .context("Failed to get initial beneficiary balance")?; - - tracing::info!("Initial gas pool balance: {}", initial_pool_balance); - tracing::info!("Initial beneficiary balance: {}", initial_beneficiary_balance); + .context("Failed to get final beneficiary balance")?; let final_pool_balance = coin_client .get_account_balance(&ggp_account_address) .await .context("Failed to get final gas pool balance")?; - assert!(final_pool_balance > initial_pool_balance, "Gas fees were not collected by the pool"); + tracing::info!("Final gas pool balance: {}", final_pool_balance); + tracing::info!("Final beneficiary balance: {}", final_beneficiary_balance); + tracing::info!("Final gas payer balance: {}", final_gas_payer_balance); + + // Verify beneficiary received full amount + assert_eq!( + final_beneficiary_balance - initial_beneficiary_balance, + 1000, + "Beneficiary did not receive the full amount" + ); + + // Verify gas pool didn't collect any fees + assert_eq!( + final_pool_balance, initial_pool_balance, + "Gas pool collected fees when it shouldn't have" + ); + + // Verify gas payer only paid the transfer amount (no fees) + let total_cost = pre_transfer_gas_payer_balance - final_gas_payer_balance; + assert_eq!( + total_cost, 1000, + "Gas payer was charged more than the transfer amount (fees were taken)" + ); Ok(()) } + From 39503ed63cad1abc3ed83f8ba38a3a89aae57971 Mon Sep 17 00:00:00 2001 From: Icarus131 Date: Wed, 22 Jan 2025 03:04:50 +0530 Subject: [PATCH 07/13] fix: remove assertion to check gas pool balance --- networks/movement/movement-client/src/bin/e2e/ggp_fund.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/networks/movement/movement-client/src/bin/e2e/ggp_fund.rs b/networks/movement/movement-client/src/bin/e2e/ggp_fund.rs index 3a47f339c..920b3fff8 100644 --- a/networks/movement/movement-client/src/bin/e2e/ggp_fund.rs +++ b/networks/movement/movement-client/src/bin/e2e/ggp_fund.rs @@ -177,12 +177,6 @@ async fn main() -> Result<(), anyhow::Error> { "Beneficiary did not receive the full amount" ); - // Verify gas pool didn't collect any fees - assert_eq!( - final_pool_balance, initial_pool_balance, - "Gas pool collected fees when it shouldn't have" - ); - // Verify gas payer only paid the transfer amount (no fees) let total_cost = pre_transfer_gas_payer_balance - final_gas_payer_balance; assert_eq!( @@ -192,4 +186,3 @@ async fn main() -> Result<(), anyhow::Error> { Ok(()) } - From a2a2713e2dc7d36694ab5c017e580d3f2c66653d Mon Sep 17 00:00:00 2001 From: Icarus131 Date: Wed, 22 Jan 2025 03:26:00 +0530 Subject: [PATCH 08/13] chore: remove irrelevant assertions --- networks/movement/movement-client/src/bin/e2e/ggp_fund.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/networks/movement/movement-client/src/bin/e2e/ggp_fund.rs b/networks/movement/movement-client/src/bin/e2e/ggp_fund.rs index 920b3fff8..70418c8ac 100644 --- a/networks/movement/movement-client/src/bin/e2e/ggp_fund.rs +++ b/networks/movement/movement-client/src/bin/e2e/ggp_fund.rs @@ -177,12 +177,5 @@ async fn main() -> Result<(), anyhow::Error> { "Beneficiary did not receive the full amount" ); - // Verify gas payer only paid the transfer amount (no fees) - let total_cost = pre_transfer_gas_payer_balance - final_gas_payer_balance; - assert_eq!( - total_cost, 1000, - "Gas payer was charged more than the transfer amount (fees were taken)" - ); - Ok(()) } From a2052b81dba15b5a308c90005f5fe484362a66f9 Mon Sep 17 00:00:00 2001 From: Icarus131 Date: Tue, 28 Jan 2025 12:53:52 +0530 Subject: [PATCH 09/13] feat: first pass for complex gas fee accumulation e2e test --- networks/movement/movement-client/Cargo.toml | 4 + .../src/bin/e2e/complex_ggp_e2e.rs | 186 ++++++++++++++++++ .../process-compose.test-complex-ggp-gas.yml | 13 ++ 3 files changed, 203 insertions(+) create mode 100644 networks/movement/movement-client/src/bin/e2e/complex_ggp_e2e.rs create mode 100644 process-compose/movement-full-node/process-compose.test-complex-ggp-gas.yml diff --git a/networks/movement/movement-client/Cargo.toml b/networks/movement/movement-client/Cargo.toml index a462d5abb..7901aa8dc 100644 --- a/networks/movement/movement-client/Cargo.toml +++ b/networks/movement/movement-client/Cargo.toml @@ -44,6 +44,10 @@ path = "src/bin/e2e/ggp_gas_fee.rs" name = "movement-tests-e2e-ggp-fund-fee" path = "src/bin/e2e/ggp_fund.rs" +[[bin]] +name = "movement-tests-e2e-complex-ggp-gas" +path = "src/bin/e2e/complex-ggp-e2e" + [dependencies] aptos-sdk = { workspace = true } aptos-types = { workspace = true } diff --git a/networks/movement/movement-client/src/bin/e2e/complex_ggp_e2e.rs b/networks/movement/movement-client/src/bin/e2e/complex_ggp_e2e.rs new file mode 100644 index 000000000..0d3fc25ad --- /dev/null +++ b/networks/movement/movement-client/src/bin/e2e/complex_ggp_e2e.rs @@ -0,0 +1,186 @@ +use anyhow::Context; +use aptos_sdk::rest_client::{ + aptos_api_types::{Address, EntryFunctionId, IdentifierWrapper, MoveModuleId, ViewRequest}, + Response, +}; +use aptos_sdk::types::account_address::AccountAddress; +use movement_client::{ + coin_client::CoinClient, + rest_client::{Client, FaucetClient}, + types::LocalAccount, +}; +use once_cell::sync::Lazy; +use std::str::FromStr; +use tracing; +use url::Url; + +static SUZUKA_CONFIG: Lazy = Lazy::new(|| { + let dot_movement = dot_movement::DotMovement::try_from_env().unwrap(); + let config = dot_movement.try_get_config_from_json::().unwrap(); + config +}); + +static NODE_URL: Lazy = Lazy::new(|| { + let node_connection_address = SUZUKA_CONFIG + .execution_config + .maptos_config + .client + .maptos_rest_connection_hostname + .clone(); + let node_connection_port = SUZUKA_CONFIG + .execution_config + .maptos_config + .client + .maptos_rest_connection_port + .clone(); + let node_connection_url = + format!("http://{}:{}", node_connection_address, node_connection_port); + Url::from_str(node_connection_url.as_str()).unwrap() +}); + +static FAUCET_URL: Lazy = Lazy::new(|| { + let faucet_listen_address = SUZUKA_CONFIG + .execution_config + .maptos_config + .client + .maptos_faucet_rest_connection_hostname + .clone(); + let faucet_listen_port = SUZUKA_CONFIG + .execution_config + .maptos_config + .client + .maptos_faucet_rest_connection_port + .clone(); + let faucet_listen_url = format!("http://{}:{}", faucet_listen_address, faucet_listen_port); + Url::from_str(faucet_listen_url.as_str()).unwrap() +}); + +const NUM_ACCOUNTS: usize = 5; +const TRANSACTIONS_PER_ACCOUNT: usize = 100; +const INITIAL_FUNDING: u64 = 10_000_000; +const TRANSFER_AMOUNT: u64 = 100; + +#[tokio::main] +async fn main() -> Result<(), anyhow::Error> { + let rest_client = Client::new(NODE_URL.clone()); + let faucet_client = FaucetClient::new(FAUCET_URL.clone(), NODE_URL.clone()); + let coin_client = CoinClient::new(&rest_client); + + let ggp_address = get_governed_gas_pool_address(&rest_client).await?; + + let mut accounts = create_and_fund_accounts(&faucet_client, NUM_ACCOUNTS).await?; + + let initial_pool_balance = coin_client + .get_account_balance(&ggp_address) + .await + .context("Failed to get initial gas pool balance")?; + tracing::info!("Initial gas pool balance: {}", initial_pool_balance); + + execute_transaction_rounds(&mut accounts, &coin_client, &rest_client).await?; + + let final_pool_balance = coin_client + .get_account_balance(&ggp_address) + .await + .context("Failed to get final gas pool balance")?; + tracing::info!("Final gas pool balance: {}", final_pool_balance); + + assert!( + final_pool_balance > initial_pool_balance, + "Gas pool balance did not increase after {} transactions", + NUM_ACCOUNTS * TRANSACTIONS_PER_ACCOUNT + ); + + tracing::info!("Total gas fees collected: {}", final_pool_balance - initial_pool_balance); + + Ok(()) +} + +async fn get_governed_gas_pool_address( + rest_client: &Client, +) -> Result { + let view_req = ViewRequest { + function: EntryFunctionId { + module: MoveModuleId { + address: Address::from_str("0x1").unwrap(), + name: IdentifierWrapper::from_str("governed_gas_pool").unwrap(), + }, + name: IdentifierWrapper::from_str("governed_gas_pool_address").unwrap(), + }, + type_arguments: vec![], + arguments: vec![], + }; + + let view_res: Response> = rest_client + .view(&view_req, None) + .await + .context("Failed to get governed gas pool address")?; + + let inner_value = serde_json::to_value(view_res.inner()) + .context("Failed to convert response inner to serde_json::Value")?; + + let ggp_address: Vec = + serde_json::from_value(inner_value).context("Failed to deserialize AddressResponse")?; + + Ok(AccountAddress::from_str(&ggp_address[0]).expect("Failed to parse address")) +} + +async fn create_and_fund_accounts( + faucet_client: &FaucetClient, + num_accounts: usize, +) -> Result, anyhow::Error> { + let mut accounts = Vec::with_capacity(num_accounts); + + for i in 0..num_accounts { + let account = LocalAccount::generate(&mut rand::rngs::OsRng); + tracing::info!("Creating account {}: {}", i, account.address()); + + faucet_client + .fund(account.address(), INITIAL_FUNDING) + .await + .context(format!("Failed to fund account {}", i))?; + + accounts.push(account); + } + + Ok(accounts) +} + +async fn execute_transaction_rounds( + accounts: &mut [LocalAccount], + coin_client: &CoinClient, + rest_client: &Client, +) -> Result<(), anyhow::Error> { + for round in 0..TRANSACTIONS_PER_ACCOUNT { + tracing::info!("Starting transaction round {}", round); + + // Each account sends a transaction to the next account in the list + for i in 0..accounts.len() { + let sender_idx = i; + let receiver_idx = (i + 1) % accounts.len(); + + let txn_hash = coin_client + .transfer( + &mut accounts[sender_idx], + accounts[receiver_idx].address(), + TRANSFER_AMOUNT, + None, + ) + .await + .context(format!( + "Failed to submit transfer from account {} to {}", + sender_idx, receiver_idx + ))?; + + rest_client + .wait_for_transaction(&txn_hash) + .await + .context("Failed when waiting for transfer transaction")?; + + if round % 10 == 0 && i == 0 { + tracing::info!("Completed {} transactions per account", round + 1); + } + } + } + + Ok(()) +} diff --git a/process-compose/movement-full-node/process-compose.test-complex-ggp-gas.yml b/process-compose/movement-full-node/process-compose.test-complex-ggp-gas.yml new file mode 100644 index 000000000..71e9d3dc8 --- /dev/null +++ b/process-compose/movement-full-node/process-compose.test-complex-ggp-gas.yml @@ -0,0 +1,13 @@ +version: "3" + +environment: + +processes: + test-ggp-gas-fee: + command: | + cargo run --bin movement-tests-e2e-complex-ggp-gas + depends_on: + movement-full-node: + condition: process_healthy + movement-faucet: + condition: process_healthy From ca6df78f79f1faa8aed0d87c32d9a3ceb813ada0 Mon Sep 17 00:00:00 2001 From: Icarus131 Date: Tue, 28 Jan 2025 12:58:23 +0530 Subject: [PATCH 10/13] fix: fix path for bin in cargo --- networks/movement/movement-client/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/networks/movement/movement-client/Cargo.toml b/networks/movement/movement-client/Cargo.toml index 7901aa8dc..6ce7225bd 100644 --- a/networks/movement/movement-client/Cargo.toml +++ b/networks/movement/movement-client/Cargo.toml @@ -46,7 +46,7 @@ path = "src/bin/e2e/ggp_fund.rs" [[bin]] name = "movement-tests-e2e-complex-ggp-gas" -path = "src/bin/e2e/complex-ggp-e2e" +path = "src/bin/e2e/complex_ggp_e2e.rs" [dependencies] aptos-sdk = { workspace = true } From 1d1485d2a643198541cd92e3b486dff34887963c Mon Sep 17 00:00:00 2001 From: Icarus131 Date: Wed, 29 Jan 2025 19:10:29 +0530 Subject: [PATCH 11/13] fix: fix borrow issue with rest_client --- .../src/bin/e2e/complex_ggp_e2e.rs | 50 ++++++++++++------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/networks/movement/movement-client/src/bin/e2e/complex_ggp_e2e.rs b/networks/movement/movement-client/src/bin/e2e/complex_ggp_e2e.rs index 0d3fc25ad..e77a140e0 100644 --- a/networks/movement/movement-client/src/bin/e2e/complex_ggp_e2e.rs +++ b/networks/movement/movement-client/src/bin/e2e/complex_ggp_e2e.rs @@ -70,20 +70,24 @@ async fn main() -> Result<(), anyhow::Error> { let mut accounts = create_and_fund_accounts(&faucet_client, NUM_ACCOUNTS).await?; + // Get initial gas pool balance let initial_pool_balance = coin_client .get_account_balance(&ggp_address) .await .context("Failed to get initial gas pool balance")?; tracing::info!("Initial gas pool balance: {}", initial_pool_balance); + // Execute multiple rounds of transactions between accounts execute_transaction_rounds(&mut accounts, &coin_client, &rest_client).await?; + // Get final gas pool balance let final_pool_balance = coin_client .get_account_balance(&ggp_address) .await .context("Failed to get final gas pool balance")?; tracing::info!("Final gas pool balance: {}", final_pool_balance); + // Verify gas fees were collected assert!( final_pool_balance > initial_pool_balance, "Gas pool balance did not increase after {} transactions", @@ -145,31 +149,41 @@ async fn create_and_fund_accounts( Ok(accounts) } -async fn execute_transaction_rounds( +async fn execute_transaction_rounds<'a>( accounts: &mut [LocalAccount], - coin_client: &CoinClient, - rest_client: &Client, + coin_client: &'a CoinClient<'a>, + rest_client: &'a Client, ) -> Result<(), anyhow::Error> { for round in 0..TRANSACTIONS_PER_ACCOUNT { tracing::info!("Starting transaction round {}", round); - - // Each account sends a transaction to the next account in the list for i in 0..accounts.len() { - let sender_idx = i; let receiver_idx = (i + 1) % accounts.len(); - let txn_hash = coin_client - .transfer( - &mut accounts[sender_idx], - accounts[receiver_idx].address(), - TRANSFER_AMOUNT, - None, - ) - .await - .context(format!( - "Failed to submit transfer from account {} to {}", - sender_idx, receiver_idx - ))?; + let receiver_address = accounts[receiver_idx].address(); + + let txn_hash = if receiver_idx <= i { + let (left, right) = accounts.split_at_mut(i + 1); + let sender = &mut left[i]; + + coin_client + .transfer(sender, receiver_address, TRANSFER_AMOUNT, None) + .await + .context(format!( + "Failed to submit transfer from account {} to {}", + i, receiver_idx + ))? + } else { + let (left, right) = accounts.split_at_mut(i + 1); + let sender = &mut left[i]; + + coin_client + .transfer(sender, receiver_address, TRANSFER_AMOUNT, None) + .await + .context(format!( + "Failed to submit transfer from account {} to {}", + i, receiver_idx + ))? + }; rest_client .wait_for_transaction(&txn_hash) From 964b6c38577852e99db06124776b562d92648f15 Mon Sep 17 00:00:00 2001 From: Icarus131 Date: Wed, 29 Jan 2025 19:48:50 +0530 Subject: [PATCH 12/13] chore: add logging statements to debug --- .../src/bin/e2e/complex_ggp_e2e.rs | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/networks/movement/movement-client/src/bin/e2e/complex_ggp_e2e.rs b/networks/movement/movement-client/src/bin/e2e/complex_ggp_e2e.rs index e77a140e0..23edf82f8 100644 --- a/networks/movement/movement-client/src/bin/e2e/complex_ggp_e2e.rs +++ b/networks/movement/movement-client/src/bin/e2e/complex_ggp_e2e.rs @@ -75,7 +75,7 @@ async fn main() -> Result<(), anyhow::Error> { .get_account_balance(&ggp_address) .await .context("Failed to get initial gas pool balance")?; - tracing::info!("Initial gas pool balance: {}", initial_pool_balance); + println!("Initial gas pool balance: {}", initial_pool_balance); // Execute multiple rounds of transactions between accounts execute_transaction_rounds(&mut accounts, &coin_client, &rest_client).await?; @@ -85,7 +85,7 @@ async fn main() -> Result<(), anyhow::Error> { .get_account_balance(&ggp_address) .await .context("Failed to get final gas pool balance")?; - tracing::info!("Final gas pool balance: {}", final_pool_balance); + println!("Final gas pool balance: {}", final_pool_balance); // Verify gas fees were collected assert!( @@ -94,7 +94,7 @@ async fn main() -> Result<(), anyhow::Error> { NUM_ACCOUNTS * TRANSACTIONS_PER_ACCOUNT ); - tracing::info!("Total gas fees collected: {}", final_pool_balance - initial_pool_balance); + println!("Total gas fees collected: {}", final_pool_balance - initial_pool_balance); Ok(()) } @@ -136,7 +136,7 @@ async fn create_and_fund_accounts( for i in 0..num_accounts { let account = LocalAccount::generate(&mut rand::rngs::OsRng); - tracing::info!("Creating account {}: {}", i, account.address()); + println!("Creating account {}: {}", i, account.address()); faucet_client .fund(account.address(), INITIAL_FUNDING) @@ -155,16 +155,25 @@ async fn execute_transaction_rounds<'a>( rest_client: &'a Client, ) -> Result<(), anyhow::Error> { for round in 0..TRANSACTIONS_PER_ACCOUNT { - tracing::info!("Starting transaction round {}", round); + println!("Starting transaction round {}", round); + for i in 0..accounts.len() { let receiver_idx = (i + 1) % accounts.len(); + println!( + "Attempting transfer: Account {} -> Account {}, Round {}", + i, receiver_idx, round + ); + let receiver_address = accounts[receiver_idx].address(); + println!("Receiver address retrieved: {}", receiver_address); let txn_hash = if receiver_idx <= i { + println!("Using first branch of split_at_mut"); let (left, right) = accounts.split_at_mut(i + 1); let sender = &mut left[i]; + println!("Initiating transfer..."); coin_client .transfer(sender, receiver_address, TRANSFER_AMOUNT, None) .await @@ -173,9 +182,11 @@ async fn execute_transaction_rounds<'a>( i, receiver_idx ))? } else { + println!("Using second branch of split_at_mut"); let (left, right) = accounts.split_at_mut(i + 1); let sender = &mut left[i]; + println!("Initiating transfer..."); coin_client .transfer(sender, receiver_address, TRANSFER_AMOUNT, None) .await @@ -185,13 +196,21 @@ async fn execute_transaction_rounds<'a>( ))? }; + println!("Transfer submitted. Transaction hash: {:?}", txn_hash); + + println!("Waiting for transaction confirmation..."); rest_client .wait_for_transaction(&txn_hash) .await .context("Failed when waiting for transfer transaction")?; + println!( + "Transaction confirmed: Account {} -> Account {}, Round {}", + i, receiver_idx, round + ); + if round % 10 == 0 && i == 0 { - tracing::info!("Completed {} transactions per account", round + 1); + println!("Completed {} transactions per account", round + 1); } } } From f171b7497e0899f9673c0b4c1f156a2854d967a8 Mon Sep 17 00:00:00 2001 From: Icarus131 Date: Wed, 29 Jan 2025 20:02:29 +0530 Subject: [PATCH 13/13] chore: fallback to tracing instead of println --- .../src/bin/e2e/complex_ggp_e2e.rs | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/networks/movement/movement-client/src/bin/e2e/complex_ggp_e2e.rs b/networks/movement/movement-client/src/bin/e2e/complex_ggp_e2e.rs index 23edf82f8..87e611c6c 100644 --- a/networks/movement/movement-client/src/bin/e2e/complex_ggp_e2e.rs +++ b/networks/movement/movement-client/src/bin/e2e/complex_ggp_e2e.rs @@ -75,7 +75,7 @@ async fn main() -> Result<(), anyhow::Error> { .get_account_balance(&ggp_address) .await .context("Failed to get initial gas pool balance")?; - println!("Initial gas pool balance: {}", initial_pool_balance); + tracing::info!("Initial gas pool balance: {}", initial_pool_balance); // Execute multiple rounds of transactions between accounts execute_transaction_rounds(&mut accounts, &coin_client, &rest_client).await?; @@ -85,7 +85,7 @@ async fn main() -> Result<(), anyhow::Error> { .get_account_balance(&ggp_address) .await .context("Failed to get final gas pool balance")?; - println!("Final gas pool balance: {}", final_pool_balance); + tracing::info!("Final gas pool balance: {}", final_pool_balance); // Verify gas fees were collected assert!( @@ -94,7 +94,7 @@ async fn main() -> Result<(), anyhow::Error> { NUM_ACCOUNTS * TRANSACTIONS_PER_ACCOUNT ); - println!("Total gas fees collected: {}", final_pool_balance - initial_pool_balance); + tracing::info!("Total gas fees collected: {}", final_pool_balance - initial_pool_balance); Ok(()) } @@ -136,7 +136,7 @@ async fn create_and_fund_accounts( for i in 0..num_accounts { let account = LocalAccount::generate(&mut rand::rngs::OsRng); - println!("Creating account {}: {}", i, account.address()); + tracing::info!("Creating account {}: {}", i, account.address()); faucet_client .fund(account.address(), INITIAL_FUNDING) @@ -155,25 +155,27 @@ async fn execute_transaction_rounds<'a>( rest_client: &'a Client, ) -> Result<(), anyhow::Error> { for round in 0..TRANSACTIONS_PER_ACCOUNT { - println!("Starting transaction round {}", round); + tracing::info!("Starting transaction round {}", round); for i in 0..accounts.len() { let receiver_idx = (i + 1) % accounts.len(); - println!( + tracing::info!( "Attempting transfer: Account {} -> Account {}, Round {}", - i, receiver_idx, round + i, + receiver_idx, + round ); let receiver_address = accounts[receiver_idx].address(); - println!("Receiver address retrieved: {}", receiver_address); + tracing::info!("Receiver address retrieved: {}", receiver_address); let txn_hash = if receiver_idx <= i { - println!("Using first branch of split_at_mut"); + tracing::info!("Using first branch of split_at_mut"); let (left, right) = accounts.split_at_mut(i + 1); let sender = &mut left[i]; - println!("Initiating transfer..."); + tracing::info!("Initiating transfer..."); coin_client .transfer(sender, receiver_address, TRANSFER_AMOUNT, None) .await @@ -182,11 +184,11 @@ async fn execute_transaction_rounds<'a>( i, receiver_idx ))? } else { - println!("Using second branch of split_at_mut"); + tracing::info!("Using second branch of split_at_mut"); let (left, right) = accounts.split_at_mut(i + 1); let sender = &mut left[i]; - println!("Initiating transfer..."); + tracing::info!("Initiating transfer..."); coin_client .transfer(sender, receiver_address, TRANSFER_AMOUNT, None) .await @@ -196,21 +198,23 @@ async fn execute_transaction_rounds<'a>( ))? }; - println!("Transfer submitted. Transaction hash: {:?}", txn_hash); + tracing::info!("Transfer submitted. Transaction hash: {:?}", txn_hash); - println!("Waiting for transaction confirmation..."); + tracing::info!("Waiting for transaction confirmation..."); rest_client .wait_for_transaction(&txn_hash) .await .context("Failed when waiting for transfer transaction")?; - println!( + tracing::info!( "Transaction confirmed: Account {} -> Account {}, Round {}", - i, receiver_idx, round + i, + receiver_idx, + round ); if round % 10 == 0 && i == 0 { - println!("Completed {} transactions per account", round + 1); + tracing::info!("Completed {} transactions per account", round + 1); } } }