From 713006f6483f9b5f79a4df9f060f5ce91e0033fd Mon Sep 17 00:00:00 2001 From: f3kilo Date: Thu, 21 Nov 2024 13:34:54 +0300 Subject: [PATCH 01/31] txs priority queue --- Cargo.lock | 1 + .../src/commands/bitfinity_send_raw_txs.rs | 54 +++++++++++++++++++ bin/reth/src/commands/mod.rs | 3 +- crates/node/builder/src/launch/mod.rs | 6 ++- crates/rpc/rpc-eth-api/Cargo.toml | 3 +- .../src/helpers/bitfinity_evm_rpc.rs | 30 +++++++++-- .../rpc/src/eth/helpers/bitfinity_evm_rpc.rs | 20 ++++--- 7 files changed, 104 insertions(+), 13 deletions(-) create mode 100644 bin/reth/src/commands/bitfinity_send_raw_txs.rs diff --git a/Cargo.lock b/Cargo.lock index 6d19aa342f0..d45ef3cf4fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9095,6 +9095,7 @@ name = "reth-rpc-eth-api" version = "1.0.0" dependencies = [ "alloy-dyn-abi", + "alloy-rlp", "async-trait", "auto_impl", "dyn-clone", diff --git a/bin/reth/src/commands/bitfinity_send_raw_txs.rs b/bin/reth/src/commands/bitfinity_send_raw_txs.rs new file mode 100644 index 00000000000..f1cca60b075 --- /dev/null +++ b/bin/reth/src/commands/bitfinity_send_raw_txs.rs @@ -0,0 +1,54 @@ +use std::{collections::BTreeMap, sync::Arc}; + +use crate::primitives::ruint::Uint; +use alloy_rlp::{Bytes, Decodable}; +use reth_chainspec::ChainSpec; +use reth_primitives::{TransactionSigned, U256}; +use reth_rpc::eth::RawTransactionForwarder; +use reth_rpc_eth_types::{EthApiError, EthResult}; +use tokio::sync::Mutex; +use tracing::warn; + +/// Command to send transactions by timer. +#[derive(Debug)] +pub struct BitfinityTransactionsForwarder { + queue: Arc>, + chain_spec: Arc, +} + +#[async_trait::async_trait] +impl RawTransactionForwarder for BitfinityTransactionsForwarder { + async fn forward_raw_transaction(&self, mut raw: &[u8]) -> EthResult<()> { + let typed_tx = TransactionSigned::decode(&mut raw).map_err(|e| { + warn!("failed to decode signed transaction in the BitfinityTransactionsForwarder: {e}"); + EthApiError::FailedToDecodeSignedTransaction + })?; + + let gas_price = typed_tx.effective_gas_price(None); + + self.queue.lock().await.push(Uint::from(gas_price), raw.to_vec().into()); + + Ok(()) + } +} + +#[derive(Debug, Default)] +pub struct TransactionsPriorityQueue(BTreeMap); + +impl TransactionsPriorityQueue { + pub fn push(&mut self, gas_price: U256, tx: Bytes) { + self.0.insert(gas_price, tx); + } + + pub fn pop_tx_with_highest_price(&mut self) -> Option<(U256, Bytes)> { + self.0.pop_last() + } + + pub fn len(&self) -> usize { + self.0.len() + } + + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } +} diff --git a/bin/reth/src/commands/mod.rs b/bin/reth/src/commands/mod.rs index 412c0609b67..a2950e08133 100644 --- a/bin/reth/src/commands/mod.rs +++ b/bin/reth/src/commands/mod.rs @@ -1,7 +1,8 @@ //! This contains all of the `reth` commands -pub mod bitfinity_reset_evm_state; pub mod bitfinity_import; +pub mod bitfinity_reset_evm_state; +pub mod bitfinity_send_raw_txs; pub mod config_cmd; pub mod debug_cmd; pub mod dump_genesis; diff --git a/crates/node/builder/src/launch/mod.rs b/crates/node/builder/src/launch/mod.rs index 4077137c58f..a3e0baa4f56 100644 --- a/crates/node/builder/src/launch/mod.rs +++ b/crates/node/builder/src/launch/mod.rs @@ -394,7 +394,11 @@ where full_node.config.debug.terminate, ), node: full_node, - bitfinity_import: Some((ctx.provider_factory().clone(), ctx.node_config().bitfinity_import_arg.clone()))}; + bitfinity_import: Some(( + ctx.provider_factory().clone(), + ctx.node_config().bitfinity_import_arg.clone(), + )), + }; Ok(handle) } diff --git a/crates/rpc/rpc-eth-api/Cargo.toml b/crates/rpc/rpc-eth-api/Cargo.toml index fc31fdc7ed3..11420146558 100644 --- a/crates/rpc/rpc-eth-api/Cargo.toml +++ b/crates/rpc/rpc-eth-api/Cargo.toml @@ -32,6 +32,7 @@ reth-rpc-server-types.workspace = true # ethereum alloy-dyn-abi = { workspace = true, features = ["eip712"] } +alloy-rlp.workspace = true # rpc jsonrpsee = { workspace = true, features = ["server", "macros"] } @@ -57,4 +58,4 @@ optimism = [ "revm/optimism", "reth-provider/optimism", "reth-rpc-eth-types/optimism" -] \ No newline at end of file +] diff --git a/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs b/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs index 995cb21742b..503ac621904 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs @@ -2,17 +2,26 @@ use std::sync::Arc; +use alloy_rlp::Decodable; use ethereum_json_rpc_client::{reqwest::ReqwestClient, EthJsonRpcClient}; use ethereum_json_rpc_client::{Block, CertifiedResult, H256}; use futures::Future; use jsonrpsee::core::RpcResult; use reth_chainspec::ChainSpec; -use reth_rpc_server_types::result::internal_rpc_err; +use reth_primitives::TransactionSigned; +use reth_rpc_server_types::result::{internal_rpc_err, invalid_params_rpc_err}; use revm_primitives::{Address, Bytes, B256, U256}; +use crate::RawTransactionForwarder; + /// Proxy to the Bitfinity EVM RPC. pub trait BitfinityEvmRpc { - /// Returns the ChainSpec. + /// Returns raw transactions forwarder. + fn raw_tx_forwarder(&self) -> Option> { + None + } + + /// Returns the `ChainSpec`. fn chain_spec(&self) -> Arc; /// Forwards `eth_gasPrice` calls to the Bitfinity EVM. @@ -52,7 +61,22 @@ pub trait BitfinityEvmRpc { /// Forwards `eth_sendRawTransaction` calls to the Bitfinity EVM fn send_raw_transaction(&self, tx: Bytes) -> impl Future> + Send { let chain_spec = self.chain_spec(); + let forwarder = self.raw_tx_forwarder(); + async move { + // If tx_forwarder is set, use it. + if let Some(forwarder) = forwarder { + let typed_tx = TransactionSigned::decode(&mut tx.as_ref()).map_err(|e| { + invalid_params_rpc_err(format!( + "failed to decode eth_sendRawTransaction input: {e}" + )) + })?; + let hash = typed_tx.hash(); + forwarder.forward_raw_transaction(&tx).await?; + return Ok(hash); + } + + // Otherwise, send tx directly. let (rpc_url, client) = get_client(&chain_spec)?; let tx_hash = client.send_raw_transaction_bytes(&tx).await.map_err(|e| { @@ -94,7 +118,7 @@ pub trait BitfinityEvmRpc { async move { let (rpc_url, client) = get_client(&chain_spec)?; - let certified_block = client.get_last_certified_block().await.map_err(|e| { + let certified_block = client.get_last_certified_block().await.map_err(|e| { internal_rpc_err(format!( "failed to forward get_last_certified_block request to {}: {}", rpc_url, e diff --git a/crates/rpc/rpc/src/eth/helpers/bitfinity_evm_rpc.rs b/crates/rpc/rpc/src/eth/helpers/bitfinity_evm_rpc.rs index 6d39468ebf3..0a9978aec42 100644 --- a/crates/rpc/rpc/src/eth/helpers/bitfinity_evm_rpc.rs +++ b/crates/rpc/rpc/src/eth/helpers/bitfinity_evm_rpc.rs @@ -1,18 +1,24 @@ //! Implements Bifitnity EVM RPC methods. -//! +//! use std::sync::Arc; +use alloy_primitives::Uint; +use reth_primitives::TransactionSigned; use reth_provider::ChainSpecProvider; -use reth_rpc_eth_api::helpers::bitfinity_evm_rpc::BitfinityEvmRpc; +use reth_rpc_eth_api::{helpers::bitfinity_evm_rpc::BitfinityEvmRpc, RawTransactionForwarder}; use crate::EthApi; - -impl BitfinityEvmRpc for EthApi -where Provider: ChainSpecProvider { +impl BitfinityEvmRpc + for EthApi +where + Provider: ChainSpecProvider, +{ + fn raw_tx_forwarder(&self) -> Option> { + self.inner.raw_tx_forwarder() + } fn chain_spec(&self) -> Arc { self.inner.provider().chain_spec() } - -} \ No newline at end of file +} From 5faa2d3fcff310cf433b99a119485788d6a63b13 Mon Sep 17 00:00:00 2001 From: f3kilo Date: Thu, 21 Nov 2024 14:00:44 +0300 Subject: [PATCH 02/31] added forwarder to the node --- .../src/commands/bitfinity_send_raw_txs.rs | 17 ++++++++++++++- bin/reth/src/main.rs | 21 +++++++++++++++++-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/bin/reth/src/commands/bitfinity_send_raw_txs.rs b/bin/reth/src/commands/bitfinity_send_raw_txs.rs index f1cca60b075..b3dd89ed8f4 100644 --- a/bin/reth/src/commands/bitfinity_send_raw_txs.rs +++ b/bin/reth/src/commands/bitfinity_send_raw_txs.rs @@ -9,13 +9,23 @@ use reth_rpc_eth_types::{EthApiError, EthResult}; use tokio::sync::Mutex; use tracing::warn; -/// Command to send transactions by timer. +/// Forwarder to push transactions to the priority queue. #[derive(Debug)] pub struct BitfinityTransactionsForwarder { queue: Arc>, chain_spec: Arc, } +impl BitfinityTransactionsForwarder { + /// Creates new forwarder with the given parameters. + pub const fn new( + queue: Arc>, + chain_spec: Arc, + ) -> Self { + Self { queue, chain_spec } + } +} + #[async_trait::async_trait] impl RawTransactionForwarder for BitfinityTransactionsForwarder { async fn forward_raw_transaction(&self, mut raw: &[u8]) -> EthResult<()> { @@ -32,22 +42,27 @@ impl RawTransactionForwarder for BitfinityTransactionsForwarder { } } +/// Priority queue to get transactions sorted by gas price. #[derive(Debug, Default)] pub struct TransactionsPriorityQueue(BTreeMap); impl TransactionsPriorityQueue { + /// Adds the tx with the given gas price. pub fn push(&mut self, gas_price: U256, tx: Bytes) { self.0.insert(gas_price, tx); } + /// Returns tx with highest gas price, if present. pub fn pop_tx_with_highest_price(&mut self) -> Option<(U256, Bytes)> { self.0.pop_last() } + /// Number of transactions in the queue. pub fn len(&self) -> usize { self.0.len() } + /// Returns true if length == 0. pub fn is_empty(&self) -> bool { self.0.is_empty() } diff --git a/bin/reth/src/main.rs b/bin/reth/src/main.rs index ff3237a562d..7a0601faf08 100644 --- a/bin/reth/src/main.rs +++ b/bin/reth/src/main.rs @@ -1,5 +1,12 @@ #![allow(missing_docs)] +use std::sync::Arc; + +use reth::commands::bitfinity_send_raw_txs::{ + BitfinityTransactionsForwarder, TransactionsPriorityQueue, +}; +use tokio::sync::Mutex; + // We use jemalloc for performance reasons. #[cfg(all(feature = "jemalloc", unix))] #[global_allocator] @@ -8,7 +15,7 @@ static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc; #[cfg(all(feature = "optimism", not(test)))] compile_error!("Cannot build the `reth` binary with the `optimism` feature flag enabled. Did you mean to build `op-reth`?"); -#[cfg(not(feature = "optimism"))] +// #[cfg(not(feature = "optimism"))] fn main() { use reth::cli::Cli; use reth::commands::bitfinity_import::BitfinityImportCommand; @@ -22,7 +29,17 @@ fn main() { } if let Err(err) = Cli::parse_args().run(|builder, _| async { - let handle = builder.launch_node(EthereumNode::default()).await?; + let handle = builder + .node(EthereumNode::default()) + .extend_rpc_modules(move |ctx| { + let chain_spec = ctx.config().chain.clone(); + let queue = Arc::new(Mutex::new(TransactionsPriorityQueue::default())); + let forwarder = BitfinityTransactionsForwarder::new(queue, chain_spec); + ctx.registry.set_eth_raw_transaction_forwarder(Arc::new(forwarder)); + Ok(()) + }) + .launch() + .await?; let blockchain_provider = handle.node.provider.clone(); let config = handle.node.config.config.clone(); From c35929564497e244551950393544819d32180b99 Mon Sep 17 00:00:00 2001 From: f3kilo Date: Fri, 22 Nov 2024 13:12:02 +0300 Subject: [PATCH 03/31] transaction sender --- bin/reth/src/commands/bitfinity_import.rs | 3 +- .../src/commands/bitfinity_send_raw_txs.rs | 202 ++++++++++++++++-- bin/reth/src/main.rs | 50 +++-- bin/reth/tests/commands/utils.rs | 7 +- crates/node/core/src/args/bitfinity_args.rs | 26 +++ 5 files changed, 257 insertions(+), 31 deletions(-) diff --git a/bin/reth/src/commands/bitfinity_import.rs b/bin/reth/src/commands/bitfinity_import.rs index 8ded202c962..43dc822a6d2 100644 --- a/bin/reth/src/commands/bitfinity_import.rs +++ b/bin/reth/src/commands/bitfinity_import.rs @@ -96,10 +96,11 @@ impl BitfinityImportCommand { /// Schedule the import job and return a handle to it. pub async fn schedule_execution( self, + job_executor: Option, ) -> eyre::Result<(JobExecutor, tokio::task::JoinHandle<()>)> { info!(target: "reth::cli - BitfinityImportCommand", "reth {} starting", SHORT_VERSION); - let job_executor = JobExecutor::new_with_local_tz(); + let job_executor = job_executor.unwrap_or_else(JobExecutor::new_with_local_tz); // Schedule the import job { diff --git a/bin/reth/src/commands/bitfinity_send_raw_txs.rs b/bin/reth/src/commands/bitfinity_send_raw_txs.rs index b3dd89ed8f4..1854ca07c8d 100644 --- a/bin/reth/src/commands/bitfinity_send_raw_txs.rs +++ b/bin/reth/src/commands/bitfinity_send_raw_txs.rs @@ -1,28 +1,165 @@ -use std::{collections::BTreeMap, sync::Arc}; +use std::{collections::BTreeMap, sync::Arc, time::Duration}; use crate::primitives::ruint::Uint; use alloy_rlp::{Bytes, Decodable}; +use did::keccak::keccak_hash; +use did::H256; +use ethereum_json_rpc_client::{reqwest::ReqwestClient, EthJsonRpcClient, Id, Params}; +use eyre::eyre; +use lightspeed_scheduler::{job::Job, scheduler::Scheduler, JobExecutor}; use reth_chainspec::ChainSpec; +use reth_node_core::version::SHORT_VERSION; +use reth_primitives::hex; use reth_primitives::{TransactionSigned, U256}; use reth_rpc::eth::RawTransactionForwarder; use reth_rpc_eth_types::{EthApiError, EthResult}; use tokio::sync::Mutex; -use tracing::warn; +use tracing::{debug, info, trace, warn}; + +/// Alias for multithread transactions priority queue. +pub type SharedQueue = Arc>; + +/// Periodically sends transactions from priority queue. +#[derive(Debug, Clone)] +pub struct BitfinityTransactionSender { + queue: SharedQueue, + chain_spec: Arc, + period: Duration, + batch_size: u32, + txs_per_execution_threshold: u32, +} + +impl BitfinityTransactionSender { + /// Creates new instance of the transaction sender. + pub const fn new( + queue: SharedQueue, + chain_spec: Arc, + period: Duration, + batch_size: u32, + txs_per_execution_threshold: u32, + ) -> Self { + Self { queue, chain_spec, period, batch_size, txs_per_execution_threshold } + } + + /// Schedule the transaction sending job and return a handle to it. + pub async fn schedule_execution( + self, + job_executor: Option, + ) -> eyre::Result<(JobExecutor, tokio::task::JoinHandle<()>)> { + info!(target: "reth::cli - BitfinityTransactionSender", "reth {} starting", SHORT_VERSION); + + let job_executor = job_executor.unwrap_or_else(JobExecutor::new_with_local_tz); + + // Schedule the import job + { + let interval = + Scheduler::Interval { interval_duration: self.period, execute_at_startup: true }; + job_executor + .add_job_with_scheduler( + interval, + Job::new("send transactions", "bitfinity tx sending", None, move || { + let tx_sender = self.clone(); + Box::pin(async move { + tx_sender.single_execution().await?; + Ok(()) + }) + }), + ) + .await; + } + + let job_handle = job_executor.run().await?; + Ok((job_executor, job_handle)) + } + + /// Execute the transaction sending job. + async fn single_execution(&self) -> eyre::Result<()> { + let mut total_sent = 0; + loop { + let to_send = self.get_transactions_to_send().await; + let result = match to_send.len() { + 0 => return Ok(()), + 1 => self.send_single_tx(&to_send[0].1).await, + _ => self.send_txs_batch(&to_send).await, + }; + + if let Err(e) = result { + warn!("Failed to send transactions to EVM canister: {e}"); + continue; + } + + total_sent += to_send.len(); + if total_sent > self.txs_per_execution_threshold as usize { + return Ok(()); + } + } + } + + async fn get_transactions_to_send(&self) -> Vec<(U256, Bytes)> { + let mut batch = Vec::with_capacity(self.batch_size as _); + let mut queue = self.queue.lock().await; + let txs_to_pop = self.batch_size.max(1); // if batch size is zero, take at least one tx. + + for _ in 0..txs_to_pop { + let Some(entry) = queue.pop_tx_with_highest_price() else { + break; + }; + + batch.push(entry); + } + + batch + } + + async fn send_single_tx(&self, to_send: &Bytes) -> Result<(), eyre::Error> { + let client = self.get_client()?; + let hash = client + .send_raw_transaction_bytes(to_send) + .await + .map_err(|e| eyre!("failed to send single transaction: {e}"))?; + + trace!("Single transaction with hash {hash} sent."); + + Ok(()) + } + + async fn send_txs_batch(&self, to_send: &[(U256, Bytes)]) -> Result<(), eyre::Error> { + let client = self.get_client()?; + + let params = + to_send.iter().map(|(_, raw)| (Params::Array(vec![hex::encode(raw).into()]), Id::Null)); + let max_batch_size = usize::MAX; + let hashes = client + .batch_request::("eth_sendRawTransaction".into(), params, max_batch_size) + .await + .map_err(|e| eyre!("failed to send single transaction: {e}"))?; + + trace!("Raw transactions batch sent. Hashes: {hashes:?}"); + + Ok(()) + } + + fn get_client(&self) -> eyre::Result> { + let Some(rpc_url) = &self.chain_spec.bitfinity_evm_url else { + return Err(eyre!("bitfinity_evm_url not found in chain spec")); + }; + + let client = EthJsonRpcClient::new(ReqwestClient::new(rpc_url.to_string())); + + Ok(client) + } +} /// Forwarder to push transactions to the priority queue. #[derive(Debug)] pub struct BitfinityTransactionsForwarder { - queue: Arc>, - chain_spec: Arc, + queue: SharedQueue, } impl BitfinityTransactionsForwarder { /// Creates new forwarder with the given parameters. - pub const fn new( - queue: Arc>, - chain_spec: Arc, - ) -> Self { - Self { queue, chain_spec } + pub const fn new(queue: SharedQueue) -> Self { + Self { queue } } } @@ -30,10 +167,12 @@ impl BitfinityTransactionsForwarder { impl RawTransactionForwarder for BitfinityTransactionsForwarder { async fn forward_raw_transaction(&self, mut raw: &[u8]) -> EthResult<()> { let typed_tx = TransactionSigned::decode(&mut raw).map_err(|e| { - warn!("failed to decode signed transaction in the BitfinityTransactionsForwarder: {e}"); + warn!("Failed to decode signed transaction in the BitfinityTransactionsForwarder: {e}"); EthApiError::FailedToDecodeSignedTransaction })?; + debug!("Pushing tx with hash {} to priority queue", typed_tx.hash); + let gas_price = typed_tx.effective_gas_price(None); self.queue.lock().await.push(Uint::from(gas_price), raw.to_vec().into()); @@ -43,27 +182,58 @@ impl RawTransactionForwarder for BitfinityTransactionsForwarder { } /// Priority queue to get transactions sorted by gas price. -#[derive(Debug, Default)] -pub struct TransactionsPriorityQueue(BTreeMap); +#[derive(Debug)] +pub struct TransactionsPriorityQueue { + queue: BTreeMap, + size_limit: usize, +} impl TransactionsPriorityQueue { + /// Creates new instance of the queue with the given limil. + pub fn new(size_limit: usize) -> Self { + Self { queue: BTreeMap::default(), size_limit } + } + /// Adds the tx with the given gas price. pub fn push(&mut self, gas_price: U256, tx: Bytes) { - self.0.insert(gas_price, tx); + let key = TxKey { gas_price, hash: keccak_hash(&tx) }; + self.queue.insert(key, tx); + + if self.len() > self.size_limit { + self.queue.pop_first(); + } } /// Returns tx with highest gas price, if present. pub fn pop_tx_with_highest_price(&mut self) -> Option<(U256, Bytes)> { - self.0.pop_last() + let entry = self.queue.pop_last(); + entry.map(|(key, tx)| (key.gas_price, tx)) } /// Number of transactions in the queue. pub fn len(&self) -> usize { - self.0.len() + self.queue.len() + } + + /// Change size limit of the queue. + pub fn set_size_limit(&mut self, new_limit: usize) { + self.size_limit = new_limit; + + while self.len() > self.size_limit { + self.queue.pop_first(); + } } /// Returns true if length == 0. pub fn is_empty(&self) -> bool { - self.0.is_empty() + self.queue.is_empty() } } + +/// This struct will sort transactions by gas price, +/// but if it is equal, the key will still be different due to hash difference. +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] +struct TxKey { + gas_price: U256, + hash: H256, +} diff --git a/bin/reth/src/main.rs b/bin/reth/src/main.rs index 7a0601faf08..2b25e4dd2c5 100644 --- a/bin/reth/src/main.rs +++ b/bin/reth/src/main.rs @@ -1,9 +1,9 @@ #![allow(missing_docs)] -use std::sync::Arc; +use std::{sync::Arc, time::Duration}; use reth::commands::bitfinity_send_raw_txs::{ - BitfinityTransactionsForwarder, TransactionsPriorityQueue, + BitfinityTransactionSender, BitfinityTransactionsForwarder, TransactionsPriorityQueue, }; use tokio::sync::Mutex; @@ -15,7 +15,7 @@ static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc; #[cfg(all(feature = "optimism", not(test)))] compile_error!("Cannot build the `reth` binary with the `optimism` feature flag enabled. Did you mean to build `op-reth`?"); -// #[cfg(not(feature = "optimism"))] +#[cfg(not(feature = "optimism"))] fn main() { use reth::cli::Cli; use reth::commands::bitfinity_import::BitfinityImportCommand; @@ -28,14 +28,24 @@ fn main() { std::env::set_var("RUST_BACKTRACE", "1"); } - if let Err(err) = Cli::parse_args().run(|builder, _| async { + let queue = Arc::new(Mutex::new(TransactionsPriorityQueue::new(1000))); + let queue_clone = Arc::clone(&queue); + + if let Err(err) = Cli::parse_args().run(move |builder, _| async { let handle = builder .node(EthereumNode::default()) .extend_rpc_modules(move |ctx| { - let chain_spec = ctx.config().chain.clone(); - let queue = Arc::new(Mutex::new(TransactionsPriorityQueue::default())); - let forwarder = BitfinityTransactionsForwarder::new(queue, chain_spec); - ctx.registry.set_eth_raw_transaction_forwarder(Arc::new(forwarder)); + let forwarder_required = ctx.config().bitfinity_import_arg.tx_queue; + if forwarder_required { + // Add custom forwarder with transactions priority queue. + queue + .blocking_lock() + .set_size_limit(ctx.config().bitfinity_import_arg.tx_queue_size as _); + + let forwarder = BitfinityTransactionsForwarder::new(queue); + ctx.registry.set_eth_raw_transaction_forwarder(Arc::new(forwarder)); + } + Ok(()) }) .launch() @@ -43,22 +53,36 @@ fn main() { let blockchain_provider = handle.node.provider.clone(); let config = handle.node.config.config.clone(); - let chain = handle.node.chain_spec(); + let chain_spec = handle.node.chain_spec(); let datadir = handle.node.data_dir.clone(); let (provider_factory, bitfinity) = handle.bitfinity_import.clone().expect("Bitfinity import not configured"); // Init bitfinity import - { + let executor = { let import = BitfinityImportCommand::new( config, datadir, - chain, - bitfinity, + chain_spec.clone(), + bitfinity.clone(), provider_factory, blockchain_provider, ); - let _import_handle = import.schedule_execution().await?; + let (executor, _job_handle) = import.schedule_execution(None).await?; + executor + }; + + if bitfinity.tx_queue { + // Init transaction sending cycle. + let period = Duration::from_secs(bitfinity.send_queued_txs_period_secs as _); + let transaction_sending = BitfinityTransactionSender::new( + queue_clone, + chain_spec, + period, + bitfinity.queued_txs_batch_size, + bitfinity.queued_txs_per_execution_threshold, + ); + let _sending_handle = transaction_sending.schedule_execution(Some(executor)).await?; } handle.node_exit_future.await diff --git a/bin/reth/tests/commands/utils.rs b/bin/reth/tests/commands/utils.rs index b2fa8338932..d047bfd89cd 100644 --- a/bin/reth/tests/commands/utils.rs +++ b/bin/reth/tests/commands/utils.rs @@ -83,7 +83,7 @@ pub async fn import_blocks( import_data.provider_factory.clone(), import_data.blockchain_db, ); - let (job_executor, _import_handle) = import.schedule_execution().await.unwrap(); + let (job_executor, _import_handle) = import.schedule_execution(None).await.unwrap(); wait_until_local_block_imported(&import_data.provider_factory, end_block, timeout).await; if shutdown_when_done { @@ -153,6 +153,11 @@ pub async fn bitfinity_import_config_data( backup_rpc_url: backup_evm_datasource_url, max_retries: 3, retry_delay_secs: 3, + tx_queue: false, + tx_queue_size: 1000, + send_queued_txs_period_secs: 3, + queued_txs_batch_size: 10, + queued_txs_per_execution_threshold: 100, }; Ok(( diff --git a/crates/node/core/src/args/bitfinity_args.rs b/crates/node/core/src/args/bitfinity_args.rs index 97489ff823a..3af14af963a 100644 --- a/crates/node/core/src/args/bitfinity_args.rs +++ b/crates/node/core/src/args/bitfinity_args.rs @@ -56,6 +56,32 @@ pub struct BitfinityImportArgs { /// Root key for the IC network #[arg(long, value_name = "IC_ROOT_KEY", default_value = IC_MAINNET_KEY)] pub ic_root_key: String, + + /// Enable transactions priority queue + #[arg(long, value_name = "TX_PRIORITY_QUEUE", default_value = "true")] + pub tx_queue: bool, + + /// Transactions priority queue will contain this much transactions at max. + #[arg(long, value_name = "TX_PRIORITY_QUEUE_SIZE", default_value = "1000")] + pub tx_queue_size: u32, + + /// Time period to send transactions batch from the priority queue. + /// Do nothing, if `tx_queue` is disabled. + #[arg(long, value_name = "SEND_QUEUED_TXS_PERIOD_SECS", default_value = "3")] + pub send_queued_txs_period_secs: u32, + + /// Send queued transactions by batches with this number of entries. + /// If set to 0 or 1, no batching is used. + /// Do nothing, if `tx_queue` is disabled. + #[arg(long, value_name = "QUEUED_TXS_BATCH_SIZE", default_value = "10")] + pub queued_txs_batch_size: u32, + + /// If transaction sender sent more queued transactions at single execution, + /// it will wait for next execution to continue. + /// If set to 0, transaction sender will try to empty queue at each execution. + /// Do nothing, if `tx_queue` is disabled. + #[arg(long, value_name = "QUEUED_TXS_PER_EXECUTION", default_value = "100")] + pub queued_txs_per_execution_threshold: u32, } /// Bitfinity Related Args From 2d87ebb8b0e4ff122b95b7de1b0ba89db3c13806 Mon Sep 17 00:00:00 2001 From: f3kilo Date: Mon, 25 Nov 2024 10:50:37 +0300 Subject: [PATCH 04/31] tests --- .../src/commands/bitfinity_send_raw_txs.rs | 70 +++++++++++++++++++ bin/reth/tests/commands/bitfinity_node_it.rs | 43 ++++++++++-- .../rpc/src/eth/helpers/bitfinity_evm_rpc.rs | 2 - 3 files changed, 106 insertions(+), 9 deletions(-) diff --git a/bin/reth/src/commands/bitfinity_send_raw_txs.rs b/bin/reth/src/commands/bitfinity_send_raw_txs.rs index 1854ca07c8d..21023ce86c6 100644 --- a/bin/reth/src/commands/bitfinity_send_raw_txs.rs +++ b/bin/reth/src/commands/bitfinity_send_raw_txs.rs @@ -1,3 +1,5 @@ +//! Utils for raw transaction batching. + use std::{collections::BTreeMap, sync::Arc, time::Duration}; use crate::primitives::ruint::Uint; @@ -237,3 +239,71 @@ struct TxKey { gas_price: U256, hash: H256, } + +#[cfg(test)] +mod tests { + use super::TransactionsPriorityQueue; + use crate::primitives::U256; + use alloy_rlp::Bytes; + use reth_primitives::TransactionSigned; + use reth_transaction_pool::test_utils::MockTransaction; + use reth_transaction_pool::PoolTransaction; + + #[test] + fn test_pop_order() { + let mut queue = TransactionsPriorityQueue::new(10); + let tx1 = transaction_with_gas_price(100); + let tx2 = transaction_with_gas_price(300); + let tx3 = transaction_with_gas_price(200); + + let tx1_bytes: Bytes = alloy_rlp::encode(&tx1).into(); + let tx2_bytes: Bytes = alloy_rlp::encode(&tx2).into(); + let tx3_bytes: Bytes = alloy_rlp::encode(&tx3).into(); + + queue.push(U256::from(tx1.effective_gas_price(None)), tx1_bytes.clone()); + queue.push(U256::from(tx2.effective_gas_price(None)), tx2_bytes.clone()); + queue.push(U256::from(tx3.effective_gas_price(None)), tx3_bytes.clone()); + + let expected_order = [tx2_bytes, tx3_bytes, tx1_bytes]; + for expected_tx in expected_order { + let popped_tx = queue.pop_tx_with_highest_price().unwrap().1; + assert_eq!(popped_tx, expected_tx); + } + + assert!(queue.is_empty()) + } + + #[test] + fn test_size_limit_should_shrink_tx_with_lowest_price() { + let mut queue = TransactionsPriorityQueue::new(2); + let tx1 = transaction_with_gas_price(100); + let tx2 = transaction_with_gas_price(300); + let tx3 = transaction_with_gas_price(200); + + let tx1_bytes: Bytes = alloy_rlp::encode(&tx1).into(); + let tx2_bytes: Bytes = alloy_rlp::encode(&tx2).into(); + let tx3_bytes: Bytes = alloy_rlp::encode(&tx3).into(); + + queue.push(U256::from(tx1.effective_gas_price(None)), tx1_bytes); + queue.push(U256::from(tx2.effective_gas_price(None)), tx2_bytes.clone()); + queue.push(U256::from(tx3.effective_gas_price(None)), tx3_bytes.clone()); + + let expected_order = [tx2_bytes, tx3_bytes]; + for expected_tx in expected_order { + let popped_tx = queue.pop_tx_with_highest_price().unwrap().1; + assert_eq!(popped_tx, expected_tx); + } + + assert!(queue.is_empty()) + } + + fn transaction_with_gas_price(gas_price: u128) -> TransactionSigned { + let tx = MockTransaction::legacy().with_gas_price(gas_price); + + TransactionSigned { + hash: *tx.hash(), + signature: Default::default(), + transaction: tx.into(), + } + } +} diff --git a/bin/reth/tests/commands/bitfinity_node_it.rs b/bin/reth/tests/commands/bitfinity_node_it.rs index 392003c611a..9aef934f400 100644 --- a/bin/reth/tests/commands/bitfinity_node_it.rs +++ b/bin/reth/tests/commands/bitfinity_node_it.rs @@ -12,6 +12,9 @@ use jsonrpsee::{ Methods, RpcModule, }; use rand::RngCore; +use reth::commands::bitfinity_send_raw_txs::{ + BitfinityTransactionSender, BitfinityTransactionsForwarder, TransactionsPriorityQueue, +}; use reth::{ args::{DatadirArgs, RpcServerArgs}, dirs::{DataDirPath, MaybePlatformPath}, @@ -22,7 +25,9 @@ use reth_node_builder::{NodeBuilder, NodeConfig, NodeHandle}; use reth_node_ethereum::EthereumNode; use reth_tasks::TaskManager; use revm_primitives::{Address, U256}; +use std::time::Duration; use std::{net::SocketAddr, str::FromStr, sync::Arc}; +use tokio::sync::Mutex; #[tokio::test] async fn bitfinity_test_should_start_local_reth_node() { @@ -62,7 +67,6 @@ async fn bitfinity_test_node_forward_ic_or_eth_get_last_certified_block() { .unwrap(); assert_eq!(result.certificate, vec![1u8, 3, 11]); - } #[tokio::test] @@ -257,14 +261,40 @@ async fn start_reth_node( Arc::new(init_db(data_dir.db(), Default::default()).unwrap()) }; + let queue = Arc::new(Mutex::new(TransactionsPriorityQueue::new(1000))); + let queue_clone = Arc::clone(&queue); + let node_handle = NodeBuilder::new(node_config) .with_database(database) .with_launch_context(tasks.executor()) - .launch_node(EthereumNode::default()) + .node(EthereumNode::default()) + .extend_rpc_modules(|ctx| { + let forwarder_required = ctx.config().bitfinity_import_arg.tx_queue; + if forwarder_required { + // Add custom forwarder with transactions priority queue. + queue + .blocking_lock() + .set_size_limit(ctx.config().bitfinity_import_arg.tx_queue_size as _); + + let forwarder = BitfinityTransactionsForwarder::new(queue); + ctx.registry.set_eth_raw_transaction_forwarder(Arc::new(forwarder)); + } + + Ok(()) + }) + .launch() .await .unwrap(); let reth_address = node_handle.node.rpc_server_handle().http_local_addr().unwrap(); + let transaction_sending = BitfinityTransactionSender::new( + queue_clone, + node_handle.node.chain_spec(), + Duration::from_secs(1), + 10, + 100, + ); + let _sending_handle = transaction_sending.schedule_execution(None).await.unwrap(); let client: EthJsonRpcClient = EthJsonRpcClient::new(ReqwestClient::new(format!("http://{}", reth_address))); @@ -311,7 +341,6 @@ pub mod eth_server { #[method(name = "getLastCertifiedBlock", aliases = ["ic_getLastCertifiedBlock"])] async fn get_last_certified_block(&self) -> RpcResult>>; - } #[derive(Debug)] @@ -356,10 +385,10 @@ pub mod eth_server { } async fn get_last_certified_block(&self) -> RpcResult>> { - Ok(CertifiedResult { - data: Default::default(), - witness: vec![], - certificate: vec![1u8, 3, 11] + Ok(CertifiedResult { + data: Default::default(), + witness: vec![], + certificate: vec![1u8, 3, 11], }) } } diff --git a/crates/rpc/rpc/src/eth/helpers/bitfinity_evm_rpc.rs b/crates/rpc/rpc/src/eth/helpers/bitfinity_evm_rpc.rs index 0a9978aec42..1f02bc99fb3 100644 --- a/crates/rpc/rpc/src/eth/helpers/bitfinity_evm_rpc.rs +++ b/crates/rpc/rpc/src/eth/helpers/bitfinity_evm_rpc.rs @@ -2,8 +2,6 @@ //! use std::sync::Arc; -use alloy_primitives::Uint; -use reth_primitives::TransactionSigned; use reth_provider::ChainSpecProvider; use reth_rpc_eth_api::{helpers::bitfinity_evm_rpc::BitfinityEvmRpc, RawTransactionForwarder}; From 67fe67d633f9ea7e3de1c89e2bb5a0c1f809288f Mon Sep 17 00:00:00 2001 From: f3kilo Date: Mon, 25 Nov 2024 14:37:39 +0300 Subject: [PATCH 05/31] single tx test with queue --- .../src/commands/bitfinity_send_raw_txs.rs | 49 +++++----- bin/reth/src/main.rs | 4 +- bin/reth/tests/commands/bitfinity_node_it.rs | 93 +++++++++++++------ .../src/helpers/bitfinity_evm_rpc.rs | 2 +- 4 files changed, 89 insertions(+), 59 deletions(-) diff --git a/bin/reth/src/commands/bitfinity_send_raw_txs.rs b/bin/reth/src/commands/bitfinity_send_raw_txs.rs index 21023ce86c6..33fad3856fb 100644 --- a/bin/reth/src/commands/bitfinity_send_raw_txs.rs +++ b/bin/reth/src/commands/bitfinity_send_raw_txs.rs @@ -3,13 +3,12 @@ use std::{collections::BTreeMap, sync::Arc, time::Duration}; use crate::primitives::ruint::Uint; -use alloy_rlp::{Bytes, Decodable}; +use alloy_rlp::Decodable; use did::keccak::keccak_hash; use did::H256; use ethereum_json_rpc_client::{reqwest::ReqwestClient, EthJsonRpcClient, Id, Params}; use eyre::eyre; use lightspeed_scheduler::{job::Job, scheduler::Scheduler, JobExecutor}; -use reth_chainspec::ChainSpec; use reth_node_core::version::SHORT_VERSION; use reth_primitives::hex; use reth_primitives::{TransactionSigned, U256}; @@ -25,7 +24,7 @@ pub type SharedQueue = Arc>; #[derive(Debug, Clone)] pub struct BitfinityTransactionSender { queue: SharedQueue, - chain_spec: Arc, + rpc_url: String, period: Duration, batch_size: u32, txs_per_execution_threshold: u32, @@ -35,12 +34,12 @@ impl BitfinityTransactionSender { /// Creates new instance of the transaction sender. pub const fn new( queue: SharedQueue, - chain_spec: Arc, + rpc_url: String, period: Duration, batch_size: u32, txs_per_execution_threshold: u32, ) -> Self { - Self { queue, chain_spec, period, batch_size, txs_per_execution_threshold } + Self { queue, rpc_url, period, batch_size, txs_per_execution_threshold } } /// Schedule the transaction sending job and return a handle to it. @@ -86,7 +85,7 @@ impl BitfinityTransactionSender { }; if let Err(e) = result { - warn!("Failed to send transactions to EVM canister: {e}"); + warn!("Failed to send transactions to EVM: {e}"); continue; } @@ -97,7 +96,7 @@ impl BitfinityTransactionSender { } } - async fn get_transactions_to_send(&self) -> Vec<(U256, Bytes)> { + async fn get_transactions_to_send(&self) -> Vec<(U256, Vec)> { let mut batch = Vec::with_capacity(self.batch_size as _); let mut queue = self.queue.lock().await; let txs_to_pop = self.batch_size.max(1); // if batch size is zero, take at least one tx. @@ -113,7 +112,7 @@ impl BitfinityTransactionSender { batch } - async fn send_single_tx(&self, to_send: &Bytes) -> Result<(), eyre::Error> { + async fn send_single_tx(&self, to_send: &[u8]) -> Result<(), eyre::Error> { let client = self.get_client()?; let hash = client .send_raw_transaction_bytes(to_send) @@ -125,7 +124,7 @@ impl BitfinityTransactionSender { Ok(()) } - async fn send_txs_batch(&self, to_send: &[(U256, Bytes)]) -> Result<(), eyre::Error> { + async fn send_txs_batch(&self, to_send: &[(U256, Vec)]) -> Result<(), eyre::Error> { let client = self.get_client()?; let params = @@ -142,11 +141,7 @@ impl BitfinityTransactionSender { } fn get_client(&self) -> eyre::Result> { - let Some(rpc_url) = &self.chain_spec.bitfinity_evm_url else { - return Err(eyre!("bitfinity_evm_url not found in chain spec")); - }; - - let client = EthJsonRpcClient::new(ReqwestClient::new(rpc_url.to_string())); + let client = EthJsonRpcClient::new(ReqwestClient::new(self.rpc_url.clone())); Ok(client) } @@ -167,17 +162,16 @@ impl BitfinityTransactionsForwarder { #[async_trait::async_trait] impl RawTransactionForwarder for BitfinityTransactionsForwarder { - async fn forward_raw_transaction(&self, mut raw: &[u8]) -> EthResult<()> { - let typed_tx = TransactionSigned::decode(&mut raw).map_err(|e| { + async fn forward_raw_transaction(&self, raw: &[u8]) -> EthResult<()> { + let typed_tx = TransactionSigned::decode(&mut (&raw[..])).map_err(|e| { warn!("Failed to decode signed transaction in the BitfinityTransactionsForwarder: {e}"); EthApiError::FailedToDecodeSignedTransaction })?; debug!("Pushing tx with hash {} to priority queue", typed_tx.hash); - let gas_price = typed_tx.effective_gas_price(None); - self.queue.lock().await.push(Uint::from(gas_price), raw.to_vec().into()); + self.queue.lock().await.push(Uint::from(gas_price), raw.to_vec()); Ok(()) } @@ -186,7 +180,7 @@ impl RawTransactionForwarder for BitfinityTransactionsForwarder { /// Priority queue to get transactions sorted by gas price. #[derive(Debug)] pub struct TransactionsPriorityQueue { - queue: BTreeMap, + queue: BTreeMap>, size_limit: usize, } @@ -197,7 +191,7 @@ impl TransactionsPriorityQueue { } /// Adds the tx with the given gas price. - pub fn push(&mut self, gas_price: U256, tx: Bytes) { + pub fn push(&mut self, gas_price: U256, tx: Vec) { let key = TxKey { gas_price, hash: keccak_hash(&tx) }; self.queue.insert(key, tx); @@ -207,7 +201,7 @@ impl TransactionsPriorityQueue { } /// Returns tx with highest gas price, if present. - pub fn pop_tx_with_highest_price(&mut self) -> Option<(U256, Bytes)> { + pub fn pop_tx_with_highest_price(&mut self) -> Option<(U256, Vec)> { let entry = self.queue.pop_last(); entry.map(|(key, tx)| (key.gas_price, tx)) } @@ -244,7 +238,6 @@ struct TxKey { mod tests { use super::TransactionsPriorityQueue; use crate::primitives::U256; - use alloy_rlp::Bytes; use reth_primitives::TransactionSigned; use reth_transaction_pool::test_utils::MockTransaction; use reth_transaction_pool::PoolTransaction; @@ -256,9 +249,9 @@ mod tests { let tx2 = transaction_with_gas_price(300); let tx3 = transaction_with_gas_price(200); - let tx1_bytes: Bytes = alloy_rlp::encode(&tx1).into(); - let tx2_bytes: Bytes = alloy_rlp::encode(&tx2).into(); - let tx3_bytes: Bytes = alloy_rlp::encode(&tx3).into(); + let tx1_bytes = alloy_rlp::encode(&tx1); + let tx2_bytes = alloy_rlp::encode(&tx2); + let tx3_bytes = alloy_rlp::encode(&tx3); queue.push(U256::from(tx1.effective_gas_price(None)), tx1_bytes.clone()); queue.push(U256::from(tx2.effective_gas_price(None)), tx2_bytes.clone()); @@ -280,9 +273,9 @@ mod tests { let tx2 = transaction_with_gas_price(300); let tx3 = transaction_with_gas_price(200); - let tx1_bytes: Bytes = alloy_rlp::encode(&tx1).into(); - let tx2_bytes: Bytes = alloy_rlp::encode(&tx2).into(); - let tx3_bytes: Bytes = alloy_rlp::encode(&tx3).into(); + let tx1_bytes = alloy_rlp::encode(&tx1); + let tx2_bytes = alloy_rlp::encode(&tx2); + let tx3_bytes = alloy_rlp::encode(&tx3); queue.push(U256::from(tx1.effective_gas_price(None)), tx1_bytes); queue.push(U256::from(tx2.effective_gas_price(None)), tx2_bytes.clone()); diff --git a/bin/reth/src/main.rs b/bin/reth/src/main.rs index 2b25e4dd2c5..626ff561170 100644 --- a/bin/reth/src/main.rs +++ b/bin/reth/src/main.rs @@ -73,11 +73,13 @@ fn main() { }; if bitfinity.tx_queue { + let url = bitfinity.send_raw_transaction_rpc_url.unwrap_or(bitfinity.rpc_url); + // Init transaction sending cycle. let period = Duration::from_secs(bitfinity.send_queued_txs_period_secs as _); let transaction_sending = BitfinityTransactionSender::new( queue_clone, - chain_spec, + url, period, bitfinity.queued_txs_batch_size, bitfinity.queued_txs_per_execution_threshold, diff --git a/bin/reth/tests/commands/bitfinity_node_it.rs b/bin/reth/tests/commands/bitfinity_node_it.rs index 9aef934f400..1642bd62d17 100644 --- a/bin/reth/tests/commands/bitfinity_node_it.rs +++ b/bin/reth/tests/commands/bitfinity_node_it.rs @@ -11,7 +11,6 @@ use jsonrpsee::{ server::{Server, ServerHandle}, Methods, RpcModule, }; -use rand::RngCore; use reth::commands::bitfinity_send_raw_txs::{ BitfinityTransactionSender, BitfinityTransactionsForwarder, TransactionsPriorityQueue, }; @@ -23,8 +22,10 @@ use reth_consensus::Consensus; use reth_db::{init_db, test_utils::tempdir_path}; use reth_node_builder::{NodeBuilder, NodeConfig, NodeHandle}; use reth_node_ethereum::EthereumNode; +use reth_primitives::{Transaction, TransactionSigned}; use reth_tasks::TaskManager; -use revm_primitives::{Address, U256}; +use reth_transaction_pool::test_utils::MockTransaction; +use revm_primitives::{hex, Address, U256}; use std::time::Duration; use std::{net::SocketAddr, str::FromStr, sync::Arc}; use tokio::sync::Mutex; @@ -180,16 +181,51 @@ async fn bitfinity_test_node_forward_send_raw_transaction_requests() { start_reth_node(Some(format!("http://{}", eth_server_address)), None).await; // Create a random transaction - let mut tx = [0u8; 256]; - rand::thread_rng().fill_bytes(&mut tx); - let expected_tx_hash = - keccak::keccak_hash(format!("0x{}", reth_primitives::hex::encode(tx)).as_bytes()); + let tx = transaction_with_gas_price(100); + // let codec = TransactionSigned::decode(&mut alloy_rlp::encode(&tx).as_ref()).unwrap(); + let encoded = alloy_rlp::encode(&tx); + let expected_tx_hash = keccak::keccak_hash(&encoded); // Act - let result = reth_client.send_raw_transaction_bytes(&tx).await; + let result = reth_client.send_raw_transaction_bytes(&encoded).await.unwrap(); // Assert - assert_eq!(result.unwrap(), expected_tx_hash.0); + assert_eq!(result.to_fixed_bytes(), expected_tx_hash.0.to_fixed_bytes()); + + tokio::time::sleep(Duration::from_secs(3)).await; + + assert_eq!(eth_server::TXS_ORDER.lock().await[0].0, expected_tx_hash.0.to_fixed_bytes()); +} + +// #[tokio::test] +// async fn bitfinity_test_node_send_raw_transaction_in_gas_price_order() { +// // Arrange +// let _log = init_logs(); + +// let eth_server = EthImpl::new(); +// let (_server, eth_server_address) = +// mock_eth_server_start(EthServer::into_rpc(eth_server)).await; +// let (reth_client, _reth_node) = +// start_reth_node(Some(format!("http://{}", eth_server_address)), None).await; + +// // Create a random transaction +// let mut tx = [0u8; 256]; +// rand::thread_rng().fill_bytes(&mut tx); +// let expected_tx_hash = +// keccak::keccak_hash(format!("0x{}", reth_primitives::hex::encode(tx)).as_bytes()); + +// // Act +// let result = reth_client.send_raw_transaction_bytes(&tx).await; + +// // Assert +// assert_eq!(result.unwrap(), expected_tx_hash.0); +// } + +fn transaction_with_gas_price(gas_price: u128) -> TransactionSigned { + let mock = MockTransaction::legacy().with_gas_price(gas_price); + let transaction: Transaction = mock.into(); + + TransactionSigned { hash: Default::default(), signature: Default::default(), transaction } } /// Start a local reth node @@ -238,7 +274,7 @@ async fn start_reth_node( node_config.dev.dev = false; let mut chain = node_config.chain.as_ref().clone(); - chain.bitfinity_evm_url = bitfinity_evm_url; + chain.bitfinity_evm_url = bitfinity_evm_url.clone(); let mut node_config = node_config.with_chain(chain); let database = if let Some(import_data) = import_data { @@ -269,16 +305,9 @@ async fn start_reth_node( .with_launch_context(tasks.executor()) .node(EthereumNode::default()) .extend_rpc_modules(|ctx| { - let forwarder_required = ctx.config().bitfinity_import_arg.tx_queue; - if forwarder_required { - // Add custom forwarder with transactions priority queue. - queue - .blocking_lock() - .set_size_limit(ctx.config().bitfinity_import_arg.tx_queue_size as _); - - let forwarder = BitfinityTransactionsForwarder::new(queue); - ctx.registry.set_eth_raw_transaction_forwarder(Arc::new(forwarder)); - } + // Add custom forwarder with transactions priority queue. + let forwarder = BitfinityTransactionsForwarder::new(queue); + ctx.registry.set_eth_raw_transaction_forwarder(Arc::new(forwarder)); Ok(()) }) @@ -286,18 +315,19 @@ async fn start_reth_node( .await .unwrap(); - let reth_address = node_handle.node.rpc_server_handle().http_local_addr().unwrap(); let transaction_sending = BitfinityTransactionSender::new( queue_clone, - node_handle.node.chain_spec(), - Duration::from_secs(1), + bitfinity_evm_url.unwrap_or_default(), + Duration::from_millis(100), 10, 100, ); let _sending_handle = transaction_sending.schedule_execution(None).await.unwrap(); + let reth_address = node_handle.node.rpc_server_handle().http_local_addr().unwrap(); + let addr_string = format!("http://{}", reth_address); let client: EthJsonRpcClient = - EthJsonRpcClient::new(ReqwestClient::new(format!("http://{}", reth_address))); + EthJsonRpcClient::new(ReqwestClient::new(addr_string)); (client, node_handle) } @@ -318,12 +348,12 @@ async fn mock_eth_server_start(methods: impl Into) -> (ServerHandle, So } pub mod eth_server { - - use alloy_rlp::Bytes; - use did::keccak; + use alloy_rlp::{Bytes, Decodable}; use ethereum_json_rpc_client::{Block, CertifiedResult, H256}; use jsonrpsee::{core::RpcResult, proc_macros::rpc}; - use revm_primitives::{Address, B256, U256}; + use reth_primitives::TransactionSigned; + use revm_primitives::{hex, Address, B256, U256}; + use tokio::sync::Mutex; #[rpc(server, namespace = "eth")] pub trait Eth { @@ -343,6 +373,8 @@ pub mod eth_server { async fn get_last_certified_block(&self) -> RpcResult>>; } + pub static TXS_ORDER: Mutex> = Mutex::const_new(Vec::new()); + #[derive(Debug)] pub struct EthImpl { pub gas_price: u128, @@ -372,8 +404,11 @@ pub mod eth_server { } async fn send_raw_transaction(&self, tx: Bytes) -> RpcResult { - let hash = keccak::keccak_hash(&tx); - Ok(hash.into()) + let decoded = hex::decode(&tx).unwrap(); + let tx = TransactionSigned::decode(&mut decoded.as_ref()).unwrap(); + let hash = tx.hash(); + TXS_ORDER.lock().await.push(hash); + Ok(hash) } async fn get_genesis_balances(&self) -> RpcResult> { diff --git a/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs b/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs index 503ac621904..812e3e60313 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs @@ -68,7 +68,7 @@ pub trait BitfinityEvmRpc { if let Some(forwarder) = forwarder { let typed_tx = TransactionSigned::decode(&mut tx.as_ref()).map_err(|e| { invalid_params_rpc_err(format!( - "failed to decode eth_sendRawTransaction input: {e}" + "failed to decode eth_sendRawTransaction input {tx}: {e}" )) })?; let hash = typed_tx.hash(); From 119312fce555ac95c3f6bd8ab1a1d7b0bf206bab Mon Sep 17 00:00:00 2001 From: f3kilo Date: Mon, 25 Nov 2024 14:49:53 +0300 Subject: [PATCH 06/31] test transactions order --- bin/reth/tests/commands/bitfinity_node_it.rs | 58 +++++++++++--------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/bin/reth/tests/commands/bitfinity_node_it.rs b/bin/reth/tests/commands/bitfinity_node_it.rs index 1642bd62d17..ec181533783 100644 --- a/bin/reth/tests/commands/bitfinity_node_it.rs +++ b/bin/reth/tests/commands/bitfinity_node_it.rs @@ -25,7 +25,7 @@ use reth_node_ethereum::EthereumNode; use reth_primitives::{Transaction, TransactionSigned}; use reth_tasks::TaskManager; use reth_transaction_pool::test_utils::MockTransaction; -use revm_primitives::{hex, Address, U256}; +use revm_primitives::{Address, U256}; use std::time::Duration; use std::{net::SocketAddr, str::FromStr, sync::Arc}; use tokio::sync::Mutex; @@ -182,7 +182,6 @@ async fn bitfinity_test_node_forward_send_raw_transaction_requests() { // Create a random transaction let tx = transaction_with_gas_price(100); - // let codec = TransactionSigned::decode(&mut alloy_rlp::encode(&tx).as_ref()).unwrap(); let encoded = alloy_rlp::encode(&tx); let expected_tx_hash = keccak::keccak_hash(&encoded); @@ -192,34 +191,41 @@ async fn bitfinity_test_node_forward_send_raw_transaction_requests() { // Assert assert_eq!(result.to_fixed_bytes(), expected_tx_hash.0.to_fixed_bytes()); - tokio::time::sleep(Duration::from_secs(3)).await; + tokio::time::sleep(Duration::from_secs(1)).await; assert_eq!(eth_server::TXS_ORDER.lock().await[0].0, expected_tx_hash.0.to_fixed_bytes()); } -// #[tokio::test] -// async fn bitfinity_test_node_send_raw_transaction_in_gas_price_order() { -// // Arrange -// let _log = init_logs(); - -// let eth_server = EthImpl::new(); -// let (_server, eth_server_address) = -// mock_eth_server_start(EthServer::into_rpc(eth_server)).await; -// let (reth_client, _reth_node) = -// start_reth_node(Some(format!("http://{}", eth_server_address)), None).await; - -// // Create a random transaction -// let mut tx = [0u8; 256]; -// rand::thread_rng().fill_bytes(&mut tx); -// let expected_tx_hash = -// keccak::keccak_hash(format!("0x{}", reth_primitives::hex::encode(tx)).as_bytes()); - -// // Act -// let result = reth_client.send_raw_transaction_bytes(&tx).await; - -// // Assert -// assert_eq!(result.unwrap(), expected_tx_hash.0); -// } +#[tokio::test] +async fn bitfinity_test_node_send_raw_transaction_in_gas_price_order() { + // Arrange + let _log = init_logs(); + + let eth_server = EthImpl::new(); + let (_server, eth_server_address) = + mock_eth_server_start(EthServer::into_rpc(eth_server)).await; + let (reth_client, _reth_node) = + start_reth_node(Some(format!("http://{}", eth_server_address)), None).await; + + // Create a random transactions + let transactions = (1..=10) + .map(|i| alloy_rlp::encode(transaction_with_gas_price(100 * i))) + .collect::>(); + + let expected_hashes = transactions.iter().map(|tx| keccak::keccak_hash(tx)).collect::>(); + + // Act + for (tx, expected_hash) in transactions.iter().zip(expected_hashes.iter()) { + let hash = reth_client.send_raw_transaction_bytes(tx).await.unwrap(); + assert_eq!(hash.to_fixed_bytes(), expected_hash.0.to_fixed_bytes()); + } + + tokio::time::sleep(Duration::from_secs(3)).await; + + for (idx, expected_hash) in expected_hashes.iter().rev().enumerate() { + assert_eq!(eth_server::TXS_ORDER.lock().await[idx].0, expected_hash.0.to_fixed_bytes()); + } +} fn transaction_with_gas_price(gas_price: u128) -> TransactionSigned { let mock = MockTransaction::legacy().with_gas_price(gas_price); From 690b162fdfd15898064b76dc2d47f39c66926b3c Mon Sep 17 00:00:00 2001 From: f3kilo Date: Wed, 27 Nov 2024 09:12:39 +0300 Subject: [PATCH 07/31] test fixed --- bin/reth/tests/commands/bitfinity_node_it.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/reth/tests/commands/bitfinity_node_it.rs b/bin/reth/tests/commands/bitfinity_node_it.rs index ec181533783..589add05ba8 100644 --- a/bin/reth/tests/commands/bitfinity_node_it.rs +++ b/bin/reth/tests/commands/bitfinity_node_it.rs @@ -191,7 +191,7 @@ async fn bitfinity_test_node_forward_send_raw_transaction_requests() { // Assert assert_eq!(result.to_fixed_bytes(), expected_tx_hash.0.to_fixed_bytes()); - tokio::time::sleep(Duration::from_secs(1)).await; + tokio::time::sleep(Duration::from_secs(3)).await; assert_eq!(eth_server::TXS_ORDER.lock().await[0].0, expected_tx_hash.0.to_fixed_bytes()); } From 5289ab18e86a174692b9e3950e6e2a2d95c45ccc Mon Sep 17 00:00:00 2001 From: f3kilo Date: Wed, 27 Nov 2024 10:04:33 +0300 Subject: [PATCH 08/31] tests fixed --- bin/reth/tests/commands/bitfinity_node_it.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/reth/tests/commands/bitfinity_node_it.rs b/bin/reth/tests/commands/bitfinity_node_it.rs index 589add05ba8..f6cf7473077 100644 --- a/bin/reth/tests/commands/bitfinity_node_it.rs +++ b/bin/reth/tests/commands/bitfinity_node_it.rs @@ -324,7 +324,7 @@ async fn start_reth_node( let transaction_sending = BitfinityTransactionSender::new( queue_clone, bitfinity_evm_url.unwrap_or_default(), - Duration::from_millis(100), + Duration::from_millis(1000), 10, 100, ); From 3a5b76d7aa929162bfc8168188361352ffd87e85 Mon Sep 17 00:00:00 2001 From: f3kilo Date: Wed, 27 Nov 2024 13:04:02 +0300 Subject: [PATCH 09/31] clear global state --- bin/reth/tests/commands/bitfinity_node_it.rs | 23 ++++++++++---------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/bin/reth/tests/commands/bitfinity_node_it.rs b/bin/reth/tests/commands/bitfinity_node_it.rs index f6cf7473077..a88f43c1b9d 100644 --- a/bin/reth/tests/commands/bitfinity_node_it.rs +++ b/bin/reth/tests/commands/bitfinity_node_it.rs @@ -45,7 +45,7 @@ async fn bitfinity_test_node_forward_ic_or_eth_get_last_certified_block() { // Arrange let _log = init_logs(); - let eth_server = EthImpl::new(); + let eth_server = EthImpl::new().await; let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; let (reth_client, _reth_node) = @@ -75,7 +75,7 @@ async fn bitfinity_test_node_forward_get_gas_price_requests() { // Arrange let _log = init_logs(); - let eth_server = EthImpl::new(); + let eth_server = EthImpl::new().await; let gas_price = eth_server.gas_price; let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; @@ -94,7 +94,7 @@ async fn bitfinity_test_node_forward_max_priority_fee_per_gas_requests() { // Arrange let _log = init_logs(); - let eth_server = EthImpl::new(); + let eth_server = EthImpl::new().await; let max_priority_fee_per_gas = eth_server.max_priority_fee_per_gas; let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; @@ -113,7 +113,7 @@ async fn bitfinity_test_node_forward_eth_get_genesis_balances() { // Arrange let _log = init_logs(); - let eth_server = EthImpl::new(); + let eth_server = EthImpl::new().await; let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; let (reth_client, _reth_node) = @@ -147,7 +147,7 @@ async fn bitfinity_test_node_forward_ic_get_genesis_balances() { // Arrange let _log = init_logs(); - let eth_server = EthImpl::new(); + let eth_server = EthImpl::new().await; let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; let (reth_client, _reth_node) = @@ -174,7 +174,7 @@ async fn bitfinity_test_node_forward_send_raw_transaction_requests() { // Arrange let _log = init_logs(); - let eth_server = EthImpl::new(); + let eth_server = EthImpl::new().await; let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; let (reth_client, _reth_node) = @@ -191,7 +191,7 @@ async fn bitfinity_test_node_forward_send_raw_transaction_requests() { // Assert assert_eq!(result.to_fixed_bytes(), expected_tx_hash.0.to_fixed_bytes()); - tokio::time::sleep(Duration::from_secs(3)).await; + tokio::time::sleep(Duration::from_secs(1)).await; assert_eq!(eth_server::TXS_ORDER.lock().await[0].0, expected_tx_hash.0.to_fixed_bytes()); } @@ -201,7 +201,7 @@ async fn bitfinity_test_node_send_raw_transaction_in_gas_price_order() { // Arrange let _log = init_logs(); - let eth_server = EthImpl::new(); + let eth_server = EthImpl::new().await; let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; let (reth_client, _reth_node) = @@ -220,7 +220,7 @@ async fn bitfinity_test_node_send_raw_transaction_in_gas_price_order() { assert_eq!(hash.to_fixed_bytes(), expected_hash.0.to_fixed_bytes()); } - tokio::time::sleep(Duration::from_secs(3)).await; + tokio::time::sleep(Duration::from_secs(1)).await; for (idx, expected_hash) in expected_hashes.iter().rev().enumerate() { assert_eq!(eth_server::TXS_ORDER.lock().await[idx].0, expected_hash.0.to_fixed_bytes()); @@ -324,7 +324,7 @@ async fn start_reth_node( let transaction_sending = BitfinityTransactionSender::new( queue_clone, bitfinity_evm_url.unwrap_or_default(), - Duration::from_millis(1000), + Duration::from_millis(200), 10, 100, ); @@ -388,7 +388,8 @@ pub mod eth_server { } impl EthImpl { - pub fn new() -> Self { + pub async fn new() -> Self { + TXS_ORDER.lock().await.clear(); Self { gas_price: rand::random(), max_priority_fee_per_gas: rand::random() } } } From 4502c54e27386d0013289e83567948b5f82db6f4 Mon Sep 17 00:00:00 2001 From: f3kilo Date: Wed, 27 Nov 2024 13:33:51 +0300 Subject: [PATCH 10/31] build fixed --- bin/reth/tests/commands/bitfinity_node_it.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/bin/reth/tests/commands/bitfinity_node_it.rs b/bin/reth/tests/commands/bitfinity_node_it.rs index a88f43c1b9d..f721e8e92c2 100644 --- a/bin/reth/tests/commands/bitfinity_node_it.rs +++ b/bin/reth/tests/commands/bitfinity_node_it.rs @@ -394,12 +394,6 @@ pub mod eth_server { } } - impl Default for EthImpl { - fn default() -> Self { - Self::new() - } - } - #[async_trait::async_trait] impl EthServer for EthImpl { async fn gas_price(&self) -> RpcResult { From d26ccc7e2140ccdf046f7267c3c039d483d284c1 Mon Sep 17 00:00:00 2001 From: f3kilo Date: Fri, 29 Nov 2024 11:39:37 +0300 Subject: [PATCH 11/31] remove global txs list --- bin/reth/tests/commands/bitfinity_node_it.rs | 74 ++++++++++++++------ bin/reth/tests/commands/utils.rs | 3 +- bitfinity.md | 4 +- docker-compose.yml | 2 +- 4 files changed, 59 insertions(+), 24 deletions(-) diff --git a/bin/reth/tests/commands/bitfinity_node_it.rs b/bin/reth/tests/commands/bitfinity_node_it.rs index f721e8e92c2..4bba195243b 100644 --- a/bin/reth/tests/commands/bitfinity_node_it.rs +++ b/bin/reth/tests/commands/bitfinity_node_it.rs @@ -25,7 +25,7 @@ use reth_node_ethereum::EthereumNode; use reth_primitives::{Transaction, TransactionSigned}; use reth_tasks::TaskManager; use reth_transaction_pool::test_utils::MockTransaction; -use revm_primitives::{Address, U256}; +use revm_primitives::{Address, B256, U256}; use std::time::Duration; use std::{net::SocketAddr, str::FromStr, sync::Arc}; use tokio::sync::Mutex; @@ -45,7 +45,7 @@ async fn bitfinity_test_node_forward_ic_or_eth_get_last_certified_block() { // Arrange let _log = init_logs(); - let eth_server = EthImpl::new().await; + let eth_server = EthImpl::new(); let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; let (reth_client, _reth_node) = @@ -75,7 +75,7 @@ async fn bitfinity_test_node_forward_get_gas_price_requests() { // Arrange let _log = init_logs(); - let eth_server = EthImpl::new().await; + let eth_server = EthImpl::new(); let gas_price = eth_server.gas_price; let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; @@ -94,7 +94,7 @@ async fn bitfinity_test_node_forward_max_priority_fee_per_gas_requests() { // Arrange let _log = init_logs(); - let eth_server = EthImpl::new().await; + let eth_server = EthImpl::new(); let max_priority_fee_per_gas = eth_server.max_priority_fee_per_gas; let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; @@ -113,7 +113,7 @@ async fn bitfinity_test_node_forward_eth_get_genesis_balances() { // Arrange let _log = init_logs(); - let eth_server = EthImpl::new().await; + let eth_server = EthImpl::new(); let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; let (reth_client, _reth_node) = @@ -147,7 +147,7 @@ async fn bitfinity_test_node_forward_ic_get_genesis_balances() { // Arrange let _log = init_logs(); - let eth_server = EthImpl::new().await; + let eth_server = EthImpl::new(); let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; let (reth_client, _reth_node) = @@ -174,7 +174,9 @@ async fn bitfinity_test_node_forward_send_raw_transaction_requests() { // Arrange let _log = init_logs(); - let eth_server = EthImpl::new().await; + let eth_server = EthImpl::new(); + let received_txs = eth_server.txs.clone(); + let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; let (reth_client, _reth_node) = @@ -191,9 +193,9 @@ async fn bitfinity_test_node_forward_send_raw_transaction_requests() { // Assert assert_eq!(result.to_fixed_bytes(), expected_tx_hash.0.to_fixed_bytes()); - tokio::time::sleep(Duration::from_secs(1)).await; + assert!(check_transactions_received(&received_txs, 1).await); - assert_eq!(eth_server::TXS_ORDER.lock().await[0].0, expected_tx_hash.0.to_fixed_bytes()); + assert_eq!(received_txs.lock().await[0].0, expected_tx_hash.0.to_fixed_bytes()); } #[tokio::test] @@ -201,15 +203,19 @@ async fn bitfinity_test_node_send_raw_transaction_in_gas_price_order() { // Arrange let _log = init_logs(); - let eth_server = EthImpl::new().await; + let eth_server = EthImpl::new(); + let received_txs = eth_server.txs.clone(); + let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; let (reth_client, _reth_node) = start_reth_node(Some(format!("http://{}", eth_server_address)), None).await; + const TXS_NUMBER: usize = 10; + // Create a random transactions - let transactions = (1..=10) - .map(|i| alloy_rlp::encode(transaction_with_gas_price(100 * i))) + let transactions = (1..=TXS_NUMBER) + .map(|i| alloy_rlp::encode(transaction_with_gas_price(100 * i as u128))) .collect::>(); let expected_hashes = transactions.iter().map(|tx| keccak::keccak_hash(tx)).collect::>(); @@ -220,13 +226,31 @@ async fn bitfinity_test_node_send_raw_transaction_in_gas_price_order() { assert_eq!(hash.to_fixed_bytes(), expected_hash.0.to_fixed_bytes()); } - tokio::time::sleep(Duration::from_secs(1)).await; + assert!(check_transactions_received(&received_txs, TXS_NUMBER).await); for (idx, expected_hash) in expected_hashes.iter().rev().enumerate() { - assert_eq!(eth_server::TXS_ORDER.lock().await[idx].0, expected_hash.0.to_fixed_bytes()); + assert_eq!(received_txs.lock().await[idx].0, expected_hash.0.to_fixed_bytes()); } } +/// Waits until `n` transactions appear in `received_txs` with one second timeout. +/// Returns true if `received_txs` contains at least `n` transactions. +async fn check_transactions_received(received_txs: &Mutex>, n: usize) -> bool { + let wait_future = async { + loop { + let txs_number = received_txs.lock().await.len(); + if txs_number >= n { + break; + } + + tokio::time::sleep(Duration::from_millis(50)).await; + } + }; + + let wait_result = tokio::time::timeout(Duration::from_secs(3), wait_future).await; + wait_result.is_ok() +} + fn transaction_with_gas_price(gas_price: u128) -> TransactionSigned { let mock = MockTransaction::legacy().with_gas_price(gas_price); let transaction: Transaction = mock.into(); @@ -354,6 +378,8 @@ async fn mock_eth_server_start(methods: impl Into) -> (ServerHandle, So } pub mod eth_server { + use std::sync::Arc; + use alloy_rlp::{Bytes, Decodable}; use ethereum_json_rpc_client::{Block, CertifiedResult, H256}; use jsonrpsee::{core::RpcResult, proc_macros::rpc}; @@ -379,18 +405,26 @@ pub mod eth_server { async fn get_last_certified_block(&self) -> RpcResult>>; } - pub static TXS_ORDER: Mutex> = Mutex::const_new(Vec::new()); - #[derive(Debug)] pub struct EthImpl { pub gas_price: u128, pub max_priority_fee_per_gas: u128, + pub txs: Arc>>, } impl EthImpl { - pub async fn new() -> Self { - TXS_ORDER.lock().await.clear(); - Self { gas_price: rand::random(), max_priority_fee_per_gas: rand::random() } + pub fn new() -> Self { + Self { + gas_price: rand::random(), + max_priority_fee_per_gas: rand::random(), + txs: Arc::default(), + } + } + } + + impl Default for EthImpl { + fn default() -> Self { + Self::new() } } @@ -408,7 +442,7 @@ pub mod eth_server { let decoded = hex::decode(&tx).unwrap(); let tx = TransactionSigned::decode(&mut decoded.as_ref()).unwrap(); let hash = tx.hash(); - TXS_ORDER.lock().await.push(hash); + self.txs.lock().await.push(hash); Ok(hash) } diff --git a/bin/reth/tests/commands/utils.rs b/bin/reth/tests/commands/utils.rs index d047bfd89cd..27ea66bc920 100644 --- a/bin/reth/tests/commands/utils.rs +++ b/bin/reth/tests/commands/utils.rs @@ -36,7 +36,8 @@ use tracing::{debug, info}; pub const LOCAL_EVM_CANISTER_ID: &str = "bkyz2-fmaaa-aaaaa-qaaaq-cai"; /// EVM block extractor for devnet running on Digital Ocean. -pub const DEFAULT_EVM_DATASOURCE_URL: &str = "https://orca-app-5yyst.ondigitalocean.app"; +pub const DEFAULT_EVM_DATASOURCE_URL: &str = + "https://block-extractor-testnet-1052151659755.europe-west9.run.app"; pub fn init_logs() -> eyre::Result> { let mut tracer = RethTracer::new(); diff --git a/bitfinity.md b/bitfinity.md index 881910319ab..fa1ed8ed621 100644 --- a/bitfinity.md +++ b/bitfinity.md @@ -34,7 +34,7 @@ reth node -vvv --http --http.port 8080 --http.addr 0.0.0.0 --http.api "debug,eth With cargo: ```sh -cargo run -p reth -- node -vvv --http --http.port 8080 --http.addr 0.0.0.0 --http.api "debug,eth,net,trace,txpool,web3" --disable-discovery --ipcdisable --no-persist-peers -r https://orca-app-5yyst.ondigitalocean.app -i 30 -b 100 --max-fetch-blocks 5000 --log.file.directory ./target/logs --datadir ./target/reth +cargo run -p reth -- node -vvv --http --http.port 8080 --http.addr 0.0.0.0 --http.api "debug,eth,net,trace,txpool,web3" --disable-discovery --ipcdisable --no-persist-peers -r https://block-extractor-testnet-1052151659755.europe-west9.run.app -i 30 -b 100 --max-fetch-blocks 5000 --log.file.directory ./target/logs --datadir ./target/reth ``` You can query the node using the JSON-RPC API. For example, to get the block number, you can use the following command: @@ -83,7 +83,7 @@ dfx canister --network=ic call EVM_CANISTER_ID admin_disable_evm '(true)' 3. Run the EVM reset command. For example: ```sh -cargo run -p reth -- bitfinity-reset-evm-state -vvv --datadir ./target/reth --ic-identity-file-path PATH_TO_IDENTITY/identity.pem --evm-network https://ic0.app --evmc-principal EVM_CANISTER_ID --evm-datasource-url https://orca-app-5yyst.ondigitalocean.app +cargo run -p reth -- bitfinity-reset-evm-state -vvv --datadir ./target/reth --ic-identity-file-path PATH_TO_IDENTITY/identity.pem --evm-network https://ic0.app --evmc-principal EVM_CANISTER_ID --evm-datasource-url https://block-extractor-testnet-1052151659755.europe-west9.run.app ``` 4. Enable the EVM canister: diff --git a/docker-compose.yml b/docker-compose.yml index cd04856e6ca..9079832014a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,6 +8,6 @@ services: dockerfile: ./Dockerfile ports: - '8080:8080' - command: node -vvv --http --http.port 8080 --http.addr 0.0.0.0 --http.api "debug,eth,net,trace,txpool,web3" --disable-discovery --ipcdisable --no-persist-peers -r https://orca-app-5yyst.ondigitalocean.app -i 10 -b 100 --datadir /reth/data + # command: node -vvv --http --http.port 8080 --http.addr 0.0.0.0 --http.api "debug,eth,net,trace,txpool,web3" --disable-discovery --ipcdisable --no-persist-peers -r https://block-extractor-testnet-1052151659755.europe-west9.run.app -i 10 -b 100 --datadir /reth/data volumes: - ./target/reth:/reth From 3e1a018191d80aa9ad6fce6eb35d445943bfbe2d Mon Sep 17 00:00:00 2001 From: f3kilo Date: Fri, 29 Nov 2024 11:57:52 +0300 Subject: [PATCH 12/31] move send txs code to tasks module --- bin/reth/src/bitfinity_tasks.rs | 3 +++ .../bitfinity_send_raw_txs.rs => bitfinity_tasks/send_txs.rs} | 0 bin/reth/src/commands/mod.rs | 1 - bin/reth/src/lib.rs | 1 + bin/reth/src/main.rs | 2 +- bin/reth/tests/commands/bitfinity_node_it.rs | 2 +- 6 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 bin/reth/src/bitfinity_tasks.rs rename bin/reth/src/{commands/bitfinity_send_raw_txs.rs => bitfinity_tasks/send_txs.rs} (100%) diff --git a/bin/reth/src/bitfinity_tasks.rs b/bin/reth/src/bitfinity_tasks.rs new file mode 100644 index 00000000000..66032569f2b --- /dev/null +++ b/bin/reth/src/bitfinity_tasks.rs @@ -0,0 +1,3 @@ +//! This module contains tasks to run in parallel with reth node. + +pub mod send_txs; diff --git a/bin/reth/src/commands/bitfinity_send_raw_txs.rs b/bin/reth/src/bitfinity_tasks/send_txs.rs similarity index 100% rename from bin/reth/src/commands/bitfinity_send_raw_txs.rs rename to bin/reth/src/bitfinity_tasks/send_txs.rs diff --git a/bin/reth/src/commands/mod.rs b/bin/reth/src/commands/mod.rs index a2950e08133..8cc5ea7ea2f 100644 --- a/bin/reth/src/commands/mod.rs +++ b/bin/reth/src/commands/mod.rs @@ -2,7 +2,6 @@ pub mod bitfinity_import; pub mod bitfinity_reset_evm_state; -pub mod bitfinity_send_raw_txs; pub mod config_cmd; pub mod debug_cmd; pub mod dump_genesis; diff --git a/bin/reth/src/lib.rs b/bin/reth/src/lib.rs index c725b033b2c..221ae46c528 100644 --- a/bin/reth/src/lib.rs +++ b/bin/reth/src/lib.rs @@ -29,6 +29,7 @@ )] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] +pub mod bitfinity_tasks; pub mod cli; pub mod commands; mod macros; diff --git a/bin/reth/src/main.rs b/bin/reth/src/main.rs index 626ff561170..5dc8d76c839 100644 --- a/bin/reth/src/main.rs +++ b/bin/reth/src/main.rs @@ -2,7 +2,7 @@ use std::{sync::Arc, time::Duration}; -use reth::commands::bitfinity_send_raw_txs::{ +use reth::bitfinity_tasks::send_txs::{ BitfinityTransactionSender, BitfinityTransactionsForwarder, TransactionsPriorityQueue, }; use tokio::sync::Mutex; diff --git a/bin/reth/tests/commands/bitfinity_node_it.rs b/bin/reth/tests/commands/bitfinity_node_it.rs index 4bba195243b..447a4ebdd53 100644 --- a/bin/reth/tests/commands/bitfinity_node_it.rs +++ b/bin/reth/tests/commands/bitfinity_node_it.rs @@ -11,7 +11,7 @@ use jsonrpsee::{ server::{Server, ServerHandle}, Methods, RpcModule, }; -use reth::commands::bitfinity_send_raw_txs::{ +use reth::bitfinity_tasks::send_txs::{ BitfinityTransactionSender, BitfinityTransactionsForwarder, TransactionsPriorityQueue, }; use reth::{ From 992f6d1809804149e08c0d34fd890fe628a4fba5 Mon Sep 17 00:00:00 2001 From: f3kilo Date: Fri, 29 Nov 2024 12:23:58 +0300 Subject: [PATCH 13/31] better cli args types + use channel --- bin/reth/src/bitfinity_tasks/send_txs.rs | 12 ++-- bin/reth/src/main.rs | 4 +- bin/reth/tests/commands/bitfinity_node_it.rs | 63 +++++++++----------- crates/node/core/src/args/bitfinity_args.rs | 15 +++-- crates/rpc/rpc-eth-api/Cargo.toml | 2 +- 5 files changed, 48 insertions(+), 48 deletions(-) diff --git a/bin/reth/src/bitfinity_tasks/send_txs.rs b/bin/reth/src/bitfinity_tasks/send_txs.rs index 33fad3856fb..a5ceb341d37 100644 --- a/bin/reth/src/bitfinity_tasks/send_txs.rs +++ b/bin/reth/src/bitfinity_tasks/send_txs.rs @@ -26,8 +26,8 @@ pub struct BitfinityTransactionSender { queue: SharedQueue, rpc_url: String, period: Duration, - batch_size: u32, - txs_per_execution_threshold: u32, + batch_size: usize, + txs_per_execution_threshold: usize, } impl BitfinityTransactionSender { @@ -36,8 +36,8 @@ impl BitfinityTransactionSender { queue: SharedQueue, rpc_url: String, period: Duration, - batch_size: u32, - txs_per_execution_threshold: u32, + batch_size: usize, + txs_per_execution_threshold: usize, ) -> Self { Self { queue, rpc_url, period, batch_size, txs_per_execution_threshold } } @@ -90,14 +90,14 @@ impl BitfinityTransactionSender { } total_sent += to_send.len(); - if total_sent > self.txs_per_execution_threshold as usize { + if total_sent > self.txs_per_execution_threshold { return Ok(()); } } } async fn get_transactions_to_send(&self) -> Vec<(U256, Vec)> { - let mut batch = Vec::with_capacity(self.batch_size as _); + let mut batch = Vec::with_capacity(self.batch_size); let mut queue = self.queue.lock().await; let txs_to_pop = self.batch_size.max(1); // if batch size is zero, take at least one tx. diff --git a/bin/reth/src/main.rs b/bin/reth/src/main.rs index 5dc8d76c839..f8ec74db244 100644 --- a/bin/reth/src/main.rs +++ b/bin/reth/src/main.rs @@ -40,7 +40,7 @@ fn main() { // Add custom forwarder with transactions priority queue. queue .blocking_lock() - .set_size_limit(ctx.config().bitfinity_import_arg.tx_queue_size as _); + .set_size_limit(ctx.config().bitfinity_import_arg.tx_queue_size); let forwarder = BitfinityTransactionsForwarder::new(queue); ctx.registry.set_eth_raw_transaction_forwarder(Arc::new(forwarder)); @@ -76,7 +76,7 @@ fn main() { let url = bitfinity.send_raw_transaction_rpc_url.unwrap_or(bitfinity.rpc_url); // Init transaction sending cycle. - let period = Duration::from_secs(bitfinity.send_queued_txs_period_secs as _); + let period = Duration::from_secs(bitfinity.send_queued_txs_period_secs); let transaction_sending = BitfinityTransactionSender::new( queue_clone, url, diff --git a/bin/reth/tests/commands/bitfinity_node_it.rs b/bin/reth/tests/commands/bitfinity_node_it.rs index 447a4ebdd53..adce2b7a5da 100644 --- a/bin/reth/tests/commands/bitfinity_node_it.rs +++ b/bin/reth/tests/commands/bitfinity_node_it.rs @@ -28,6 +28,7 @@ use reth_transaction_pool::test_utils::MockTransaction; use revm_primitives::{Address, B256, U256}; use std::time::Duration; use std::{net::SocketAddr, str::FromStr, sync::Arc}; +use tokio::sync::mpsc::Receiver; use tokio::sync::Mutex; #[tokio::test] @@ -45,7 +46,7 @@ async fn bitfinity_test_node_forward_ic_or_eth_get_last_certified_block() { // Arrange let _log = init_logs(); - let eth_server = EthImpl::new(); + let eth_server = EthImpl::default(); let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; let (reth_client, _reth_node) = @@ -75,7 +76,7 @@ async fn bitfinity_test_node_forward_get_gas_price_requests() { // Arrange let _log = init_logs(); - let eth_server = EthImpl::new(); + let eth_server = EthImpl::default(); let gas_price = eth_server.gas_price; let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; @@ -94,7 +95,7 @@ async fn bitfinity_test_node_forward_max_priority_fee_per_gas_requests() { // Arrange let _log = init_logs(); - let eth_server = EthImpl::new(); + let eth_server = EthImpl::default(); let max_priority_fee_per_gas = eth_server.max_priority_fee_per_gas; let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; @@ -113,7 +114,7 @@ async fn bitfinity_test_node_forward_eth_get_genesis_balances() { // Arrange let _log = init_logs(); - let eth_server = EthImpl::new(); + let eth_server = EthImpl::default(); let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; let (reth_client, _reth_node) = @@ -147,7 +148,7 @@ async fn bitfinity_test_node_forward_ic_get_genesis_balances() { // Arrange let _log = init_logs(); - let eth_server = EthImpl::new(); + let eth_server = EthImpl::default(); let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; let (reth_client, _reth_node) = @@ -174,8 +175,8 @@ async fn bitfinity_test_node_forward_send_raw_transaction_requests() { // Arrange let _log = init_logs(); - let eth_server = EthImpl::new(); - let received_txs = eth_server.txs.clone(); + let (tx_sender, mut tx_receiver) = tokio::sync::mpsc::channel(10); + let eth_server = EthImpl::new(Some(tx_sender)); let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; @@ -193,9 +194,9 @@ async fn bitfinity_test_node_forward_send_raw_transaction_requests() { // Assert assert_eq!(result.to_fixed_bytes(), expected_tx_hash.0.to_fixed_bytes()); - assert!(check_transactions_received(&received_txs, 1).await); + let received_txs = consume_received_txs(&mut tx_receiver, 1).await.unwrap(); - assert_eq!(received_txs.lock().await[0].0, expected_tx_hash.0.to_fixed_bytes()); + assert_eq!(received_txs[0].0, expected_tx_hash.0.to_fixed_bytes()); } #[tokio::test] @@ -203,8 +204,8 @@ async fn bitfinity_test_node_send_raw_transaction_in_gas_price_order() { // Arrange let _log = init_logs(); - let eth_server = EthImpl::new(); - let received_txs = eth_server.txs.clone(); + let (tx_sender, mut tx_receiver) = tokio::sync::mpsc::channel(10); + let eth_server = EthImpl::new(Some(tx_sender)); let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; @@ -226,29 +227,27 @@ async fn bitfinity_test_node_send_raw_transaction_in_gas_price_order() { assert_eq!(hash.to_fixed_bytes(), expected_hash.0.to_fixed_bytes()); } - assert!(check_transactions_received(&received_txs, TXS_NUMBER).await); + let received_txs = consume_received_txs(&mut tx_receiver, 10).await.unwrap(); for (idx, expected_hash) in expected_hashes.iter().rev().enumerate() { - assert_eq!(received_txs.lock().await[idx].0, expected_hash.0.to_fixed_bytes()); + assert_eq!(received_txs[idx].0, expected_hash.0.to_fixed_bytes()); } } /// Waits until `n` transactions appear in `received_txs` with one second timeout. /// Returns true if `received_txs` contains at least `n` transactions. -async fn check_transactions_received(received_txs: &Mutex>, n: usize) -> bool { +async fn consume_received_txs(received_txs: &mut Receiver, n: usize) -> Option> { let wait_future = async { - loop { - let txs_number = received_txs.lock().await.len(); - if txs_number >= n { - break; - } - - tokio::time::sleep(Duration::from_millis(50)).await; + let mut txs = Vec::with_capacity(n); + while txs.len() < n { + let tx = received_txs.recv().await.unwrap(); + txs.push(tx); } + txs }; let wait_result = tokio::time::timeout(Duration::from_secs(3), wait_future).await; - wait_result.is_ok() + wait_result.ok() } fn transaction_with_gas_price(gas_price: u128) -> TransactionSigned { @@ -378,14 +377,12 @@ async fn mock_eth_server_start(methods: impl Into) -> (ServerHandle, So } pub mod eth_server { - use std::sync::Arc; - use alloy_rlp::{Bytes, Decodable}; use ethereum_json_rpc_client::{Block, CertifiedResult, H256}; use jsonrpsee::{core::RpcResult, proc_macros::rpc}; use reth_primitives::TransactionSigned; use revm_primitives::{hex, Address, B256, U256}; - use tokio::sync::Mutex; + use tokio::sync::mpsc::Sender; #[rpc(server, namespace = "eth")] pub trait Eth { @@ -409,22 +406,18 @@ pub mod eth_server { pub struct EthImpl { pub gas_price: u128, pub max_priority_fee_per_gas: u128, - pub txs: Arc>>, + pub txs_sender: Option>, } impl EthImpl { - pub fn new() -> Self { - Self { - gas_price: rand::random(), - max_priority_fee_per_gas: rand::random(), - txs: Arc::default(), - } + pub fn new(txs_sender: Option>) -> Self { + Self { gas_price: rand::random(), max_priority_fee_per_gas: rand::random(), txs_sender } } } impl Default for EthImpl { fn default() -> Self { - Self::new() + Self::new(None) } } @@ -442,7 +435,9 @@ pub mod eth_server { let decoded = hex::decode(&tx).unwrap(); let tx = TransactionSigned::decode(&mut decoded.as_ref()).unwrap(); let hash = tx.hash(); - self.txs.lock().await.push(hash); + if let Some(sender) = &self.txs_sender { + sender.send(hash).await.unwrap(); + } Ok(hash) } diff --git a/crates/node/core/src/args/bitfinity_args.rs b/crates/node/core/src/args/bitfinity_args.rs index 3af14af963a..099df41955f 100644 --- a/crates/node/core/src/args/bitfinity_args.rs +++ b/crates/node/core/src/args/bitfinity_args.rs @@ -58,30 +58,35 @@ pub struct BitfinityImportArgs { pub ic_root_key: String, /// Enable transactions priority queue + /// Default: true #[arg(long, value_name = "TX_PRIORITY_QUEUE", default_value = "true")] pub tx_queue: bool, /// Transactions priority queue will contain this much transactions at max. + /// Default: 1000 #[arg(long, value_name = "TX_PRIORITY_QUEUE_SIZE", default_value = "1000")] - pub tx_queue_size: u32, + pub tx_queue_size: usize, /// Time period to send transactions batch from the priority queue. /// Do nothing, if `tx_queue` is disabled. + /// Default: 3 #[arg(long, value_name = "SEND_QUEUED_TXS_PERIOD_SECS", default_value = "3")] - pub send_queued_txs_period_secs: u32, + pub send_queued_txs_period_secs: u64, /// Send queued transactions by batches with this number of entries. /// If set to 0 or 1, no batching is used. /// Do nothing, if `tx_queue` is disabled. + /// Default: 10 #[arg(long, value_name = "QUEUED_TXS_BATCH_SIZE", default_value = "10")] - pub queued_txs_batch_size: u32, + pub queued_txs_batch_size: usize, /// If transaction sender sent more queued transactions at single execution, /// it will wait for next execution to continue. /// If set to 0, transaction sender will try to empty queue at each execution. /// Do nothing, if `tx_queue` is disabled. - #[arg(long, value_name = "QUEUED_TXS_PER_EXECUTION", default_value = "100")] - pub queued_txs_per_execution_threshold: u32, + /// Default: 500 + #[arg(long, value_name = "QUEUED_TXS_PER_EXECUTION", default_value = "500")] + pub queued_txs_per_execution_threshold: usize, } /// Bitfinity Related Args diff --git a/crates/rpc/rpc-eth-api/Cargo.toml b/crates/rpc/rpc-eth-api/Cargo.toml index 11420146558..825c52f0571 100644 --- a/crates/rpc/rpc-eth-api/Cargo.toml +++ b/crates/rpc/rpc-eth-api/Cargo.toml @@ -32,7 +32,6 @@ reth-rpc-server-types.workspace = true # ethereum alloy-dyn-abi = { workspace = true, features = ["eip712"] } -alloy-rlp.workspace = true # rpc jsonrpsee = { workspace = true, features = ["server", "macros"] } @@ -49,6 +48,7 @@ dyn-clone.workspace = true tracing.workspace = true # Bitfinity dependencies +alloy-rlp.workspace = true ethereum-json-rpc-client.workspace = true [features] From b4ca64a18f2178f906bf05ee96988258315ede88 Mon Sep 17 00:00:00 2001 From: f3kilo Date: Tue, 3 Dec 2024 11:58:29 +0300 Subject: [PATCH 14/31] get transactions from forwarder, reth, and evmc --- bin/reth/src/bitfinity_tasks/send_txs.rs | 107 ++++++++++++++---- crates/rpc/rpc-eth-api/src/core.rs | 9 +- .../src/helpers/bitfinity_evm_rpc.rs | 82 +++++++++++++- .../rpc-eth-api/src/helpers/transaction.rs | 14 ++- 4 files changed, 181 insertions(+), 31 deletions(-) diff --git a/bin/reth/src/bitfinity_tasks/send_txs.rs b/bin/reth/src/bitfinity_tasks/send_txs.rs index a5ceb341d37..31cd48c0ea6 100644 --- a/bin/reth/src/bitfinity_tasks/send_txs.rs +++ b/bin/reth/src/bitfinity_tasks/send_txs.rs @@ -1,17 +1,21 @@ //! Utils for raw transaction batching. -use std::{collections::BTreeMap, sync::Arc, time::Duration}; +use std::collections::{BTreeSet, HashMap}; +use std::sync::Arc; +use std::time::Duration; use crate::primitives::ruint::Uint; use alloy_rlp::Decodable; -use did::keccak::keccak_hash; use did::H256; -use ethereum_json_rpc_client::{reqwest::ReqwestClient, EthJsonRpcClient, Id, Params}; +use ethereum_json_rpc_client::reqwest::ReqwestClient; +use ethereum_json_rpc_client::{EthJsonRpcClient, Id, Params}; use eyre::eyre; -use lightspeed_scheduler::{job::Job, scheduler::Scheduler, JobExecutor}; +use lightspeed_scheduler::job::Job; +use lightspeed_scheduler::scheduler::Scheduler; +use lightspeed_scheduler::JobExecutor; use reth_node_core::version::SHORT_VERSION; use reth_primitives::hex; -use reth_primitives::{TransactionSigned, U256}; +use reth_primitives::{TransactionSigned, B256, U256}; use reth_rpc::eth::RawTransactionForwarder; use reth_rpc_eth_types::{EthApiError, EthResult}; use tokio::sync::Mutex; @@ -171,44 +175,71 @@ impl RawTransactionForwarder for BitfinityTransactionsForwarder { debug!("Pushing tx with hash {} to priority queue", typed_tx.hash); let gas_price = typed_tx.effective_gas_price(None); - self.queue.lock().await.push(Uint::from(gas_price), raw.to_vec()); + self.queue.lock().await.push(typed_tx.hash(), Uint::from(gas_price), raw.to_vec()); Ok(()) } + + async fn get_transaction_by_hash(&self, hash: B256) -> Option> { + self.queue.lock().await.get(&hash) + } } /// Priority queue to get transactions sorted by gas price. #[derive(Debug)] pub struct TransactionsPriorityQueue { - queue: BTreeMap>, + priority: BTreeSet, + transactions: HashMap>, size_limit: usize, } impl TransactionsPriorityQueue { /// Creates new instance of the queue with the given limil. pub fn new(size_limit: usize) -> Self { - Self { queue: BTreeMap::default(), size_limit } + Self { priority: BTreeSet::default(), transactions: HashMap::default(), size_limit } } /// Adds the tx with the given gas price. - pub fn push(&mut self, gas_price: U256, tx: Vec) { - let key = TxKey { gas_price, hash: keccak_hash(&tx) }; - self.queue.insert(key, tx); + pub fn push(&mut self, hash: B256, gas_price: U256, tx: Vec) { + let key = TxKey { gas_price, hash }; + self.priority.insert(key); + self.transactions.insert(hash, tx); if self.len() > self.size_limit { - self.queue.pop_first(); + self.pop_tx_with_lowest_price(); } } + /// Returns raw transaction if it is present in the queue. + pub fn get(&self, hash: &B256) -> Option> { + self.transactions.get(hash).cloned() + } + /// Returns tx with highest gas price, if present. pub fn pop_tx_with_highest_price(&mut self) -> Option<(U256, Vec)> { - let entry = self.queue.pop_last(); - entry.map(|(key, tx)| (key.gas_price, tx)) + let tx_key = self.priority.pop_last()?; + let Some(tx) = self.transactions.remove(&tx_key.hash) else { + warn!("Transaction key present in priority queue, but not found in transactions map."); + return None; + }; + + Some((tx_key.gas_price, tx)) + } + + /// Returns tx with lowest gas price, if present. + pub fn pop_tx_with_lowest_price(&mut self) -> Option<(U256, Vec)> { + let tx_key = self.priority.pop_first()?; + let Some(tx) = self.transactions.remove(&tx_key.hash) else { + warn!("Transaction key present in priority queue, but not found in transactions map."); + return None; + }; + + Some((tx_key.gas_price, tx)) } /// Number of transactions in the queue. pub fn len(&self) -> usize { - self.queue.len() + self.transactions.len() } /// Change size limit of the queue. @@ -216,13 +247,13 @@ impl TransactionsPriorityQueue { self.size_limit = new_limit; while self.len() > self.size_limit { - self.queue.pop_first(); + self.pop_tx_with_lowest_price(); } } /// Returns true if length == 0. pub fn is_empty(&self) -> bool { - self.queue.is_empty() + self.transactions.is_empty() } } @@ -231,7 +262,7 @@ impl TransactionsPriorityQueue { #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] struct TxKey { gas_price: U256, - hash: H256, + hash: B256, } #[cfg(test)] @@ -253,9 +284,9 @@ mod tests { let tx2_bytes = alloy_rlp::encode(&tx2); let tx3_bytes = alloy_rlp::encode(&tx3); - queue.push(U256::from(tx1.effective_gas_price(None)), tx1_bytes.clone()); - queue.push(U256::from(tx2.effective_gas_price(None)), tx2_bytes.clone()); - queue.push(U256::from(tx3.effective_gas_price(None)), tx3_bytes.clone()); + queue.push(tx1.hash(), U256::from(tx1.effective_gas_price(None)), tx1_bytes.clone()); + queue.push(tx2.hash(), U256::from(tx2.effective_gas_price(None)), tx2_bytes.clone()); + queue.push(tx3.hash(), U256::from(tx3.effective_gas_price(None)), tx3_bytes.clone()); let expected_order = [tx2_bytes, tx3_bytes, tx1_bytes]; for expected_tx in expected_order { @@ -277,9 +308,9 @@ mod tests { let tx2_bytes = alloy_rlp::encode(&tx2); let tx3_bytes = alloy_rlp::encode(&tx3); - queue.push(U256::from(tx1.effective_gas_price(None)), tx1_bytes); - queue.push(U256::from(tx2.effective_gas_price(None)), tx2_bytes.clone()); - queue.push(U256::from(tx3.effective_gas_price(None)), tx3_bytes.clone()); + queue.push(tx1.hash(), U256::from(tx1.effective_gas_price(None)), tx1_bytes); + queue.push(tx2.hash(), U256::from(tx2.effective_gas_price(None)), tx2_bytes.clone()); + queue.push(tx3.hash(), U256::from(tx3.effective_gas_price(None)), tx3_bytes.clone()); let expected_order = [tx2_bytes, tx3_bytes]; for expected_tx in expected_order { @@ -290,8 +321,34 @@ mod tests { assert!(queue.is_empty()) } + #[test] + fn test_get_transaction_from_queue() { + let mut queue = TransactionsPriorityQueue::new(100); + let tx1 = transaction_with_gas_price(100); + let tx2 = transaction_with_gas_price(300); + let tx3 = transaction_with_gas_price(200); + + let tx1_bytes = alloy_rlp::encode(&tx1); + let tx2_bytes = alloy_rlp::encode(&tx2); + let tx3_bytes = alloy_rlp::encode(&tx3); + + queue.push(tx1.hash(), U256::from(tx1.effective_gas_price(None)), tx1_bytes); + queue.push(tx2.hash(), U256::from(tx2.effective_gas_price(None)), tx2_bytes); + queue.push(tx3.hash(), U256::from(tx3.effective_gas_price(None)), tx3_bytes); + + let hashes = [tx1.hash(), tx2.hash(), tx3.hash()]; + for hash in hashes { + assert!(queue.get(&hash).is_some()); + } + + assert_eq!(queue.len(), 3); + + let tx4 = transaction_with_gas_price(400); + assert!(queue.get(&tx4.hash()).is_none()); + } + fn transaction_with_gas_price(gas_price: u128) -> TransactionSigned { - let tx = MockTransaction::legacy().with_gas_price(gas_price); + let tx = MockTransaction::legacy().with_gas_price(gas_price).rng_hash(); TransactionSigned { hash: *tx.hash(), diff --git a/crates/rpc/rpc-eth-api/src/core.rs b/crates/rpc/rpc-eth-api/src/core.rs index 6a6abccf246..55f90dbfd12 100644 --- a/crates/rpc/rpc-eth-api/src/core.rs +++ b/crates/rpc/rpc-eth-api/src/core.rs @@ -469,7 +469,14 @@ where /// Handler for: `eth_getTransactionByHash` async fn transaction_by_hash(&self, hash: B256) -> RpcResult> { trace!(target: "rpc::eth", ?hash, "Serving eth_getTransactionByHash"); - Ok(EthTransactions::transaction_by_hash(self, hash).await?.map(Into::into)) + // Ok(EthTransactions::transaction_by_hash(self, hash).await?.map(Into::into)) + + let mut tx_opt = + EthTransactions::transaction_by_hash(self, hash).await?.map(Transaction::from); + if tx_opt.is_none() { + tx_opt = BitfinityEvmRpc::transaction_by_hash(self, hash).await?; + } + Ok(tx_opt) } /// Handler for: `eth_getRawTransactionByBlockHashAndIndex` diff --git a/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs b/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs index 812e3e60313..475fdb98497 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs @@ -4,12 +4,13 @@ use std::sync::Arc; use alloy_rlp::Decodable; use ethereum_json_rpc_client::{reqwest::ReqwestClient, EthJsonRpcClient}; -use ethereum_json_rpc_client::{Block, CertifiedResult, H256}; +use ethereum_json_rpc_client::{Block, CertifiedResult, Id, Params, H256}; use futures::Future; use jsonrpsee::core::RpcResult; use reth_chainspec::ChainSpec; use reth_primitives::TransactionSigned; use reth_rpc_server_types::result::{internal_rpc_err, invalid_params_rpc_err}; +use reth_rpc_types::{Signature, Transaction}; use revm_primitives::{Address, Bytes, B256, U256}; use crate::RawTransactionForwarder; @@ -41,6 +42,43 @@ pub trait BitfinityEvmRpc { } } + /// Returns transaction from forwarder or query it from EVM RPC. + fn transaction_by_hash( + &self, + hash: B256, + ) -> impl Future>> + Send { + let chain_spec = self.chain_spec(); + let forwarder = self.raw_tx_forwarder(); + + async move { + if let Some(forwarder) = forwarder { + let tx_opt = get_transaction_from_forwarder(&*forwarder, hash).await?; + if tx_opt.is_some() { + return Ok(tx_opt); + } + }; + + // If transaction not found in forwarder, query it from EVM rpc. + let (rpc_url, client) = get_client(&chain_spec)?; + let method = "eth_getTransactionByHash".to_string(); + let tx: Option = client + .single_request( + method.clone(), + Params::Array(vec![hash.to_string().into()]), + Id::Str(method), + ) + .await + .map_err(|e| { + internal_rpc_err(format!( + "failed to forward eth_getTransactionByHash request to {}: {}", + rpc_url, e + )) + })?; + + Ok(tx) + } + } + /// Forwards `eth_maxPriorityFeePerGas` calls to the Bitfinity EVM fn max_priority_fee_per_gas(&self) -> impl Future> + Send { let chain_spec = self.chain_spec(); @@ -142,3 +180,45 @@ fn get_client(chain_spec: &ChainSpec) -> RpcResult<(&String, EthJsonRpcClient RpcResult> { + let Some(raw) = forwarder.get_transaction_by_hash(hash).await else { return Ok(None) }; + let typed_tx = TransactionSigned::decode(&mut &raw[..]) + .map_err(|e| internal_rpc_err(format!("failed to decode transaction from bytes: {e}")))?; + + let Some(from) = typed_tx.recover_signer() else { + return Err(internal_rpc_err("Failed to recover signer from raw transaction")); + }; + + let sig = typed_tx.signature; + let signature = + Signature { r: sig.r, s: sig.s, v: U256::from(sig.v(typed_tx.chain_id())), y_parity: None }; + + let tx = Transaction { + hash, + nonce: typed_tx.nonce(), + block_hash: None, + block_number: None, + transaction_index: None, + from, + to: typed_tx.to(), + value: typed_tx.value(), + gas_price: Some(typed_tx.effective_gas_price(None)), + gas: typed_tx.gas_limit() as _, + max_fee_per_gas: Some(typed_tx.max_fee_per_gas()), + max_priority_fee_per_gas: typed_tx.max_priority_fee_per_gas(), + max_fee_per_blob_gas: typed_tx.max_fee_per_blob_gas(), + input: typed_tx.input().clone(), + signature: Some(signature), + chain_id: typed_tx.chain_id(), + blob_versioned_hashes: typed_tx.blob_versioned_hashes(), + access_list: typed_tx.access_list().cloned(), + transaction_type: Some(typed_tx.transaction.tx_type().into()), + other: Default::default(), + }; + + Ok(Some(tx)) +} diff --git a/crates/rpc/rpc-eth-api/src/helpers/transaction.rs b/crates/rpc/rpc-eth-api/src/helpers/transaction.rs index acf0156c6d9..80d6e1e4d27 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/transaction.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/transaction.rs @@ -105,7 +105,7 @@ pub trait EthTransactions: LoadTransaction { if let Some(tx) = self.pool().get_pooled_transaction_element(hash).map(|tx| tx.envelope_encoded()) { - return Ok(Some(tx)) + return Ok(Some(tx)); } self.spawn_blocking_io(move |ref this| { @@ -201,7 +201,7 @@ pub trait EthTransactions: LoadTransaction { block_number, base_fee_per_gas, index.into(), - ))) + ))); } } @@ -223,7 +223,7 @@ pub trait EthTransactions: LoadTransaction { async move { if let Some(block) = self.block_with_senders(block_id).await? { if let Some(tx) = block.transactions().nth(index.into()) { - return Ok(Some(tx.envelope_encoded())) + return Ok(Some(tx.envelope_encoded())); } } @@ -476,7 +476,7 @@ pub trait EthTransactions: LoadTransaction { return match signer.sign_transaction(request, from) { Ok(tx) => Ok(tx), Err(e) => Err(e.into()), - } + }; } } Err(EthApiError::InvalidTransactionSignature) @@ -647,4 +647,10 @@ pub trait LoadTransaction: SpawnBlocking { pub trait RawTransactionForwarder: fmt::Debug + Send + Sync + 'static { /// Forwards raw transaction bytes for `eth_sendRawTransaction` async fn forward_raw_transaction(&self, raw: &[u8]) -> EthResult<()>; + + /// Added by Bitfinity. + /// Method to check if the transaction is forwarding. + async fn get_transaction_by_hash(&self, _hash: B256) -> Option> { + None + } } From b589177f9a2b72c1ab4fe5841a7151b496e91784 Mon Sep 17 00:00:00 2001 From: f3kilo Date: Wed, 4 Dec 2024 10:46:32 +0300 Subject: [PATCH 15/31] better tests + clippy fixes --- bin/reth/src/bitfinity_tasks/send_txs.rs | 2 +- bin/reth/tests/bitfinity_it.rs | 4 +- bin/reth/tests/commands/bitfinity_node_it.rs | 71 ++++++++++++++------ bin/reth/tests/commands/mod.rs | 2 + bin/reth/tests/commands/utils.rs | 18 +++++ 5 files changed, 74 insertions(+), 23 deletions(-) diff --git a/bin/reth/src/bitfinity_tasks/send_txs.rs b/bin/reth/src/bitfinity_tasks/send_txs.rs index 31cd48c0ea6..2761a13523a 100644 --- a/bin/reth/src/bitfinity_tasks/send_txs.rs +++ b/bin/reth/src/bitfinity_tasks/send_txs.rs @@ -78,7 +78,7 @@ impl BitfinityTransactionSender { } /// Execute the transaction sending job. - async fn single_execution(&self) -> eyre::Result<()> { + pub async fn single_execution(&self) -> eyre::Result<()> { let mut total_sent = 0; loop { let to_send = self.get_transactions_to_send().await; diff --git a/bin/reth/tests/bitfinity_it.rs b/bin/reth/tests/bitfinity_it.rs index 6be336ee9ff..5cb6f668aad 100644 --- a/bin/reth/tests/bitfinity_it.rs +++ b/bin/reth/tests/bitfinity_it.rs @@ -1 +1,3 @@ -pub mod commands; \ No newline at end of file +//! Bitfinity integration tests. + +pub mod commands; diff --git a/bin/reth/tests/commands/bitfinity_node_it.rs b/bin/reth/tests/commands/bitfinity_node_it.rs index adce2b7a5da..ec536786717 100644 --- a/bin/reth/tests/commands/bitfinity_node_it.rs +++ b/bin/reth/tests/commands/bitfinity_node_it.rs @@ -12,7 +12,8 @@ use jsonrpsee::{ Methods, RpcModule, }; use reth::bitfinity_tasks::send_txs::{ - BitfinityTransactionSender, BitfinityTransactionsForwarder, TransactionsPriorityQueue, + BitfinityTransactionSender, BitfinityTransactionsForwarder, SharedQueue, + TransactionsPriorityQueue, }; use reth::{ args::{DatadirArgs, RpcServerArgs}, @@ -35,7 +36,7 @@ use tokio::sync::Mutex; async fn bitfinity_test_should_start_local_reth_node() { // Arrange let _log = init_logs(); - let (reth_client, _reth_node) = start_reth_node(None, None).await; + let (reth_client, _reth_node) = start_reth_node(None, None, None).await; // Act & Assert assert!(reth_client.get_chain_id().await.is_ok()); @@ -50,7 +51,7 @@ async fn bitfinity_test_node_forward_ic_or_eth_get_last_certified_block() { let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; let (reth_client, _reth_node) = - start_reth_node(Some(format!("http://{}", eth_server_address)), None).await; + start_reth_node(Some(format!("http://{}", eth_server_address)), None, None).await; // Act let result = reth_client.get_last_certified_block().await; @@ -81,7 +82,7 @@ async fn bitfinity_test_node_forward_get_gas_price_requests() { let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; let (reth_client, _reth_node) = - start_reth_node(Some(format!("http://{}", eth_server_address)), None).await; + start_reth_node(Some(format!("http://{}", eth_server_address)), None, None).await; // Act let gas_price_result = reth_client.gas_price().await; @@ -100,7 +101,7 @@ async fn bitfinity_test_node_forward_max_priority_fee_per_gas_requests() { let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; let (reth_client, _reth_node) = - start_reth_node(Some(format!("http://{}", eth_server_address)), None).await; + start_reth_node(Some(format!("http://{}", eth_server_address)), None, None).await; // Act let result = reth_client.max_priority_fee_per_gas().await; @@ -118,7 +119,7 @@ async fn bitfinity_test_node_forward_eth_get_genesis_balances() { let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; let (reth_client, _reth_node) = - start_reth_node(Some(format!("http://{}", eth_server_address)), None).await; + start_reth_node(Some(format!("http://{}", eth_server_address)), None, None).await; // Act let result: Vec<(ethereum_json_rpc_client::H160, ethereum_json_rpc_client::U256)> = reth_client @@ -152,7 +153,7 @@ async fn bitfinity_test_node_forward_ic_get_genesis_balances() { let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; let (reth_client, _reth_node) = - start_reth_node(Some(format!("http://{}", eth_server_address)), None).await; + start_reth_node(Some(format!("http://{}", eth_server_address)), None, None).await; // Act let result = reth_client.get_genesis_balances().await.unwrap(); @@ -178,10 +179,14 @@ async fn bitfinity_test_node_forward_send_raw_transaction_requests() { let (tx_sender, mut tx_receiver) = tokio::sync::mpsc::channel(10); let eth_server = EthImpl::new(Some(tx_sender)); + let queue = Arc::new(Mutex::new(TransactionsPriorityQueue::new(10))); + let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; + let bitfinity_evm_url = format!("http://{}", eth_server_address); let (reth_client, _reth_node) = - start_reth_node(Some(format!("http://{}", eth_server_address)), None).await; + start_reth_node(Some(format!("http://{}", eth_server_address)), None, Some(queue.clone())) + .await; // Create a random transaction let tx = transaction_with_gas_price(100); @@ -194,6 +199,15 @@ async fn bitfinity_test_node_forward_send_raw_transaction_requests() { // Assert assert_eq!(result.to_fixed_bytes(), expected_tx_hash.0.to_fixed_bytes()); + let transaction_sending = BitfinityTransactionSender::new( + queue, + bitfinity_evm_url, + Duration::from_millis(200), + 10, + 100, + ); + transaction_sending.single_execution().await.unwrap(); + let received_txs = consume_received_txs(&mut tx_receiver, 1).await.unwrap(); assert_eq!(received_txs[0].0, expected_tx_hash.0.to_fixed_bytes()); @@ -207,10 +221,13 @@ async fn bitfinity_test_node_send_raw_transaction_in_gas_price_order() { let (tx_sender, mut tx_receiver) = tokio::sync::mpsc::channel(10); let eth_server = EthImpl::new(Some(tx_sender)); + let queue = Arc::new(Mutex::new(TransactionsPriorityQueue::new(10))); + let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; + let bitfinity_evm_url = format!("http://{}", eth_server_address); let (reth_client, _reth_node) = - start_reth_node(Some(format!("http://{}", eth_server_address)), None).await; + start_reth_node(Some(bitfinity_evm_url.clone()), None, Some(queue.clone())).await; const TXS_NUMBER: usize = 10; @@ -227,6 +244,15 @@ async fn bitfinity_test_node_send_raw_transaction_in_gas_price_order() { assert_eq!(hash.to_fixed_bytes(), expected_hash.0.to_fixed_bytes()); } + let transaction_sending = BitfinityTransactionSender::new( + queue, + bitfinity_evm_url, + Duration::from_millis(200), + 10, + 100, + ); + transaction_sending.single_execution().await.unwrap(); + let received_txs = consume_received_txs(&mut tx_receiver, 10).await.unwrap(); for (idx, expected_hash) in expected_hashes.iter().rev().enumerate() { @@ -261,6 +287,7 @@ fn transaction_with_gas_price(gas_price: u128) -> TransactionSigned { async fn start_reth_node( bitfinity_evm_url: Option, import_data: Option, + queue: Option, ) -> ( EthJsonRpcClient, NodeHandle< @@ -326,15 +353,13 @@ async fn start_reth_node( Arc::new(init_db(data_dir.db(), Default::default()).unwrap()) }; - let queue = Arc::new(Mutex::new(TransactionsPriorityQueue::new(1000))); - let queue_clone = Arc::clone(&queue); - let node_handle = NodeBuilder::new(node_config) .with_database(database) .with_launch_context(tasks.executor()) .node(EthereumNode::default()) .extend_rpc_modules(|ctx| { // Add custom forwarder with transactions priority queue. + let Some(queue) = queue else { return Ok(()) }; let forwarder = BitfinityTransactionsForwarder::new(queue); ctx.registry.set_eth_raw_transaction_forwarder(Arc::new(forwarder)); @@ -344,15 +369,6 @@ async fn start_reth_node( .await .unwrap(); - let transaction_sending = BitfinityTransactionSender::new( - queue_clone, - bitfinity_evm_url.unwrap_or_default(), - Duration::from_millis(200), - 10, - 100, - ); - let _sending_handle = transaction_sending.schedule_execution(None).await.unwrap(); - let reth_address = node_handle.node.rpc_server_handle().http_local_addr().unwrap(); let addr_string = format!("http://{}", reth_address); let client: EthJsonRpcClient = @@ -376,6 +392,7 @@ async fn mock_eth_server_start(methods: impl Into) -> (ServerHandle, So (handle, server_address) } +/// Eth server mock utils. pub mod eth_server { use alloy_rlp::{Bytes, Decodable}; use ethereum_json_rpc_client::{Block, CertifiedResult, H256}; @@ -386,30 +403,42 @@ pub mod eth_server { #[rpc(server, namespace = "eth")] pub trait Eth { + /// Returns gasPrice #[method(name = "gasPrice")] async fn gas_price(&self) -> RpcResult; + /// Returns maxPriorityFeePerGas #[method(name = "maxPriorityFeePerGas")] async fn max_priority_fee_per_gas(&self) -> RpcResult; + /// Returns sendRawTransaction #[method(name = "sendRawTransaction")] async fn send_raw_transaction(&self, tx: Bytes) -> RpcResult; + /// Returns getGenesisBalances #[method(name = "getGenesisBalances", aliases = ["ic_getGenesisBalances"])] async fn get_genesis_balances(&self) -> RpcResult>; + /// Returns getLastCertifiedBlock #[method(name = "getLastCertifiedBlock", aliases = ["ic_getLastCertifiedBlock"])] async fn get_last_certified_block(&self) -> RpcResult>>; } + /// Eth server mock. #[derive(Debug)] pub struct EthImpl { + /// Current gas price pub gas_price: u128, + + /// Current `max_priority_fee_per_gas` pub max_priority_fee_per_gas: u128, + + /// The mock will send transactions to the sender, if present. pub txs_sender: Option>, } impl EthImpl { + /// New mock instance. pub fn new(txs_sender: Option>) -> Self { Self { gas_price: rand::random(), max_priority_fee_per_gas: rand::random(), txs_sender } } diff --git a/bin/reth/tests/commands/mod.rs b/bin/reth/tests/commands/mod.rs index 1522662c37a..b50ce4058ed 100644 --- a/bin/reth/tests/commands/mod.rs +++ b/bin/reth/tests/commands/mod.rs @@ -1,3 +1,5 @@ +//! Bitfinity integration tests. + pub mod bitfinity_import_it; pub mod bitfinity_node_it; pub mod bitfinity_reset_evm_state_it; diff --git a/bin/reth/tests/commands/utils.rs b/bin/reth/tests/commands/utils.rs index 27ea66bc920..5b423a95208 100644 --- a/bin/reth/tests/commands/utils.rs +++ b/bin/reth/tests/commands/utils.rs @@ -1,3 +1,5 @@ +//! Bitfinity integration tests utils. + use std::{ fmt::{Debug, Display, Formatter}, path::PathBuf, @@ -34,11 +36,14 @@ use revm_primitives::db::Database; use tempfile::TempDir; use tracing::{debug, info}; +/// Local evm canister for tests. pub const LOCAL_EVM_CANISTER_ID: &str = "bkyz2-fmaaa-aaaaa-qaaaq-cai"; + /// EVM block extractor for devnet running on Digital Ocean. pub const DEFAULT_EVM_DATASOURCE_URL: &str = "https://block-extractor-testnet-1052151659755.europe-west9.run.app"; +/// Initialize logger. pub fn init_logs() -> eyre::Result> { let mut tracer = RethTracer::new(); let stdout = LayerInfo::new( @@ -53,13 +58,25 @@ pub fn init_logs() -> eyre::Result> { Ok(guard) } +/// Bitfinity config for reth node. #[derive(Clone)] pub struct ImportData { + /// Chain config. pub chain: Arc, + + /// Path to data. pub data_dir: ChainPath, + + /// Database config. pub database: Arc, + + /// Database provider. pub provider_factory: ProviderFactory>, + + /// Blockchain provider. pub blockchain_db: BlockchainProvider>, + + /// Bitfinity import config. pub bitfinity_args: BitfinityImportArgs, } @@ -185,6 +202,7 @@ pub async fn wait_until_local_block_imported( } } +/// Returns local port of dfx replica. pub fn get_dfx_local_port() -> u16 { use std::process::Command; let output = Command::new("dfx") From ccbec99a094a1a6760bad5cb1dab8a33a55307bc Mon Sep 17 00:00:00 2001 From: f3kilo Date: Thu, 5 Dec 2024 09:24:26 +0300 Subject: [PATCH 16/31] query transactions test --- Cargo.lock | 413 +++++++++--------- Cargo.toml | 6 +- bin/reth/tests/commands/bitfinity_node_it.rs | 102 ++++- crates/node/core/src/args/bitfinity_args.rs | 6 +- .../src/helpers/bitfinity_evm_rpc.rs | 111 ++++- 5 files changed, 416 insertions(+), 222 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d45ef3cf4fd..a749069bdd8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -207,7 +207,7 @@ dependencies = [ "alloy-primitives", "serde", "serde_json", - "thiserror", + "thiserror 1.0.61", "tracing", ] @@ -228,7 +228,7 @@ dependencies = [ "async-trait", "auto_impl", "futures-utils-wasm", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -242,7 +242,7 @@ dependencies = [ "k256", "serde_json", "tempfile", - "thiserror", + "thiserror 1.0.61", "tracing", "url", ] @@ -348,7 +348,7 @@ checksum = "d83524c1f6162fcb5b0decf775498a125066c86dda6066ed609531b0e912f85a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -421,7 +421,7 @@ dependencies = [ "alloy-rpc-types-engine", "serde", "serde_with", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -440,7 +440,7 @@ dependencies = [ "jsonwebtoken", "rand 0.8.5", "serde", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -462,7 +462,7 @@ dependencies = [ "proptest-derive 0.4.0", "serde", "serde_json", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -476,7 +476,7 @@ dependencies = [ "alloy-serde", "serde", "serde_json", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -516,7 +516,7 @@ dependencies = [ "auto_impl", "elliptic-curve", "k256", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -534,7 +534,7 @@ dependencies = [ "coins-bip39", "k256", "rand 0.8.5", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -548,7 +548,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -565,7 +565,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", "syn-solidity", "tiny-keccak", ] @@ -583,7 +583,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.68", + "syn 2.0.90", "syn-solidity", ] @@ -621,7 +621,7 @@ dependencies = [ "futures-utils-wasm", "serde", "serde_json", - "thiserror", + "thiserror 1.0.61", "tokio", "tower", "url", @@ -786,7 +786,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -1041,7 +1041,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -1052,7 +1052,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -1090,7 +1090,7 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -1222,7 +1222,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.68", + "syn 2.0.90", "which", ] @@ -1402,7 +1402,7 @@ dependencies = [ "static_assertions", "tap", "thin-vec", - "thiserror", + "thiserror 1.0.61", "time", ] @@ -1442,7 +1442,7 @@ checksum = "6be9c93793b60dac381af475b98634d4b451e28336e72218cad9a20176218dbc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", "synstructure", ] @@ -1551,7 +1551,7 @@ checksum = "1ee891b04274a59bd38b412188e24b849617b2e45a0fd8d057deb63e7403761b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -1595,7 +1595,7 @@ dependencies = [ "hashbrown 0.14.5", "instant", "once_cell", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -1608,7 +1608,7 @@ dependencies = [ "hashbrown 0.14.5", "instant", "once_cell", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -1658,7 +1658,7 @@ dependencies = [ "serde", "serde_bytes", "stacker", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -1670,7 +1670,7 @@ dependencies = [ "lazy_static", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -1693,7 +1693,7 @@ dependencies = [ "semver 1.0.23", "serde", "serde_json", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -1874,7 +1874,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -1896,7 +1896,7 @@ dependencies = [ "k256", "serde", "sha2 0.10.8", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -1912,7 +1912,7 @@ dependencies = [ "pbkdf2", "rand 0.8.5", "sha2 0.10.8", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -1931,7 +1931,7 @@ dependencies = [ "serde", "sha2 0.10.8", "sha3", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -2001,7 +2001,7 @@ checksum = "45b1f4c00870f07dc34adcac82bb6a72cc5aabca8536ba1797e01df51d2ce9a0" dependencies = [ "directories", "serde", - "thiserror", + "thiserror 1.0.61", "toml", ] @@ -2371,7 +2371,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -2432,7 +2432,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -2454,7 +2454,7 @@ checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ "darling_core 0.20.9", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -2561,7 +2561,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -2574,7 +2574,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version 0.4.0", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -2594,14 +2594,14 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", "unicode-xid", ] [[package]] name = "did" -version = "0.34.0" -source = "git+https://github.com/bitfinity-network/bitfinity-evm-sdk?tag=v0.34.x#498b6e18e4734ba6c95e80c50f17b314b27630ba" +version = "0.36.0" +source = "git+https://github.com/bitfinity-network/bitfinity-evm-sdk?tag=v0.36.x#50c63713c5273c023eda9efdf4a6c140ae502c91" dependencies = [ "alloy-primitives", "bincode", @@ -2612,18 +2612,17 @@ dependencies = [ "ethers-core", "hex", "ic-log", - "ic-stable-structures 0.22.0", + "ic-stable-structures 0.23.0", "jsonrpc-core", "log", "num", - "once_cell", "rlp", "serde", "serde_json", "serde_with", "sha2 0.10.8", "sha3", - "thiserror", + "thiserror 2.0.4", ] [[package]] @@ -2737,7 +2736,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -2805,7 +2804,7 @@ dependencies = [ "rand_core 0.6.4", "serde", "sha2 0.9.9", - "thiserror", + "thiserror 1.0.61", "zeroize", ] @@ -2839,7 +2838,7 @@ dependencies = [ "reth-stages", "serde", "serde_json", - "thiserror", + "thiserror 1.0.61", "walkdir", ] @@ -2910,7 +2909,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -2921,7 +2920,7 @@ checksum = "6fd000fd6988e73bbe993ea3db9b1aa64906ab88766d654973924340c8cddb42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -2963,7 +2962,7 @@ dependencies = [ "serde", "serde_json", "sha3", - "thiserror", + "thiserror 1.0.61", "uint", ] @@ -2984,8 +2983,8 @@ dependencies = [ [[package]] name = "ethereum-json-rpc-client" -version = "0.34.0" -source = "git+https://github.com/bitfinity-network/bitfinity-evm-sdk?tag=v0.34.x#498b6e18e4734ba6c95e80c50f17b314b27630ba" +version = "0.36.0" +source = "git+https://github.com/bitfinity-network/bitfinity-evm-sdk?tag=v0.36.x#50c63713c5273c023eda9efdf4a6c140ae502c91" dependencies = [ "anyhow", "candid", @@ -3051,7 +3050,7 @@ dependencies = [ "serde_json", "strum", "tempfile", - "thiserror", + "thiserror 1.0.61", "tiny-keccak", "unicode-xid", ] @@ -3085,8 +3084,8 @@ dependencies = [ [[package]] name = "evm-canister-client" -version = "0.34.0" -source = "git+https://github.com/bitfinity-network/bitfinity-evm-sdk?tag=v0.34.x#498b6e18e4734ba6c95e80c50f17b314b27630ba" +version = "0.36.0" +source = "git+https://github.com/bitfinity-network/bitfinity-evm-sdk?tag=v0.36.x#50c63713c5273c023eda9efdf4a6c140ae502c91" dependencies = [ "candid", "did", @@ -3107,7 +3106,7 @@ dependencies = [ "reth-node-ethereum", "serde", "serde_json", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -3174,7 +3173,7 @@ dependencies = [ "reth-rpc-types", "reth-tracing", "serde", - "thiserror", + "thiserror 1.0.61", "tokio", ] @@ -3555,7 +3554,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e182f7dbc2ef73d9ef67351c5fbbea084729c48362d3ce9dd44c28e32e277fe5" dependencies = [ "libc", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -3724,7 +3723,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -3845,7 +3844,7 @@ dependencies = [ "pin-project", "serde", "serde_json", - "thiserror", + "thiserror 1.0.61", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -4260,7 +4259,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -4297,15 +4296,19 @@ dependencies = [ [[package]] name = "ic-agent" -version = "0.37.1" +version = "0.39.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fd3fdf5e5c4f4a9fe5ca612f0febd22dcb161d2f2b75b0142326732be5e4978" +checksum = "158138fcb769fe6288e63d5db221c904e472cfb7d376aba13a38c060f2984e63" dependencies = [ "async-lock", + "async-trait", "backoff", "cached 0.52.0", "candid", + "der", + "ecdsa", "ed25519-consensus", + "elliptic-curve", "futures-util", "hex", "http 1.1.0", @@ -4321,8 +4324,6 @@ dependencies = [ "rand 0.8.5", "rangemap", "reqwest", - "ring", - "rustls-webpki", "sec1", "serde", "serde_bytes", @@ -4330,23 +4331,24 @@ dependencies = [ "serde_repr", "sha2 0.10.8", "simple_asn1", - "thiserror", + "thiserror 1.0.61", "time", "tokio", + "tower-service", "url", ] [[package]] name = "ic-canister-client" -version = "0.22.0" -source = "git+https://github.com/bitfinity-network/canister-sdk?tag=v0.22.x#ea99e9ffef07699f57b810e9c58e5926c526212c" +version = "0.23.0" +source = "git+https://github.com/bitfinity-network/canister-sdk?tag=v0.23.x#df53171fb8706c650a60d5c2af35d5c868daabd2" dependencies = [ "async-trait", "candid", "ic-agent", "ic-exports", "serde", - "thiserror", + "thiserror 2.0.4", ] [[package]] @@ -4359,14 +4361,14 @@ dependencies = [ "ic-certification", "leb128", "nom", - "thiserror", + "thiserror 1.0.61", ] [[package]] name = "ic-cdk" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8ecacd682fa05a985253592963306cb9799622d7b1cce4b1edb89c6ec85be1" +checksum = "b2abdf9341da9f9f6b451a40609cb69645a05a8e9eb7784c16209f16f2c0f76f" dependencies = [ "candid", "ic-cdk-macros", @@ -4377,23 +4379,23 @@ dependencies = [ [[package]] name = "ic-cdk-macros" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d4d857135deef20cc7ea8f3869a30cd9cfeb1392b3a81043790b2cd82adc3e0" +checksum = "b8df41980e95dead28735ab0f748c75477b0c5eab37a09a5641c78ec406a1db0" dependencies = [ "candid", "proc-macro2", "quote", "serde", "serde_tokenstream", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] name = "ic-cdk-timers" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7c528bbb3d4d934b43a364855995d318649217c7510f40f92ad52eba3ff7be" +checksum = "fb8fd812a9e26f6aa00594546f8fbf4d4853f39c3ba794c8ff11ecf86fd3c9e4" dependencies = [ "futures", "ic-cdk", @@ -4419,7 +4421,7 @@ dependencies = [ "nom", "parking_lot 0.12.3", "sha2 0.10.8", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -4436,16 +4438,16 @@ dependencies = [ [[package]] name = "ic-crypto-getrandom-for-wasm" -version = "0.22.0" -source = "git+https://github.com/bitfinity-network/canister-sdk?tag=v0.22.x#ea99e9ffef07699f57b810e9c58e5926c526212c" +version = "0.23.0" +source = "git+https://github.com/bitfinity-network/canister-sdk?tag=v0.23.x#df53171fb8706c650a60d5c2af35d5c868daabd2" dependencies = [ "getrandom 0.2.15", ] [[package]] name = "ic-exports" -version = "0.22.0" -source = "git+https://github.com/bitfinity-network/canister-sdk?tag=v0.22.x#ea99e9ffef07699f57b810e9c58e5926c526212c" +version = "0.23.0" +source = "git+https://github.com/bitfinity-network/canister-sdk?tag=v0.23.x#df53171fb8706c650a60d5c2af35d5c868daabd2" dependencies = [ "candid", "ic-cdk", @@ -4458,8 +4460,8 @@ dependencies = [ [[package]] name = "ic-kit" -version = "0.22.0" -source = "git+https://github.com/bitfinity-network/canister-sdk?tag=v0.22.x#ea99e9ffef07699f57b810e9c58e5926c526212c" +version = "0.23.0" +source = "git+https://github.com/bitfinity-network/canister-sdk?tag=v0.23.x#df53171fb8706c650a60d5c2af35d5c868daabd2" dependencies = [ "candid", "futures", @@ -4471,8 +4473,8 @@ dependencies = [ [[package]] name = "ic-log" -version = "0.22.0" -source = "git+https://github.com/bitfinity-network/canister-sdk?tag=v0.22.x#ea99e9ffef07699f57b810e9c58e5926c526212c" +version = "0.23.0" +source = "git+https://github.com/bitfinity-network/canister-sdk?tag=v0.23.x#df53171fb8706c650a60d5c2af35d5c868daabd2" dependencies = [ "anyhow", "arc-swap", @@ -4496,21 +4498,21 @@ dependencies = [ [[package]] name = "ic-stable-structures" -version = "0.22.0" -source = "git+https://github.com/bitfinity-network/canister-sdk?tag=v0.22.x#ea99e9ffef07699f57b810e9c58e5926c526212c" +version = "0.23.0" +source = "git+https://github.com/bitfinity-network/canister-sdk?tag=v0.23.x#df53171fb8706c650a60d5c2af35d5c868daabd2" dependencies = [ "candid", "ic-stable-structures 0.6.5", "parking_lot 0.12.3", "schnellru", - "thiserror", + "thiserror 2.0.4", ] [[package]] name = "ic-transport-types" -version = "0.37.1" +version = "0.39.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875dc4704780383112e8e8b5063a1b98de114321d0c7d3e7f635dcf360a57fba" +checksum = "2d8789a5c176bb1b925fa58ca97c651a3995d504e76101e93d2a17f558bdcf66" dependencies = [ "candid", "hex", @@ -4518,9 +4520,10 @@ dependencies = [ "leb128", "serde", "serde_bytes", + "serde_cbor", "serde_repr", "sha2 0.10.8", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -4567,7 +4570,7 @@ dependencies = [ "data-encoding", "serde", "sha2 0.10.8", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -4685,7 +4688,7 @@ checksum = "d2abdd3a62551e8337af119c5899e600ca0c88ec8f23a46c60ba216c803dcf1a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -4954,7 +4957,7 @@ dependencies = [ "combine", "jni-sys", "log", - "thiserror", + "thiserror 1.0.61", "walkdir", ] @@ -5032,7 +5035,7 @@ dependencies = [ "rustls-pki-types", "rustls-platform-verifier", "soketto", - "thiserror", + "thiserror 1.0.61", "tokio", "tokio-rustls", "tokio-util", @@ -5062,7 +5065,7 @@ dependencies = [ "rustc-hash 1.1.0", "serde", "serde_json", - "thiserror", + "thiserror 1.0.61", "tokio", "tokio-stream", "tracing", @@ -5087,7 +5090,7 @@ dependencies = [ "rustls-platform-verifier", "serde", "serde_json", - "thiserror", + "thiserror 1.0.61", "tokio", "tower", "tracing", @@ -5104,7 +5107,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -5127,7 +5130,7 @@ dependencies = [ "serde", "serde_json", "soketto", - "thiserror", + "thiserror 1.0.61", "tokio", "tokio-stream", "tokio-util", @@ -5145,7 +5148,7 @@ dependencies = [ "http 1.1.0", "serde", "serde_json", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -5189,9 +5192,9 @@ dependencies = [ [[package]] name = "k256" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" dependencies = [ "cfg-if", "ecdsa", @@ -5298,7 +5301,7 @@ dependencies = [ "multiaddr", "pin-project", "rw-stream-sink", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -5347,7 +5350,7 @@ dependencies = [ "rand 0.8.5", "rw-stream-sink", "smallvec", - "thiserror", + "thiserror 1.0.61", "tracing", "unsigned-varint 0.8.0", "void", @@ -5368,7 +5371,7 @@ dependencies = [ "quick-protobuf", "rand 0.8.5", "sha2 0.10.8", - "thiserror", + "thiserror 1.0.61", "tracing", "zeroize", ] @@ -5627,7 +5630,7 @@ dependencies = [ "metrics", "metrics-util", "quanta", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -5679,7 +5682,7 @@ dependencies = [ "reqwest", "serde", "serde_json", - "thiserror", + "thiserror 1.0.61", "tokio", "tracing", ] @@ -5757,7 +5760,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -6009,7 +6012,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -6283,7 +6286,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" dependencies = [ "memchr", - "thiserror", + "thiserror 1.0.61", "ucd-trie", ] @@ -6350,7 +6353,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -6379,7 +6382,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -6496,7 +6499,7 @@ dependencies = [ "smallvec", "symbolic-demangle", "tempfile", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -6549,7 +6552,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -6610,9 +6613,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -6692,7 +6695,7 @@ checksum = "6ff7ff745a347b87471d859a377a9a404361e7efc2a971d73424a6d183c0fc77" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -6755,7 +6758,7 @@ dependencies = [ "quinn-udp", "rustc-hash 1.1.0", "rustls", - "thiserror", + "thiserror 1.0.61", "tokio", "tracing", ] @@ -6772,7 +6775,7 @@ dependencies = [ "rustc-hash 1.1.0", "rustls", "slab", - "thiserror", + "thiserror 1.0.61", "tinyvec", "tracing", ] @@ -6983,7 +6986,7 @@ checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" dependencies = [ "getrandom 0.2.15", "libredox", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -7285,7 +7288,7 @@ dependencies = [ "reth-tokio-util", "reth-tracing", "schnellru", - "thiserror", + "thiserror 1.0.61", "tokio", "tokio-stream", "tracing", @@ -7324,7 +7327,7 @@ dependencies = [ "reth-tracing", "serde", "serde_json", - "thiserror", + "thiserror 1.0.61", "tikv-jemallocator", "tokio", "tokio-util", @@ -7374,7 +7377,7 @@ dependencies = [ "reth-execution-errors", "reth-primitives", "reth-storage-errors", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -7479,7 +7482,7 @@ dependencies = [ "proc-macro2", "quote", "similar-asserts", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -7575,7 +7578,7 @@ dependencies = [ "sysinfo", "tempfile", "test-fuzz", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -7630,7 +7633,7 @@ dependencies = [ "reth-trie", "serde", "serde_json", - "thiserror", + "thiserror 1.0.61", "tracing", ] @@ -7655,7 +7658,7 @@ dependencies = [ "schnellru", "secp256k1", "serde", - "thiserror", + "thiserror 1.0.61", "tokio", "tokio-stream", "tracing", @@ -7682,7 +7685,7 @@ dependencies = [ "reth-network-peers", "reth-tracing", "secp256k1", - "thiserror", + "thiserror 1.0.61", "tokio", "tracing", ] @@ -7708,7 +7711,7 @@ dependencies = [ "secp256k1", "serde", "serde_with", - "thiserror", + "thiserror 1.0.61", "tokio", "tokio-stream", "tracing", @@ -7754,7 +7757,7 @@ dependencies = [ "rlp", "serde_json", "tempfile", - "thiserror", + "thiserror 1.0.61", "tokio", "tokio-stream", "tokio-util", @@ -7814,7 +7817,7 @@ dependencies = [ "secp256k1", "sha2 0.10.8", "sha3", - "thiserror", + "thiserror 1.0.61", "tokio", "tokio-stream", "tokio-util", @@ -7902,7 +7905,7 @@ dependencies = [ "reth-execution-errors", "reth-fs-util", "reth-storage-errors", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -7933,7 +7936,7 @@ dependencies = [ "serde", "snap", "test-fuzz", - "thiserror", + "thiserror 1.0.61", "tokio", "tokio-stream", "tokio-util", @@ -7957,7 +7960,7 @@ dependencies = [ "reth-codecs-derive", "reth-primitives", "serde", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -8089,7 +8092,7 @@ dependencies = [ "reth-revm", "revm", "revm-primitives", - "thiserror", + "thiserror 1.0.61", "tracing", ] @@ -8179,7 +8182,7 @@ dependencies = [ "reth-provider", "reth-tasks", "reth-transaction-pool", - "thiserror", + "thiserror 1.0.61", "tokio", ] @@ -8195,7 +8198,7 @@ name = "reth-fs-util" version = "1.0.0" dependencies = [ "serde_json", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -8212,7 +8215,7 @@ dependencies = [ "rand 0.8.5", "reth-tracing", "serde_json", - "thiserror", + "thiserror 1.0.61", "tokio", "tokio-stream", "tokio-util", @@ -8236,7 +8239,7 @@ dependencies = [ "rand_xorshift", "reth-mdbx-sys", "tempfile", - "thiserror", + "thiserror 1.0.61", "tracing", ] @@ -8269,7 +8272,7 @@ dependencies = [ "quote", "regex", "serial_test", - "syn 2.0.68", + "syn 2.0.90", "trybuild", ] @@ -8288,7 +8291,7 @@ dependencies = [ "reqwest", "reth-tracing", "serde_with", - "thiserror", + "thiserror 1.0.61", "tokio", ] @@ -8341,7 +8344,7 @@ dependencies = [ "serial_test", "smallvec", "tempfile", - "thiserror", + "thiserror 1.0.61", "tokio", "tokio-stream", "tokio-util", @@ -8358,7 +8361,7 @@ dependencies = [ "reth-eth-wire", "reth-network-peers", "serde", - "thiserror", + "thiserror 1.0.61", "tokio", ] @@ -8375,7 +8378,7 @@ dependencies = [ "reth-network-peers", "reth-primitives", "reth-storage-errors", - "thiserror", + "thiserror 1.0.61", "tokio", "tracing", ] @@ -8391,7 +8394,7 @@ dependencies = [ "secp256k1", "serde_json", "serde_with", - "thiserror", + "thiserror 1.0.61", "tokio", "url", ] @@ -8425,7 +8428,7 @@ dependencies = [ "serde", "sucds", "tempfile", - "thiserror", + "thiserror 1.0.61", "tracing", "zstd", ] @@ -8548,7 +8551,7 @@ dependencies = [ "secp256k1", "serde_json", "shellexpand", - "thiserror", + "thiserror 1.0.61", "tikv-jemalloc-ctl", "tokio", "tower", @@ -8653,7 +8656,7 @@ dependencies = [ "revm-primitives", "serde", "serde_json", - "thiserror", + "thiserror 1.0.61", "tokio", "tracing", ] @@ -8693,7 +8696,7 @@ dependencies = [ "reth-transaction-pool", "revm", "sha2 0.10.8", - "thiserror", + "thiserror 1.0.61", "tracing", ] @@ -8717,7 +8720,7 @@ dependencies = [ "reth-transaction-pool", "revm", "serde_json", - "thiserror", + "thiserror 1.0.61", "tokio", "tokio-stream", "tracing", @@ -8733,7 +8736,7 @@ dependencies = [ "reth-rpc-types", "reth-transaction-pool", "serde", - "thiserror", + "thiserror 1.0.61", "tokio", ] @@ -8884,7 +8887,7 @@ dependencies = [ "reth-testing-utils", "reth-tokio-util", "reth-tracing", - "thiserror", + "thiserror 1.0.61", "tokio", "tracing", ] @@ -8906,7 +8909,7 @@ dependencies = [ "serde", "serde_json", "test-fuzz", - "thiserror", + "thiserror 1.0.61", "toml", ] @@ -8976,7 +8979,7 @@ dependencies = [ "serde", "serde_json", "tempfile", - "thiserror", + "thiserror 1.0.61", "tokio", "tokio-stream", "tower", @@ -9050,7 +9053,7 @@ dependencies = [ "reth-transaction-pool", "serde", "serde_json", - "thiserror", + "thiserror 1.0.61", "tokio", "tower", "tower-http", @@ -9085,7 +9088,7 @@ dependencies = [ "reth-testing-utils", "reth-tokio-util", "serde", - "thiserror", + "thiserror 1.0.61", "tokio", "tracing", ] @@ -9154,7 +9157,7 @@ dependencies = [ "schnellru", "serde", "serde_json", - "thiserror", + "thiserror 1.0.61", "tokio", "tokio-stream", "tracing", @@ -9268,7 +9271,7 @@ dependencies = [ "reth-trie", "serde_json", "tempfile", - "thiserror", + "thiserror 1.0.61", "tokio", "tracing", ] @@ -9296,7 +9299,7 @@ dependencies = [ "reth-static-file-types", "reth-testing-utils", "reth-tokio-util", - "thiserror", + "thiserror 1.0.61", "tokio", "tokio-stream", "tracing", @@ -9390,7 +9393,7 @@ dependencies = [ "pin-project", "rayon", "reth-metrics", - "thiserror", + "thiserror 1.0.61", "tokio", "tracing", "tracing-futures", @@ -9463,7 +9466,7 @@ dependencies = [ "serde_json", "smallvec", "tempfile", - "thiserror", + "thiserror 1.0.61", "tokio", "tokio-stream", "tracing", @@ -9552,7 +9555,7 @@ dependencies = [ "reth-provider", "reth-tasks", "reth-trie", - "thiserror", + "thiserror 1.0.61", "tokio", "tracing", ] @@ -9587,7 +9590,7 @@ dependencies = [ "colorchoice", "revm", "serde_json", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -10175,7 +10178,7 @@ checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -10198,7 +10201,7 @@ checksum = "c7715380eec75f029a4ef7de39a9200e0a63823176b759d055b613f5a87df6a6" dependencies = [ "percent-encoding", "serde", - "thiserror", + "thiserror 1.0.61", ] [[package]] @@ -10209,7 +10212,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -10230,7 +10233,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -10272,7 +10275,7 @@ dependencies = [ "darling 0.20.9", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -10297,7 +10300,7 @@ checksum = "82fe9db325bcef1fbcde82e078a5cc4efdf787e96b3b9cf45b50b529f2083d67" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -10447,7 +10450,7 @@ checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" dependencies = [ "num-bigint", "num-traits", - "thiserror", + "thiserror 1.0.61", "time", ] @@ -10562,7 +10565,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ff9eaf853dec4c8802325d8b6d3dffa86cc707fd7a1a4cdbf416e13b061787a" dependencies = [ "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -10627,7 +10630,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -10701,9 +10704,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.68" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -10719,7 +10722,7 @@ dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -10736,7 +10739,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -10821,7 +10824,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -10849,7 +10852,16 @@ version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.61", +] + +[[package]] +name = "thiserror" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f49a1853cf82743e3b7950f77e0f4d622ca36cf4317cba00c767838bac8d490" +dependencies = [ + "thiserror-impl 2.0.4", ] [[package]] @@ -10860,7 +10872,18 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8381894bb3efe0c4acac3ded651301ceee58a15d47c2e34885ed1908ad667061" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.90", ] [[package]] @@ -11038,7 +11061,7 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -11223,7 +11246,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" dependencies = [ "crossbeam-channel", - "thiserror", + "thiserror 1.0.61", "time", "tracing-subscriber", ] @@ -11236,7 +11259,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -11352,7 +11375,7 @@ dependencies = [ "once_cell", "rand 0.8.5", "smallvec", - "thiserror", + "thiserror 1.0.61", "tinyvec", "tokio", "tracing", @@ -11374,7 +11397,7 @@ dependencies = [ "rand 0.8.5", "resolv-conf", "smallvec", - "thiserror", + "thiserror 1.0.61", "tokio", "tracing", "trust-dns-proto", @@ -11416,7 +11439,7 @@ dependencies = [ "rustls", "rustls-pki-types", "sha1", - "thiserror", + "thiserror 1.0.61", "utf-8", ] @@ -11693,7 +11716,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", "wasm-bindgen-shared", ] @@ -11727,7 +11750,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -11868,7 +11891,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -11879,7 +11902,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -12093,7 +12116,7 @@ dependencies = [ "pharos", "rustc_version 0.4.0", "send_wrapper 0.6.0", - "thiserror", + "thiserror 1.0.61", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -12137,7 +12160,7 @@ checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", "synstructure", ] @@ -12158,7 +12181,7 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -12178,7 +12201,7 @@ checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", "synstructure", ] @@ -12199,7 +12222,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] @@ -12221,7 +12244,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.68", + "syn 2.0.90", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 1711e063f9e..16a44221596 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -530,14 +530,14 @@ iai-callgrind = "0.11" # Bitfinity Deps async-channel = "2" candid = "0.10" -did = { git = "https://github.com/bitfinity-network/bitfinity-evm-sdk", package = "did", features = ["alloy-primitives-07"], tag = "v0.34.x" } +did = { git = "https://github.com/bitfinity-network/bitfinity-evm-sdk", package = "did", features = ["alloy-primitives-07"], tag = "v0.36.x" } dirs = "5.0.1" -ethereum-json-rpc-client = { git = "https://github.com/bitfinity-network/bitfinity-evm-sdk", package = "ethereum-json-rpc-client", tag = "v0.34.x", features = [ +ethereum-json-rpc-client = { git = "https://github.com/bitfinity-network/bitfinity-evm-sdk", package = "ethereum-json-rpc-client", tag = "v0.36.x", features = [ "reqwest", ] } evm-canister-client = { git = "https://github.com/bitfinity-network/bitfinity-evm-sdk", package = "evm-canister-client", features = [ "ic-agent-client", -], tag = "v0.34.x" } +], tag = "v0.36.x" } ic-cbor = "2.3" ic-certificate-verification = "2.3" ic-certification = "2.3" diff --git a/bin/reth/tests/commands/bitfinity_node_it.rs b/bin/reth/tests/commands/bitfinity_node_it.rs index ec536786717..8370787424b 100644 --- a/bin/reth/tests/commands/bitfinity_node_it.rs +++ b/bin/reth/tests/commands/bitfinity_node_it.rs @@ -260,6 +260,58 @@ async fn bitfinity_test_node_send_raw_transaction_in_gas_price_order() { } } +#[tokio::test] +async fn bitfinity_test_node_get_transaction_when_it_is_queued() { + // Arrange + let _log = init_logs(); + + let eth_server = EthImpl::new(None); + + let queue = Arc::new(Mutex::new(TransactionsPriorityQueue::new(10))); + + let (_server, eth_server_address) = + mock_eth_server_start(EthServer::into_rpc(eth_server)).await; + let bitfinity_evm_url = format!("http://{}", eth_server_address); + let (reth_client, _reth_node) = + start_reth_node(Some(bitfinity_evm_url.clone()), None, Some(queue.clone())).await; + + const TXS_NUMBER: usize = 10; + + // Create a random transactions + let transactions = (1..=TXS_NUMBER) + .map(|i| alloy_rlp::encode(transaction_with_gas_price(100 * i as u128))) + .collect::>(); + + let expected_hashes = transactions.iter().map(|tx| keccak::keccak_hash(tx)).collect::>(); + + // Act + for (tx, expected_hash) in transactions.iter().zip(expected_hashes.iter()) { + let hash = reth_client.send_raw_transaction_bytes(tx).await.unwrap(); + assert_eq!(hash.to_fixed_bytes(), expected_hash.0.to_fixed_bytes()); + } + + for hash in &expected_hashes { + let tx = reth_client.get_transaction_by_hash(hash.0).await.unwrap().unwrap(); + // Transaction in forwarder has NO block number. + assert!(tx.block_number.is_none()); + } + + let transaction_sending = BitfinityTransactionSender::new( + queue, + bitfinity_evm_url, + Duration::from_millis(200), + 10, + 100, + ); + transaction_sending.single_execution().await.unwrap(); + + for hash in &expected_hashes { + let tx = reth_client.get_transaction_by_hash(hash.0).await.unwrap().unwrap(); + // Transaction in mock has block number. + assert!(tx.block_number.is_some()); + } +} + /// Waits until `n` transactions appear in `received_txs` with one second timeout. /// Returns true if `received_txs` contains at least `n` transactions. async fn consume_received_txs(received_txs: &mut Receiver, n: usize) -> Option> { @@ -398,8 +450,9 @@ pub mod eth_server { use ethereum_json_rpc_client::{Block, CertifiedResult, H256}; use jsonrpsee::{core::RpcResult, proc_macros::rpc}; use reth_primitives::TransactionSigned; + use reth_rpc_types::Transaction; use revm_primitives::{hex, Address, B256, U256}; - use tokio::sync::mpsc::Sender; + use tokio::sync::{mpsc::Sender, Mutex}; #[rpc(server, namespace = "eth")] pub trait Eth { @@ -415,6 +468,10 @@ pub mod eth_server { #[method(name = "sendRawTransaction")] async fn send_raw_transaction(&self, tx: Bytes) -> RpcResult; + /// Returns getTransactionByHash + #[method(name = "getTransactionByHash")] + async fn get_transaction_by_hash(&self, hash: B256) -> RpcResult>; + /// Returns getGenesisBalances #[method(name = "getGenesisBalances", aliases = ["ic_getGenesisBalances"])] async fn get_genesis_balances(&self) -> RpcResult>; @@ -433,6 +490,9 @@ pub mod eth_server { /// Current `max_priority_fee_per_gas` pub max_priority_fee_per_gas: u128, + /// List of received transactions. + pub received_txs: Mutex>, + /// The mock will send transactions to the sender, if present. pub txs_sender: Option>, } @@ -440,7 +500,12 @@ pub mod eth_server { impl EthImpl { /// New mock instance. pub fn new(txs_sender: Option>) -> Self { - Self { gas_price: rand::random(), max_priority_fee_per_gas: rand::random(), txs_sender } + Self { + gas_price: rand::random(), + max_priority_fee_per_gas: rand::random(), + received_txs: Mutex::default(), + txs_sender, + } } } @@ -464,12 +529,45 @@ pub mod eth_server { let decoded = hex::decode(&tx).unwrap(); let tx = TransactionSigned::decode(&mut decoded.as_ref()).unwrap(); let hash = tx.hash(); + self.received_txs.lock().await.push(hash); if let Some(sender) = &self.txs_sender { sender.send(hash).await.unwrap(); } Ok(hash) } + async fn get_transaction_by_hash(&self, hash: B256) -> RpcResult> { + if !self.received_txs.lock().await.contains(&hash) { + return Ok(None); + } + + // If tx present, ruturn it with some block number. + let tx = Transaction { + hash, + nonce: 42, + block_hash: Some(B256::random()), + block_number: Some(42), + transaction_index: Some(42), + from: Address::random(), + to: Some(Address::random()), + value: Default::default(), + gas_price: Default::default(), + gas: Default::default(), + max_fee_per_gas: Default::default(), + max_priority_fee_per_gas: Default::default(), + max_fee_per_blob_gas: Default::default(), + input: Default::default(), + signature: Default::default(), + chain_id: Default::default(), + blob_versioned_hashes: Default::default(), + access_list: Default::default(), + transaction_type: Default::default(), + other: Default::default(), + }; + + Ok(Some(tx)) + } + async fn get_genesis_balances(&self) -> RpcResult> { Ok(vec![ (Address::from_slice(&[1u8; 20]), U256::from(10)), diff --git a/crates/node/core/src/args/bitfinity_args.rs b/crates/node/core/src/args/bitfinity_args.rs index 099df41955f..bed6fb912b7 100644 --- a/crates/node/core/src/args/bitfinity_args.rs +++ b/crates/node/core/src/args/bitfinity_args.rs @@ -107,12 +107,12 @@ pub struct BitfinityResetEvmStateArgs { /// Network url /// This is the URL of the IC network. /// E.g. - /// - https://ic0.app - /// - http://127.0.0.1:3333 + /// - + /// - #[arg(long)] pub evm_network: String, - /// URL used to fetch the ChainSpec information. + /// URL used to fetch the `ChainSpec` information. /// This is usually the URL of the Bitfinity EVM block extractor. #[arg(long)] pub evm_datasource_url: String, diff --git a/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs b/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs index 475fdb98497..ebd5c6bb2e2 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs @@ -4,13 +4,13 @@ use std::sync::Arc; use alloy_rlp::Decodable; use ethereum_json_rpc_client::{reqwest::ReqwestClient, EthJsonRpcClient}; -use ethereum_json_rpc_client::{Block, CertifiedResult, Id, Params, H256}; +use ethereum_json_rpc_client::{Block, CertifiedResult, H256}; use futures::Future; use jsonrpsee::core::RpcResult; use reth_chainspec::ChainSpec; use reth_primitives::TransactionSigned; use reth_rpc_server_types::result::{internal_rpc_err, invalid_params_rpc_err}; -use reth_rpc_types::{Signature, Transaction}; +use reth_rpc_types::{AccessList, AccessListItem, Signature, Transaction}; use revm_primitives::{Address, Bytes, B256, U256}; use crate::RawTransactionForwarder; @@ -58,23 +58,8 @@ pub trait BitfinityEvmRpc { } }; - // If transaction not found in forwarder, query it from EVM rpc. - let (rpc_url, client) = get_client(&chain_spec)?; - let method = "eth_getTransactionByHash".to_string(); - let tx: Option = client - .single_request( - method.clone(), - Params::Array(vec![hash.to_string().into()]), - Id::Str(method), - ) - .await - .map_err(|e| { - internal_rpc_err(format!( - "failed to forward eth_getTransactionByHash request to {}: {}", - rpc_url, e - )) - })?; - + // If transaction is not found in forwarder, query it from EVM rpc. + let tx = transaction_from_evm_rpc(&chain_spec, hash).await?; Ok(tx) } } @@ -222,3 +207,91 @@ async fn get_transaction_from_forwarder( Ok(Some(tx)) } + +async fn transaction_from_evm_rpc( + chain_spec: &ChainSpec, + hash: B256, +) -> RpcResult> { + let (rpc_url, client) = get_client(chain_spec)?; + let tx = client.get_transaction_by_hash(hash.0.into()).await.map_err(|e| { + internal_rpc_err(format!( + "failed to forward eth_getTransactionByHash request to {}: {}", + rpc_url, e + )) + })?; + + let Some(typed_tx) = tx else { return Ok(None) }; + + fn to_u128_or_err(val: ethereum_json_rpc_client::U256) -> RpcResult { + if val > ethereum_json_rpc_client::U256::from(u128::MAX) { + return Err(invalid_params_rpc_err("value expected to be less then u128::MAX")); + } + Ok(val.low_u128()) + } + + fn to_u64_or_err(val: ethereum_json_rpc_client::U256) -> RpcResult { + if val > ethereum_json_rpc_client::U256::from(u128::MAX) { + return Err(invalid_params_rpc_err("value expected to be less then u64::MAX")); + } + Ok(val.low_u64()) + } + + let convert_access_list = || { + let items = typed_tx + .access_list? + .0 + .iter() + .map(|item| AccessListItem { + address: item.address.0.into(), + storage_keys: item.storage_keys.iter().map(|i| i.0.into()).collect(), + }) + .collect(); + Some(AccessList(items)) + }; + + let signature = Signature { + r: U256::from_limbs(typed_tx.r.0), + s: U256::from_limbs(typed_tx.s.0), + v: U256::from(typed_tx.v.as_u64()), + y_parity: None, + }; + + let transaction_type = typed_tx + .transaction_type + .map(|v| { + let tx_type_u64 = v.as_u64(); + if tx_type_u64 > u8::MAX as u64 { + return Err(invalid_params_rpc_err("transaction type should be less than u8::MAX")); + } + Ok(tx_type_u64 as u8) + }) + .transpose()?; + + let tx = Transaction { + hash, + nonce: typed_tx.nonce.as_u64(), + block_hash: None, + block_number: None, + transaction_index: None, + from: typed_tx.from.0.into(), + to: typed_tx.to.map(|addr| addr.0.into()), + value: U256::from_limbs(typed_tx.value.0), + gas_price: typed_tx.gas_price.map(to_u128_or_err).transpose()?, + gas: to_u128_or_err(typed_tx.gas)?, + max_fee_per_gas: typed_tx.max_fee_per_gas.map(to_u128_or_err).transpose()?, + max_priority_fee_per_gas: typed_tx + .max_priority_fee_per_gas + .map(to_u128_or_err) + .transpose()?, + max_fee_per_blob_gas: None, + input: typed_tx.input.to_vec().into(), + signature: Some(signature), + chain_id: typed_tx.chain_id.map(to_u64_or_err).transpose()?, + blob_versioned_hashes: None, + access_list: convert_access_list(), + transaction_type, + other: Default::default(), + }; + + Ok(Some(tx)) +} From b2a6db0db57d534ca20b189c1bdedd3ca8646c92 Mon Sep 17 00:00:00 2001 From: f3kilo Date: Fri, 6 Dec 2024 11:16:28 +0300 Subject: [PATCH 17/31] taks manager live long enough --- bin/reth/tests/commands/bitfinity_node_it.rs | 57 ++++++++++++++------ 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/bin/reth/tests/commands/bitfinity_node_it.rs b/bin/reth/tests/commands/bitfinity_node_it.rs index 8370787424b..30c35aa21a4 100644 --- a/bin/reth/tests/commands/bitfinity_node_it.rs +++ b/bin/reth/tests/commands/bitfinity_node_it.rs @@ -4,6 +4,7 @@ use super::utils::*; use did::keccak; +use discv5::enr::secp256k1::{Keypair, Secp256k1}; use eth_server::{EthImpl, EthServer}; use ethereum_json_rpc_client::{reqwest::ReqwestClient, EthJsonRpcClient}; use ethereum_json_rpc_client::{Block, CertifiedResult, H256}; @@ -23,7 +24,7 @@ use reth_consensus::Consensus; use reth_db::{init_db, test_utils::tempdir_path}; use reth_node_builder::{NodeBuilder, NodeConfig, NodeHandle}; use reth_node_ethereum::EthereumNode; -use reth_primitives::{Transaction, TransactionSigned}; +use reth_primitives::{sign_message, Transaction, TransactionSigned}; use reth_tasks::TaskManager; use reth_transaction_pool::test_utils::MockTransaction; use revm_primitives::{Address, B256, U256}; @@ -36,7 +37,8 @@ use tokio::sync::Mutex; async fn bitfinity_test_should_start_local_reth_node() { // Arrange let _log = init_logs(); - let (reth_client, _reth_node) = start_reth_node(None, None, None).await; + let tasks = TaskManager::current(); + let (reth_client, _reth_node) = start_reth_node(&tasks, None, None, None).await; // Act & Assert assert!(reth_client.get_chain_id().await.is_ok()); @@ -46,12 +48,13 @@ async fn bitfinity_test_should_start_local_reth_node() { async fn bitfinity_test_node_forward_ic_or_eth_get_last_certified_block() { // Arrange let _log = init_logs(); + let tasks = TaskManager::current(); let eth_server = EthImpl::default(); let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; let (reth_client, _reth_node) = - start_reth_node(Some(format!("http://{}", eth_server_address)), None, None).await; + start_reth_node(&tasks, Some(format!("http://{}", eth_server_address)), None, None).await; // Act let result = reth_client.get_last_certified_block().await; @@ -76,13 +79,14 @@ async fn bitfinity_test_node_forward_ic_or_eth_get_last_certified_block() { async fn bitfinity_test_node_forward_get_gas_price_requests() { // Arrange let _log = init_logs(); + let tasks = TaskManager::current(); let eth_server = EthImpl::default(); let gas_price = eth_server.gas_price; let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; let (reth_client, _reth_node) = - start_reth_node(Some(format!("http://{}", eth_server_address)), None, None).await; + start_reth_node(&tasks, Some(format!("http://{}", eth_server_address)), None, None).await; // Act let gas_price_result = reth_client.gas_price().await; @@ -95,13 +99,14 @@ async fn bitfinity_test_node_forward_get_gas_price_requests() { async fn bitfinity_test_node_forward_max_priority_fee_per_gas_requests() { // Arrange let _log = init_logs(); + let tasks = TaskManager::current(); let eth_server = EthImpl::default(); let max_priority_fee_per_gas = eth_server.max_priority_fee_per_gas; let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; let (reth_client, _reth_node) = - start_reth_node(Some(format!("http://{}", eth_server_address)), None, None).await; + start_reth_node(&tasks, Some(format!("http://{}", eth_server_address)), None, None).await; // Act let result = reth_client.max_priority_fee_per_gas().await; @@ -114,12 +119,13 @@ async fn bitfinity_test_node_forward_max_priority_fee_per_gas_requests() { async fn bitfinity_test_node_forward_eth_get_genesis_balances() { // Arrange let _log = init_logs(); + let tasks = TaskManager::current(); let eth_server = EthImpl::default(); let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; let (reth_client, _reth_node) = - start_reth_node(Some(format!("http://{}", eth_server_address)), None, None).await; + start_reth_node(&tasks, Some(format!("http://{}", eth_server_address)), None, None).await; // Act let result: Vec<(ethereum_json_rpc_client::H160, ethereum_json_rpc_client::U256)> = reth_client @@ -148,12 +154,13 @@ async fn bitfinity_test_node_forward_eth_get_genesis_balances() { async fn bitfinity_test_node_forward_ic_get_genesis_balances() { // Arrange let _log = init_logs(); + let tasks = TaskManager::current(); let eth_server = EthImpl::default(); let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; let (reth_client, _reth_node) = - start_reth_node(Some(format!("http://{}", eth_server_address)), None, None).await; + start_reth_node(&tasks, Some(format!("http://{}", eth_server_address)), None, None).await; // Act let result = reth_client.get_genesis_balances().await.unwrap(); @@ -175,6 +182,7 @@ async fn bitfinity_test_node_forward_ic_get_genesis_balances() { async fn bitfinity_test_node_forward_send_raw_transaction_requests() { // Arrange let _log = init_logs(); + let tasks = TaskManager::current(); let (tx_sender, mut tx_receiver) = tokio::sync::mpsc::channel(10); let eth_server = EthImpl::new(Some(tx_sender)); @@ -184,9 +192,13 @@ async fn bitfinity_test_node_forward_send_raw_transaction_requests() { let (_server, eth_server_address) = mock_eth_server_start(EthServer::into_rpc(eth_server)).await; let bitfinity_evm_url = format!("http://{}", eth_server_address); - let (reth_client, _reth_node) = - start_reth_node(Some(format!("http://{}", eth_server_address)), None, Some(queue.clone())) - .await; + let (reth_client, _reth_node) = start_reth_node( + &tasks, + Some(format!("http://{}", eth_server_address)), + None, + Some(queue.clone()), + ) + .await; // Create a random transaction let tx = transaction_with_gas_price(100); @@ -217,6 +229,7 @@ async fn bitfinity_test_node_forward_send_raw_transaction_requests() { async fn bitfinity_test_node_send_raw_transaction_in_gas_price_order() { // Arrange let _log = init_logs(); + let tasks = TaskManager::current(); let (tx_sender, mut tx_receiver) = tokio::sync::mpsc::channel(10); let eth_server = EthImpl::new(Some(tx_sender)); @@ -227,7 +240,7 @@ async fn bitfinity_test_node_send_raw_transaction_in_gas_price_order() { mock_eth_server_start(EthServer::into_rpc(eth_server)).await; let bitfinity_evm_url = format!("http://{}", eth_server_address); let (reth_client, _reth_node) = - start_reth_node(Some(bitfinity_evm_url.clone()), None, Some(queue.clone())).await; + start_reth_node(&tasks, Some(bitfinity_evm_url.clone()), None, Some(queue.clone())).await; const TXS_NUMBER: usize = 10; @@ -264,6 +277,7 @@ async fn bitfinity_test_node_send_raw_transaction_in_gas_price_order() { async fn bitfinity_test_node_get_transaction_when_it_is_queued() { // Arrange let _log = init_logs(); + let tasks = TaskManager::current(); let eth_server = EthImpl::new(None); @@ -273,9 +287,9 @@ async fn bitfinity_test_node_get_transaction_when_it_is_queued() { mock_eth_server_start(EthServer::into_rpc(eth_server)).await; let bitfinity_evm_url = format!("http://{}", eth_server_address); let (reth_client, _reth_node) = - start_reth_node(Some(bitfinity_evm_url.clone()), None, Some(queue.clone())).await; + start_reth_node(&tasks, Some(bitfinity_evm_url.clone()), None, Some(queue.clone())).await; - const TXS_NUMBER: usize = 10; + const TXS_NUMBER: usize = 1; // Create a random transactions let transactions = (1..=TXS_NUMBER) @@ -332,11 +346,24 @@ fn transaction_with_gas_price(gas_price: u128) -> TransactionSigned { let mock = MockTransaction::legacy().with_gas_price(gas_price); let transaction: Transaction = mock.into(); - TransactionSigned { hash: Default::default(), signature: Default::default(), transaction } + sign_tx_with_random_key_pair(transaction) +} + +fn sign_tx_with_random_key_pair(tx: Transaction) -> TransactionSigned { + let secp = Secp256k1::new(); + let key_pair = Keypair::new(&secp, &mut rand::thread_rng()); + sign_tx_with_key_pair(key_pair, tx) +} + +fn sign_tx_with_key_pair(key_pair: Keypair, tx: Transaction) -> TransactionSigned { + let signature = + sign_message(B256::from_slice(&key_pair.secret_bytes()[..]), tx.signature_hash()).unwrap(); + TransactionSigned::from_transaction_and_signature(tx, signature) } /// Start a local reth node async fn start_reth_node( + tasks: &TaskManager, bitfinity_evm_url: Option, import_data: Option, queue: Option, @@ -374,8 +401,6 @@ async fn start_reth_node( >, >, ) { - let tasks = TaskManager::current(); - // create node config let mut node_config = NodeConfig::test().dev().with_rpc(RpcServerArgs::default().with_http()).with_unused_ports(); From 01c73c6cb35ef6471e99db25437613d9f94a3f87 Mon Sep 17 00:00:00 2001 From: f3kilo Date: Fri, 6 Dec 2024 12:25:23 +0300 Subject: [PATCH 18/31] fixed block number bug --- bin/reth/tests/commands/bitfinity_node_it.rs | 18 ++++++++++++++---- .../src/helpers/bitfinity_evm_rpc.rs | 6 +++--- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/bin/reth/tests/commands/bitfinity_node_it.rs b/bin/reth/tests/commands/bitfinity_node_it.rs index 30c35aa21a4..7565c3a90d4 100644 --- a/bin/reth/tests/commands/bitfinity_node_it.rs +++ b/bin/reth/tests/commands/bitfinity_node_it.rs @@ -289,7 +289,7 @@ async fn bitfinity_test_node_get_transaction_when_it_is_queued() { let (reth_client, _reth_node) = start_reth_node(&tasks, Some(bitfinity_evm_url.clone()), None, Some(queue.clone())).await; - const TXS_NUMBER: usize = 1; + const TXS_NUMBER: usize = 10; // Create a random transactions let transactions = (1..=TXS_NUMBER) @@ -472,10 +472,11 @@ async fn mock_eth_server_start(methods: impl Into) -> (ServerHandle, So /// Eth server mock utils. pub mod eth_server { use alloy_rlp::{Bytes, Decodable}; + use discv5::enr::secp256k1::{Keypair, Secp256k1}; use ethereum_json_rpc_client::{Block, CertifiedResult, H256}; use jsonrpsee::{core::RpcResult, proc_macros::rpc}; - use reth_primitives::TransactionSigned; - use reth_rpc_types::Transaction; + use reth_primitives::{sign_message, TransactionSigned}; + use reth_rpc_types::{Signature, Transaction}; use revm_primitives::{hex, Address, B256, U256}; use tokio::sync::{mpsc::Sender, Mutex}; @@ -567,7 +568,7 @@ pub mod eth_server { } // If tx present, ruturn it with some block number. - let tx = Transaction { + let mut tx = Transaction { hash, nonce: 42, block_hash: Some(B256::random()), @@ -589,6 +590,15 @@ pub mod eth_server { transaction_type: Default::default(), other: Default::default(), }; + let key_pair = Keypair::new(&Secp256k1::new(), &mut rand::thread_rng()); + let signature = + sign_message(B256::from_slice(&key_pair.secret_bytes()[..]), tx.hash).unwrap(); + tx.signature = Some(Signature { + r: signature.r, + s: signature.s, + v: U256::from(signature.v(None)), + y_parity: None, + }); Ok(Some(tx)) } diff --git a/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs b/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs index ebd5c6bb2e2..39c9f616451 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs @@ -270,9 +270,9 @@ async fn transaction_from_evm_rpc( let tx = Transaction { hash, nonce: typed_tx.nonce.as_u64(), - block_hash: None, - block_number: None, - transaction_index: None, + block_hash: typed_tx.block_hash.map(|h| h.0.into()), + block_number: typed_tx.block_number.map(|v| v.as_u64()), + transaction_index: typed_tx.transaction_index.map(|v| v.as_u64()), from: typed_tx.from.0.into(), to: typed_tx.to.map(|addr| addr.0.into()), value: U256::from_limbs(typed_tx.value.0), From 6afe3f5c64517362781a25f2ba9212cdc24a5d3e Mon Sep 17 00:00:00 2001 From: f3kilo Date: Fri, 6 Dec 2024 12:49:45 +0300 Subject: [PATCH 19/31] increased timeout to fix test --- bin/reth/tests/commands/bitfinity_import_it.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/reth/tests/commands/bitfinity_import_it.rs b/bin/reth/tests/commands/bitfinity_import_it.rs index 29181286120..60d1fdb716e 100644 --- a/bin/reth/tests/commands/bitfinity_import_it.rs +++ b/bin/reth/tests/commands/bitfinity_import_it.rs @@ -119,7 +119,7 @@ async fn bitfinity_test_should_import_data_from_evm_with_backup_rpc_url() { import_data.bitfinity_args.batch_size = (end_block as usize) * 10; // Act - import_blocks(import_data.clone(), Duration::from_secs(20), false).await; + import_blocks(import_data.clone(), Duration::from_secs(120), false).await; // Assert { From 170cecc097f5da93d9e525d76d8ef1bf423ca485 Mon Sep 17 00:00:00 2001 From: f3kilo Date: Fri, 6 Dec 2024 12:51:19 +0300 Subject: [PATCH 20/31] increase timeout in another test --- bin/reth/tests/commands/bitfinity_reset_evm_state_it.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/reth/tests/commands/bitfinity_reset_evm_state_it.rs b/bin/reth/tests/commands/bitfinity_reset_evm_state_it.rs index 78b47a48477..c7e956d5f14 100644 --- a/bin/reth/tests/commands/bitfinity_reset_evm_state_it.rs +++ b/bin/reth/tests/commands/bitfinity_reset_evm_state_it.rs @@ -101,7 +101,7 @@ async fn bitfinity_test_reset_should_extract_all_accounts_data() { let (_temp_dir, mut import_data) = bitfinity_import_config_data(evm_datasource_url, None, data_dir).await.unwrap(); - let fetch_block_timeout_secs = std::cmp::max(20, end_block / 100); + let fetch_block_timeout_secs = std::cmp::max(120, end_block / 100); // Import block from block explorer import_data.bitfinity_args.end_block = Some(end_block); From da1747b56e8653c4f65c36172071973f5bafbb53 Mon Sep 17 00:00:00 2001 From: f3kilo Date: Mon, 9 Dec 2024 10:27:43 +0300 Subject: [PATCH 21/31] higher timeout for bitfinity_test_reset_should_extract_all_accounts_data --- bin/reth/tests/commands/bitfinity_reset_evm_state_it.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/reth/tests/commands/bitfinity_reset_evm_state_it.rs b/bin/reth/tests/commands/bitfinity_reset_evm_state_it.rs index c7e956d5f14..76eba6f082a 100644 --- a/bin/reth/tests/commands/bitfinity_reset_evm_state_it.rs +++ b/bin/reth/tests/commands/bitfinity_reset_evm_state_it.rs @@ -101,7 +101,7 @@ async fn bitfinity_test_reset_should_extract_all_accounts_data() { let (_temp_dir, mut import_data) = bitfinity_import_config_data(evm_datasource_url, None, data_dir).await.unwrap(); - let fetch_block_timeout_secs = std::cmp::max(120, end_block / 100); + let fetch_block_timeout_secs = std::cmp::max(300, end_block / 100); // Import block from block explorer import_data.bitfinity_args.end_block = Some(end_block); From 76b59b3abc4a0f9dfe69df460de5ad15abaf4540 Mon Sep 17 00:00:00 2001 From: f3kilo Date: Mon, 9 Dec 2024 10:52:25 +0300 Subject: [PATCH 22/31] much more timeout --- bin/reth/tests/commands/bitfinity_reset_evm_state_it.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/reth/tests/commands/bitfinity_reset_evm_state_it.rs b/bin/reth/tests/commands/bitfinity_reset_evm_state_it.rs index 76eba6f082a..369709d2b6c 100644 --- a/bin/reth/tests/commands/bitfinity_reset_evm_state_it.rs +++ b/bin/reth/tests/commands/bitfinity_reset_evm_state_it.rs @@ -101,7 +101,7 @@ async fn bitfinity_test_reset_should_extract_all_accounts_data() { let (_temp_dir, mut import_data) = bitfinity_import_config_data(evm_datasource_url, None, data_dir).await.unwrap(); - let fetch_block_timeout_secs = std::cmp::max(300, end_block / 100); + let fetch_block_timeout_secs = std::cmp::max(3000, end_block / 100); // Import block from block explorer import_data.bitfinity_args.end_block = Some(end_block); From bc307066e56b20b1c614456323af5c232fb69501 Mon Sep 17 00:00:00 2001 From: f3kilo Date: Tue, 10 Dec 2024 11:38:11 +0300 Subject: [PATCH 23/31] send tx batches concurrently --- bin/reth/src/bitfinity_tasks/send_txs.rs | 45 ++++++++++++-------- bin/reth/tests/commands/bitfinity_node_it.rs | 21 +++++---- 2 files changed, 41 insertions(+), 25 deletions(-) diff --git a/bin/reth/src/bitfinity_tasks/send_txs.rs b/bin/reth/src/bitfinity_tasks/send_txs.rs index 2761a13523a..92c152ccd51 100644 --- a/bin/reth/src/bitfinity_tasks/send_txs.rs +++ b/bin/reth/src/bitfinity_tasks/send_txs.rs @@ -10,6 +10,7 @@ use did::H256; use ethereum_json_rpc_client::reqwest::ReqwestClient; use ethereum_json_rpc_client::{EthJsonRpcClient, Id, Params}; use eyre::eyre; +use futures::future::join_all; use lightspeed_scheduler::job::Job; use lightspeed_scheduler::scheduler::Scheduler; use lightspeed_scheduler::JobExecutor; @@ -79,31 +80,41 @@ impl BitfinityTransactionSender { /// Execute the transaction sending job. pub async fn single_execution(&self) -> eyre::Result<()> { - let mut total_sent = 0; - loop { - let to_send = self.get_transactions_to_send().await; - let result = match to_send.len() { - 0 => return Ok(()), - 1 => self.send_single_tx(&to_send[0].1).await, - _ => self.send_txs_batch(&to_send).await, - }; + let mut to_send = self.get_transactions_to_send().await; + let batch_size = self.batch_size.max(1); + let mut send_futures = vec![]; - if let Err(e) = result { - warn!("Failed to send transactions to EVM: {e}"); - continue; + loop { + let last_idx = batch_size.min(to_send.len()); + if last_idx == 0 { + break; } - total_sent += to_send.len(); - if total_sent > self.txs_per_execution_threshold { - return Ok(()); - } + let to_send_batch: Vec<_> = to_send.drain(..last_idx).collect(); + + let send_future = async move { + let result = match to_send_batch.len() { + 0 => return, + 1 => self.send_single_tx(&to_send_batch[0].1).await, + _ => self.send_txs_batch(&to_send_batch).await, + }; + + if let Err(e) = result { + warn!("Failed to send transactions to EVM: {e}"); + } + }; + send_futures.push(send_future); } + + join_all(send_futures).await; + + Ok(()) } async fn get_transactions_to_send(&self) -> Vec<(U256, Vec)> { - let mut batch = Vec::with_capacity(self.batch_size); + let mut batch = Vec::with_capacity(self.txs_per_execution_threshold); let mut queue = self.queue.lock().await; - let txs_to_pop = self.batch_size.max(1); // if batch size is zero, take at least one tx. + let txs_to_pop = self.txs_per_execution_threshold.max(1); // if batch size is zero, take at least one tx. for _ in 0..txs_to_pop { let Some(entry) = queue.pop_tx_with_highest_price() else { diff --git a/bin/reth/tests/commands/bitfinity_node_it.rs b/bin/reth/tests/commands/bitfinity_node_it.rs index 7565c3a90d4..35fe753b7cf 100644 --- a/bin/reth/tests/commands/bitfinity_node_it.rs +++ b/bin/reth/tests/commands/bitfinity_node_it.rs @@ -242,23 +242,24 @@ async fn bitfinity_test_node_send_raw_transaction_in_gas_price_order() { let (reth_client, _reth_node) = start_reth_node(&tasks, Some(bitfinity_evm_url.clone()), None, Some(queue.clone())).await; - const TXS_NUMBER: usize = 10; + const TXS_NUMBER: usize = 100; // Create a random transactions let transactions = (1..=TXS_NUMBER) .map(|i| alloy_rlp::encode(transaction_with_gas_price(100 * i as u128))) .collect::>(); - let expected_hashes = transactions.iter().map(|tx| keccak::keccak_hash(tx)).collect::>(); + // Only highest price transactions should be sent. + let expected_hashes = + transactions.iter().rev().take(10).map(|tx| keccak::keccak_hash(tx)).collect::>(); // Act - for (tx, expected_hash) in transactions.iter().zip(expected_hashes.iter()) { - let hash = reth_client.send_raw_transaction_bytes(tx).await.unwrap(); - assert_eq!(hash.to_fixed_bytes(), expected_hash.0.to_fixed_bytes()); + for tx in &transactions { + reth_client.send_raw_transaction_bytes(tx).await.unwrap(); } let transaction_sending = BitfinityTransactionSender::new( - queue, + queue.clone(), bitfinity_evm_url, Duration::from_millis(200), 10, @@ -268,8 +269,12 @@ async fn bitfinity_test_node_send_raw_transaction_in_gas_price_order() { let received_txs = consume_received_txs(&mut tx_receiver, 10).await.unwrap(); - for (idx, expected_hash) in expected_hashes.iter().rev().enumerate() { - assert_eq!(received_txs[idx].0, expected_hash.0.to_fixed_bytes()); + // Check all queued transactions sent. + assert!(queue.lock().await.is_empty()); + + for expected_hash in expected_hashes.iter().rev() { + let expected = B256::from(expected_hash.0.to_fixed_bytes()); + assert!(received_txs.contains(&expected)); } } From 78ccfbadda354818899c3b3944b6964ecf3bae7c Mon Sep 17 00:00:00 2001 From: f3kilo Date: Mon, 16 Dec 2024 12:54:44 +0300 Subject: [PATCH 24/31] use newer evm-sdk --- Cargo.lock | 1240 ++++++++++++----- Cargo.toml | 6 +- .../downloaders/src/bitfinity_evm_client.rs | 22 +- crates/rpc/rpc-eth-api/Cargo.toml | 1 + crates/rpc/rpc-eth-api/src/core.rs | 9 +- .../src/helpers/bitfinity_evm_rpc.rs | 10 +- 6 files changed, 917 insertions(+), 371 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a749069bdd8..c5670622f39 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -107,6 +107,24 @@ version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +[[package]] +name = "alloy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "689e271a72a5c0b05bfdf41c9d0424f11e9df721385dc5bd9045a51f9ea3313b" +dependencies = [ + "alloy-consensus 0.8.0", + "alloy-core", + "alloy-eips 0.8.0", + "alloy-genesis 0.8.0", + "alloy-network 0.8.0", + "alloy-provider 0.8.0", + "alloy-rpc-client 0.8.0", + "alloy-rpc-types 0.8.0", + "alloy-serde 0.8.0", + "alloy-transport-http 0.8.0", +] + [[package]] name = "alloy-chains" version = "0.1.23" @@ -127,10 +145,10 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f63a6c9eb45684a5468536bc55379a2af0f45ffa5d756e4e4964532737e1836" dependencies = [ - "alloy-eips", - "alloy-primitives", + "alloy-eips 0.1.3", + "alloy-primitives 0.7.6", "alloy-rlp", - "alloy-serde", + "alloy-serde 0.1.3", "arbitrary", "c-kzg", "proptest", @@ -138,16 +156,61 @@ dependencies = [ "serde", ] +[[package]] +name = "alloy-consensus" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ba14856660f31807ebb26ce8f667e814c72694e1077e97ef102e326ad580f3f" +dependencies = [ + "alloy-eips 0.8.0", + "alloy-primitives 0.8.15", + "alloy-rlp", + "alloy-serde 0.8.0", + "alloy-trie 0.7.6", + "auto_impl", + "c-kzg", + "derive_more 1.0.0", + "k256", + "serde", +] + +[[package]] +name = "alloy-consensus-any" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28666307e76441e7af37a2b90cde7391c28112121bea59f4e0d804df8b20057e" +dependencies = [ + "alloy-consensus 0.8.0", + "alloy-eips 0.8.0", + "alloy-primitives 0.8.15", + "alloy-rlp", + "alloy-serde 0.8.0", + "serde", +] + +[[package]] +name = "alloy-core" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c618bd382f0bc2ac26a7e4bfae01c9b015ca8f21b37ca40059ae35a7e62b3dc6" +dependencies = [ + "alloy-dyn-abi 0.8.15", + "alloy-json-abi 0.8.15", + "alloy-primitives 0.8.15", + "alloy-rlp", + "alloy-sol-types 0.8.15", +] + [[package]] name = "alloy-dyn-abi" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb6e6436a9530f25010d13653e206fab4c9feddacf21a54de8d7311b275bc56b" dependencies = [ - "alloy-json-abi", - "alloy-primitives", - "alloy-sol-type-parser", - "alloy-sol-types", + "alloy-json-abi 0.7.6", + "alloy-primitives 0.7.6", + "alloy-sol-type-parser 0.7.7", + "alloy-sol-types 0.7.6", "const-hex", "derive_more 0.99.18", "itoa", @@ -156,15 +219,56 @@ dependencies = [ "winnow 0.6.13", ] +[[package]] +name = "alloy-dyn-abi" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41056bde53ae10ffbbf11618efbe1e0290859e5eab0fe9ef82ebdb62f12a866f" +dependencies = [ + "alloy-json-abi 0.8.15", + "alloy-primitives 0.8.15", + "alloy-sol-type-parser 0.8.15", + "alloy-sol-types 0.8.15", + "const-hex", + "itoa", + "serde", + "serde_json", + "winnow 0.6.13", +] + +[[package]] +name = "alloy-eip2930" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0069cf0642457f87a01a014f6dc29d5d893cd4fd8fddf0c3cdfad1bb3ebafc41" +dependencies = [ + "alloy-primitives 0.8.15", + "alloy-rlp", + "serde", +] + +[[package]] +name = "alloy-eip7702" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c986539255fb839d1533c128e190e557e52ff652c9ef62939e233a81dd93f7e" +dependencies = [ + "alloy-primitives 0.8.15", + "alloy-rlp", + "derive_more 1.0.0", + "k256", + "serde", +] + [[package]] name = "alloy-eips" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4b0fc6a572ef2eebda0a31a5e393d451abda703fec917c75d9615d8c978cf2" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.7.6", "alloy-rlp", - "alloy-serde", + "alloy-serde 0.1.3", "arbitrary", "c-kzg", "derive_more 0.99.18", @@ -175,14 +279,44 @@ dependencies = [ "sha2 0.10.8", ] +[[package]] +name = "alloy-eips" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e922d558006ba371681d484d12aa73fe673d84884f83747730af7433c0e86d" +dependencies = [ + "alloy-eip2930", + "alloy-eip7702", + "alloy-primitives 0.8.15", + "alloy-rlp", + "alloy-serde 0.8.0", + "c-kzg", + "derive_more 1.0.0", + "once_cell", + "serde", + "sha2 0.10.8", +] + [[package]] name = "alloy-genesis" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48450f9c6f0821c1eee00ed912942492ed4f11dd69532825833de23ecc7a2256" dependencies = [ - "alloy-primitives", - "alloy-serde", + "alloy-primitives 0.7.6", + "alloy-serde 0.1.3", + "serde", +] + +[[package]] +name = "alloy-genesis" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dca170827a7ca156b43588faebf9e9d27c27d0fb07cab82cfd830345e2b24f5" +dependencies = [ + "alloy-primitives 0.8.15", + "alloy-serde 0.8.0", + "alloy-trie 0.7.6", "serde", ] @@ -192,8 +326,20 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aaeaccd50238126e3a0ff9387c7c568837726ad4f4e399b528ca88104d6c25ef" dependencies = [ - "alloy-primitives", - "alloy-sol-type-parser", + "alloy-primitives 0.7.6", + "alloy-sol-type-parser 0.7.7", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-json-abi" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c357da577dfb56998d01f574d81ad7a1958d248740a7981b205d69d65a7da404" +dependencies = [ + "alloy-primitives 0.8.15", + "alloy-sol-type-parser 0.8.15", "serde", "serde_json", ] @@ -204,41 +350,93 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d484c2a934d0a4d86f8ad4db8113cb1d607707a6c54f6e78f4f1b4451b47aa70" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.7.6", "serde", "serde_json", "thiserror 1.0.61", "tracing", ] +[[package]] +name = "alloy-json-rpc" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9335278f50b0273e0a187680ee742bb6b154a948adf036f448575bacc5ccb315" +dependencies = [ + "alloy-primitives 0.8.15", + "alloy-sol-types 0.8.15", + "serde", + "serde_json", + "thiserror 2.0.4", + "tracing", +] + [[package]] name = "alloy-network" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a20eba9bc551037f0626d6d29e191888638d979943fa4e842e9e6fc72bf0565" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-json-rpc", - "alloy-primitives", - "alloy-rpc-types-eth", - "alloy-serde", - "alloy-signer", - "alloy-sol-types", + "alloy-consensus 0.1.3", + "alloy-eips 0.1.3", + "alloy-json-rpc 0.1.3", + "alloy-primitives 0.7.6", + "alloy-rpc-types-eth 0.1.3", + "alloy-serde 0.1.3", + "alloy-signer 0.1.3", + "alloy-sol-types 0.7.6", "async-trait", "auto_impl", "futures-utils-wasm", "thiserror 1.0.61", ] +[[package]] +name = "alloy-network" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad4e6ad4230df8c4a254c20f8d6a84ab9df151bfca13f463177dbc96571cc1f8" +dependencies = [ + "alloy-consensus 0.8.0", + "alloy-consensus-any", + "alloy-eips 0.8.0", + "alloy-json-rpc 0.8.0", + "alloy-network-primitives", + "alloy-primitives 0.8.15", + "alloy-rpc-types-any", + "alloy-rpc-types-eth 0.8.0", + "alloy-serde 0.8.0", + "alloy-signer 0.8.0", + "alloy-sol-types 0.8.15", + "async-trait", + "auto_impl", + "futures-utils-wasm", + "serde", + "serde_json", + "thiserror 2.0.4", +] + +[[package]] +name = "alloy-network-primitives" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4df88a2f8020801e0fefce79471d3946d39ca3311802dbbd0ecfdeee5e972e3" +dependencies = [ + "alloy-consensus 0.8.0", + "alloy-eips 0.8.0", + "alloy-primitives 0.8.15", + "alloy-serde 0.8.0", + "serde", +] + [[package]] name = "alloy-node-bindings" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22e07c66b8b0ba8c87461a15fe3247c5b46fb500e103111b0ad4798738e45b1e" dependencies = [ - "alloy-genesis", - "alloy-primitives", + "alloy-genesis 0.1.3", + "alloy-primitives 0.7.6", "k256", "serde_json", "tempfile", @@ -274,6 +472,34 @@ dependencies = [ "tiny-keccak", ] +[[package]] +name = "alloy-primitives" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6259a506ab13e1d658796c31e6e39d2e2ee89243bcc505ddc613b35732e0a430" +dependencies = [ + "alloy-rlp", + "bytes", + "cfg-if", + "const-hex", + "derive_more 1.0.0", + "foldhash", + "hashbrown 0.15.2", + "hex-literal", + "indexmap 2.7.0", + "itoa", + "k256", + "keccak-asm", + "paste", + "proptest", + "rand 0.8.5", + "ruint", + "rustc-hash 2.0.0", + "serde", + "sha3", + "tiny-keccak", +] + [[package]] name = "alloy-provider" version = "0.1.3" @@ -281,33 +507,70 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad5d89acb7339fad13bc69e7b925232f242835bfd91c82fcb9326b36481bd0f0" dependencies = [ "alloy-chains", - "alloy-consensus", - "alloy-eips", - "alloy-json-rpc", - "alloy-network", - "alloy-primitives", + "alloy-consensus 0.1.3", + "alloy-eips 0.1.3", + "alloy-json-rpc 0.1.3", + "alloy-network 0.1.3", + "alloy-primitives 0.7.6", "alloy-pubsub", - "alloy-rpc-client", + "alloy-rpc-client 0.1.3", "alloy-rpc-types-admin", "alloy-rpc-types-engine", - "alloy-rpc-types-eth", - "alloy-transport", - "alloy-transport-http", + "alloy-rpc-types-eth 0.1.3", + "alloy-transport 0.1.3", + "alloy-transport-http 0.1.3", "alloy-transport-ws", "async-stream", "async-trait", "auto_impl", - "dashmap", + "dashmap 5.5.3", + "futures", + "futures-utils-wasm", + "lru", + "pin-project", + "reqwest", + "serde", + "serde_json", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "alloy-provider" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5115c74c037714e1b02a86f742289113afa5d494b5ea58308ba8aa378e739101" +dependencies = [ + "alloy-chains", + "alloy-consensus 0.8.0", + "alloy-eips 0.8.0", + "alloy-json-rpc 0.8.0", + "alloy-network 0.8.0", + "alloy-network-primitives", + "alloy-primitives 0.8.15", + "alloy-rpc-client 0.8.0", + "alloy-rpc-types-eth 0.8.0", + "alloy-transport 0.8.0", + "alloy-transport-http 0.8.0", + "async-stream", + "async-trait", + "auto_impl", + "dashmap 6.1.0", "futures", "futures-utils-wasm", "lru", + "parking_lot 0.12.3", "pin-project", "reqwest", + "schnellru", "serde", "serde_json", + "thiserror 2.0.4", "tokio", "tracing", "url", + "wasmtimer", ] [[package]] @@ -316,24 +579,24 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "034258dfaa51c278e1f7fcc46e587d10079ec9372866fa48c5df9d908fc1f6b1" dependencies = [ - "alloy-json-rpc", - "alloy-primitives", - "alloy-transport", + "alloy-json-rpc 0.1.3", + "alloy-primitives 0.7.6", + "alloy-transport 0.1.3", "bimap", "futures", "serde", "serde_json", "tokio", "tokio-stream", - "tower", + "tower 0.4.13", "tracing", ] [[package]] name = "alloy-rlp" -version = "0.3.7" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a43b18702501396fa9bcdeecd533bc85fac75150d308fc0f6800a01e6234a003" +checksum = "f542548a609dca89fcd72b3b9f355928cf844d4363c5eed9c5273a3dd225e097" dependencies = [ "alloy-rlp-derive", "arrayvec 0.7.4", @@ -342,9 +605,9 @@ dependencies = [ [[package]] name = "alloy-rlp-derive" -version = "0.3.7" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d83524c1f6162fcb5b0decf775498a125066c86dda6066ed609531b0e912f85a" +checksum = "5a833d97bf8a5f0f878daf2c8451fff7de7f9de38baa5a45d936ec718d81255a" dependencies = [ "proc-macro2", "quote", @@ -357,11 +620,11 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ce003e8c74bbbc7d4235131c1d6b7eaf14a533ae850295b90d240340989cb" dependencies = [ - "alloy-json-rpc", - "alloy-primitives", + "alloy-json-rpc 0.1.3", + "alloy-primitives 0.7.6", "alloy-pubsub", - "alloy-transport", - "alloy-transport-http", + "alloy-transport 0.1.3", + "alloy-transport-http 0.1.3", "alloy-transport-ws", "futures", "pin-project", @@ -370,11 +633,34 @@ dependencies = [ "serde_json", "tokio", "tokio-stream", - "tower", + "tower 0.4.13", "tracing", "url", ] +[[package]] +name = "alloy-rpc-client" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6a0bd0ce5660ac48e4f3bb0c7c5c3a94db287a0be94971599d83928476cbcd" +dependencies = [ + "alloy-json-rpc 0.8.0", + "alloy-primitives 0.8.15", + "alloy-transport 0.8.0", + "alloy-transport-http 0.8.0", + "futures", + "pin-project", + "reqwest", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tower 0.5.0", + "tracing", + "url", + "wasmtimer", +] + [[package]] name = "alloy-rpc-types" version = "0.1.3" @@ -382,9 +668,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dfa1dd3e0bc3a3d89744fba8d1511216e83257160da2cd028a18b7d9c026030" dependencies = [ "alloy-rpc-types-engine", - "alloy-rpc-types-eth", + "alloy-rpc-types-eth 0.1.3", "alloy-rpc-types-trace", - "alloy-serde", + "alloy-serde 0.1.3", +] + +[[package]] +name = "alloy-rpc-types" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "374ac12e35bb90ebccd86e7c943ddba9590149a6e35cc4d9cd860d6635fd1018" +dependencies = [ + "alloy-primitives 0.8.15", + "alloy-rpc-types-eth 0.8.0", + "alloy-serde 0.8.0", + "serde", ] [[package]] @@ -393,8 +691,8 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bae99de76a362c4311f0892e286eb752cf2a3a6ef6555dff6d93f51de2c24648" dependencies = [ - "alloy-genesis", - "alloy-primitives", + "alloy-genesis 0.1.3", + "alloy-primitives 0.7.6", "serde", "serde_json", ] @@ -405,19 +703,30 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f67aec11f9f3bc5e96c2b7f342dba6e9541a8a48d2cfbe27b6b195136aa18eee" dependencies = [ - "alloy-primitives", - "alloy-serde", + "alloy-primitives 0.7.6", + "alloy-serde 0.1.3", "serde", ] +[[package]] +name = "alloy-rpc-types-any" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea98f81bcd759dbfa3601565f9d7a02220d8ef1d294ec955948b90aaafbfd857" +dependencies = [ + "alloy-consensus-any", + "alloy-rpc-types-eth 0.8.0", + "alloy-serde 0.8.0", +] + [[package]] name = "alloy-rpc-types-beacon" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd2c363d49f460538899aaeb3325918f55fa01841fd7f3f11f58d438343ea083" dependencies = [ - "alloy-eips", - "alloy-primitives", + "alloy-eips 0.1.3", + "alloy-primitives 0.7.6", "alloy-rpc-types-engine", "serde", "serde_with", @@ -430,12 +739,12 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc40df2dda7561d1406d0bee1d19c8787483a2cf2ee8011c05909475e7bc102d" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives", + "alloy-consensus 0.1.3", + "alloy-eips 0.1.3", + "alloy-primitives 0.7.6", "alloy-rlp", - "alloy-rpc-types-eth", - "alloy-serde", + "alloy-rpc-types-eth 0.1.3", + "alloy-serde 0.1.3", "jsonrpsee-types", "jsonwebtoken", "rand 0.8.5", @@ -449,12 +758,12 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13bd7aa9ff9e67f1ba7ee0dd8cebfc95831d1649b0e4eeefae940dc3681079fa" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives", + "alloy-consensus 0.1.3", + "alloy-eips 0.1.3", + "alloy-primitives 0.7.6", "alloy-rlp", - "alloy-serde", - "alloy-sol-types", + "alloy-serde 0.1.3", + "alloy-sol-types 0.7.6", "arbitrary", "itertools 0.13.0", "jsonrpsee-types", @@ -465,15 +774,35 @@ dependencies = [ "thiserror 1.0.61", ] +[[package]] +name = "alloy-rpc-types-eth" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e518b0a7771e00728f18be0708f828b18a1cfc542a7153bef630966a26388e0" +dependencies = [ + "alloy-consensus 0.8.0", + "alloy-consensus-any", + "alloy-eips 0.8.0", + "alloy-network-primitives", + "alloy-primitives 0.8.15", + "alloy-rlp", + "alloy-serde 0.8.0", + "alloy-sol-types 0.8.15", + "derive_more 1.0.0", + "itertools 0.13.0", + "serde", + "serde_json", +] + [[package]] name = "alloy-rpc-types-trace" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "535d26db98ac320a0d1637faf3e210328c3df3b1998abd7e72343d3857058efe" dependencies = [ - "alloy-primitives", - "alloy-rpc-types-eth", - "alloy-serde", + "alloy-primitives 0.7.6", + "alloy-rpc-types-eth 0.1.3", + "alloy-serde 0.1.3", "serde", "serde_json", "thiserror 1.0.61", @@ -485,9 +814,9 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5971c92989c6a5588d3f6d1e99e5328fba6e68694efbe969d6ec96ae5b9d1037" dependencies = [ - "alloy-primitives", - "alloy-rpc-types-eth", - "alloy-serde", + "alloy-primitives 0.7.6", + "alloy-rpc-types-eth 0.1.3", + "alloy-serde 0.1.3", "serde", ] @@ -497,7 +826,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8913f9e825068d77c516188c221c44f78fd814fce8effe550a783295a2757d19" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.7.6", "arbitrary", "proptest", "proptest-derive 0.4.0", @@ -505,13 +834,24 @@ dependencies = [ "serde_json", ] +[[package]] +name = "alloy-serde" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3dc8d4a08ffc90c1381d39a4afa2227668259a42c97ab6eecf51cbd82a8761" +dependencies = [ + "alloy-primitives 0.8.15", + "serde", + "serde_json", +] + [[package]] name = "alloy-signer" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f740e13eb4c6a0e4d0e49738f1e86f31ad2d7ef93be499539f492805000f7237" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.7.6", "async-trait", "auto_impl", "elliptic-curve", @@ -519,16 +859,30 @@ dependencies = [ "thiserror 1.0.61", ] +[[package]] +name = "alloy-signer" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16188684100f6e0f2a2b949968fe3007749c5be431549064a1bce4e7b3a196a9" +dependencies = [ + "alloy-primitives 0.8.15", + "async-trait", + "auto_impl", + "elliptic-curve", + "k256", + "thiserror 2.0.4", +] + [[package]] name = "alloy-signer-local" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87db68d926887393a1d0f9c43833b44446ea29d603291e7b20e5d115f31aa4e3" dependencies = [ - "alloy-consensus", - "alloy-network", - "alloy-primitives", - "alloy-signer", + "alloy-consensus 0.1.3", + "alloy-network 0.1.3", + "alloy-primitives 0.7.6", + "alloy-signer 0.1.3", "async-trait", "coins-bip32", "coins-bip39", @@ -543,30 +897,62 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bad41a7c19498e3f6079f7744656328699f8ea3e783bdd10d85788cd439f572" dependencies = [ - "alloy-sol-macro-expander", - "alloy-sol-macro-input", + "alloy-sol-macro-expander 0.7.6", + "alloy-sol-macro-input 0.7.6", "proc-macro-error", "proc-macro2", "quote", "syn 2.0.90", ] +[[package]] +name = "alloy-sol-macro" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9d64f851d95619233f74b310f12bcf16e0cbc27ee3762b6115c14a84809280a" +dependencies = [ + "alloy-sol-macro-expander 0.8.15", + "alloy-sol-macro-input 0.8.15", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "alloy-sol-macro-expander" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd9899da7d011b4fe4c406a524ed3e3f963797dbc93b45479d60341d3a27b252" dependencies = [ - "alloy-json-abi", - "alloy-sol-macro-input", + "alloy-json-abi 0.7.6", + "alloy-sol-macro-input 0.7.6", "const-hex", "heck 0.5.0", - "indexmap 2.2.6", + "indexmap 2.7.0", "proc-macro-error", "proc-macro2", "quote", "syn 2.0.90", - "syn-solidity", + "syn-solidity 0.7.6", + "tiny-keccak", +] + +[[package]] +name = "alloy-sol-macro-expander" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bf7ed1574b699f48bf17caab4e6e54c6d12bc3c006ab33d58b1e227c1c3559f" +dependencies = [ + "alloy-sol-macro-input 0.8.15", + "const-hex", + "heck 0.5.0", + "indexmap 2.7.0", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.90", + "syn-solidity 0.8.15", "tiny-keccak", ] @@ -576,7 +962,7 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d32d595768fdc61331a132b6f65db41afae41b9b97d36c21eb1b955c422a7e60" dependencies = [ - "alloy-json-abi", + "alloy-json-abi 0.7.6", "const-hex", "dunce", "heck 0.5.0", @@ -584,15 +970,40 @@ dependencies = [ "quote", "serde_json", "syn 2.0.90", - "syn-solidity", + "syn-solidity 0.7.6", +] + +[[package]] +name = "alloy-sol-macro-input" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c02997ccef5f34f9c099277d4145f183b422938ed5322dc57a089fe9b9ad9ee" +dependencies = [ + "const-hex", + "dunce", + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.90", + "syn-solidity 0.8.15", ] [[package]] name = "alloy-sol-type-parser" -version = "0.7.6" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbcba3ca07cf7975f15d871b721fb18031eec8bce51103907f6dcce00b255d98" +dependencies = [ + "winnow 0.6.13", +] + +[[package]] +name = "alloy-sol-type-parser" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baa2fbd22d353d8685bd9fee11ba2d8b5c3b1d11e56adb3265fcf1f32bfdf404" +checksum = "ce13ff37285b0870d0a0746992a4ae48efaf34b766ae4c2640fa15e5305f8e73" dependencies = [ + "serde", "winnow 0.6.13", ] @@ -602,29 +1013,62 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a49042c6d3b66a9fe6b2b5a8bf0d39fc2ae1ee0310a2a26ffedd79fb097878dd" dependencies = [ - "alloy-json-abi", - "alloy-primitives", - "alloy-sol-macro", + "alloy-json-abi 0.7.6", + "alloy-primitives 0.7.6", + "alloy-sol-macro 0.7.6", + "const-hex", + "serde", +] + +[[package]] +name = "alloy-sol-types" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1174cafd6c6d810711b4e00383037bdb458efc4fe3dbafafa16567e0320c54d8" +dependencies = [ + "alloy-json-abi 0.8.15", + "alloy-primitives 0.8.15", + "alloy-sol-macro 0.8.15", "const-hex", "serde", ] [[package]] name = "alloy-transport" -version = "0.1.3" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd9773e4ec6832346171605c776315544bd06e40f803e7b5b7824b325d5442ca" +dependencies = [ + "alloy-json-rpc 0.1.3", + "base64 0.22.1", + "futures-util", + "futures-utils-wasm", + "serde", + "serde_json", + "thiserror 1.0.61", + "tokio", + "tower 0.4.13", + "url", +] + +[[package]] +name = "alloy-transport" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd9773e4ec6832346171605c776315544bd06e40f803e7b5b7824b325d5442ca" +checksum = "628be5b9b75e4f4c4f2a71d985bbaca4f23de356dc83f1625454c505f5eef4df" dependencies = [ - "alloy-json-rpc", + "alloy-json-rpc 0.8.0", "base64 0.22.1", "futures-util", "futures-utils-wasm", "serde", "serde_json", - "thiserror 1.0.61", + "thiserror 2.0.4", "tokio", - "tower", + "tower 0.5.0", + "tracing", "url", + "wasmtimer", ] [[package]] @@ -633,11 +1077,26 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff8ef947b901c0d4e97370f9fa25844cf8b63b1a58fd4011ee82342dc8a9fc6b" dependencies = [ - "alloy-json-rpc", - "alloy-transport", + "alloy-json-rpc 0.1.3", + "alloy-transport 0.1.3", + "reqwest", + "serde_json", + "tower 0.4.13", + "tracing", + "url", +] + +[[package]] +name = "alloy-transport-http" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e24412cf72f79c95cd9b1d9482e3a31f9d94c24b43c4b3b710cc8d4341eaab0" +dependencies = [ + "alloy-json-rpc 0.8.0", + "alloy-transport 0.8.0", "reqwest", "serde_json", - "tower", + "tower 0.5.0", "tracing", "url", ] @@ -648,9 +1107,9 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb40ee66887a66d875a5bb5e01cee4c9a467c263ef28c865cd4b0ebf15f705af" dependencies = [ - "alloy-json-rpc", + "alloy-json-rpc 0.1.3", "alloy-pubsub", - "alloy-transport", + "alloy-transport 0.1.3", "bytes", "futures", "interprocess", @@ -668,7 +1127,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d92049d6642a18c9849ce7659430151e7c92b51552a0cabdc038c1af4cd7308" dependencies = [ "alloy-pubsub", - "alloy-transport", + "alloy-transport 0.1.3", "futures", "http 1.1.0", "rustls", @@ -685,7 +1144,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03704f265cbbb943b117ecb5055fd46e8f41e7dc8a58b1aed20bcd40ace38c15" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.7.6", "alloy-rlp", "arbitrary", "derive_arbitrary", @@ -699,6 +1158,22 @@ dependencies = [ "tracing", ] +[[package]] +name = "alloy-trie" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a5fd8fea044cc9a8c8a50bb6f28e31f0385d820f116c5b98f6f4e55d6e5590b" +dependencies = [ + "alloy-primitives 0.8.15", + "alloy-rlp", + "arrayvec 0.7.4", + "derive_more 1.0.0", + "nybbles", + "serde", + "smallvec", + "tracing", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -945,6 +1420,9 @@ name = "arrayvec" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +dependencies = [ + "serde", +] [[package]] name = "asn1_der" @@ -1356,7 +1834,7 @@ dependencies = [ "bitflags 2.6.0", "boa_interner", "boa_macros", - "indexmap 2.2.6", + "indexmap 2.7.0", "num-bigint", "rustc-hash 1.1.0", ] @@ -1377,11 +1855,11 @@ dependencies = [ "boa_profiler", "bytemuck", "cfg-if", - "dashmap", + "dashmap 5.5.3", "fast-float", "hashbrown 0.14.5", "icu_normalizer", - "indexmap 2.2.6", + "indexmap 2.7.0", "intrusive-collections", "itertools 0.12.1", "num-bigint", @@ -1427,7 +1905,7 @@ dependencies = [ "boa_gc", "boa_macros", "hashbrown 0.14.5", - "indexmap 2.2.6", + "indexmap 2.7.0", "once_cell", "phf", "rustc-hash 1.1.0", @@ -2019,9 +2497,9 @@ dependencies = [ [[package]] name = "const-hex" -version = "1.12.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8a24a26d37e1ffd45343323dc9fe6654ceea44c12f2fcb3d7ac29e610bc6" +checksum = "4b0485bab839b018a8f1723fc5391819fea5f8f0f32288ef8a735fd096b6160c" dependencies = [ "cfg-if", "cpufeatures", @@ -2470,6 +2948,20 @@ dependencies = [ "parking_lot_core 0.9.10", ] +[[package]] +name = "dashmap" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core 0.9.10", +] + [[package]] name = "data-encoding" version = "2.6.0" @@ -2600,23 +3092,19 @@ dependencies = [ [[package]] name = "did" -version = "0.36.0" -source = "git+https://github.com/bitfinity-network/bitfinity-evm-sdk?tag=v0.36.x#50c63713c5273c023eda9efdf4a6c140ae502c91" +version = "0.38.0" +source = "git+https://github.com/bitfinity-network/bitfinity-evm-sdk?tag=v0.38.x#f8f0c47dcfb1a9c531f6b9f85daf9d5e63dd3760" dependencies = [ - "alloy-primitives", + "alloy", "bincode", "bytes", "candid", "derive_more 1.0.0", - "ethereum-types", - "ethers-core", - "hex", "ic-log", "ic-stable-structures 0.23.0", "jsonrpc-core", "log", "num", - "rlp", "serde", "serde_json", "serde_with", @@ -2949,23 +3437,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "ethabi" -version = "18.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7413c5f74cc903ea37386a8965a936cbeb334bd270862fdece542c1b2dcbc898" -dependencies = [ - "ethereum-types", - "hex", - "once_cell", - "regex", - "serde", - "serde_json", - "sha3", - "thiserror 1.0.61", - "uint", -] - [[package]] name = "ethbloom" version = "0.13.0" @@ -2974,23 +3445,20 @@ checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" dependencies = [ "crunchy", "fixed-hash", - "impl-codec", "impl-rlp", "impl-serde", - "scale-info", "tiny-keccak", ] [[package]] name = "ethereum-json-rpc-client" -version = "0.36.0" -source = "git+https://github.com/bitfinity-network/bitfinity-evm-sdk?tag=v0.36.x#50c63713c5273c023eda9efdf4a6c140ae502c91" +version = "0.38.0" +source = "git+https://github.com/bitfinity-network/bitfinity-evm-sdk?tag=v0.38.x#f8f0c47dcfb1a9c531f6b9f85daf9d5e63dd3760" dependencies = [ + "alloy", "anyhow", "candid", "did", - "ethers-core", - "hex", "ic-exports", "itertools 0.13.0", "jsonrpc-core", @@ -3009,11 +3477,9 @@ checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" dependencies = [ "ethbloom", "fixed-hash", - "impl-codec", "impl-rlp", "impl-serde", "primitive-types", - "scale-info", "uint", ] @@ -3028,33 +3494,6 @@ dependencies = [ "smallvec", ] -[[package]] -name = "ethers-core" -version = "2.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d80cc6ad30b14a48ab786523af33b37f28a8623fc06afd55324816ef18fb1f" -dependencies = [ - "arrayvec 0.7.4", - "bytes", - "chrono", - "const-hex", - "elliptic-curve", - "ethabi", - "generic-array", - "k256", - "num_enum", - "open-fastrlp", - "rand 0.8.5", - "rlp", - "serde", - "serde_json", - "strum", - "tempfile", - "thiserror 1.0.61", - "tiny-keccak", - "unicode-xid", -] - [[package]] name = "event-listener" version = "2.5.3" @@ -3084,8 +3523,8 @@ dependencies = [ [[package]] name = "evm-canister-client" -version = "0.36.0" -source = "git+https://github.com/bitfinity-network/bitfinity-evm-sdk?tag=v0.36.x#50c63713c5273c023eda9efdf4a6c140ae502c91" +version = "0.38.0" +source = "git+https://github.com/bitfinity-network/bitfinity-evm-sdk?tag=v0.38.x#f8f0c47dcfb1a9c531f6b9f85daf9d5e63dd3760" dependencies = [ "candid", "did", @@ -3159,7 +3598,7 @@ dependencies = [ name = "example-custom-engine-types" version = "0.0.0" dependencies = [ - "alloy-genesis", + "alloy-genesis 0.1.3", "eyre", "reth", "reth-basic-payload-builder", @@ -3181,7 +3620,7 @@ dependencies = [ name = "example-custom-evm" version = "0.0.0" dependencies = [ - "alloy-genesis", + "alloy-genesis 0.1.3", "eyre", "reth", "reth-chainspec", @@ -3327,7 +3766,7 @@ dependencies = [ name = "example-exex-op-bridge" version = "0.0.0" dependencies = [ - "alloy-sol-types", + "alloy-sol-types 0.7.6", "eyre", "futures", "rand 0.8.5", @@ -3349,10 +3788,10 @@ dependencies = [ name = "example-exex-rollup" version = "0.0.0" dependencies = [ - "alloy-consensus", - "alloy-genesis", + "alloy-consensus 0.1.3", + "alloy-genesis 0.1.3", "alloy-rlp", - "alloy-sol-types", + "alloy-sol-types 0.7.6", "eyre", "foundry-blob-explorers", "once_cell", @@ -3469,7 +3908,7 @@ dependencies = [ name = "example-stateful-precompile" version = "0.0.0" dependencies = [ - "alloy-genesis", + "alloy-genesis 0.1.3", "eyre", "parking_lot 0.12.3", "reth", @@ -3614,6 +4053,27 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -3630,10 +4090,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "195bb5b228e1215c50d828f3e7d48a809a0af2bc0120462710ea5e7fcba3cbe2" dependencies = [ "alloy-chains", - "alloy-eips", - "alloy-primitives", - "alloy-rpc-types-eth", - "alloy-serde", + "alloy-eips 0.1.3", + "alloy-primitives 0.7.6", + "alloy-rpc-types-eth 0.1.3", + "alloy-serde 0.1.3", "chrono", "reqwest", "serde", @@ -3898,7 +4358,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.1.0", - "indexmap 2.2.6", + "indexmap 2.7.0", "slab", "tokio", "tokio-util", @@ -3950,6 +4410,16 @@ dependencies = [ "serde", ] +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +dependencies = [ + "foldhash", + "serde", +] + [[package]] name = "hashlink" version = "0.8.4" @@ -4216,6 +4686,22 @@ dependencies = [ "webpki-roots", ] +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + [[package]] name = "hyper-util" version = "0.1.6" @@ -4231,7 +4717,7 @@ dependencies = [ "pin-project-lite", "socket2 0.5.7", "tokio", - "tower", + "tower 0.4.13", "tower-service", "tracing", ] @@ -4793,12 +5279,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.6" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.2", "serde", ] @@ -4815,7 +5301,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "321f0f839cd44a4686e9504b0a62b4d69a50b62072144c71c68f5873c167b8d9" dependencies = [ "ahash", - "indexmap 2.2.6", + "indexmap 2.7.0", "is-terminal", "itoa", "log", @@ -5092,7 +5578,7 @@ dependencies = [ "serde_json", "thiserror 1.0.61", "tokio", - "tower", + "tower 0.4.13", "tracing", "url", ] @@ -5134,7 +5620,7 @@ dependencies = [ "tokio", "tokio-stream", "tokio-util", - "tower", + "tower 0.4.13", "tracing", ] @@ -5626,7 +6112,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf0af7a0d7ced10c0151f870e5e3f3f8bc9ffc5992d32873566ca1f9169ae776" dependencies = [ "base64 0.22.1", - "indexmap 2.2.6", + "indexmap 2.7.0", "metrics", "metrics-util", "quanta", @@ -5658,7 +6144,7 @@ dependencies = [ "crossbeam-epoch", "crossbeam-utils", "hashbrown 0.14.5", - "indexmap 2.2.6", + "indexmap 2.7.0", "metrics", "num_cpus", "ordered-float", @@ -5673,7 +6159,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e00cdd87dab765e7dac55c21eb680bfd10655b6c2530f6fe578acdfbb66c757c" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.7.6", "async-sse", "bytes", "futures-util", @@ -5844,6 +6330,23 @@ dependencies = [ "unsigned-varint 0.7.2", ] +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "nibble_vec" version = "0.1.0" @@ -6066,28 +6569,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] -name = "open-fastrlp" -version = "0.1.4" +name = "openssl" +version = "0.10.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" dependencies = [ - "arrayvec 0.7.4", - "auto_impl", - "bytes", - "ethereum-types", - "open-fastrlp-derive", + "bitflags 2.6.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", ] [[package]] -name = "open-fastrlp-derive" +name = "openssl-macros" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "003b2be5c6c53c1cfeb0a238b8a1c3915cd410feb684457a36c10038f764bb1c" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ - "bytes", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.90", ] [[package]] @@ -6096,6 +6600,18 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +[[package]] +name = "openssl-sys" +version = "0.9.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "option-ext" version = "0.2.0" @@ -6574,7 +7090,6 @@ dependencies = [ "impl-codec", "impl-rlp", "impl-serde", - "scale-info", "uint", ] @@ -6611,6 +7126,28 @@ dependencies = [ "version_check", ] +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "proc-macro2" version = "1.0.92" @@ -6840,6 +7377,7 @@ dependencies = [ "libc", "rand_chacha 0.3.1", "rand_core 0.6.4", + "serde", ] [[package]] @@ -7060,11 +7598,13 @@ dependencies = [ "http-body-util", "hyper", "hyper-rustls", + "hyper-tls", "hyper-util", "ipnet", "js-sys", "log", "mime", + "native-tls", "once_cell", "percent-encoding", "pin-project-lite", @@ -7076,8 +7616,9 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 1.0.1", "tokio", + "tokio-native-tls", "tokio-rustls", "tokio-util", "tower-service", @@ -7247,7 +7788,7 @@ dependencies = [ name = "reth-beacon-consensus" version = "1.0.0" dependencies = [ - "alloy-genesis", + "alloy-genesis 0.1.3", "assert_matches", "futures", "itertools 0.13.0", @@ -7298,15 +7839,15 @@ dependencies = [ name = "reth-bench" version = "1.0.0" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-json-rpc", - "alloy-provider", + "alloy-consensus 0.1.3", + "alloy-eips 0.1.3", + "alloy-json-rpc 0.1.3", + "alloy-provider 0.1.3", "alloy-pubsub", - "alloy-rpc-client", + "alloy-rpc-client 0.1.3", "alloy-rpc-types-engine", - "alloy-transport", - "alloy-transport-http", + "alloy-transport 0.1.3", + "alloy-transport-http 0.1.3", "alloy-transport-ipc", "alloy-transport-ws", "async-trait", @@ -7331,7 +7872,7 @@ dependencies = [ "tikv-jemallocator", "tokio", "tokio-util", - "tower", + "tower 0.4.13", "tracing", ] @@ -7339,7 +7880,7 @@ dependencies = [ name = "reth-blockchain-tree" version = "1.0.0" dependencies = [ - "alloy-genesis", + "alloy-genesis 0.1.3", "aquamarine", "assert_matches", "linked_hash_set", @@ -7385,11 +7926,11 @@ name = "reth-chainspec" version = "1.0.0" dependencies = [ "alloy-chains", - "alloy-eips", - "alloy-genesis", - "alloy-primitives", + "alloy-eips 0.1.3", + "alloy-genesis 0.1.3", + "alloy-primitives 0.7.6", "alloy-rlp", - "alloy-trie", + "alloy-trie 0.4.1", "derive_more 0.99.18", "nybbles", "once_cell", @@ -7458,10 +7999,10 @@ dependencies = [ name = "reth-codecs" version = "1.0.0" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-genesis", - "alloy-primitives", + "alloy-consensus 0.1.3", + "alloy-eips 0.1.3", + "alloy-genesis 0.1.3", + "alloy-primitives 0.7.6", "arbitrary", "bytes", "modular-bitfield", @@ -7524,9 +8065,9 @@ dependencies = [ name = "reth-consensus-debug-client" version = "1.0.0" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-provider", + "alloy-consensus 0.1.3", + "alloy-eips 0.1.3", + "alloy-provider 0.1.3", "auto_impl", "eyre", "futures", @@ -7616,7 +8157,7 @@ dependencies = [ name = "reth-db-common" version = "1.0.0" dependencies = [ - "alloy-genesis", + "alloy-genesis 0.1.3", "boyer-moore-magiclen", "eyre", "reth-chainspec", @@ -7641,7 +8182,7 @@ dependencies = [ name = "reth-discv4" version = "1.0.0" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.7.6", "alloy-rlp", "assert_matches", "discv5", @@ -7668,7 +8209,7 @@ dependencies = [ name = "reth-discv5" version = "1.0.0" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.7.6", "alloy-rlp", "derive_more 0.99.18", "discv5", @@ -7695,7 +8236,7 @@ name = "reth-dns-discovery" version = "1.0.0" dependencies = [ "alloy-chains", - "alloy-primitives", + "alloy-primitives 0.7.6", "alloy-rlp", "data-encoding", "enr", @@ -7768,10 +8309,10 @@ dependencies = [ name = "reth-e2e-test-utils" version = "1.0.0" dependencies = [ - "alloy-consensus", - "alloy-network", - "alloy-rpc-types", - "alloy-signer", + "alloy-consensus 0.1.3", + "alloy-network 0.1.3", + "alloy-rpc-types 0.1.3", + "alloy-signer 0.1.3", "alloy-signer-local", "eyre", "futures-util", @@ -7800,7 +8341,7 @@ name = "reth-ecies" version = "1.0.0" dependencies = [ "aes 0.8.4", - "alloy-primitives", + "alloy-primitives 0.7.6", "alloy-rlp", "block-padding", "byteorder", @@ -7947,7 +8488,7 @@ dependencies = [ name = "reth-eth-wire-types" version = "1.0.0" dependencies = [ - "alloy-genesis", + "alloy-genesis 0.1.3", "alloy-rlp", "arbitrary", "bytes", @@ -7997,7 +8538,7 @@ name = "reth-ethereum-forks" version = "1.0.0" dependencies = [ "alloy-chains", - "alloy-primitives", + "alloy-primitives 0.7.6", "alloy-rlp", "arbitrary", "auto_impl", @@ -8033,7 +8574,7 @@ dependencies = [ name = "reth-etl" version = "1.0.0" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.7.6", "rayon", "reth-db-api", "tempfile", @@ -8060,8 +8601,8 @@ dependencies = [ name = "reth-evm-ethereum" version = "1.0.0" dependencies = [ - "alloy-eips", - "alloy-sol-types", + "alloy-eips 0.1.3", + "alloy-sol-types 0.7.6", "reth-chainspec", "reth-ethereum-consensus", "reth-ethereum-forks", @@ -8100,8 +8641,8 @@ dependencies = [ name = "reth-execution-errors" version = "1.0.0" dependencies = [ - "alloy-eips", - "alloy-primitives", + "alloy-eips 0.1.3", + "alloy-primitives 0.7.6", "reth-consensus", "reth-prune-types", "reth-storage-errors", @@ -8113,8 +8654,8 @@ dependencies = [ name = "reth-execution-types" version = "1.0.0" dependencies = [ - "alloy-eips", - "alloy-primitives", + "alloy-eips 0.1.3", + "alloy-primitives 0.7.6", "reth-chainspec", "reth-execution-errors", "reth-primitives", @@ -8190,7 +8731,7 @@ dependencies = [ name = "reth-exex-types" version = "1.0.0" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.7.6", ] [[package]] @@ -8219,7 +8760,7 @@ dependencies = [ "tokio", "tokio-stream", "tokio-util", - "tower", + "tower 0.4.13", "tracing", ] @@ -8230,9 +8771,9 @@ dependencies = [ "bitflags 2.6.0", "byteorder", "criterion", - "dashmap", + "dashmap 5.5.3", "derive_more 0.99.18", - "indexmap 2.2.6", + "indexmap 2.7.0", "parking_lot 0.12.3", "pprof", "rand 0.8.5", @@ -8280,7 +8821,7 @@ dependencies = [ name = "reth-net-banlist" version = "1.0.0" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.7.6", ] [[package]] @@ -8300,7 +8841,7 @@ name = "reth-network" version = "1.0.0" dependencies = [ "alloy-node-bindings", - "alloy-provider", + "alloy-provider 0.1.3", "alloy-rlp", "aquamarine", "auto_impl", @@ -8355,7 +8896,7 @@ dependencies = [ name = "reth-network-api" version = "1.0.0" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.7.6", "alloy-rpc-types-admin", "enr", "reth-eth-wire", @@ -8387,7 +8928,7 @@ dependencies = [ name = "reth-network-peers" version = "1.0.0" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.7.6", "alloy-rlp", "enr", "rand 0.8.5", @@ -8502,7 +9043,7 @@ dependencies = [ name = "reth-node-core" version = "1.0.0" dependencies = [ - "alloy-genesis", + "alloy-genesis 0.1.3", "alloy-rpc-types-engine", "clap", "const_format", @@ -8554,7 +9095,7 @@ dependencies = [ "thiserror 1.0.61", "tikv-jemalloc-ctl", "tokio", - "tower", + "tower 0.4.13", "tracing", "vergen", ] @@ -8563,8 +9104,8 @@ dependencies = [ name = "reth-node-ethereum" version = "1.0.0" dependencies = [ - "alloy-genesis", - "alloy-primitives", + "alloy-genesis 0.1.3", + "alloy-primitives 0.7.6", "eyre", "futures", "futures-util", @@ -8617,8 +9158,8 @@ dependencies = [ name = "reth-node-optimism" version = "1.0.0" dependencies = [ - "alloy-genesis", - "alloy-primitives", + "alloy-genesis 0.1.3", + "alloy-primitives 0.7.6", "async-trait", "clap", "eyre", @@ -8754,12 +9295,12 @@ dependencies = [ name = "reth-primitives" version = "1.0.0" dependencies = [ - "alloy-eips", - "alloy-genesis", - "alloy-primitives", + "alloy-eips 0.1.3", + "alloy-genesis 0.1.3", + "alloy-primitives 0.7.6", "alloy-rlp", - "alloy-rpc-types", - "alloy-trie", + "alloy-rpc-types 0.1.3", + "alloy-trie 0.4.1", "arbitrary", "assert_matches", "bytes", @@ -8798,12 +9339,12 @@ dependencies = [ name = "reth-primitives-traits" version = "1.0.0" dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-genesis", - "alloy-primitives", + "alloy-consensus 0.1.3", + "alloy-eips 0.1.3", + "alloy-genesis 0.1.3", + "alloy-primitives 0.7.6", "alloy-rlp", - "alloy-rpc-types-eth", + "alloy-rpc-types-eth 0.1.3", "arbitrary", "byteorder", "bytes", @@ -8830,7 +9371,7 @@ dependencies = [ "alloy-rpc-types-engine", "assert_matches", "auto_impl", - "dashmap", + "dashmap 5.5.3", "itertools 0.13.0", "metrics", "parking_lot 0.12.3", @@ -8868,7 +9409,7 @@ dependencies = [ name = "reth-prune" version = "1.0.0" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.7.6", "assert_matches", "itertools 0.13.0", "metrics", @@ -8896,7 +9437,7 @@ dependencies = [ name = "reth-prune-types" version = "1.0.0" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.7.6", "arbitrary", "assert_matches", "bytes", @@ -8917,7 +9458,7 @@ dependencies = [ name = "reth-revm" version = "1.0.0" dependencies = [ - "alloy-eips", + "alloy-eips 0.1.3", "alloy-rlp", "reth-chainspec", "reth-consensus-common", @@ -8935,9 +9476,9 @@ dependencies = [ name = "reth-rpc" version = "1.0.0" dependencies = [ - "alloy-dyn-abi", - "alloy-genesis", - "alloy-primitives", + "alloy-dyn-abi 0.7.6", + "alloy-genesis 0.1.3", + "alloy-primitives 0.7.6", "alloy-rlp", "assert_matches", "async-trait", @@ -8982,7 +9523,7 @@ dependencies = [ "thiserror 1.0.61", "tokio", "tokio-stream", - "tower", + "tower 0.4.13", "tracing", "tracing-futures", ] @@ -9055,7 +9596,7 @@ dependencies = [ "serde_json", "thiserror 1.0.61", "tokio", - "tower", + "tower 0.4.13", "tower-http", "tracing", ] @@ -9097,10 +9638,11 @@ dependencies = [ name = "reth-rpc-eth-api" version = "1.0.0" dependencies = [ - "alloy-dyn-abi", + "alloy-dyn-abi 0.7.6", "alloy-rlp", "async-trait", "auto_impl", + "did", "dyn-clone", "ethereum-json-rpc-client", "futures", @@ -9130,7 +9672,7 @@ dependencies = [ name = "reth-rpc-eth-types" version = "1.0.0" dependencies = [ - "alloy-sol-types", + "alloy-sol-types 0.7.6", "derive_more 0.99.18", "futures", "jsonrpsee-core", @@ -9176,7 +9718,7 @@ dependencies = [ "reqwest", "tempfile", "tokio", - "tower", + "tower 0.4.13", "tracing", ] @@ -9184,7 +9726,7 @@ dependencies = [ name = "reth-rpc-server-types" version = "1.0.0" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.7.6", "jsonrpsee-core", "jsonrpsee-types", "reth-errors", @@ -9199,15 +9741,15 @@ dependencies = [ name = "reth-rpc-types" version = "1.0.0" dependencies = [ - "alloy-primitives", - "alloy-rpc-types", + "alloy-primitives 0.7.6", + "alloy-rpc-types 0.1.3", "alloy-rpc-types-admin", "alloy-rpc-types-anvil", "alloy-rpc-types-beacon", "alloy-rpc-types-engine", "alloy-rpc-types-trace", "alloy-rpc-types-txpool", - "alloy-serde", + "alloy-serde 0.1.3", "arbitrary", "bytes", "jsonrpsee-types", @@ -9224,7 +9766,7 @@ name = "reth-rpc-types-compat" version = "1.0.0" dependencies = [ "alloy-rlp", - "alloy-rpc-types", + "alloy-rpc-types 0.1.3", "reth-primitives", "reth-rpc-types", "reth-trie-common", @@ -9280,7 +9822,7 @@ dependencies = [ name = "reth-stages-api" version = "1.0.0" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.7.6", "aquamarine", "assert_matches", "auto_impl", @@ -9309,7 +9851,7 @@ dependencies = [ name = "reth-stages-types" version = "1.0.0" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.7.6", "arbitrary", "bytes", "modular-bitfield", @@ -9327,7 +9869,7 @@ dependencies = [ name = "reth-static-file" version = "1.0.0" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.7.6", "assert_matches", "parking_lot 0.12.3", "rayon", @@ -9350,7 +9892,7 @@ dependencies = [ name = "reth-static-file-types" version = "1.0.0" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.7.6", "clap", "derive_more 0.99.18", "serde", @@ -9403,7 +9945,7 @@ dependencies = [ name = "reth-testing-utils" version = "1.0.0" dependencies = [ - "alloy-genesis", + "alloy-genesis 0.1.3", "rand 0.8.5", "reth-primitives", "secp256k1", @@ -9509,11 +10051,11 @@ dependencies = [ name = "reth-trie-common" version = "1.0.0" dependencies = [ - "alloy-consensus", - "alloy-genesis", - "alloy-primitives", + "alloy-consensus 0.1.3", + "alloy-genesis 0.1.3", + "alloy-primitives 0.7.6", "alloy-rlp", - "alloy-trie", + "alloy-trie 0.4.1", "arbitrary", "assert_matches", "bytes", @@ -9581,9 +10123,9 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b0971cad2f8f1ecb10e270d80646e63bf19daef0dc0a17a45680d24bb346b7c" dependencies = [ - "alloy-primitives", - "alloy-rpc-types", - "alloy-sol-types", + "alloy-primitives 0.7.6", + "alloy-rpc-types 0.1.3", + "alloy-sol-types 0.7.6", "anstyle", "boa_engine", "boa_gc", @@ -9628,7 +10170,7 @@ version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "902184a7a781550858d4b96707098da357429f1e4545806fd5b589f455555cf2" dependencies = [ - "alloy-primitives", + "alloy-primitives 0.7.6", "auto_impl", "bitflags 2.6.0", "bitvec", @@ -9708,21 +10250,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" dependencies = [ "bytes", - "rlp-derive", "rustc-hex", ] -[[package]] -name = "rlp-derive" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "roaring" version = "0.10.5" @@ -9980,30 +10510,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "scale-info" -version = "2.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" -dependencies = [ - "cfg-if", - "derive_more 0.99.18", - "parity-scale-codec", - "scale-info-derive", -] - -[[package]] -name = "scale-info-derive" -version = "2.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "scc" version = "2.1.1" @@ -10187,7 +10693,7 @@ version = "1.0.120" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.7.0", "itoa", "ryu", "serde", @@ -10258,7 +10764,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.2.6", + "indexmap 2.7.0", "serde", "serde_derive", "serde_json", @@ -10725,6 +11231,24 @@ dependencies = [ "syn 2.0.90", ] +[[package]] +name = "syn-solidity" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "219389c1ebe89f8333df8bdfb871f6631c552ff399c23cac02480b6088aad8f0" +dependencies = [ + "paste", + "proc-macro2", + "quote", + "syn 2.0.90", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "sync_wrapper" version = "1.0.1" @@ -11064,6 +11588,16 @@ dependencies = [ "syn 2.0.90", ] +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.26.0" @@ -11145,7 +11679,7 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.7.0", "toml_datetime", "winnow 0.5.40", ] @@ -11156,7 +11690,7 @@ version = "0.22.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.7.0", "serde", "serde_spanned", "toml_datetime", @@ -11184,6 +11718,20 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36b837f86b25d7c0d7988f00a54e74739be6477f2aac6201b8f429a7569991b7" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper 0.1.2", + "tower-layer", + "tower-service", +] + [[package]] name = "tower-http" version = "0.5.2" @@ -11208,7 +11756,7 @@ dependencies = [ "pin-project-lite", "tokio", "tokio-util", - "tower", + "tower 0.4.13", "tower-layer", "tower-service", "tracing", @@ -11774,6 +12322,20 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wasmtimer" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0048ad49a55b9deb3953841fa1fc5858f0efbcb7a18868c899a360269fac1b23" +dependencies = [ + "futures", + "js-sys", + "parking_lot 0.12.3", + "pin-utils", + "slab", + "wasm-bindgen", +] + [[package]] name = "web-sys" version = "0.3.69" diff --git a/Cargo.toml b/Cargo.toml index 16a44221596..c0f3d5bcf5d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -530,14 +530,14 @@ iai-callgrind = "0.11" # Bitfinity Deps async-channel = "2" candid = "0.10" -did = { git = "https://github.com/bitfinity-network/bitfinity-evm-sdk", package = "did", features = ["alloy-primitives-07"], tag = "v0.36.x" } +did = { git = "https://github.com/bitfinity-network/bitfinity-evm-sdk", package = "did", tag = "v0.38.x" } dirs = "5.0.1" -ethereum-json-rpc-client = { git = "https://github.com/bitfinity-network/bitfinity-evm-sdk", package = "ethereum-json-rpc-client", tag = "v0.36.x", features = [ +ethereum-json-rpc-client = { git = "https://github.com/bitfinity-network/bitfinity-evm-sdk", package = "ethereum-json-rpc-client", tag = "v0.38.x", features = [ "reqwest", ] } evm-canister-client = { git = "https://github.com/bitfinity-network/bitfinity-evm-sdk", package = "evm-canister-client", features = [ "ic-agent-client", -], tag = "v0.36.x" } +], tag = "v0.38.x" } ic-cbor = "2.3" ic-certificate-verification = "2.3" ic-certification = "2.3" diff --git a/crates/net/downloaders/src/bitfinity_evm_client.rs b/crates/net/downloaders/src/bitfinity_evm_client.rs index d95b593e623..c96cf71d641 100644 --- a/crates/net/downloaders/src/bitfinity_evm_client.rs +++ b/crates/net/downloaders/src/bitfinity_evm_client.rs @@ -24,7 +24,6 @@ use reth_primitives::{ ruint::Uint, BlockBody, BlockHash, BlockHashOrNumber, BlockNumber, ChainConfig, ForkCondition, Genesis, GenesisAccount, Header, HeadersDirection, B256, U256, }; -use rlp::Encodable; use serde_json::json; use std::time::Duration; @@ -156,7 +155,7 @@ impl BitfinityEvmClient { block_checker.check_block(&block)?; } let header = - reth_primitives::Block::decode(&mut block.rlp_bytes().to_vec().as_slice())?; + reth_primitives::Block::decode(&mut block.header_rlp_encoded().as_slice())?; let block_hash = header.hash_slow(); @@ -266,10 +265,7 @@ impl BitfinityEvmClient { k, v ); - ( - k.0.into(), - GenesisAccount { balance: Uint::from_limbs(v.0), ..Default::default() }, - ) + (k.0 .0 .0.into(), GenesisAccount { balance: v.0, ..Default::default() }) }, ); @@ -294,7 +290,7 @@ impl BitfinityEvmClient { let spec = ChainSpec { chain, - genesis_hash: genesis_block.hash.map(|h| h.0.into()), + genesis_hash: Some(genesis_block.hash.0 .0.into()), genesis, paris_block_and_final_difficulty: Some((0, Uint::ZERO)), hardforks: ChainHardforks::new(vec![ @@ -412,19 +408,11 @@ impl BlockCertificateChecker { .get_last_certified_block() .await .map_err(|e| RemoteClientError::ProviderError(e.to_string()))?; - Ok(Self { - certified_data: CertifiedResult { - data: did::Block::from(certified_data.data), - certificate: certified_data.certificate, - witness: certified_data.witness, - }, - evmc_principal, - ic_root_key, - }) + Ok(Self { certified_data, evmc_principal, ic_root_key }) } fn get_block_number(&self) -> u64 { - self.certified_data.data.number.0.as_u64() + self.certified_data.data.number.as_u64() } fn check_block(&self, block: &did::Block) -> Result<(), RemoteClientError> { diff --git a/crates/rpc/rpc-eth-api/Cargo.toml b/crates/rpc/rpc-eth-api/Cargo.toml index 825c52f0571..e22d3dd920e 100644 --- a/crates/rpc/rpc-eth-api/Cargo.toml +++ b/crates/rpc/rpc-eth-api/Cargo.toml @@ -49,6 +49,7 @@ tracing.workspace = true # Bitfinity dependencies alloy-rlp.workspace = true +did.workspace = true ethereum-json-rpc-client.workspace = true [features] diff --git a/crates/rpc/rpc-eth-api/src/core.rs b/crates/rpc/rpc-eth-api/src/core.rs index 55f90dbfd12..a0fde3421a2 100644 --- a/crates/rpc/rpc-eth-api/src/core.rs +++ b/crates/rpc/rpc-eth-api/src/core.rs @@ -330,9 +330,7 @@ pub trait EthApi { /// Aliases don't use the namespace. /// Thus, this will generate `eth_getLastCertifiedBlock` and `ic_getLastCertifiedBlock`. #[method(name = "getLastCertifiedBlock", aliases = ["ic_getLastCertifiedBlock"])] - async fn get_last_certified_block( - &self, - ) -> RpcResult>>; + async fn get_last_certified_block(&self) -> RpcResult>>; } #[async_trait::async_trait] @@ -756,10 +754,7 @@ where BitfinityEvmRpc::get_genesis_balances(self).await } - async fn get_last_certified_block( - &self, - ) -> RpcResult>> - { + async fn get_last_certified_block(&self) -> RpcResult>> { trace!(target: "rpc::eth", "Serving get_last_certified_block"); BitfinityEvmRpc::get_last_certified_block(self).await } diff --git a/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs b/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs index 39c9f616451..dfcd95b4368 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs @@ -3,8 +3,8 @@ use std::sync::Arc; use alloy_rlp::Decodable; +use ethereum_json_rpc_client::CertifiedResult; use ethereum_json_rpc_client::{reqwest::ReqwestClient, EthJsonRpcClient}; -use ethereum_json_rpc_client::{Block, CertifiedResult, H256}; use futures::Future; use jsonrpsee::core::RpcResult; use reth_chainspec::ChainSpec; @@ -38,7 +38,7 @@ pub trait BitfinityEvmRpc { )) })?; - Ok(U256::from(gas_price.as_u128())) + Ok(gas_price.0) } } @@ -77,7 +77,7 @@ pub trait BitfinityEvmRpc { )) })?; - Ok(U256::from(priority_fee.as_u128())) + Ok(priority_fee.0) } } @@ -109,7 +109,7 @@ pub trait BitfinityEvmRpc { )) })?; - Ok(tx_hash.0.into()) + Ok(tx_hash.0 .0.into()) } } @@ -128,7 +128,7 @@ pub trait BitfinityEvmRpc { Ok(balances .into_iter() - .map(|(address, balance)| (address.0.into(), U256::from(balance.as_u128()))) + .map(|(address, balance)| (address.0 .0 .0.into(), balance.0)) .collect()) } } From 79dd6b886cc425922689935586aea9d558858246 Mon Sep 17 00:00:00 2001 From: f3kilo Date: Mon, 13 Jan 2025 10:08:04 +0300 Subject: [PATCH 25/31] conflicts solved + generic tx in BitfinityEvmRpc --- bin/reth/src/commands/mod.rs | 6 -- .../tests/commands/bitfinity_import_it.rs | 6 -- bin/reth/tests/commands/bitfinity_node_it.rs | 69 ++----------------- .../commands/bitfinity_reset_evm_state_it.rs | 6 -- bin/reth/tests/commands/utils.rs | 25 ------- bitfinity.md | 6 -- crates/rpc/rpc-eth-api/src/core.rs | 5 +- .../src/helpers/bitfinity_evm_rpc.rs | 48 +++++++++++-- .../rpc-eth-api/src/helpers/transaction.rs | 15 ++-- crates/rpc/rpc-eth-api/src/types.rs | 9 ++- .../rpc/src/eth/helpers/bitfinity_evm_rpc.rs | 24 +------ 11 files changed, 66 insertions(+), 153 deletions(-) diff --git a/bin/reth/src/commands/mod.rs b/bin/reth/src/commands/mod.rs index da64a11af28..9380056c8b1 100644 --- a/bin/reth/src/commands/mod.rs +++ b/bin/reth/src/commands/mod.rs @@ -1,11 +1,5 @@ //! This contains all of the `reth` commands pub mod bitfinity_import; -<<<<<<< HEAD pub mod bitfinity_reset_evm_state; -pub mod config_cmd; -||||||| 0e2237228 -pub mod config_cmd; -======= ->>>>>>> bitfinity-archive-node pub mod debug_cmd; diff --git a/bin/reth/tests/commands/bitfinity_import_it.rs b/bin/reth/tests/commands/bitfinity_import_it.rs index 6034fdb7969..9a173787a3e 100644 --- a/bin/reth/tests/commands/bitfinity_import_it.rs +++ b/bin/reth/tests/commands/bitfinity_import_it.rs @@ -117,13 +117,7 @@ async fn bitfinity_test_should_import_data_from_evm_with_backup_rpc_url() { import_data.bitfinity_args.batch_size = (end_block as usize) * 10; // Act -<<<<<<< HEAD - import_blocks(import_data.clone(), Duration::from_secs(120), false).await; -||||||| 0e2237228 - import_blocks(import_data.clone(), Duration::from_secs(20), false).await; -======= import_blocks(import_data.clone(), Duration::from_secs(200), false).await; ->>>>>>> bitfinity-archive-node // Assert { diff --git a/bin/reth/tests/commands/bitfinity_node_it.rs b/bin/reth/tests/commands/bitfinity_node_it.rs index 9c643c7f703..8934a7da002 100644 --- a/bin/reth/tests/commands/bitfinity_node_it.rs +++ b/bin/reth/tests/commands/bitfinity_node_it.rs @@ -23,14 +23,6 @@ use reth::{ use reth_consensus::FullConsensus; use reth_db::DatabaseEnv; use reth_db::{init_db, test_utils::tempdir_path}; -<<<<<<< HEAD -use reth_node_builder::{NodeBuilder, NodeConfig, NodeHandle}; -use reth_node_ethereum::EthereumNode; -use reth_primitives::{sign_message, Transaction, TransactionSigned}; -||||||| 0e2237228 -use reth_node_builder::{NodeBuilder, NodeConfig, NodeHandle}; -use reth_node_ethereum::EthereumNode; -======= use reth_network::NetworkHandle; use reth_node_api::{FullNodeTypesAdapter, NodeTypesWithDBAdapter}; use reth_node_builder::components::Components; @@ -42,22 +34,13 @@ use reth_node_ethereum::{ }; use reth_provider::providers::BlockchainProvider; use reth_rpc::EthApi; ->>>>>>> bitfinity-archive-node use reth_tasks::TaskManager; -<<<<<<< HEAD -use reth_transaction_pool::test_utils::MockTransaction; -use revm_primitives::{Address, B256, U256}; -use std::time::Duration; -||||||| 0e2237228 -use revm_primitives::{Address, U256}; -======= use reth_transaction_pool::blobstore::DiskFileBlobStore; use reth_transaction_pool::{ CoinbaseTipOrdering, EthPooledTransaction, EthTransactionValidator, Pool, TransactionValidationTaskExecutor, }; use revm_primitives::{hex, Address, U256}; ->>>>>>> bitfinity-archive-node use std::{net::SocketAddr, str::FromStr, sync::Arc}; use tokio::sync::mpsc::Receiver; use tokio::sync::Mutex; @@ -230,26 +213,14 @@ async fn bitfinity_test_node_forward_send_raw_transaction_requests() { .await; // Create a random transaction -<<<<<<< HEAD - let tx = transaction_with_gas_price(100); - let encoded = alloy_rlp::encode(&tx); - let expected_tx_hash = keccak::keccak_hash(&encoded); -||||||| 0e2237228 - let mut tx = [0u8; 256]; - rand::thread_rng().fill_bytes(&mut tx); - let expected_tx_hash = - keccak::keccak_hash(format!("0x{}", reth_primitives::hex::encode(tx)).as_bytes()); -======= let mut tx = [0u8; 256]; rand::thread_rng().fill_bytes(&mut tx); let expected_tx_hash = keccak::keccak_hash(format!("0x{}", hex::encode(tx)).as_bytes()); ->>>>>>> bitfinity-archive-node // Act let result = reth_client.send_raw_transaction_bytes(&encoded).await.unwrap(); // Assert -<<<<<<< HEAD assert_eq!(result.to_fixed_bytes(), expected_tx_hash.0.to_fixed_bytes()); let transaction_sending = BitfinityTransactionSender::new( @@ -404,12 +375,8 @@ fn sign_tx_with_random_key_pair(tx: Transaction) -> TransactionSigned { fn sign_tx_with_key_pair(key_pair: Keypair, tx: Transaction) -> TransactionSigned { let signature = sign_message(B256::from_slice(&key_pair.secret_bytes()[..]), tx.signature_hash()).unwrap(); - TransactionSigned::from_transaction_and_signature(tx, signature) -||||||| 0e2237228 - assert_eq!(result.unwrap(), expected_tx_hash.0); -======= + TransactionSigned::from_transaction_and_signature(tx, signature); assert_eq!(result.unwrap(), expected_tx_hash); ->>>>>>> bitfinity-archive-node } /// Start a local reth node @@ -567,21 +534,10 @@ async fn mock_eth_server_start(methods: impl Into) -> (ServerHandle, So /// Eth server mock utils. pub mod eth_server { -<<<<<<< HEAD - use alloy_rlp::{Bytes, Decodable}; - use discv5::enr::secp256k1::{Keypair, Secp256k1}; - use ethereum_json_rpc_client::{Block, CertifiedResult, H256}; -||||||| 0e2237228 - - use alloy_rlp::Bytes; - use did::keccak; - use ethereum_json_rpc_client::{Block, CertifiedResult, H256}; -======= use alloy_rlp::Bytes; use did::keccak; use ethereum_json_rpc_client::CertifiedResult; ->>>>>>> bitfinity-archive-node use jsonrpsee::{core::RpcResult, proc_macros::rpc}; use reth_primitives::{sign_message, TransactionSigned}; use reth_rpc_types::{Signature, Transaction}; @@ -612,16 +568,9 @@ pub mod eth_server { /// Returns getLastCertifiedBlock #[method(name = "getLastCertifiedBlock", aliases = ["ic_getLastCertifiedBlock"])] -<<<<<<< HEAD - async fn get_last_certified_block(&self) -> RpcResult>>; -||||||| 0e2237228 - async fn get_last_certified_block(&self) -> RpcResult>>; - -======= async fn get_last_certified_block( &self, ) -> RpcResult>>; ->>>>>>> bitfinity-archive-node } /// Eth server mock. @@ -711,9 +660,9 @@ pub mod eth_server { let signature = sign_message(B256::from_slice(&key_pair.secret_bytes()[..]), tx.hash).unwrap(); tx.signature = Some(Signature { - r: signature.r, - s: signature.s, - v: U256::from(signature.v(None)), + r: signature.r(), + s: signature.s(), + v: U256::from(signature.v()), y_parity: None, }); @@ -728,19 +677,9 @@ pub mod eth_server { ]) } -<<<<<<< HEAD - async fn get_last_certified_block(&self) -> RpcResult>> { -||||||| 0e2237228 - async fn get_last_certified_block(&self) -> RpcResult>> { - Ok(CertifiedResult { - data: Default::default(), - witness: vec![], - certificate: vec![1u8, 3, 11] -======= async fn get_last_certified_block( &self, ) -> RpcResult>> { ->>>>>>> bitfinity-archive-node Ok(CertifiedResult { data: Default::default(), witness: vec![], diff --git a/bin/reth/tests/commands/bitfinity_reset_evm_state_it.rs b/bin/reth/tests/commands/bitfinity_reset_evm_state_it.rs index 727313806af..aa31fe309d4 100644 --- a/bin/reth/tests/commands/bitfinity_reset_evm_state_it.rs +++ b/bin/reth/tests/commands/bitfinity_reset_evm_state_it.rs @@ -100,13 +100,7 @@ async fn bitfinity_test_reset_should_extract_all_accounts_data() { let (_temp_dir, mut import_data) = bitfinity_import_config_data(evm_datasource_url, None, data_dir).await.unwrap(); -<<<<<<< HEAD - let fetch_block_timeout_secs = std::cmp::max(3000, end_block / 100); -||||||| 0e2237228 - let fetch_block_timeout_secs = std::cmp::max(20, end_block / 100); -======= let fetch_block_timeout_secs = std::cmp::max(20, end_block / 10); ->>>>>>> bitfinity-archive-node // Import block from block explorer import_data.bitfinity_args.end_block = Some(end_block); diff --git a/bin/reth/tests/commands/utils.rs b/bin/reth/tests/commands/utils.rs index 93547ab752f..96fabd283da 100644 --- a/bin/reth/tests/commands/utils.rs +++ b/bin/reth/tests/commands/utils.rs @@ -41,15 +41,9 @@ use tracing::{debug, info}; /// Local evm canister for tests. pub const LOCAL_EVM_CANISTER_ID: &str = "bkyz2-fmaaa-aaaaa-qaaaq-cai"; -<<<<<<< HEAD -||||||| 0e2237228 -/// EVM block extractor for devnet running on Digital Ocean. -pub const DEFAULT_EVM_DATASOURCE_URL: &str = "https://orca-app-5yyst.ondigitalocean.app"; -======= /// EVM block extractor for devnet running on Digital Ocean. pub const DEFAULT_EVM_DATASOURCE_URL: &str = "https://block-extractor-testnet-1052151659755.europe-west9.run.app"; ->>>>>>> bitfinity-archive-node /// EVM block extractor for devnet running on Digital Ocean. pub const DEFAULT_EVM_DATASOURCE_URL: &str = @@ -70,13 +64,8 @@ pub fn init_logs() -> eyre::Result> { Ok(guard) } -<<<<<<< HEAD -/// Bitfinity config for reth node. -||||||| 0e2237228 -======= pub type NodeTypes = NodeTypesWithDBAdapter>; ->>>>>>> bitfinity-archive-node #[derive(Clone)] pub struct ImportData { /// Chain config. @@ -87,22 +76,8 @@ pub struct ImportData { /// Database config. pub database: Arc, -<<<<<<< HEAD - - /// Database provider. - pub provider_factory: ProviderFactory>, - - /// Blockchain provider. - pub blockchain_db: BlockchainProvider>, - - /// Bitfinity import config. -||||||| 0e2237228 - pub provider_factory: ProviderFactory>, - pub blockchain_db: BlockchainProvider>, -======= pub provider_factory: ProviderFactory, pub blockchain_db: BlockchainProvider, ->>>>>>> bitfinity-archive-node pub bitfinity_args: BitfinityImportArgs, } diff --git a/bitfinity.md b/bitfinity.md index ab075dd4f84..9fa7a6f06fa 100644 --- a/bitfinity.md +++ b/bitfinity.md @@ -83,13 +83,7 @@ dfx canister --network=ic call EVM_CANISTER_ID admin_disable_evm '(true)' 3. Run the EVM reset command. For example: ```sh -<<<<<<< HEAD -cargo run -p reth -- bitfinity-reset-evm-state -vvv --datadir ./target/reth --ic-identity-file-path PATH_TO_IDENTITY/identity.pem --evm-network https://ic0.app --evmc-principal EVM_CANISTER_ID --evm-datasource-url https://block-extractor-testnet-1052151659755.europe-west9.run.app -||||||| 0e2237228 -cargo run -p reth -- bitfinity-reset-evm-state -vvv --datadir ./target/reth --ic-identity-file-path PATH_TO_IDENTITY/identity.pem --evm-network https://ic0.app --evmc-principal EVM_CANISTER_ID --evm-datasource-url https://orca-app-5yyst.ondigitalocean.app -======= cargo run -p reth -- bitfinity-reset-evm-state -vvv --datadir ./target/reth --ic-identity-file-path PATH_TO_IDENTITY/identity.pem --evm-network https://ic0.app --evmc-principal EVM_CANISTER_ID --evm-datasource-url https://evm-testnet-block-extractor-app-hvnsf.ondigitalocean.app/ ->>>>>>> bitfinity-archive-node ``` 4. Enable the EVM canister: diff --git a/crates/rpc/rpc-eth-api/src/core.rs b/crates/rpc/rpc-eth-api/src/core.rs index bc702a9075d..7d423c9e243 100644 --- a/crates/rpc/rpc-eth-api/src/core.rs +++ b/crates/rpc/rpc-eth-api/src/core.rs @@ -521,7 +521,10 @@ where .map(|tx| tx.into_transaction(self.tx_resp_builder())) .transpose()?; if tx_opt.is_none() { - tx_opt = BitfinityEvmRpc::transaction_by_hash(self, hash).await?.map(|tx| tx.into()); + tx_opt = BitfinityEvmRpc::transaction_by_hash(self, hash) + .await? + .map(|tx| tx.into_transaction(self.tx_resp_builder())) + .transpose()?; } Ok(tx_opt) diff --git a/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs b/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs index 905fc5ba7f8..cb520131cd3 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs @@ -2,18 +2,23 @@ use std::sync::Arc; -use alloy_rpc_types_eth::Transaction; +use alloy_network::TransactionResponse; use did::{Block, H256}; use ethereum_json_rpc_client::CertifiedResult; use ethereum_json_rpc_client::{reqwest::ReqwestClient, EthJsonRpcClient}; use futures::Future; use jsonrpsee::core::RpcResult; use reth_chainspec::ChainSpec; +use reth_primitives::RecoveredTx; +use reth_primitives_traits::SignedTransaction; +use reth_rpc_eth_types::TransactionSource; use reth_rpc_server_types::result::internal_rpc_err; use revm_primitives::{Address, Bytes, B256, U256}; /// Proxy to the Bitfinity EVM RPC. pub trait BitfinityEvmRpc { + type Transaction: SignedTransaction; + /// Returns the `ChainSpec`. fn chain_spec(&self) -> Arc; @@ -38,7 +43,7 @@ pub trait BitfinityEvmRpc { fn transaction_by_hash( &self, hash: B256, - ) -> impl Future>> + Send { + ) -> impl Future>>> + Send { let chain_spec = self.chain_spec(); // let forwarder = self.raw_tx_forwarder(); @@ -52,18 +57,49 @@ pub trait BitfinityEvmRpc { // If transaction is not found in forwarder, query it from EVM rpc. let (rpc_url, client) = get_client(&chain_spec)?; - let tx = client.get_transaction_by_hash(hash.into()).await.map_err(|e| { + let Some(tx) = client.get_transaction_by_hash(hash.into()).await.map_err(|e| { internal_rpc_err(format!( "failed to forward eth_transactionByHash request to {}: {}", rpc_url, e )) + })? + else { + return Ok(None); + }; + + let alloy_tx: alloy_rpc_types_eth::Transaction = tx.into(); + let encoded = alloy_rlp::encode(&alloy_tx.inner); + let self_tx = + ::decode(&mut encoded.as_ref()) + .map_err(|e| internal_rpc_err(format!("failed to decode BitfinityEvmRpc::Transaction from received did::Transaction: {e}")))?; + + let signer = self_tx.recover_signer().ok_or_else(|| { + internal_rpc_err( + "failed to recover signer from decoded BitfinityEvmRpc::Transaction", + ) })?; - - Ok(tx.map(Into::into)) + let recovered_tx = RecoveredTx::from_signed_transaction(self_tx, signer); + + let block_params = alloy_tx + .block_number() + .zip(alloy_tx.transaction_index()) + .zip(alloy_tx.block_hash()); + let tx_source = match block_params { + Some(((block_number, index), block_hash)) => TransactionSource::Block { + transaction: recovered_tx, + index, + block_hash, + block_number, + base_fee: None, + }, + None => TransactionSource::Pool(recovered_tx), + }; + + Ok(Some(tx_source)) } } - /// Forwards `eth_maxPriorityFeePerGas` calls to the Bitfinity EVM + /// Forwards `eth_maxPriorityFeePerGas` calls to the Bitfinity EVM fn max_priority_fee_per_gas(&self) -> impl Future> + Send { let chain_spec = self.chain_spec(); async move { diff --git a/crates/rpc/rpc-eth-api/src/helpers/transaction.rs b/crates/rpc/rpc-eth-api/src/helpers/transaction.rs index d0223cb9d45..ff05e1d2865 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/transaction.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/transaction.rs @@ -555,12 +555,15 @@ pub trait LoadTransaction: SpawnBlocking + FullEthApiTypes + RpcNodeCoreExt { >, > + Send { async move { - Ok(self.transaction_by_hash(transaction_hash).await?.map(|tx| match tx { - tx @ TransactionSource::Pool(_) => (tx, BlockId::pending()), - tx @ TransactionSource::Block { block_hash, .. } => { - (tx, BlockId::Hash(block_hash.into())) - } - })) + // Ok(self.transaction_by_hash(transaction_hash).await?.map(|tx| match tx { + Ok(::transaction_by_hash(self, transaction_hash).await?.map( + |tx| match tx { + tx @ TransactionSource::Pool(_) => (tx, BlockId::pending()), + tx @ TransactionSource::Block { block_hash, .. } => { + (tx, BlockId::Hash(block_hash.into())) + } + }, + )) } } diff --git a/crates/rpc/rpc-eth-api/src/types.rs b/crates/rpc/rpc-eth-api/src/types.rs index 2da1bdac281..6f570350019 100644 --- a/crates/rpc/rpc-eth-api/src/types.rs +++ b/crates/rpc/rpc-eth-api/src/types.rs @@ -11,7 +11,10 @@ use reth_provider::{ProviderTx, ReceiptProvider, TransactionsProvider}; use reth_rpc_types_compat::TransactionCompat; use reth_transaction_pool::{PoolTransaction, TransactionPool}; -use crate::{AsEthApiError, FromEthApiError, FromEvmError, RpcNodeCore}; +use crate::{ + helpers::bitfinity_evm_rpc::BitfinityEvmRpc, AsEthApiError, FromEthApiError, FromEvmError, + RpcNodeCore, +}; /// Network specific `eth` API types. pub trait EthApiTypes: Send + Sync + Clone { @@ -61,7 +64,7 @@ where Transaction = RpcTransaction, Error = RpcError, >, - >, + > + BitfinityEvmRpc::Transaction>, { } @@ -77,6 +80,6 @@ impl FullEthApiTypes for T where Transaction = RpcTransaction, Error = RpcError, >, - > + > + BitfinityEvmRpc::Transaction> { } diff --git a/crates/rpc/rpc/src/eth/helpers/bitfinity_evm_rpc.rs b/crates/rpc/rpc/src/eth/helpers/bitfinity_evm_rpc.rs index 85896410855..e3ee692389c 100644 --- a/crates/rpc/rpc/src/eth/helpers/bitfinity_evm_rpc.rs +++ b/crates/rpc/rpc/src/eth/helpers/bitfinity_evm_rpc.rs @@ -2,38 +2,16 @@ //! use std::sync::Arc; -<<<<<<< HEAD -use reth_provider::ChainSpecProvider; -use reth_rpc_eth_api::{helpers::bitfinity_evm_rpc::BitfinityEvmRpc, RawTransactionForwarder}; -||||||| 0e2237228 -use reth_provider::ChainSpecProvider; -use reth_rpc_eth_api::helpers::bitfinity_evm_rpc::BitfinityEvmRpc; -======= use reth_provider::{BlockReader, ChainSpecProvider}; use reth_rpc_eth_api::helpers::bitfinity_evm_rpc::BitfinityEvmRpc; ->>>>>>> bitfinity-archive-node use crate::EthApi; -impl BitfinityEvmRpc +impl BitfinityEvmRpc for EthApi where -<<<<<<< HEAD - Provider: ChainSpecProvider, -{ - fn raw_tx_forwarder(&self) -> Option> { - self.inner.raw_tx_forwarder() - } - -||||||| 0e2237228 - -impl BitfinityEvmRpc for EthApi -where Provider: ChainSpecProvider { - -======= Provider: BlockReader + ChainSpecProvider, { ->>>>>>> bitfinity-archive-node fn chain_spec(&self) -> Arc { self.inner.provider().chain_spec() } From ae0eb85af2238bda7f57e5719d97e4352b3e901a Mon Sep 17 00:00:00 2001 From: f3kilo Date: Tue, 14 Jan 2025 11:45:04 +0300 Subject: [PATCH 26/31] tx forwarder as EthApi module --- bin/reth/src/bitfinity_tasks/send_txs.rs | 225 +----------------- bin/reth/tests/commands/bitfinity_node_it.rs | 5 +- crates/rpc/rpc/src/eth/core.rs | 3 + .../src/eth/core/bitfinity_tx_forwarder.rs | 223 +++++++++++++++++ 4 files changed, 231 insertions(+), 225 deletions(-) create mode 100644 crates/rpc/rpc/src/eth/core/bitfinity_tx_forwarder.rs diff --git a/bin/reth/src/bitfinity_tasks/send_txs.rs b/bin/reth/src/bitfinity_tasks/send_txs.rs index d7a22874c07..4ddbde95595 100644 --- a/bin/reth/src/bitfinity_tasks/send_txs.rs +++ b/bin/reth/src/bitfinity_tasks/send_txs.rs @@ -1,7 +1,5 @@ //! Utils for raw transaction batching. -use std::collections::{BTreeSet, HashMap}; -use std::sync::Arc; use std::time::Duration; use did::H256; @@ -13,13 +11,9 @@ use lightspeed_scheduler::job::Job; use lightspeed_scheduler::scheduler::Scheduler; use lightspeed_scheduler::JobExecutor; use reth_node_core::version::SHORT_VERSION; -use reth_rpc_eth_types::{EthApiError, EthResult}; -use revm_primitives::{hex, B256, U256}; -use tokio::sync::Mutex; -use tracing::{debug, info, trace, warn}; - -/// Alias for multithread transactions priority queue. -pub type SharedQueue = Arc>; +use reth_rpc::eth::core::bitfinity_tx_forwarder::SharedQueue; +use revm_primitives::{hex, U256}; +use tracing::{info, trace, warn}; /// Periodically sends transactions from priority queue. #[derive(Debug, Clone)] @@ -157,216 +151,3 @@ impl BitfinityTransactionSender { Ok(client) } } - -/// Forwarder to push transactions to the priority queue. -#[derive(Debug)] -pub struct BitfinityTransactionsForwarder { - queue: SharedQueue, -} - -impl BitfinityTransactionsForwarder { - /// Creates new forwarder with the given parameters. - pub const fn new(queue: SharedQueue) -> Self { - Self { queue } - } -} - -// #[async_trait::async_trait] -// impl RawTransactionForwarder for BitfinityTransactionsForwarder { -// async fn forward_raw_transaction(&self, raw: &[u8]) -> EthResult<()> { -// let typed_tx = TransactionSigned::decode(&mut (&raw[..])).map_err(|e| { -// warn!("Failed to decode signed transaction in the BitfinityTransactionsForwarder: {e}"); -// EthApiError::FailedToDecodeSignedTransaction -// })?; - -// debug!("Pushing tx with hash {} to priority queue", typed_tx.hash); -// let gas_price = typed_tx.effective_gas_price(None); - -// self.queue.lock().await.push(typed_tx.hash(), Uint::from(gas_price), raw.to_vec()); - -// Ok(()) -// } - -// async fn get_transaction_by_hash(&self, hash: B256) -> Option> { -// self.queue.lock().await.get(&hash) -// } -// } - -/// Priority queue to get transactions sorted by gas price. -#[derive(Debug)] -pub struct TransactionsPriorityQueue { - priority: BTreeSet, - transactions: HashMap>, - size_limit: usize, -} - -impl TransactionsPriorityQueue { - /// Creates new instance of the queue with the given limil. - pub fn new(size_limit: usize) -> Self { - Self { priority: BTreeSet::default(), transactions: HashMap::default(), size_limit } - } - - /// Adds the tx with the given gas price. - pub fn push(&mut self, hash: B256, gas_price: U256, tx: Vec) { - let key = TxKey { gas_price, hash }; - self.priority.insert(key); - self.transactions.insert(hash, tx); - - if self.len() > self.size_limit { - self.pop_tx_with_lowest_price(); - } - } - - /// Returns raw transaction if it is present in the queue. - pub fn get(&self, hash: &B256) -> Option> { - self.transactions.get(hash).cloned() - } - - /// Returns tx with highest gas price, if present. - pub fn pop_tx_with_highest_price(&mut self) -> Option<(U256, Vec)> { - let tx_key = self.priority.pop_last()?; - let Some(tx) = self.transactions.remove(&tx_key.hash) else { - warn!("Transaction key present in priority queue, but not found in transactions map."); - return None; - }; - - Some((tx_key.gas_price, tx)) - } - - /// Returns tx with lowest gas price, if present. - pub fn pop_tx_with_lowest_price(&mut self) -> Option<(U256, Vec)> { - let tx_key = self.priority.pop_first()?; - let Some(tx) = self.transactions.remove(&tx_key.hash) else { - warn!("Transaction key present in priority queue, but not found in transactions map."); - return None; - }; - - Some((tx_key.gas_price, tx)) - } - - /// Number of transactions in the queue. - pub fn len(&self) -> usize { - self.transactions.len() - } - - /// Change size limit of the queue. - pub fn set_size_limit(&mut self, new_limit: usize) { - self.size_limit = new_limit; - - while self.len() > self.size_limit { - self.pop_tx_with_lowest_price(); - } - } - - /// Returns true if length == 0. - pub fn is_empty(&self) -> bool { - self.transactions.is_empty() - } -} - -/// This struct will sort transactions by gas price, -/// but if it is equal, the key will still be different due to hash difference. -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] -struct TxKey { - gas_price: U256, - hash: B256, -} - -#[cfg(test)] -mod tests { - use std::sync::OnceLock; - - use super::TransactionsPriorityQueue; - use alloy_consensus::Transaction; - use reth_primitives::TransactionSigned; - use reth_transaction_pool::test_utils::MockTransaction; - use reth_transaction_pool::PoolTransaction; - use revm_primitives::{PrimitiveSignature, U256}; - - #[test] - fn test_pop_order() { - let mut queue = TransactionsPriorityQueue::new(10); - let tx1 = transaction_with_gas_price(100); - let tx2 = transaction_with_gas_price(300); - let tx3 = transaction_with_gas_price(200); - - let tx1_bytes = alloy_rlp::encode(&tx1); - let tx2_bytes = alloy_rlp::encode(&tx2); - let tx3_bytes = alloy_rlp::encode(&tx3); - - queue.push(tx1.hash(), U256::from(tx1.effective_gas_price(None)), tx1_bytes.clone()); - queue.push(tx2.hash(), U256::from(tx2.effective_gas_price(None)), tx2_bytes.clone()); - queue.push(tx3.hash(), U256::from(tx3.effective_gas_price(None)), tx3_bytes.clone()); - - let expected_order = [tx2_bytes, tx3_bytes, tx1_bytes]; - for expected_tx in expected_order { - let popped_tx = queue.pop_tx_with_highest_price().unwrap().1; - assert_eq!(popped_tx, expected_tx); - } - - assert!(queue.is_empty()) - } - - #[test] - fn test_size_limit_should_shrink_tx_with_lowest_price() { - let mut queue = TransactionsPriorityQueue::new(2); - let tx1 = transaction_with_gas_price(100); - let tx2 = transaction_with_gas_price(300); - let tx3 = transaction_with_gas_price(200); - - let tx1_bytes = alloy_rlp::encode(&tx1); - let tx2_bytes = alloy_rlp::encode(&tx2); - let tx3_bytes = alloy_rlp::encode(&tx3); - - queue.push(tx1.hash(), U256::from(tx1.effective_gas_price(None)), tx1_bytes); - queue.push(tx2.hash(), U256::from(tx2.effective_gas_price(None)), tx2_bytes.clone()); - queue.push(tx3.hash(), U256::from(tx3.effective_gas_price(None)), tx3_bytes.clone()); - - let expected_order = [tx2_bytes, tx3_bytes]; - for expected_tx in expected_order { - let popped_tx = queue.pop_tx_with_highest_price().unwrap().1; - assert_eq!(popped_tx, expected_tx); - } - - assert!(queue.is_empty()) - } - - #[test] - fn test_get_transaction_from_queue() { - let mut queue = TransactionsPriorityQueue::new(100); - let tx1 = transaction_with_gas_price(100); - let tx2 = transaction_with_gas_price(300); - let tx3 = transaction_with_gas_price(200); - - let tx1_bytes = alloy_rlp::encode(&tx1); - let tx2_bytes = alloy_rlp::encode(&tx2); - let tx3_bytes = alloy_rlp::encode(&tx3); - - queue.push(tx1.hash(), U256::from(tx1.effective_gas_price(None)), tx1_bytes); - queue.push(tx2.hash(), U256::from(tx2.effective_gas_price(None)), tx2_bytes); - queue.push(tx3.hash(), U256::from(tx3.effective_gas_price(None)), tx3_bytes); - - let hashes = [tx1.hash(), tx2.hash(), tx3.hash()]; - for hash in hashes { - assert!(queue.get(&hash).is_some()); - } - - assert_eq!(queue.len(), 3); - - let tx4 = transaction_with_gas_price(400); - assert!(queue.get(&tx4.hash()).is_none()); - } - - fn transaction_with_gas_price(gas_price: u128) -> TransactionSigned { - let tx = MockTransaction::legacy().with_gas_price(gas_price).rng_hash(); - - let hash = OnceLock::new(); - hash.get_or_init(|| *tx.hash()); - - TransactionSigned { - hash, - signature: PrimitiveSignature::test_signature(), - transaction: tx.into(), - } - } -} diff --git a/bin/reth/tests/commands/bitfinity_node_it.rs b/bin/reth/tests/commands/bitfinity_node_it.rs index 0bd836643e8..702d21b0d5c 100644 --- a/bin/reth/tests/commands/bitfinity_node_it.rs +++ b/bin/reth/tests/commands/bitfinity_node_it.rs @@ -11,9 +11,7 @@ use jsonrpsee::{ server::{Server, ServerHandle}, Methods, RpcModule, }; -use reth::bitfinity_tasks::send_txs::{ - BitfinityTransactionSender, SharedQueue, TransactionsPriorityQueue, -}; +use reth::bitfinity_tasks::send_txs::BitfinityTransactionSender; use reth::{ args::{DatadirArgs, RpcServerArgs}, dirs::{DataDirPath, MaybePlatformPath}, @@ -33,6 +31,7 @@ use reth_node_ethereum::{ }; use reth_primitives::{Transaction, TransactionSigned}; use reth_provider::providers::BlockchainProvider; +use reth_rpc::eth::core::bitfinity_tx_forwarder::{SharedQueue, TransactionsPriorityQueue}; use reth_rpc::EthApi; use reth_tasks::TaskManager; use reth_transaction_pool::blobstore::DiskFileBlobStore; diff --git a/crates/rpc/rpc/src/eth/core.rs b/crates/rpc/rpc/src/eth/core.rs index cf5753a34c1..532651787cc 100644 --- a/crates/rpc/rpc/src/eth/core.rs +++ b/crates/rpc/rpc/src/eth/core.rs @@ -30,6 +30,8 @@ use tokio::sync::{broadcast, Mutex}; use crate::eth::EthTxBuilder; +pub mod bitfinity_tx_forwarder; + const DEFAULT_BROADCAST_CAPACITY: usize = 2000; /// `Eth` API implementation. @@ -48,6 +50,7 @@ pub struct EthApi { pub(super) inner: Arc>, /// Transaction RPC response builder. pub tx_resp_builder: EthTxBuilder, + // pub bitfinity_tx_forwarder: Option<()>, } impl Clone for EthApi diff --git a/crates/rpc/rpc/src/eth/core/bitfinity_tx_forwarder.rs b/crates/rpc/rpc/src/eth/core/bitfinity_tx_forwarder.rs new file mode 100644 index 00000000000..82da0bc805f --- /dev/null +++ b/crates/rpc/rpc/src/eth/core/bitfinity_tx_forwarder.rs @@ -0,0 +1,223 @@ +use std::{collections::BTreeSet, sync::Arc}; + +use alloy_consensus::Transaction; +use alloy_primitives::Uint; +use alloy_rlp::Decodable; +use reth_primitives::TransactionSigned; +use reth_rpc_eth_types::{EthApiError, EthResult}; +use revm_primitives::{HashMap, B256, U256}; +use tokio::sync::Mutex; +use tracing::{debug, warn}; + +/// Alias for multithread transactions priority queue. +pub type SharedQueue = Arc>; + +/// Forwarder to push transactions to the priority queue. +#[derive(Debug)] +pub struct BitfinityTransactionsForwarder { + queue: SharedQueue, +} + +impl BitfinityTransactionsForwarder { + /// Creates new forwarder with the given parameters. + pub const fn new(queue: SharedQueue) -> Self { + Self { queue } + } + + async fn forward_raw_transaction(&self, raw: &[u8]) -> EthResult<()> { + let typed_tx = TransactionSigned::decode(&mut (&raw[..])).map_err(|e| { + warn!("Failed to decode signed transaction in the BitfinityTransactionsForwarder: {e}"); + EthApiError::FailedToDecodeSignedTransaction + })?; + + debug!("Pushing tx with hash {:?} to priority queue", typed_tx.hash); + let gas_price = typed_tx.effective_gas_price(None); + + self.queue.lock().await.push(typed_tx.hash(), Uint::from(gas_price), raw.to_vec()); + + Ok(()) + } + + async fn get_transaction_by_hash(&self, hash: B256) -> Option> { + self.queue.lock().await.get(&hash) + } +} + +/// Priority queue to get transactions sorted by gas price. +#[derive(Debug)] +pub struct TransactionsPriorityQueue { + priority: BTreeSet, + transactions: HashMap>, + size_limit: usize, +} + +impl TransactionsPriorityQueue { + /// Creates new instance of the queue with the given limil. + pub fn new(size_limit: usize) -> Self { + Self { priority: BTreeSet::default(), transactions: HashMap::default(), size_limit } + } + + /// Adds the tx with the given gas price. + pub fn push(&mut self, hash: B256, gas_price: U256, tx: Vec) { + let key = TxKey { gas_price, hash }; + self.priority.insert(key); + self.transactions.insert(hash, tx); + + if self.len() > self.size_limit { + self.pop_tx_with_lowest_price(); + } + } + + /// Returns raw transaction if it is present in the queue. + pub fn get(&self, hash: &B256) -> Option> { + self.transactions.get(hash).cloned() + } + + /// Returns tx with highest gas price, if present. + pub fn pop_tx_with_highest_price(&mut self) -> Option<(U256, Vec)> { + let tx_key = self.priority.pop_last()?; + let Some(tx) = self.transactions.remove(&tx_key.hash) else { + warn!("Transaction key present in priority queue, but not found in transactions map."); + return None; + }; + + Some((tx_key.gas_price, tx)) + } + + /// Returns tx with lowest gas price, if present. + pub fn pop_tx_with_lowest_price(&mut self) -> Option<(U256, Vec)> { + let tx_key = self.priority.pop_first()?; + let Some(tx) = self.transactions.remove(&tx_key.hash) else { + warn!("Transaction key present in priority queue, but not found in transactions map."); + return None; + }; + + Some((tx_key.gas_price, tx)) + } + + /// Number of transactions in the queue. + pub fn len(&self) -> usize { + self.transactions.len() + } + + /// Change size limit of the queue. + pub fn set_size_limit(&mut self, new_limit: usize) { + self.size_limit = new_limit; + + while self.len() > self.size_limit { + self.pop_tx_with_lowest_price(); + } + } + + /// Returns true if length == 0. + pub fn is_empty(&self) -> bool { + self.transactions.is_empty() + } +} + +/// This struct will sort transactions by gas price, +/// but if it is equal, the key will still be different due to hash difference. +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] +struct TxKey { + gas_price: U256, + hash: B256, +} + +#[cfg(test)] +mod tests { + use std::sync::OnceLock; + + use super::TransactionsPriorityQueue; + use alloy_consensus::Transaction; + use reth_primitives::TransactionSigned; + use reth_transaction_pool::test_utils::MockTransaction; + use reth_transaction_pool::PoolTransaction; + use revm_primitives::{PrimitiveSignature, U256}; + + #[test] + fn test_pop_order() { + let mut queue = TransactionsPriorityQueue::new(10); + let tx1 = transaction_with_gas_price(100); + let tx2 = transaction_with_gas_price(300); + let tx3 = transaction_with_gas_price(200); + + let tx1_bytes = alloy_rlp::encode(&tx1); + let tx2_bytes = alloy_rlp::encode(&tx2); + let tx3_bytes = alloy_rlp::encode(&tx3); + + queue.push(tx1.hash(), U256::from(tx1.effective_gas_price(None)), tx1_bytes.clone()); + queue.push(tx2.hash(), U256::from(tx2.effective_gas_price(None)), tx2_bytes.clone()); + queue.push(tx3.hash(), U256::from(tx3.effective_gas_price(None)), tx3_bytes.clone()); + + let expected_order = [tx2_bytes, tx3_bytes, tx1_bytes]; + for expected_tx in expected_order { + let popped_tx = queue.pop_tx_with_highest_price().unwrap().1; + assert_eq!(popped_tx, expected_tx); + } + + assert!(queue.is_empty()) + } + + #[test] + fn test_size_limit_should_shrink_tx_with_lowest_price() { + let mut queue = TransactionsPriorityQueue::new(2); + let tx1 = transaction_with_gas_price(100); + let tx2 = transaction_with_gas_price(300); + let tx3 = transaction_with_gas_price(200); + + let tx1_bytes = alloy_rlp::encode(&tx1); + let tx2_bytes = alloy_rlp::encode(&tx2); + let tx3_bytes = alloy_rlp::encode(&tx3); + + queue.push(tx1.hash(), U256::from(tx1.effective_gas_price(None)), tx1_bytes); + queue.push(tx2.hash(), U256::from(tx2.effective_gas_price(None)), tx2_bytes.clone()); + queue.push(tx3.hash(), U256::from(tx3.effective_gas_price(None)), tx3_bytes.clone()); + + let expected_order = [tx2_bytes, tx3_bytes]; + for expected_tx in expected_order { + let popped_tx = queue.pop_tx_with_highest_price().unwrap().1; + assert_eq!(popped_tx, expected_tx); + } + + assert!(queue.is_empty()) + } + + #[test] + fn test_get_transaction_from_queue() { + let mut queue = TransactionsPriorityQueue::new(100); + let tx1 = transaction_with_gas_price(100); + let tx2 = transaction_with_gas_price(300); + let tx3 = transaction_with_gas_price(200); + + let tx1_bytes = alloy_rlp::encode(&tx1); + let tx2_bytes = alloy_rlp::encode(&tx2); + let tx3_bytes = alloy_rlp::encode(&tx3); + + queue.push(tx1.hash(), U256::from(tx1.effective_gas_price(None)), tx1_bytes); + queue.push(tx2.hash(), U256::from(tx2.effective_gas_price(None)), tx2_bytes); + queue.push(tx3.hash(), U256::from(tx3.effective_gas_price(None)), tx3_bytes); + + let hashes = [tx1.hash(), tx2.hash(), tx3.hash()]; + for hash in hashes { + assert!(queue.get(&hash).is_some()); + } + + assert_eq!(queue.len(), 3); + + let tx4 = transaction_with_gas_price(400); + assert!(queue.get(&tx4.hash()).is_none()); + } + + fn transaction_with_gas_price(gas_price: u128) -> TransactionSigned { + let tx = MockTransaction::legacy().with_gas_price(gas_price).rng_hash(); + + let hash = OnceLock::new(); + hash.get_or_init(|| *tx.hash()); + + TransactionSigned { + hash, + signature: PrimitiveSignature::test_signature(), + transaction: tx.into(), + } + } +} From 82c8696bfb1c2e5c6b9176acdf5dca83ced745a9 Mon Sep 17 00:00:00 2001 From: f3kilo Date: Tue, 14 Jan 2025 12:45:33 +0300 Subject: [PATCH 27/31] put tx forwarder into EthApi --- bin/reth/src/main.rs | 33 +++++++++++++++++-- crates/rpc/rpc/src/eth/core.rs | 32 +++++++++++++++--- .../src/eth/core/bitfinity_tx_forwarder.rs | 6 ++-- 3 files changed, 60 insertions(+), 11 deletions(-) diff --git a/bin/reth/src/main.rs b/bin/reth/src/main.rs index 1a94d05ca7b..73744606d11 100644 --- a/bin/reth/src/main.rs +++ b/bin/reth/src/main.rs @@ -3,7 +3,10 @@ #[global_allocator] static ALLOC: reth_cli_util::allocator::Allocator = reth_cli_util::allocator::new_allocator(); +use std::{sync::Arc, time::Duration}; + use clap::{Args, Parser}; +use reth::bitfinity_tasks::send_txs::BitfinityTransactionSender; use reth_ethereum_cli::chainspec::EthereumChainSpecParser; use reth_node_builder::{ engine_tree_config::{ @@ -13,7 +16,9 @@ use reth_node_builder::{ }; use reth_node_ethereum::node::EthereumAddOns; use reth_provider::providers::BlockchainProvider2; +use reth_rpc::eth::core::bitfinity_tx_forwarder::{BitfinityTransactionsForwarder, TransactionsPriorityQueue}; use reth_tracing::tracing::warn; +use tokio::sync::Mutex; use tracing::info; /// Parameters for configuring the engine @@ -102,19 +107,41 @@ fn main() { let datadir = handle.node.data_dir.clone(); let (provider_factory, bitfinity) = handle.bitfinity_import.clone().expect("Bitfinity import not configured"); + // Init bitfinity import - { + let executor = { let import = BitfinityImportCommand::new( config, datadir, chain, - bitfinity, + bitfinity.clone(), provider_factory, blockchain_provider, ); - let _import_handle = import.schedule_execution(None).await?; + let (executor, _import_handle) = import.schedule_execution(None).await?; + executor }; + if bitfinity.tx_queue { + let queue = Arc::new(Mutex::new(TransactionsPriorityQueue::new(1000))); + + // Make EthApi handler move new txs to queue. + let queue_clone = Arc::clone(&queue); + handle.node.add_ons_handle.eth_api().set_bitfinity_tx_forwarder(BitfinityTransactionsForwarder::new(queue_clone)); + + // Run batch transaction sender. + let url = bitfinity.send_raw_transaction_rpc_url.unwrap_or(bitfinity.rpc_url); + let period = Duration::from_secs(bitfinity.send_queued_txs_period_secs); + let transaction_sending = BitfinityTransactionSender::new( + queue, + url, + period, + bitfinity.queued_txs_batch_size, + bitfinity.queued_txs_per_execution_threshold, + ); + let _sending_handle = transaction_sending.schedule_execution(Some(executor)).await?; + } + handle.node_exit_future.await } } diff --git a/crates/rpc/rpc/src/eth/core.rs b/crates/rpc/rpc/src/eth/core.rs index 532651787cc..b9ebcdaa4b0 100644 --- a/crates/rpc/rpc/src/eth/core.rs +++ b/crates/rpc/rpc/src/eth/core.rs @@ -1,12 +1,13 @@ //! Implementation of the [`jsonrpsee`] generated [`EthApiServer`](crate::EthApi) trait //! Handles RPC requests for the `eth_` namespace. -use std::sync::Arc; +use std::sync::{Arc, OnceLock}; use alloy_consensus::BlockHeader; use alloy_eips::BlockNumberOrTag; use alloy_network::Ethereum; use alloy_primitives::{Bytes, U256}; +use bitfinity_tx_forwarder::BitfinityTransactionsForwarder; use derive_more::Deref; use reth_primitives::NodePrimitives; use reth_provider::{ @@ -50,7 +51,9 @@ pub struct EthApi { pub(super) inner: Arc>, /// Transaction RPC response builder. pub tx_resp_builder: EthTxBuilder, - // pub bitfinity_tx_forwarder: Option<()>, + + /// Bitfinity transaction forwarder. + pub bitfinity_tx_forwarder: OnceLock, } impl Clone for EthApi @@ -58,7 +61,11 @@ where Provider: BlockReader, { fn clone(&self) -> Self { - Self { inner: self.inner.clone(), tx_resp_builder: EthTxBuilder } + Self { + inner: self.inner.clone(), + tx_resp_builder: EthTxBuilder, + bitfinity_tx_forwarder: self.bitfinity_tx_forwarder.clone(), + } } } @@ -98,7 +105,18 @@ where proof_permits, ); - Self { inner: Arc::new(inner), tx_resp_builder: EthTxBuilder } + Self { + inner: Arc::new(inner), + tx_resp_builder: EthTxBuilder, + bitfinity_tx_forwarder: OnceLock::new(), + } + } + + pub fn set_bitfinity_tx_forwarder( + &self, + bitfinity_tx_forwarder: BitfinityTransactionsForwarder, + ) { + self.bitfinity_tx_forwarder.get_or_init(|| bitfinity_tx_forwarder); } } @@ -141,7 +159,11 @@ where ctx.config.proof_permits, ); - Self { inner: Arc::new(inner), tx_resp_builder: EthTxBuilder } + Self { + inner: Arc::new(inner), + tx_resp_builder: EthTxBuilder, + bitfinity_tx_forwarder: OnceLock::new(), + } } } diff --git a/crates/rpc/rpc/src/eth/core/bitfinity_tx_forwarder.rs b/crates/rpc/rpc/src/eth/core/bitfinity_tx_forwarder.rs index 82da0bc805f..4d68fb0586f 100644 --- a/crates/rpc/rpc/src/eth/core/bitfinity_tx_forwarder.rs +++ b/crates/rpc/rpc/src/eth/core/bitfinity_tx_forwarder.rs @@ -13,7 +13,7 @@ use tracing::{debug, warn}; pub type SharedQueue = Arc>; /// Forwarder to push transactions to the priority queue. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct BitfinityTransactionsForwarder { queue: SharedQueue, } @@ -24,7 +24,7 @@ impl BitfinityTransactionsForwarder { Self { queue } } - async fn forward_raw_transaction(&self, raw: &[u8]) -> EthResult<()> { + pub async fn forward_raw_transaction(&self, raw: &[u8]) -> EthResult<()> { let typed_tx = TransactionSigned::decode(&mut (&raw[..])).map_err(|e| { warn!("Failed to decode signed transaction in the BitfinityTransactionsForwarder: {e}"); EthApiError::FailedToDecodeSignedTransaction @@ -38,7 +38,7 @@ impl BitfinityTransactionsForwarder { Ok(()) } - async fn get_transaction_by_hash(&self, hash: B256) -> Option> { + pub async fn get_transaction_by_hash(&self, hash: B256) -> Option> { self.queue.lock().await.get(&hash) } } From 31537d09ab3cd8a1878e1d1d7b7caf972ed87f0e Mon Sep 17 00:00:00 2001 From: f3kilo Date: Tue, 14 Jan 2025 13:18:45 +0300 Subject: [PATCH 28/31] compilation fixed --- bin/reth/src/bitfinity_tasks/send_txs.rs | 2 +- bin/reth/src/main.rs | 2 +- bin/reth/tests/commands/bitfinity_node_it.rs | 107 +++++++++--------- .../src/helpers/bitfinity_evm_rpc.rs | 51 +++++++-- .../src/helpers}/bitfinity_tx_forwarder.rs | 4 + crates/rpc/rpc-eth-api/src/helpers/mod.rs | 2 + crates/rpc/rpc/src/eth/core.rs | 6 +- .../rpc/src/eth/helpers/bitfinity_evm_rpc.rs | 8 +- 8 files changed, 113 insertions(+), 69 deletions(-) rename crates/rpc/{rpc/src/eth/core => rpc-eth-api/src/helpers}/bitfinity_tx_forwarder.rs (97%) diff --git a/bin/reth/src/bitfinity_tasks/send_txs.rs b/bin/reth/src/bitfinity_tasks/send_txs.rs index 4ddbde95595..a65a7ea174e 100644 --- a/bin/reth/src/bitfinity_tasks/send_txs.rs +++ b/bin/reth/src/bitfinity_tasks/send_txs.rs @@ -11,7 +11,7 @@ use lightspeed_scheduler::job::Job; use lightspeed_scheduler::scheduler::Scheduler; use lightspeed_scheduler::JobExecutor; use reth_node_core::version::SHORT_VERSION; -use reth_rpc::eth::core::bitfinity_tx_forwarder::SharedQueue; +use reth_rpc_api::eth::helpers::bitfinity_tx_forwarder::SharedQueue; use revm_primitives::{hex, U256}; use tracing::{info, trace, warn}; diff --git a/bin/reth/src/main.rs b/bin/reth/src/main.rs index 73744606d11..88d13499ea7 100644 --- a/bin/reth/src/main.rs +++ b/bin/reth/src/main.rs @@ -16,7 +16,7 @@ use reth_node_builder::{ }; use reth_node_ethereum::node::EthereumAddOns; use reth_provider::providers::BlockchainProvider2; -use reth_rpc::eth::core::bitfinity_tx_forwarder::{BitfinityTransactionsForwarder, TransactionsPriorityQueue}; +use reth_rpc_api::eth::helpers::bitfinity_tx_forwarder::{BitfinityTransactionsForwarder, TransactionsPriorityQueue}; use reth_tracing::tracing::warn; use tokio::sync::Mutex; use tracing::info; diff --git a/bin/reth/tests/commands/bitfinity_node_it.rs b/bin/reth/tests/commands/bitfinity_node_it.rs index 702d21b0d5c..669d0bcd6b7 100644 --- a/bin/reth/tests/commands/bitfinity_node_it.rs +++ b/bin/reth/tests/commands/bitfinity_node_it.rs @@ -31,8 +31,10 @@ use reth_node_ethereum::{ }; use reth_primitives::{Transaction, TransactionSigned}; use reth_provider::providers::BlockchainProvider; -use reth_rpc::eth::core::bitfinity_tx_forwarder::{SharedQueue, TransactionsPriorityQueue}; use reth_rpc::EthApi; +use reth_rpc_api::eth::helpers::bitfinity_tx_forwarder::{ + BitfinityTransactionsForwarder, SharedQueue, TransactionsPriorityQueue, +}; use reth_tasks::TaskManager; use reth_transaction_pool::blobstore::DiskFileBlobStore; use reth_transaction_pool::test_utils::MockTransaction; @@ -191,52 +193,52 @@ async fn bitfinity_test_node_forward_ic_get_genesis_balances() { assert_eq!(result[2].1, U256::from(30).into()); } -// #[tokio::test] -// async fn bitfinity_test_node_forward_send_raw_transaction_requests() { -// // Arrange -// let _log = init_logs(); -// let tasks = TaskManager::current(); - -// let (tx_sender, mut tx_receiver) = tokio::sync::mpsc::channel(10); -// let eth_server = EthImpl::new(Some(tx_sender)); - -// let queue = Arc::new(Mutex::new(TransactionsPriorityQueue::new(10))); - -// let (_server, eth_server_address) = -// mock_eth_server_start(EthServer::into_rpc(eth_server)).await; -// let bitfinity_evm_url = format!("http://{}", eth_server_address); -// let (reth_client, _reth_node) = start_reth_node( -// &tasks, -// Some(format!("http://{}", eth_server_address)), -// None, -// Some(queue.clone()), -// ) -// .await; - -// // Create a random transaction -// let mut tx = [0u8; 256]; -// rand::thread_rng().fill_bytes(&mut tx); -// let expected_tx_hash = keccak::keccak_hash(format!("0x{}", hex::encode(tx)).as_bytes()); - -// // Act -// let result = reth_client.send_raw_transaction_bytes(&encoded).await.unwrap(); - -// // Assert -// assert_eq!(result.to_fixed_bytes(), expected_tx_hash.0.to_fixed_bytes()); - -// let transaction_sending = BitfinityTransactionSender::new( -// queue, -// bitfinity_evm_url, -// Duration::from_millis(200), -// 10, -// 100, -// ); -// transaction_sending.single_execution().await.unwrap(); - -// let received_txs = consume_received_txs(&mut tx_receiver, 1).await.unwrap(); - -// assert_eq!(received_txs[0].0, expected_tx_hash.0.to_fixed_bytes()); -// } +#[tokio::test] +async fn bitfinity_test_node_forward_send_raw_transaction_requests() { + // Arrange + let _log = init_logs(); + let tasks = TaskManager::current(); + + let (tx_sender, mut tx_receiver) = tokio::sync::mpsc::channel(10); + let eth_server = EthImpl::new(Some(tx_sender)); + + let queue = Arc::new(Mutex::new(TransactionsPriorityQueue::new(10))); + + let (_server, eth_server_address) = + mock_eth_server_start(EthServer::into_rpc(eth_server)).await; + let bitfinity_evm_url = format!("http://{}", eth_server_address); + let (reth_client, _reth_node) = start_reth_node( + &tasks, + Some(format!("http://{}", eth_server_address)), + None, + Some(queue.clone()), + ) + .await; + + // Create a random transaction + let tx = transaction_with_gas_price(100); + let encoded = alloy_rlp::encode(&tx); + let expected_tx_hash = keccak::keccak_hash(&encoded); + + // Act + let result = reth_client.send_raw_transaction_bytes(&encoded).await.unwrap(); + + // Assert + assert_eq!(result, expected_tx_hash); + + let transaction_sending = BitfinityTransactionSender::new( + queue, + bitfinity_evm_url, + Duration::from_millis(200), + 10, + 100, + ); + transaction_sending.single_execution().await.unwrap(); + + let received_txs = consume_received_txs(&mut tx_receiver, 1).await.unwrap(); + + assert_eq!(received_txs[0], expected_tx_hash.0); +} #[tokio::test] async fn bitfinity_test_node_send_raw_transaction_in_gas_price_order() { @@ -386,7 +388,7 @@ async fn start_reth_node( tasks: &TaskManager, bitfinity_evm_url: Option, import_data: Option, - _queue: Option, + queue: Option, ) -> ( EthJsonRpcClient, NodeHandle< @@ -505,12 +507,11 @@ async fn start_reth_node( .with_database(database) .with_launch_context(tasks.executor()) .node(EthereumNode::default()) - .extend_rpc_modules(|_ctx| { + .extend_rpc_modules(|ctx| { // Add custom forwarder with transactions priority queue. - // let Some(queue) = queue else { return Ok(()) }; - // let forwarder = BitfinityTransactionsForwarder::new(queue); - // ctx.registry.set_eth_raw_transaction_forwarder(Arc::new(forwarder)); - + let Some(queue) = queue else { return Ok(()) }; + let forwarder = BitfinityTransactionsForwarder::new(queue); + ctx.registry.eth_api().set_bitfinity_tx_forwarder(forwarder); Ok(()) }) .launch() diff --git a/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs b/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs index 79786abb944..1e93180341c 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/bitfinity_evm_rpc.rs @@ -3,23 +3,29 @@ use std::sync::Arc; use alloy_network::TransactionResponse; +use alloy_rlp::Decodable; use did::{Block, H256}; use ethereum_json_rpc_client::CertifiedResult; use ethereum_json_rpc_client::{reqwest::ReqwestClient, EthJsonRpcClient}; use futures::Future; use jsonrpsee::core::RpcResult; use reth_chainspec::ChainSpec; -use reth_primitives::RecoveredTx; +use reth_primitives::{RecoveredTx, TransactionSigned}; use reth_primitives_traits::SignedTransaction; use reth_rpc_eth_types::TransactionSource; -use reth_rpc_server_types::result::internal_rpc_err; +use reth_rpc_server_types::result::{internal_rpc_err, invalid_params_rpc_err}; use revm_primitives::{Address, Bytes, B256, U256}; +use super::bitfinity_tx_forwarder::BitfinityTransactionsForwarder; + /// Proxy to the Bitfinity EVM RPC. pub trait BitfinityEvmRpc { /// Transaction type. type Transaction: SignedTransaction; + /// Returns transaction forwarder. + fn bitfinity_transaction_forwarder(&self) -> Option; + /// Returns the `ChainSpec`. fn chain_spec(&self) -> Arc; @@ -46,15 +52,29 @@ pub trait BitfinityEvmRpc { hash: B256, ) -> impl Future>>> + Send { let chain_spec = self.chain_spec(); - // let forwarder = self.raw_tx_forwarder(); + let forwarder = self.bitfinity_transaction_forwarder(); async move { - // if let Some(forwarder) = forwarder { - // let tx_opt = get_transaction_from_forwarder(&*forwarder, hash).await?; - // if tx_opt.is_some() { - // return Ok(tx_opt); - // } - // }; + // Try to find transaction in transaction forwarder. + if let Some(forwarder) = forwarder { + if let Some(raw_tx) = forwarder.get_transaction_by_hash(hash).await { + let self_tx = + ::decode(&mut raw_tx.as_ref()) + .map_err(|e| { + internal_rpc_err(format!( + "failed to decode BitfinityEvmRpc::Transaction from tx forwarder: {e}" + )) + })?; + + let signer = self_tx.recover_signer().ok_or_else(|| { + internal_rpc_err( + "failed to recover signer from decoded BitfinityEvmRpc::Transaction", + ) + })?; + let recovered_tx = RecoveredTx::new_unchecked(self_tx, signer); + return Ok(Some(TransactionSource::Pool(recovered_tx))); + } + }; // If transaction is not found in forwarder, query it from EVM rpc. let (rpc_url, client) = get_client(&chain_spec)?; @@ -124,7 +144,20 @@ pub trait BitfinityEvmRpc { /// Forwards `eth_sendRawTransaction` calls to the Bitfinity EVM fn btf_send_raw_transaction(&self, tx: Bytes) -> impl Future> + Send { let chain_spec = self.chain_spec(); + let forwarder = self.bitfinity_transaction_forwarder(); + async move { + if let Some(forwarder) = forwarder { + let typed_tx = TransactionSigned::decode(&mut tx.as_ref()).map_err(|e| { + invalid_params_rpc_err(format!( + "failed to decode eth_sendRawTransaction input {tx}: {e}" + )) + })?; + let hash = typed_tx.hash(); + forwarder.forward_raw_transaction(&tx).await?; + return Ok(hash); + }; + let (rpc_url, client) = get_client(&chain_spec)?; let tx_hash = client.send_raw_transaction_bytes(&tx).await.map_err(|e| { diff --git a/crates/rpc/rpc/src/eth/core/bitfinity_tx_forwarder.rs b/crates/rpc/rpc-eth-api/src/helpers/bitfinity_tx_forwarder.rs similarity index 97% rename from crates/rpc/rpc/src/eth/core/bitfinity_tx_forwarder.rs rename to crates/rpc/rpc-eth-api/src/helpers/bitfinity_tx_forwarder.rs index 4d68fb0586f..e66de22f41e 100644 --- a/crates/rpc/rpc/src/eth/core/bitfinity_tx_forwarder.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/bitfinity_tx_forwarder.rs @@ -1,3 +1,5 @@ +//! Module with instruments for transactions sorting, batching and sending. + use std::{collections::BTreeSet, sync::Arc}; use alloy_consensus::Transaction; @@ -24,6 +26,7 @@ impl BitfinityTransactionsForwarder { Self { queue } } + /// Adds raw tx to the priority queue. pub async fn forward_raw_transaction(&self, raw: &[u8]) -> EthResult<()> { let typed_tx = TransactionSigned::decode(&mut (&raw[..])).map_err(|e| { warn!("Failed to decode signed transaction in the BitfinityTransactionsForwarder: {e}"); @@ -38,6 +41,7 @@ impl BitfinityTransactionsForwarder { Ok(()) } + /// Returns transaction from priority queue, if present. pub async fn get_transaction_by_hash(&self, hash: B256) -> Option> { self.queue.lock().await.get(&hash) } diff --git a/crates/rpc/rpc-eth-api/src/helpers/mod.rs b/crates/rpc/rpc-eth-api/src/helpers/mod.rs index 6981a7a5f9b..c533d4c53b7 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/mod.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/mod.rs @@ -15,6 +15,8 @@ //! all the `Eth` traits, e.g. `reth_rpc::EthApi`. pub mod bitfinity_evm_rpc; +pub mod bitfinity_tx_forwarder; + pub mod block; pub mod blocking_task; pub mod call; diff --git a/crates/rpc/rpc/src/eth/core.rs b/crates/rpc/rpc/src/eth/core.rs index b9ebcdaa4b0..44a01048025 100644 --- a/crates/rpc/rpc/src/eth/core.rs +++ b/crates/rpc/rpc/src/eth/core.rs @@ -7,7 +7,6 @@ use alloy_consensus::BlockHeader; use alloy_eips::BlockNumberOrTag; use alloy_network::Ethereum; use alloy_primitives::{Bytes, U256}; -use bitfinity_tx_forwarder::BitfinityTransactionsForwarder; use derive_more::Deref; use reth_primitives::NodePrimitives; use reth_provider::{ @@ -15,7 +14,7 @@ use reth_provider::{ ProviderReceipt, }; use reth_rpc_eth_api::{ - helpers::{EthSigner, SpawnBlocking}, + helpers::{bitfinity_tx_forwarder::BitfinityTransactionsForwarder, EthSigner, SpawnBlocking}, node::RpcNodeCoreExt, EthApiTypes, RpcNodeCore, }; @@ -31,8 +30,6 @@ use tokio::sync::{broadcast, Mutex}; use crate::eth::EthTxBuilder; -pub mod bitfinity_tx_forwarder; - const DEFAULT_BROADCAST_CAPACITY: usize = 2000; /// `Eth` API implementation. @@ -112,6 +109,7 @@ where } } + /// Sets bitfinity tx forwarder to handle new raw transactions. pub fn set_bitfinity_tx_forwarder( &self, bitfinity_tx_forwarder: BitfinityTransactionsForwarder, diff --git a/crates/rpc/rpc/src/eth/helpers/bitfinity_evm_rpc.rs b/crates/rpc/rpc/src/eth/helpers/bitfinity_evm_rpc.rs index 8a87aac0ba8..69ce1d7bd08 100644 --- a/crates/rpc/rpc/src/eth/helpers/bitfinity_evm_rpc.rs +++ b/crates/rpc/rpc/src/eth/helpers/bitfinity_evm_rpc.rs @@ -3,7 +3,9 @@ use std::sync::Arc; use reth_provider::{BlockReader, ChainSpecProvider}; -use reth_rpc_eth_api::helpers::bitfinity_evm_rpc::BitfinityEvmRpc; +use reth_rpc_eth_api::helpers::{ + bitfinity_evm_rpc::BitfinityEvmRpc, bitfinity_tx_forwarder::BitfinityTransactionsForwarder, +}; use crate::EthApi; @@ -14,6 +16,10 @@ where { type Transaction = Provider::Transaction; + fn bitfinity_transaction_forwarder(&self) -> Option { + self.bitfinity_tx_forwarder.get().cloned() + } + fn chain_spec(&self) -> Arc { self.inner.provider().chain_spec() } From 297e6b214752c6fdfdd0e35baefab7a4d6ef9540 Mon Sep 17 00:00:00 2001 From: f3kilo Date: Tue, 14 Jan 2025 14:18:16 +0300 Subject: [PATCH 29/31] tests fixed --- bin/reth/tests/commands/bitfinity_node_it.rs | 4 +++- crates/rpc/rpc/src/eth/core.rs | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/bin/reth/tests/commands/bitfinity_node_it.rs b/bin/reth/tests/commands/bitfinity_node_it.rs index 669d0bcd6b7..d834a6429c6 100644 --- a/bin/reth/tests/commands/bitfinity_node_it.rs +++ b/bin/reth/tests/commands/bitfinity_node_it.rs @@ -326,6 +326,7 @@ async fn bitfinity_test_node_get_transaction_when_it_is_queued() { for hash in &expected_hashes { let tx = reth_client.get_transaction_by_hash(hash.clone()).await.unwrap().unwrap(); // Transaction in forwarder has NO block number. + dbg!(tx.block_number); assert!(tx.block_number.is_none()); } @@ -507,7 +508,7 @@ async fn start_reth_node( .with_database(database) .with_launch_context(tasks.executor()) .node(EthereumNode::default()) - .extend_rpc_modules(|ctx| { + .on_rpc_started(|ctx, _| { // Add custom forwarder with transactions priority queue. let Some(queue) = queue else { return Ok(()) }; let forwarder = BitfinityTransactionsForwarder::new(queue); @@ -520,6 +521,7 @@ async fn start_reth_node( let reth_address = node_handle.node.rpc_server_handle().http_local_addr().unwrap(); let addr_string = format!("http://{}", reth_address); + let client: EthJsonRpcClient = EthJsonRpcClient::new(ReqwestClient::new(addr_string)); diff --git a/crates/rpc/rpc/src/eth/core.rs b/crates/rpc/rpc/src/eth/core.rs index 44a01048025..ca8ef9078b3 100644 --- a/crates/rpc/rpc/src/eth/core.rs +++ b/crates/rpc/rpc/src/eth/core.rs @@ -50,7 +50,7 @@ pub struct EthApi { pub tx_resp_builder: EthTxBuilder, /// Bitfinity transaction forwarder. - pub bitfinity_tx_forwarder: OnceLock, + pub bitfinity_tx_forwarder: Arc>, } impl Clone for EthApi @@ -105,7 +105,7 @@ where Self { inner: Arc::new(inner), tx_resp_builder: EthTxBuilder, - bitfinity_tx_forwarder: OnceLock::new(), + bitfinity_tx_forwarder: Arc::new(OnceLock::new()), } } @@ -160,7 +160,7 @@ where Self { inner: Arc::new(inner), tx_resp_builder: EthTxBuilder, - bitfinity_tx_forwarder: OnceLock::new(), + bitfinity_tx_forwarder: Arc::new(OnceLock::new()), } } } From 7228809299994361bc188e8b69d62acd77d1c519 Mon Sep 17 00:00:00 2001 From: f3kilo Date: Thu, 16 Jan 2025 10:36:44 +0300 Subject: [PATCH 30/31] revert unnecessary changes in reth files --- crates/ethereum/consensus/src/lib.rs | 47 +++++++++---------- crates/net/network/src/manager.rs | 4 +- .../primitives/src/transaction/signed.rs | 12 ++--- crates/primitives/src/alloy_compat.rs | 2 +- crates/primitives/src/block.rs | 2 +- crates/primitives/src/transaction/mod.rs | 30 ++++++++---- .../rpc-eth-api/src/helpers/transaction.rs | 23 ++++----- docker-compose.yml | 2 +- 8 files changed, 64 insertions(+), 58 deletions(-) diff --git a/crates/ethereum/consensus/src/lib.rs b/crates/ethereum/consensus/src/lib.rs index de11fbab10b..c1ba56b8c62 100644 --- a/crates/ethereum/consensus/src/lib.rs +++ b/crates/ethereum/consensus/src/lib.rs @@ -59,9 +59,8 @@ impl EthBeaconConsensus let parent_gas_limit = if self.chain_spec.fork(EthereumHardfork::London).transitions_at_block(header.number()) { - parent.gas_limit() - * self - .chain_spec + parent.gas_limit() * + self.chain_spec .base_fee_params_at_timestamp(header.timestamp()) .elasticity_multiplier as u64 } else { @@ -74,23 +73,23 @@ impl EthBeaconConsensus return Err(ConsensusError::GasLimitInvalidIncrease { parent_gas_limit, child_gas_limit: header.gas_limit(), - }); + }) } } // Check for a decrease in gas limit beyond the allowed threshold. - else if parent_gas_limit - header.gas_limit() - >= parent_gas_limit / GAS_LIMIT_BOUND_DIVISOR + else if parent_gas_limit - header.gas_limit() >= + parent_gas_limit / GAS_LIMIT_BOUND_DIVISOR { return Err(ConsensusError::GasLimitInvalidDecrease { parent_gas_limit, child_gas_limit: header.gas_limit(), - }); + }) } // Check if the self gas limit is below the minimum required limit. else if header.gas_limit() < MINIMUM_GAS_LIMIT { return Err(ConsensusError::GasLimitInvalidMinimum { child_gas_limit: header.gas_limit(), - }); + }) } Ok(()) @@ -143,33 +142,33 @@ where validate_header_base_fee(header.header(), &self.chain_spec)?; // EIP-4895: Beacon chain push withdrawals as operations - if self.chain_spec.is_shanghai_active_at_timestamp(header.timestamp()) - && header.withdrawals_root().is_none() + if self.chain_spec.is_shanghai_active_at_timestamp(header.timestamp()) && + header.withdrawals_root().is_none() { - return Err(ConsensusError::WithdrawalsRootMissing); - } else if !self.chain_spec.is_shanghai_active_at_timestamp(header.timestamp()) - && header.withdrawals_root().is_some() + return Err(ConsensusError::WithdrawalsRootMissing) + } else if !self.chain_spec.is_shanghai_active_at_timestamp(header.timestamp()) && + header.withdrawals_root().is_some() { - return Err(ConsensusError::WithdrawalsRootUnexpected); + return Err(ConsensusError::WithdrawalsRootUnexpected) } // Ensures that EIP-4844 fields are valid once cancun is active. if self.chain_spec.is_cancun_active_at_timestamp(header.timestamp()) { validate_4844_header_standalone(header.header())?; } else if header.blob_gas_used().is_some() { - return Err(ConsensusError::BlobGasUsedUnexpected); + return Err(ConsensusError::BlobGasUsedUnexpected) } else if header.excess_blob_gas().is_some() { - return Err(ConsensusError::ExcessBlobGasUnexpected); + return Err(ConsensusError::ExcessBlobGasUnexpected) } else if header.parent_beacon_block_root().is_some() { - return Err(ConsensusError::ParentBeaconBlockRootUnexpected); + return Err(ConsensusError::ParentBeaconBlockRootUnexpected) } if self.chain_spec.is_prague_active_at_timestamp(header.timestamp()) { if header.requests_hash().is_none() { - return Err(ConsensusError::RequestsHashMissing); + return Err(ConsensusError::RequestsHashMissing) } } else if header.requests_hash().is_some() { - return Err(ConsensusError::RequestsHashUnexpected); + return Err(ConsensusError::RequestsHashUnexpected) } Ok(()) @@ -186,7 +185,7 @@ where // TODO Check difficulty increment between parent and self // Ace age did increment it by some formula that we need to follow. - // self.validate_against_parent_gas_limit(header, parent)?; + self.validate_against_parent_gas_limit(header, parent)?; validate_against_parent_eip1559_base_fee( header.header(), @@ -221,16 +220,16 @@ where if is_post_merge { // TODO: add `is_zero_difficulty` to `alloy_consensus::BlockHeader` trait if !header.difficulty().is_zero() { - return Err(ConsensusError::TheMergeDifficultyIsNotZero); + return Err(ConsensusError::TheMergeDifficultyIsNotZero) } // TODO: helper fn in `alloy_consensus::BlockHeader` trait if !header.nonce().is_some_and(|nonce| nonce.is_zero()) { - return Err(ConsensusError::TheMergeNonceIsNotZero); + return Err(ConsensusError::TheMergeNonceIsNotZero) } if header.ommers_hash() != EMPTY_OMMER_ROOT_HASH { - return Err(ConsensusError::TheMergeOmmerRootIsNotEmpty); + return Err(ConsensusError::TheMergeOmmerRootIsNotEmpty) } // Post-merge, the consensus layer is expected to perform checks such that the block @@ -260,7 +259,7 @@ where return Err(ConsensusError::TimestampIsInFuture { timestamp: header.timestamp(), present_timestamp, - }); + }) } validate_header_extra_data(header)?; diff --git a/crates/net/network/src/manager.rs b/crates/net/network/src/manager.rs index b95099ae9de..c63f5025b56 100644 --- a/crates/net/network/src/manager.rs +++ b/crates/net/network/src/manager.rs @@ -591,7 +591,7 @@ impl NetworkManager { if self.handle.mode().is_stake() { // See [EIP-3675](https://eips.ethereum.org/EIPS/eip-3675#devp2p) warn!(target: "net", "Peer performed block propagation, but it is not supported in proof of stake (EIP-3675)"); - return; + return } let msg = NewBlockMessage { hash, block: Arc::new(block) }; self.swarm.state_mut().announce_new_block(msg); @@ -1081,7 +1081,7 @@ impl Future for NetworkManager { if maybe_more_handle_messages || maybe_more_swarm_events { // make sure we're woken up again cx.waker().wake_by_ref(); - return Poll::Pending; + return Poll::Pending } this.update_poll_metrics(start, poll_durations); diff --git a/crates/optimism/primitives/src/transaction/signed.rs b/crates/optimism/primitives/src/transaction/signed.rs index f7b10f74cf7..f5aefd9c8ff 100644 --- a/crates/optimism/primitives/src/transaction/signed.rs +++ b/crates/optimism/primitives/src/transaction/signed.rs @@ -86,7 +86,7 @@ impl SignedTransaction for OpTransactionSigned { // Optimism's Deposit transaction does not have a signature. Directly return the // `from` address. if let OpTypedTransaction::Deposit(TxDeposit { from, .. }) = self.transaction { - return Some(from); + return Some(from) } let Self { transaction, signature, .. } = self; @@ -98,7 +98,7 @@ impl SignedTransaction for OpTransactionSigned { // Optimism's Deposit transaction does not have a signature. Directly return the // `from` address. if let OpTypedTransaction::Deposit(TxDeposit { from, .. }) = &self.transaction { - return Some(*from); + return Some(*from) } let Self { transaction, signature, .. } = self; @@ -208,7 +208,7 @@ impl reth_primitives_traits::FillTxEnv for OpTransactionSigned { is_system_transaction: Some(tx.is_system_transaction), enveloped_tx: Some(envelope.into()), }; - return; + return } } @@ -415,9 +415,9 @@ impl Typed2718 for OpTransactionSigned { impl PartialEq for OpTransactionSigned { fn eq(&self, other: &Self) -> bool { - self.signature == other.signature - && self.transaction == other.transaction - && self.tx_hash() == other.tx_hash() + self.signature == other.signature && + self.transaction == other.transaction && + self.tx_hash() == other.tx_hash() } } diff --git a/crates/primitives/src/alloy_compat.rs b/crates/primitives/src/alloy_compat.rs index a425b3d9a79..88887652083 100644 --- a/crates/primitives/src/alloy_compat.rs +++ b/crates/primitives/src/alloy_compat.rs @@ -87,7 +87,7 @@ impl TryFrom for TransactionSigned { hash, ) } else { - return Err(ConversionError::Custom("unknown transaction type".to_string())); + return Err(ConversionError::Custom("unknown transaction type".to_string())) } } _ => return Err(ConversionError::Custom("unknown transaction type".to_string())), diff --git a/crates/primitives/src/block.rs b/crates/primitives/src/block.rs index a19b2d76937..3cff1646e43 100644 --- a/crates/primitives/src/block.rs +++ b/crates/primitives/src/block.rs @@ -270,7 +270,7 @@ where return Err(GotExpected { got: calculated_root, expected: self.header.transactions_root(), - }); + }) } Ok(()) diff --git a/crates/primitives/src/transaction/mod.rs b/crates/primitives/src/transaction/mod.rs index a6ce2454551..bee59a647e9 100644 --- a/crates/primitives/src/transaction/mod.rs +++ b/crates/primitives/src/transaction/mod.rs @@ -220,10 +220,10 @@ impl Transaction { pub fn set_chain_id(&mut self, chain_id: u64) { match self { Self::Legacy(TxLegacy { chain_id: ref mut c, .. }) => *c = Some(chain_id), - Self::Eip2930(TxEip2930 { chain_id: ref mut c, .. }) - | Self::Eip1559(TxEip1559 { chain_id: ref mut c, .. }) - | Self::Eip4844(TxEip4844 { chain_id: ref mut c, .. }) - | Self::Eip7702(TxEip7702 { chain_id: ref mut c, .. }) => *c = chain_id, + Self::Eip2930(TxEip2930 { chain_id: ref mut c, .. }) | + Self::Eip1559(TxEip1559 { chain_id: ref mut c, .. }) | + Self::Eip4844(TxEip4844 { chain_id: ref mut c, .. }) | + Self::Eip7702(TxEip7702 { chain_id: ref mut c, .. }) => *c = chain_id, #[cfg(feature = "optimism")] Self::Deposit(_) => { /* noop */ } } @@ -268,7 +268,7 @@ impl Transaction { // Check if max_fee_per_gas is less than base_fee if max_fee_per_gas < base_fee { - return None; + return None } // Calculate the difference between max_fee_per_gas and base_fee @@ -815,9 +815,9 @@ impl Hash for TransactionSigned { impl PartialEq for TransactionSigned { fn eq(&self, other: &Self) -> bool { - self.signature == other.signature - && self.transaction == other.transaction - && self.tx_hash() == other.tx_hash() + self.signature == other.signature && + self.transaction == other.transaction && + self.tx_hash() == other.tx_hash() } } @@ -968,7 +968,7 @@ impl SignedTransaction for TransactionSigned { // `from` address. #[cfg(feature = "optimism")] if let Transaction::Deposit(TxDeposit { from, .. }) = self.transaction { - return Some(from); + return Some(from) } let signature_hash = self.signature_hash(); recover_signer(&self.signature, signature_hash) @@ -979,7 +979,7 @@ impl SignedTransaction for TransactionSigned { // `from` address. #[cfg(feature = "optimism")] if let Transaction::Deposit(TxDeposit { from, .. }) = self.transaction { - return Some(from); + return Some(from) } self.encode_for_signing(buf); let signature_hash = keccak256(buf); @@ -1795,6 +1795,16 @@ mod tests { assert_eq!(decoded, TxKind::Create); } + #[test] + fn test_decode_create_goerli() { + // test that an example create tx from goerli decodes properly + let tx_bytes = hex!("b901f202f901ee05228459682f008459682f11830209bf8080b90195608060405234801561001057600080fd5b50610175806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80630c49c36c14610030575b600080fd5b61003861004e565b604051610045919061011d565b60405180910390f35b60606020600052600f6020527f68656c6c6f2073746174656d696e64000000000000000000000000000000000060405260406000f35b600081519050919050565b600082825260208201905092915050565b60005b838110156100be5780820151818401526020810190506100a3565b838111156100cd576000848401525b50505050565b6000601f19601f8301169050919050565b60006100ef82610084565b6100f9818561008f565b93506101098185602086016100a0565b610112816100d3565b840191505092915050565b6000602082019050818103600083015261013781846100e4565b90509291505056fea264697066735822122051449585839a4ea5ac23cae4552ef8a96b64ff59d0668f76bfac3796b2bdbb3664736f6c63430008090033c080a0136ebffaa8fc8b9fda9124de9ccb0b1f64e90fbd44251b4c4ac2501e60b104f9a07eb2999eec6d185ef57e91ed099afb0a926c5b536f0155dd67e537c7476e1471"); + + let decoded = TransactionSigned::decode(&mut &tx_bytes[..]).unwrap(); + assert_eq!(tx_bytes.len(), decoded.length()); + assert_eq!(tx_bytes, &alloy_rlp::encode(decoded)[..]); + } + #[test] fn test_decode_recover_mainnet_tx() { // random mainnet tx diff --git a/crates/rpc/rpc-eth-api/src/helpers/transaction.rs b/crates/rpc/rpc-eth-api/src/helpers/transaction.rs index 31cef0069f1..6da59a98b24 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/transaction.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/transaction.rs @@ -112,7 +112,7 @@ pub trait EthTransactions: LoadTransaction { if let Some(tx) = self.pool().get_pooled_transaction_element(hash).map(|tx| tx.encoded_2718().into()) { - return Ok(Some(tx)); + return Ok(Some(tx)) } self.spawn_blocking_io(move |ref this| { @@ -223,7 +223,7 @@ pub trait EthTransactions: LoadTransaction { return Ok(Some( self.tx_resp_builder().fill(tx.clone().with_signer(*signer), tx_info)?, - )); + )) } } @@ -321,7 +321,7 @@ pub trait EthTransactions: LoadTransaction { async move { if let Some(block) = self.block_with_senders(block_id).await? { if let Some(tx) = block.transactions().get(index) { - return Ok(Some(tx.encoded_2718().into())); + return Ok(Some(tx.encoded_2718().into())) } } @@ -345,7 +345,7 @@ pub trait EthTransactions: LoadTransaction { }; if self.find_signer(&from).is_err() { - return Err(SignError::NoAccount.into_eth_err()); + return Err(SignError::NoAccount.into_eth_err()) } // set nonce if not already set before @@ -528,15 +528,12 @@ pub trait LoadTransaction: SpawnBlocking + FullEthApiTypes + RpcNodeCoreExt { >, > + Send { async move { - // Ok(self.transaction_by_hash(transaction_hash).await?.map(|tx| match tx { - Ok(::transaction_by_hash(self, transaction_hash).await?.map( - |tx| match tx { - tx @ TransactionSource::Pool(_) => (tx, BlockId::pending()), - tx @ TransactionSource::Block { block_hash, .. } => { - (tx, BlockId::Hash(block_hash.into())) - } - }, - )) + Ok(self.transaction_by_hash(transaction_hash).await?.map(|tx| match tx { + tx @ TransactionSource::Pool(_) => (tx, BlockId::pending()), + tx @ TransactionSource::Block { block_hash, .. } => { + (tx, BlockId::Hash(block_hash.into())) + } + })) } } diff --git a/docker-compose.yml b/docker-compose.yml index 9079832014a..01488cd7020 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,6 +8,6 @@ services: dockerfile: ./Dockerfile ports: - '8080:8080' - # command: node -vvv --http --http.port 8080 --http.addr 0.0.0.0 --http.api "debug,eth,net,trace,txpool,web3" --disable-discovery --ipcdisable --no-persist-peers -r https://block-extractor-testnet-1052151659755.europe-west9.run.app -i 10 -b 100 --datadir /reth/data + command: node -vvv --http --http.port 8080 --http.addr 0.0.0.0 --http.api "debug,eth,net,trace,txpool,web3" --disable-discovery --ipcdisable --no-persist-peers -r https://block-extractor-testnet-1052151659755.europe-west9.run.app -i 10 -b 100 --datadir /reth/data volumes: - ./target/reth:/reth From e4cbd259adde9dcb693f7096c023d0ebaad92134 Mon Sep 17 00:00:00 2001 From: f3kilo Date: Thu, 16 Jan 2025 10:40:56 +0300 Subject: [PATCH 31/31] re-apply bitfinity changes --- crates/ethereum/consensus/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ethereum/consensus/src/lib.rs b/crates/ethereum/consensus/src/lib.rs index c1ba56b8c62..fe8948187cb 100644 --- a/crates/ethereum/consensus/src/lib.rs +++ b/crates/ethereum/consensus/src/lib.rs @@ -185,7 +185,7 @@ where // TODO Check difficulty increment between parent and self // Ace age did increment it by some formula that we need to follow. - self.validate_against_parent_gas_limit(header, parent)?; + // self.validate_against_parent_gas_limit(header, parent)?; // Disabled by Bitfinity validate_against_parent_eip1559_base_fee( header.header(),