diff --git a/crates/core/src/rpc/full.rs b/crates/core/src/rpc/full.rs index 12223186..21ff13eb 100644 --- a/crates/core/src/rpc/full.rs +++ b/crates/core/src/rpc/full.rs @@ -45,8 +45,8 @@ use crate::{ error::{SurfpoolError, SurfpoolResult}, rpc::utils::{adjust_default_transaction_config, get_default_transaction_config}, surfnet::{ - FINALIZATION_SLOT_THRESHOLD, GetTransactionResult, locker::SvmAccessContext, - svm::MAX_RECENT_BLOCKHASHES_STANDARD, + FINALIZATION_SLOT_THRESHOLD, GetAccountResult, GetTransactionResult, + locker::SvmAccessContext, svm::MAX_RECENT_BLOCKHASHES_STANDARD, }, types::{SurfnetTransactionStatus, surfpool_tx_metadata_to_litesvm_tx_metadata}, }; @@ -1594,6 +1594,7 @@ impl Full for SurfpoolFullRpc { false, &tx_message, None, // No loaded addresses available in error reporting context + None, )) .map_err(|e| { Error::invalid_params(format!( @@ -1687,6 +1688,53 @@ impl Full for SurfpoolFullRpc { .get_multiple_accounts(&remote_ctx, &transaction_pubkeys, None) .await?; + let mut seen_accounts = std::collections::HashSet::new(); + let mut loaded_accounts_data_size: u64 = 0; + + let mut track_accounts_data_size = + |account_update: &GetAccountResult| match account_update { + GetAccountResult::FoundAccount(pubkey, account, _) => { + if seen_accounts.insert(*pubkey) { + loaded_accounts_data_size += account.data.len() as u64; + } + } + // According to SIMD 0186, program data is tracked as well as program accounts + GetAccountResult::FoundProgramAccount( + (pubkey, account), + (pd_pubkey, pd_account), + ) => { + if seen_accounts.insert(*pubkey) { + loaded_accounts_data_size += account.data.len() as u64; + } + if let Some(pd) = pd_account { + if seen_accounts.insert(*pd_pubkey) { + loaded_accounts_data_size += pd.data.len() as u64; + } + } + } + GetAccountResult::FoundTokenAccount( + (pubkey, account), + (td_pubkey, td_account), + ) => { + if seen_accounts.insert(*pubkey) { + loaded_accounts_data_size += account.data.len() as u64; + } + if let Some(td) = td_account { + let td_key_in_tx_pubkeys = + transaction_pubkeys.iter().find(|k| **k == *td_pubkey); + // Only count token data accounts that are explicitly loaded by the transaction + if td_key_in_tx_pubkeys.is_some() && seen_accounts.insert(*td_pubkey) { + loaded_accounts_data_size += td.data.len() as u64; + } + } + } + GetAccountResult::None(_) => {} + }; + + for res in account_updates.iter() { + track_accounts_data_size(res); + } + svm_locker.write_multiple_account_updates(&account_updates); // Convert TransactionLoadedAddresses to LoadedAddresses before it gets consumed @@ -1697,6 +1745,9 @@ impl Full for SurfpoolFullRpc { .get_multiple_accounts(&remote_ctx, &alt_pubkeys, None) .await? .inner; + for res in alt_updates.iter() { + track_accounts_data_size(res); + } svm_locker.write_multiple_account_updates(&alt_updates); } @@ -1751,6 +1802,7 @@ impl Full for SurfpoolFullRpc { config.inner_instructions, &tx_message, loaded_addresses_data.as_ref(), + Some(loaded_accounts_data_size as u32), ) } Err(tx_info) => get_simulate_transaction_result( @@ -1761,6 +1813,7 @@ impl Full for SurfpoolFullRpc { config.inner_instructions, &tx_message, loaded_addresses_data.as_ref(), + Some(loaded_accounts_data_size as u32), ), }; @@ -2402,6 +2455,7 @@ fn get_simulate_transaction_result( include_inner_instructions: bool, message: &VersionedMessage, loaded_addresses: Option<&solana_message::v0::LoadedAddresses>, + loaded_accounts_data_size: Option, ) -> RpcSimulateTransactionResult { RpcSimulateTransactionResult { accounts, @@ -2425,7 +2479,7 @@ fn get_simulate_transaction_result( Some(metadata.return_data.clone().into()) }, units_consumed: Some(metadata.compute_units_consumed), - loaded_accounts_data_size: None, + loaded_accounts_data_size, fee: None, pre_balances: None, post_balances: None, diff --git a/crates/core/src/tests/integration.rs b/crates/core/src/tests/integration.rs index ae3f6ff2..c75e7e0a 100644 --- a/crates/core/src/tests/integration.rs +++ b/crates/core/src/tests/integration.rs @@ -609,6 +609,15 @@ async fn test_simulate_add_alt_entries_fetching(test_type: TestType) { simulation_res.value.err, None, "Unexpected simulation error" ); + assert!( + simulation_res.value.loaded_accounts_data_size.is_some(), + "Expected loaded_accounts_data_size to be present" + ); + assert_eq!( + simulation_res.value.loaded_accounts_data_size.unwrap(), + 140134, + "Incorrect loaded_accounts_data_size value" + ); let simulation_res2 = full_client .simulate_transaction( data, @@ -628,6 +637,14 @@ async fn test_simulate_add_alt_entries_fetching(test_type: TestType) { simulation_res2.value.err, None, "Unexpected simulation error" ); + assert!( + simulation_res2.value.loaded_accounts_data_size.is_some(), + "Expected loaded_accounts_data_size to be present" + ); + assert!( + simulation_res2.value.loaded_accounts_data_size.unwrap() > 0, + "Expected loaded_accounts_data_size to be greater than 0" + ); } #[cfg_attr(feature = "ignore_tests_ci", ignore = "flaky CI tests")] @@ -722,6 +739,14 @@ async fn test_simulate_transaction_no_signers(test_type: TestType) { simulation_res.value.err, None, "Unexpected simulation error" ); + assert!( + simulation_res.value.loaded_accounts_data_size.is_some(), + "Expected loaded_accounts_data_size to be present" + ); + assert!( + simulation_res.value.loaded_accounts_data_size.unwrap() > 0, + "Expected loaded_accounts_data_size to be greater than 0" + ); } #[cfg_attr(feature = "ignore_tests_ci", ignore = "flaky CI tests")]