From a4ecc085d30f23b2f55ffcbcabcac5d5753bf5f8 Mon Sep 17 00:00:00 2001 From: Thomas Coratger <60488569+tcoratger@users.noreply.github.com> Date: Mon, 9 Sep 2024 00:23:30 -0700 Subject: [PATCH] setup the environnement to handle oz accounts (#1360) * setup the environnement to handle oz accounts * clean up * clean up * fix comments * fix conflicts * propagate error on AccountManager init * fix error in async loop * add eth_client in account manager struct * clean up * modify lock * modify lock * add error for empty accounts in account manager * fix error handling * clean up --- .env.example | 6 - docker-compose.prod.yaml | 2 - docker-compose.staging.yaml | 2 - docker-compose.yaml | 2 - docker/hive/Dockerfile | 2 - src/eth_rpc/servers/kakarot_rpc.rs | 3 - src/lib.rs | 1 + src/main.rs | 5 - src/pool/mempool.rs | 178 ++++++++++++------ src/pool/mod.rs | 242 ------------------------- src/providers/eth_provider/constant.rs | 4 - tests/tests/kakarot_api.rs | 6 - 12 files changed, 121 insertions(+), 332 deletions(-) diff --git a/.env.example b/.env.example index e6a4ca0dc..c2cabe8a7 100644 --- a/.env.example +++ b/.env.example @@ -37,14 +37,8 @@ EVM_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff # Number of Felt (bytes) allowed in a single call data MAX_FELTS_IN_CALLDATA=22500 -# Interval between retries of transactions (in seconds) -RETRY_TX_INTERVAL=10 - # Comma separated list of white listed pre EIP-155 transaction hashes WHITE_LISTED_EIP_155_TRANSACTION_HASHES= -# Maximum number of times a transaction can be retried -TRANSACTION_MAX_RETRIES=10 - # Maximum number of logs to output for eth_getLogs RPC Method MAX_LOGS=10000 diff --git a/docker-compose.prod.yaml b/docker-compose.prod.yaml index 5290c917b..b950733eb 100644 --- a/docker-compose.prod.yaml +++ b/docker-compose.prod.yaml @@ -125,9 +125,7 @@ services: - UNINITIALIZED_ACCOUNT_CLASS_HASH=0x600f6862938312a05a0cfecba0dcaf37693efc9e4075a6adfb62e196022678e - ACCOUNT_CONTRACT_CLASS_HASH=0x1276d0b017701646f8646b69de6c3b3584edce71879678a679f28c07a9971cf - MAX_FELTS_IN_CALLDATA=30000 - - TRANSACTION_MAX_RETRIES=10 - MAX_LOGS=10000 - - RETRY_TX_INTERVAL=10 - WHITE_LISTED_EIP_155_TRANSACTION_HASHES=0xeddf9e61fb9d8f5111840daef55e5fde0041f5702856532cdbb5a02998033d26,0xb6274b80bc7cda162df89894c7748a5cb7ba2eaa6004183c41a1837c3b072f1e,0x07471adfe8f4ec553c1199f495be97fc8be8e0626ae307281c22534460184ed1,0xb95343413e459a0f97461812111254163ae53467855c0d73e0f1e7c5b8442fa3 restart: on-failure volumes: diff --git a/docker-compose.staging.yaml b/docker-compose.staging.yaml index 357b904f5..10feebb06 100644 --- a/docker-compose.staging.yaml +++ b/docker-compose.staging.yaml @@ -125,9 +125,7 @@ services: - UNINITIALIZED_ACCOUNT_CLASS_HASH=0x600f6862938312a05a0cfecba0dcaf37693efc9e4075a6adfb62e196022678e - ACCOUNT_CONTRACT_CLASS_HASH=0x1276d0b017701646f8646b69de6c3b3584edce71879678a679f28c07a9971cf - MAX_FELTS_IN_CALLDATA=30000 - - TRANSACTION_MAX_RETRIES=10 - MAX_LOGS=10000 - - RETRY_TX_INTERVAL=10 - WHITE_LISTED_EIP_155_TRANSACTION_HASHES=0xeddf9e61fb9d8f5111840daef55e5fde0041f5702856532cdbb5a02998033d26,0xb6274b80bc7cda162df89894c7748a5cb7ba2eaa6004183c41a1837c3b072f1e,0x07471adfe8f4ec553c1199f495be97fc8be8e0626ae307281c22534460184ed1,0xb95343413e459a0f97461812111254163ae53467855c0d73e0f1e7c5b8442fa3 restart: on-failure volumes: diff --git a/docker-compose.yaml b/docker-compose.yaml index b1699edbf..44f887e37 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -138,9 +138,7 @@ services: - MONGO_CONNECTION_STRING=mongodb://mongo:mongo@mongo:27017 - MONGO_DATABASE_NAME=kakarot-local - MAX_FELTS_IN_CALLDATA=30000 - - TRANSACTION_MAX_RETRIES=10 - MAX_LOGS=10000 - - RETRY_TX_INTERVAL=1 - WHITE_LISTED_EIP_155_TRANSACTION_HASHES=0xeddf9e61fb9d8f5111840daef55e5fde0041f5702856532cdbb5a02998033d26,0xb6274b80bc7cda162df89894c7748a5cb7ba2eaa6004183c41a1837c3b072f1e,0x07471adfe8f4ec553c1199f495be97fc8be8e0626ae307281c22534460184ed1,0xb95343413e459a0f97461812111254163ae53467855c0d73e0f1e7c5b8442fa3 - OTEL_EXPORTER_OTLP_ENDPOINT=http://otel:4317 volumes: diff --git a/docker/hive/Dockerfile b/docker/hive/Dockerfile index 2aaecc76a..3006ab047 100644 --- a/docker/hive/Dockerfile +++ b/docker/hive/Dockerfile @@ -144,9 +144,7 @@ ENV KAKAROT_RPC_URL=0.0.0.0:8545 ENV STARKNET_NETWORK=http://localhost:5050 ENV RUST_LOG=info ENV MAX_FELTS_IN_CALLDATA=30000 -ENV TRANSACTION_MAX_RETRIES=10 ENV MAX_LOGS=10000 -ENV RETRY_TX_INTERVAL=10 ENV DEFAULT_BLOCK_GAS_LIMIT=7000000 HEALTHCHECK --interval=10s --timeout=10s --start-period=15s --retries=5 \ diff --git a/src/eth_rpc/servers/kakarot_rpc.rs b/src/eth_rpc/servers/kakarot_rpc.rs index 4b85dbc45..af2b2e033 100644 --- a/src/eth_rpc/servers/kakarot_rpc.rs +++ b/src/eth_rpc/servers/kakarot_rpc.rs @@ -1,7 +1,6 @@ use crate::{ config::KakarotRpcConfig, eth_rpc::api::kakarot_api::KakarotApiServer, - pool::{get_retry_tx_interval, get_transaction_max_retries}, providers::eth_provider::{ constant::{Constant, MAX_LOGS}, error::{EthApiError, EthereumDataFormatError, SignatureError}, @@ -100,8 +99,6 @@ where Ok(Constant { max_logs: *MAX_LOGS, starknet_network: String::from(starknet_config.network_url), - retry_tx_interval: get_retry_tx_interval(), - transaction_max_retries: get_transaction_max_retries(), max_felts_in_calldata: *MAX_FELTS_IN_CALLDATA, white_listed_eip_155_transaction_hashes: get_white_listed_eip_155_transaction_hashes(), }) diff --git a/src/lib.rs b/src/lib.rs index 9dbb6dba4..d3b97ba92 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ #![cfg_attr(not(any(test, feature = "testing")), warn(unused_crate_dependencies))] +use opentelemetry as _; use opentelemetry_otlp as _; use opentelemetry_sdk as _; use tracing_opentelemetry as _; diff --git a/src/main.rs b/src/main.rs index 5ca65aef4..ce6d9f1ef 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,6 @@ use kakarot_rpc::{ client::EthClient, config::KakarotRpcConfig, eth_rpc::{config::RPCConfig, rpc::KakarotRpcModuleBuilder, run_server}, - pool::RetryHandler, providers::eth_provider::database::Database, }; use mongodb::options::{DatabaseOptions, ReadConcern, WriteConcern}; @@ -50,10 +49,6 @@ async fn main() -> Result<()> { let eth_client = EthClient::try_new(starknet_provider, db.clone()).await.expect("failed to start ethereum client"); - // Setup the retry handler - let retry_handler = RetryHandler::new(eth_client.clone(), db); - retry_handler.start(&tokio::runtime::Handle::current()); - // Setup the RPC module let kakarot_rpc_module = KakarotRpcModuleBuilder::new(eth_client).rpc_module()?; diff --git a/src/pool/mempool.rs b/src/pool/mempool.rs index 9cb0dd413..492e1e1f4 100644 --- a/src/pool/mempool.rs +++ b/src/pool/mempool.rs @@ -1,12 +1,23 @@ use super::validate::KakarotTransactionValidator; -use crate::pool::EthClient; +use crate::{ + client::EthClient, + into_via_wrapper, + models::felt::Felt252Wrapper, + providers::eth_provider::{ + error::ExecutionError, + starknet::{ERC20Reader, STARKNET_NATIVE_TOKEN}, + utils::{class_hash_not_declared, contract_not_found}, + }, +}; +use reth_primitives::{BlockId, U256}; use reth_transaction_pool::{ blobstore::NoopBlobStore, CoinbaseTipOrdering, EthPooledTransaction, Pool, TransactionPool, }; use serde_json::Value; use starknet::core::types::Felt; -use std::{collections::HashSet, fs::File, io::Read, time::Duration}; -use tokio::runtime::Handle; +use std::{collections::HashMap, fs::File, io::Read, sync::Arc, time::Duration}; +use tokio::{runtime::Handle, sync::Mutex}; +use tracing::Instrument; /// A type alias for the Kakarot Transaction Validator. /// Uses the Reth implementation [`TransactionValidationTaskExecutor`]. @@ -19,55 +30,100 @@ pub type TransactionOrdering = CoinbaseTipOrdering; /// A type alias for the Kakarot Sequencer Mempool. pub type KakarotPool = Pool, TransactionOrdering, NoopBlobStore>; -#[derive(Debug, Default)] -pub struct AccountManager { - accounts: HashSet, +/// Manages a collection of accounts and their associated nonces, interfacing with an Ethereum client. +/// +/// This struct provides functionality to initialize account data from a file, monitor account balances, +/// and process transactions for accounts with sufficient balance. +#[derive(Debug)] +pub struct AccountManager { + /// A shared, mutable collection of accounts and their nonces. + accounts: Arc>>, + /// The Ethereum client used to interact with the blockchain. + eth_client: Arc>, } -impl AccountManager { - pub fn new(path: &str) -> Self { - let mut accounts = HashSet::new(); +impl AccountManager { + /// Creates a new [`AccountManager`] instance by initializing account data from a JSON file. + pub async fn new(path: &str, eth_client: Arc>) -> eyre::Result { + let mut accounts = HashMap::new(); // Open the file specified by `path` - let Ok(mut file) = File::open(path) else { - return Self::default(); - }; + let mut file = File::open(path)?; let mut contents = String::new(); - if file.read_to_string(&mut contents).is_err() { - return Self::default(); - } + file.read_to_string(&mut contents)?; // Parse the file contents as JSON - let json: Value = match serde_json::from_str(&contents) { - Ok(json) => json, - Err(_) => { - return Self::default(); - } - }; + let json: Value = serde_json::from_str(&contents)?; // Extract the account addresses from the JSON array if let Some(array) = json.as_array() { for item in array { - if let Some(address) = item.as_str() { - accounts.insert(Felt::from_hex_unchecked(address)); + if let Some(account_address) = item.as_str() { + let felt_address = Felt::from_hex_unchecked(account_address); + + let starknet_block_id = eth_client + .eth_provider() + .to_starknet_block_id(Some(BlockId::default())) + .await + .map_err(|e| eyre::eyre!("Error converting block ID: {:?}", e))?; + + // Query the initial account_nonce for the account from the provider + accounts.insert( + felt_address, + eth_client + .eth_provider() + .starknet_provider() + .get_nonce(starknet_block_id, felt_address) + .await + .unwrap_or_default(), + ); } } } - Self { accounts } + if accounts.is_empty() { + return Err(eyre::eyre!("No accounts found in file")); + } + + Ok(Self { accounts: Arc::new(Mutex::new(accounts)), eth_client }) } - pub fn start(&self, rt_handle: &Handle, eth_client: &'static EthClient) - where - SP: starknet::providers::Provider + Send + Sync + Clone + 'static, - { + /// Starts the account manager task that periodically checks account balances and processes transactions. + #[allow(clippy::significant_drop_tightening)] + pub fn start(&'static self, rt_handle: &Handle) { let accounts = self.accounts.clone(); rt_handle.spawn(async move { loop { - for address in &accounts { - Self::process_transaction(address, eth_client); + // Get account addresses first without acquiring the lock + let account_addresses: Vec = { + let accounts = accounts.lock().await; + accounts.keys().copied().collect() + }; + + // Iterate over account addresses and check balances + for account_address in account_addresses { + // Fetch the balance and handle errors functionally + let balance = self + .get_balance(&account_address) + .await + .inspect_err(|err| { + tracing::error!( + "Error getting balance for account_address {:?}: {:?}", + account_address, + err + ); + }) + .unwrap_or_default(); + + if balance > U256::from(u128::pow(10, 18)) { + // Acquire lock only when necessary to modify account state + let mut accounts = accounts.lock().await; + if let Some(account_nonce) = accounts.get_mut(&account_address) { + self.process_transaction(&account_address, account_nonce); + } + } } tokio::time::sleep(Duration::from_secs(1)).await; @@ -75,41 +131,47 @@ impl AccountManager { }); } - fn process_transaction(address: &Felt, eth_client: &EthClient) - where - SP: starknet::providers::Provider + Send + Sync + Clone + 'static, - { - let balance = Self::check_balance(address); + /// Retrieves the balance of the specified account address. + async fn get_balance(&self, account_address: &Felt) -> eyre::Result { + // Convert the optional Ethereum block ID to a Starknet block ID. + let starknet_block_id = self.eth_client.eth_provider().to_starknet_block_id(Some(BlockId::default())).await?; - if balance > Felt::ONE { - let best_hashes = eth_client.mempool().as_ref().best_transactions().map(|x| *x.hash()).collect::>(); + // Create a new `ERC20Reader` instance for the Starknet native token + let eth_contract = ERC20Reader::new(*STARKNET_NATIVE_TOKEN, self.eth_client.eth_provider().starknet_provider()); - if let Some(best_hash) = best_hashes.first() { - eth_client.mempool().as_ref().remove_transactions(vec![*best_hash]); - } + // Call the `balanceOf` method on the contract for the given account_address and block ID, awaiting the result + let span = tracing::span!(tracing::Level::INFO, "sn::balance"); + let res = eth_contract.balanceOf(account_address).block_id(starknet_block_id).call().instrument(span).await; + + if contract_not_found(&res) || class_hash_not_declared(&res) { + return Err(eyre::eyre!("Contract not found or class hash not declared")); } - } - const fn check_balance(_address: &Felt) -> Felt { - Felt::ONE - } -} + // Otherwise, extract the balance from the result, converting any errors to ExecutionError + let balance = res.map_err(ExecutionError::from)?.balance; -#[cfg(test)] -mod tests { - use super::*; + // Convert the low and high parts of the balance to U256 + let low: U256 = into_via_wrapper!(balance.low); + let high: U256 = into_via_wrapper!(balance.high); - #[test] - fn test_account_manager_new() { - let account_manager = AccountManager::new("src/pool/accounts.json"); + // Combine the low and high parts to form the final balance and return it + let balance = low + (high << 128); - let accounts = account_manager.accounts; + Ok(balance) + } - assert!(accounts - .contains(&Felt::from_hex_unchecked("0x00686735619287df0f11ec4cda22675f780886b52bf59cf899dd57fd5d5f4cad"))); - assert!(accounts - .contains(&Felt::from_hex_unchecked("0x0332825a42ccbec3e2ceb6c242f4dff4682e7d16b8559104b5df8fd925ddda09"))); - assert!(accounts - .contains(&Felt::from_hex_unchecked("0x003f5628053c2d6bdfc9e45ea8aeb14405b8917226d455a94b3225a9a7520559"))); + /// Processes a transaction for the given account if the balance is sufficient. + fn process_transaction(&self, _account_address: &Felt, account_nonce: &mut Felt) + where + SP: starknet::providers::Provider + Send + Sync + Clone + 'static, + { + let best_hashes = self.eth_client.mempool().as_ref().best_transactions().map(|x| *x.hash()).collect::>(); + + if let Some(best_hash) = best_hashes.first() { + self.eth_client.mempool().as_ref().remove_transactions(vec![*best_hash]); + + // Increment account_nonce after sending a transaction + *account_nonce = *account_nonce + 1; + } } } diff --git a/src/pool/mod.rs b/src/pool/mod.rs index f1a8855d6..6353b6168 100644 --- a/src/pool/mod.rs +++ b/src/pool/mod.rs @@ -1,244 +1,2 @@ -#![allow(clippy::used_underscore_binding)] -use crate::{ - client::{EthClient, KakarotTransactions}, - providers::eth_provider::database::{ - ethereum::EthereumTransactionStore, - filter::{self, EthDatabaseFilterBuilder}, - types::transaction::StoredPendingTransaction, - Database, - }, -}; -use eyre::Result; -use opentelemetry::metrics::{Gauge, Unit}; -use reth_primitives::{TransactionSignedEcRecovered, B256}; -use starknet::providers::Provider; -use std::{ - fmt, - str::FromStr, - time::{Duration, Instant}, -}; -use tokio::runtime::Handle; -use tracing::{instrument, Instrument}; -#[cfg(test)] -use {futures::lock::Mutex, std::sync::Arc}; - pub mod mempool; pub mod validate; - -pub fn get_retry_tx_interval() -> u64 { - u64::from_str(&std::env::var("RETRY_TX_INTERVAL").expect("Missing environment variable RETRY_TX_INTERVAL")) - .expect("failing to parse RETRY_TX_INTERVAL") -} - -pub fn get_transaction_max_retries() -> u8 { - u8::from_str( - &std::env::var("TRANSACTION_MAX_RETRIES").expect("Missing environment variable TRANSACTION_MAX_RETRIES"), - ) - .expect("failing to parse TRANSACTION_MAX_RETRIES") -} - -/// The [`RetryHandler`] is responsible for retrying transactions that have failed. -pub struct RetryHandler { - /// The Ethereum client. - eth_client: EthClient, - /// The database. - database: Database, - /// The time to retry transactions recorded in an Observable. - retry_time: Gauge, - /// The retried transactions hashes. - #[cfg(test)] - retried: Arc>>, -} - -impl fmt::Debug for RetryHandler { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("RetryHandler") - .field("eth_client", &"...") - .field("database", &self.database) - .finish_non_exhaustive() - } -} - -impl RetryHandler -where - SP: Provider + Clone + Send + Sync + 'static, -{ - /// Creates a new [`RetryHandler`] with the given Ethereum provider, database. - #[allow(clippy::missing_const_for_fn)] - pub fn new(eth_client: EthClient, database: Database) -> Self { - let retry_time = opentelemetry::global::meter("retry_service") - .u64_gauge("retry_time") - .with_description("The time taken to process pending transactions") - .with_unit(Unit::new("microseconds")) - .init(); - Self { - eth_client, - database, - retry_time, - #[cfg(test)] - retried: Arc::new(Mutex::new(Vec::new())), - } - } - - /// Spawns a new task on the provided tokio runtime that will pool transactions. - #[instrument(skip_all, name = "pool_service")] - pub fn start(self, rt_handle: &Handle) { - tracing::info!("starting pool service"); - rt_handle.spawn(async move { - loop { - let start = Instant::now(); - if let Err(err) = self.process_pending_transactions().await { - tracing::error!(?err); - } - let end = Instant::now(); - let elapsed = end - start; - self.retry_time.record(elapsed.as_micros() as u64, &[]); - - tokio::time::sleep(Duration::from_secs(get_retry_tx_interval())).await; - } - }); - } - - /// Processes all current pending transactions by retrying them - /// and pruning them if necessary. - async fn process_pending_transactions(&self) -> Result<()> { - let pending_transactions = self.pending_transactions().await?; - for transaction in pending_transactions { - if self.should_retry(&transaction).await? { - self.retry_transaction(transaction).await?; - } else { - self.prune_transaction(transaction.hash).await?; - } - } - Ok(()) - } - - /// Retries a transaction and prunes it if the conversion to a primitive transaction fails. - async fn retry_transaction(&self, transaction: StoredPendingTransaction) -> Result<()> { - let hash = transaction.hash; - tracing::info!(%hash, retries = transaction.retries + 1, "retrying"); - - // Generate primitive transaction, handle error if any - let transaction = match TransactionSignedEcRecovered::try_from(transaction.tx.clone()) { - Ok(transaction) => transaction, - Err(error) => { - self.prune_transaction(hash).await?; - return Err(error.into()); - } - }; - - let _hash = self.eth_client.send_raw_transaction(transaction.into_signed().envelope_encoded()).await?; - #[cfg(test)] - self.retried.lock().await.push(_hash); - Ok(()) - } - - /// Prunes a transaction from the database given its hash. - async fn prune_transaction(&self, hash: B256) -> Result<()> { - tracing::info!(%hash, "pruning"); - let filter = EthDatabaseFilterBuilder::::default().with_tx_hash(&hash).build(); - self.database.delete_one::(filter).await?; - Ok(()) - } - - /// Returns all pending transactions. - async fn pending_transactions(&self) -> Result> { - let span = tracing::span!(tracing::Level::INFO, "db::pending_transactions"); - Ok(self.database.get_all().instrument(span).await?) - } - - /// Returns true if the transaction should be retried. A transaction should be retried if it has - /// not been executed and the number of retries is less than the maximum number of retries. - async fn should_retry(&self, transaction: &StoredPendingTransaction) -> Result { - let max_retries_reached = transaction.retries + 1 >= get_transaction_max_retries(); - let transaction_executed = self.database.transaction(&transaction.hash).await?.is_some(); - Ok(!max_retries_reached && !transaction_executed) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::test_utils::{ - fixtures::{katana, setup}, - katana::Katana, - }; - use rstest::*; - - #[rstest] - #[awt] - #[tokio::test(flavor = "multi_thread")] - async fn test_retry_handler(#[future] katana: Katana, _setup: ()) { - // Given - let eth_provider = katana.eth_provider(); - let eth_client = katana.eth_client(); - let db = eth_provider.database().clone(); - let retry_handler = RetryHandler::new(eth_client, db.clone()); - - // Insert the first transaction into the pending transactions collection with 0 pool - let transaction1 = katana.eoa().mock_transaction_with_nonce(0).await.expect("Failed to get mock transaction"); - db.upsert_pending_transaction(transaction1.clone(), 0) - .await - .expect("Failed to insert pending transaction in database"); - - // Insert the transaction into the pending transactions collection with TRANSACTION_MAX_RETRIES + 1 pool - // Shouldn't be retried as it has reached the maximum number of retries - let transaction2 = katana.eoa().mock_transaction_with_nonce(1).await.expect("Failed to get mock transaction"); - db.upsert_pending_transaction(transaction2.clone(), get_transaction_max_retries() + 1) - .await - .expect("Failed to insert pending transaction in database"); - - // Insert the transaction into both the mined transactions and pending transactions collections - // shouldn't be retried as it has already been mined - let transaction3 = katana.eoa().mock_transaction_with_nonce(2).await.expect("Failed to get mock transaction"); - db.upsert_pending_transaction(transaction3.clone(), 0) - .await - .expect("Failed to insert pending transaction in database"); - db.upsert_transaction(transaction3.clone()).await.expect("Failed to insert transaction in mined collection"); - - let mut pending_tx_hashes: Vec = Vec::new(); - let mut last_retried_transactions_hashes_len = retry_handler.retried.lock().await.len(); - - for i in 0..get_transaction_max_retries() + 2 { - // Retry transactions. - retry_handler.process_pending_transactions().await.expect("Failed to pool transactions"); - - // Retrieve the retried transactions. - let retried = retry_handler.retried.lock().await.clone(); - // Slice the retried transactions that were not retried in the previous iteration. - let retried_transaction_hashes = retried[last_retried_transactions_hashes_len..].to_vec(); - // Update the last retried transactions length. - last_retried_transactions_hashes_len = retried.len(); - - // Assert that there is only one retried transaction before reaching pool limit. - assert_eq!(retried_transaction_hashes.len(), usize::from(i + 1 < get_transaction_max_retries())); - - // Retrieve the pending transactions. - let pending_transactions = - db.get_all::().await.expect("Failed get pending transactions"); - - if i + 1 < get_transaction_max_retries() { - // Ensure that the spurious transactions are dropped from the pending transactions collection - assert_eq!(pending_transactions.len(), 1); - - // Ensure that the pool is incremented for the first transaction - assert_eq!(pending_transactions.first().unwrap().retries, i + 1); - - // Ensure that the transaction1 is still in the pending transactions collection - assert_eq!(pending_transactions.first().unwrap().tx, transaction1); - - // Get the pending transaction hash - let pending_tx_hash = retried_transaction_hashes.first().unwrap(); - - // Ensure that the pending transaction hash is not already in the list - // Transaction hashes should be unique - assert!(!pending_tx_hashes.contains(pending_tx_hash)); - - // Add the pending transaction hash to the list - pending_tx_hashes.push(*pending_tx_hash); - } else { - assert_eq!(pending_transactions.len(), 0); - } - } - } -} diff --git a/src/providers/eth_provider/constant.rs b/src/providers/eth_provider/constant.rs index f8a4e134a..7f614f8b1 100644 --- a/src/providers/eth_provider/constant.rs +++ b/src/providers/eth_provider/constant.rs @@ -31,10 +31,6 @@ pub struct Constant { pub max_logs: Option, /// Name of the `StarkNet` network. pub starknet_network: String, - /// Interval in seconds to retry transactions. - pub retry_tx_interval: u64, - /// Maximum number of retries for a transaction. - pub transaction_max_retries: u8, /// Maximum number of Felts in calldata. pub max_felts_in_calldata: usize, /// List of whitelisted hashes allow to submit pre EIP-155 transactions. diff --git a/tests/tests/kakarot_api.rs b/tests/tests/kakarot_api.rs index 07494aaa2..429ff0e70 100644 --- a/tests/tests/kakarot_api.rs +++ b/tests/tests/kakarot_api.rs @@ -140,24 +140,18 @@ async fn test_kakarot_get_config(#[future] katana: Katana, _setup: ()) { let starknet_network = "http://0.0.0.0:1010/"; let white_listed_eip_155_transaction_hashes = "0xe65425dacfc1423823cb4766aa0192ffde61eaa9bf81af9fe15149a89ef36c28"; let max_logs = 10000; - let retry_tx_interval = 10; - let transaction_max_retries = 10; let max_felts_in_calldata = 22500; // Set environment variables for the test std::env::set_var("STARKNET_NETWORK", starknet_network); std::env::set_var("WHITE_LISTED_EIP_155_TRANSACTION_HASHES", white_listed_eip_155_transaction_hashes); std::env::set_var("MAX_LOGS", max_logs.to_string()); - std::env::set_var("RETRY_TX_INTERVAL", retry_tx_interval.to_string()); - std::env::set_var("TRANSACTION_MAX_RETRIES", transaction_max_retries.to_string()); std::env::set_var("MAX_FELTS_IN_CALLDATA", max_felts_in_calldata.to_string()); // Hardcoded expected values let expected_constant = Constant { max_logs: Some(max_logs), starknet_network: (starknet_network).to_string(), - retry_tx_interval, - transaction_max_retries, max_felts_in_calldata, white_listed_eip_155_transaction_hashes: vec![B256::from_str(white_listed_eip_155_transaction_hashes).unwrap()], };