From 09d928cb59bbeae1bac5f1719280083c6dadbdb0 Mon Sep 17 00:00:00 2001 From: Daniel Freire Date: Tue, 14 May 2024 12:24:00 -0300 Subject: [PATCH 1/5] feat: time and gas consumption metrics for each contract function --- build.rs | 8 ++++--- src/eth/evm/evm.rs | 18 ++++++++++++++ src/eth/executor.rs | 32 +++++++++++++++++++++---- src/eth/primitives/account.rs | 1 + src/eth/primitives/alias.rs | 4 +++- src/eth/primitives/bytes.rs | 11 +++++++++ src/eth/primitives/call_input.rs | 9 +++++++ src/eth/primitives/mod.rs | 2 +- src/eth/primitives/transaction_input.rs | 13 ++++++++++ src/eth/rpc/rpc_middleware.rs | 25 +++++-------------- src/infra/metrics.rs | 25 ++++++++++++++++--- 11 files changed, 116 insertions(+), 32 deletions(-) diff --git a/build.rs b/build.rs index 1395e4559..cd4d27917 100644 --- a/build.rs +++ b/build.rs @@ -38,8 +38,9 @@ fn generate_signature_maps() { let mut signatures_4_bytes = phf_codegen::Map::<[u8; 4]>::new(); let mut signatures_32_bytes = phf_codegen::Map::<[u8; 32]>::new(); for signature_file in signature_files { - let signatures_content = fs::read_to_string(signature_file).expect("Reading signature file shoult not fail"); - populate_signature_maps(&signatures_content, &mut seen, &mut signatures_4_bytes, &mut signatures_32_bytes); + let prefix = signature_file.file_name().unwrap().to_str().unwrap().split('.').next().unwrap(); + let signatures_content = fs::read_to_string(&signature_file).expect("Reading signature file shoult not fail"); + populate_signature_maps(&signatures_content, &mut seen, &mut signatures_4_bytes, &mut signatures_32_bytes, prefix); } // write signatures.rs file @@ -63,6 +64,7 @@ fn populate_signature_maps( seen: &mut HashSet>, signatures_4_bytes: &mut phf_codegen::Map<[u8; 4]>, signatures_32_bytes: &mut phf_codegen::Map<[u8; 32]>, + prefix: &str, ) { for line in input.lines() { if let Ok((_, (id, signature))) = parse_signature(line) { @@ -71,7 +73,7 @@ fn populate_signature_maps( } seen.insert(id.clone()); - let signature = format!("\"{}\"", signature); + let signature = format!("\"{}::{}\"", prefix, signature); match id.len() { 4 => { signatures_4_bytes.entry(id.try_into().unwrap(), &signature); diff --git a/src/eth/evm/evm.rs b/src/eth/evm/evm.rs index 0b8f2c274..5c4ba4c06 100644 --- a/src/eth/evm/evm.rs +++ b/src/eth/evm/evm.rs @@ -6,9 +6,12 @@ //! facilitates flexible EVM integrations, enabling the project to adapt to different blockchain environments //! or requirements while maintaining a consistent execution interface. +use std::borrow::Cow; + use display_json::DebugAsJson; use itertools::Itertools; +use crate::eth::primitives::bytes::extract_function_signature; use crate::eth::primitives::Address; use crate::eth::primitives::BlockNumber; use crate::eth::primitives::Bytes; @@ -21,10 +24,12 @@ use crate::eth::primitives::ExternalReceipt; use crate::eth::primitives::ExternalTransaction; use crate::eth::primitives::Gas; use crate::eth::primitives::Nonce; +use crate::eth::primitives::SoliditySignature; use crate::eth::primitives::StoragePointInTime; use crate::eth::primitives::TransactionInput; use crate::eth::primitives::UnixTime; use crate::eth::primitives::Wei; +use crate::ext::not; use crate::ext::OptionExt; use crate::if_else; @@ -126,6 +131,19 @@ pub struct EvmInput { } impl EvmInput { + fn is_contract_deployment(&self) -> bool { + self.to.is_none() && not(self.data.is_empty()) + } + + pub fn extract_function(&self) -> Option { + if self.is_contract_deployment() { + return Some(Cow::from("contract_deployment")); + } + let id: [u8; 4] = self.data.get(..4)?.try_into().ok()?; + + Some(extract_function_signature(id)) + } + /// Creates from a transaction that was sent directly to Stratus with `eth_sendRawTransaction`. pub fn from_eth_transaction(input: TransactionInput) -> Self { Self { diff --git a/src/eth/executor.rs b/src/eth/executor.rs index fb6b9d75d..c08ea9ef6 100644 --- a/src/eth/executor.rs +++ b/src/eth/executor.rs @@ -188,6 +188,10 @@ impl Executor { Ok(evm_input) => evm_input, Err(e) => return Err((tx, receipt, e)), }; + + #[cfg(feature = "metrics")] + let function = evm_input.extract_function(); + let evm_result = self.execute_in_evm(evm_input).await; // handle reexecution result @@ -197,6 +201,13 @@ impl Executor { if let Err(e) = evm_result.execution.apply_execution_costs(receipt) { return Err((tx, receipt, e)); }; + + #[cfg(feature = "metrics")] + let gas_used = evm_result.execution.gas; + + #[cfg(feature = "metrics")] + metrics::inc_executor_external_transaction_gas(gas_used.as_u64() as usize, function.clone()); + evm_result.execution.gas = match receipt.gas_used.unwrap_or_default().try_into() { Ok(gas) => gas, Err(e) => return Err((tx, receipt, e)), @@ -213,7 +224,7 @@ impl Executor { // track metrics #[cfg(feature = "metrics")] - metrics::inc_executor_external_transaction(start.elapsed()); + metrics::inc_executor_external_transaction(start.elapsed(), function); Ok(ExternalTransactionExecution::new(tx.clone(), receipt.clone(), evm_result)) } @@ -235,6 +246,8 @@ impl Executor { pub async fn transact(&self, tx_input: TransactionInput) -> anyhow::Result { #[cfg(feature = "metrics")] let start = metrics::now(); + #[cfg(feature = "metrics")] + let function = tx_input.extract_function(); tracing::info!( hash = %tx_input.hash, @@ -271,7 +284,7 @@ impl Executor { continue; } else { #[cfg(feature = "metrics")] - metrics::inc_executor_transact(start.elapsed(), false); + metrics::inc_executor_transact(start.elapsed(), false, function); return Err(e); } } @@ -294,7 +307,9 @@ impl Executor { }; #[cfg(feature = "metrics")] - metrics::inc_executor_transact(start.elapsed(), true); + metrics::inc_executor_transact(start.elapsed(), true, function.clone()); + #[cfg(feature = "metrics")] + metrics::inc_executor_transact_gas(tx_execution.execution().gas.as_u64() as usize, true, function); Ok(tx_execution) } @@ -304,6 +319,8 @@ impl Executor { pub async fn call(&self, input: CallInput, point_in_time: StoragePointInTime) -> anyhow::Result { #[cfg(feature = "metrics")] let start = metrics::now(); + #[cfg(feature = "metrics")] + let function = input.extract_function(); tracing::info!( from = ?input.from, @@ -318,9 +335,14 @@ impl Executor { let evm_result = self.execute_in_evm(evm_input).await; #[cfg(feature = "metrics")] - metrics::inc_executor_call(start.elapsed(), evm_result.is_ok()); + metrics::inc_executor_call(start.elapsed(), evm_result.is_ok(), function.clone()); + + let execution = evm_result?.execution; + + #[cfg(feature = "metrics")] + metrics::inc_executor_call_gas(execution.gas.as_u64() as usize, function.clone()); - evm_result.map(|x| x.execution) + Ok(execution) } // ------------------------------------------------------------------------- diff --git a/src/eth/primitives/account.rs b/src/eth/primitives/account.rs index b27a4ce6e..b40c58a03 100644 --- a/src/eth/primitives/account.rs +++ b/src/eth/primitives/account.rs @@ -167,6 +167,7 @@ pub fn test_accounts() -> Vec { hex!("15d34aaf54267db7d7c367839aaf71a00a2c6a65"), hex!("9965507d1a55bcc2695c58ba16fb37d819b0a4dc"), hex!("976ea74026e726554db657fa54763abd0c3a0aa9"), + hex!("e45b176cad7090a5cf70b69a73b6def9296ba6a2"), ] .into_iter() .map(|address| Account { diff --git a/src/eth/primitives/alias.rs b/src/eth/primitives/alias.rs index 814a72c71..d205f364e 100644 --- a/src/eth/primitives/alias.rs +++ b/src/eth/primitives/alias.rs @@ -8,6 +8,8 @@ //! maintenance by providing clear, descriptive types in Ethereum-related //! operations. +use std::borrow::Cow; + /// Alias for 4 byte signature used to identify functions and errors. pub type Signature4Bytes = [u8; 4]; @@ -15,4 +17,4 @@ pub type Signature4Bytes = [u8; 4]; pub type Signature32Bytes = [u8; 32]; /// Alias for a Solidity function, error or event signature. -pub type SoliditySignature = &'static str; +pub type SoliditySignature = Cow<'static, str>; diff --git a/src/eth/primitives/bytes.rs b/src/eth/primitives/bytes.rs index b85d1e678..1bce5ee7e 100644 --- a/src/eth/primitives/bytes.rs +++ b/src/eth/primitives/bytes.rs @@ -7,6 +7,7 @@ //! various byte formats and Ethereum-specific types, playing a key role in //! data serialization and processing. +use std::borrow::Cow; use std::fmt::Debug; use std::fmt::Display; use std::ops::Deref; @@ -17,6 +18,9 @@ use revm::primitives::Bytecode as RevmBytecode; use revm::primitives::Bytes as RevmBytes; use revm::primitives::Output as RevmOutput; +use crate::eth::codegen; +use crate::eth::primitives::Signature4Bytes; +use crate::eth::primitives::SoliditySignature; use crate::gen_newtype_from; #[derive(Clone, Default, Eq, PartialEq, fake::Dummy, sqlx::Type)] @@ -139,3 +143,10 @@ impl From for RevmBytecode { to_analysed(RevmBytecode::new_raw(value.0.into())) } } + +pub fn extract_function_signature(id: Signature4Bytes) -> SoliditySignature { + match codegen::SIGNATURES_4_BYTES.get(&id) { + Some(signature) => Cow::from(*signature), + None => Cow::from(const_hex::encode_prefixed(id)), + } +} diff --git a/src/eth/primitives/call_input.rs b/src/eth/primitives/call_input.rs index f8d5840d5..6252aa2ba 100644 --- a/src/eth/primitives/call_input.rs +++ b/src/eth/primitives/call_input.rs @@ -6,8 +6,10 @@ //! the transaction data payload (`data`). It is crucial in constructing and //! interpreting transaction calls, especially for smart contract interactions. +use crate::eth::primitives::bytes::extract_function_signature; use crate::eth::primitives::Address; use crate::eth::primitives::Bytes; +use crate::eth::primitives::SoliditySignature; use crate::eth::primitives::Wei; #[derive(Debug, Clone, serde::Deserialize)] @@ -21,3 +23,10 @@ pub struct CallInput { #[serde(default)] pub data: Bytes, } + +impl CallInput { + pub fn extract_function(&self) -> Option { + let id: [u8; 4] = self.data.get(..4)?.try_into().ok()?; + Some(extract_function_signature(id)) + } +} diff --git a/src/eth/primitives/mod.rs b/src/eth/primitives/mod.rs index 10a37a33f..cd5e81b22 100644 --- a/src/eth/primitives/mod.rs +++ b/src/eth/primitives/mod.rs @@ -82,7 +82,7 @@ mod block_header; mod block_number; mod block_selection; mod bytecode; -mod bytes; +pub mod bytes; mod call_input; mod chain_id; mod code_hash; diff --git a/src/eth/primitives/transaction_input.rs b/src/eth/primitives/transaction_input.rs index 629c90735..94df6398b 100644 --- a/src/eth/primitives/transaction_input.rs +++ b/src/eth/primitives/transaction_input.rs @@ -5,6 +5,8 @@ //! payload. It is essential for creating and interpreting Ethereum //! transactions, providing a comprehensive interface for transaction data. +use std::borrow::Cow; + use anyhow::anyhow; use display_json::DebugAsJson; use ethereum_types::U256; @@ -16,6 +18,7 @@ use fake::Fake; use fake::Faker; use rlp::Decodable; +use crate::eth::primitives::bytes::extract_function_signature; use crate::eth::primitives::Address; use crate::eth::primitives::Bytes; use crate::eth::primitives::ChainId; @@ -23,6 +26,7 @@ use crate::eth::primitives::ExternalTransaction; use crate::eth::primitives::Gas; use crate::eth::primitives::Hash; use crate::eth::primitives::Nonce; +use crate::eth::primitives::SoliditySignature; use crate::eth::primitives::Wei; use crate::ext::not; use crate::ext::OptionExt; @@ -54,6 +58,15 @@ impl TransactionInput { pub fn is_contract_deployment(&self) -> bool { self.to.is_none() && not(self.input.is_empty()) } + + pub fn extract_function(&self) -> Option { + if self.is_contract_deployment() { + return Some(Cow::from("contract_deployment")); + } + let id: [u8; 4] = self.input.get(..4)?.try_into().ok()?; + + Some(extract_function_signature(id)) + } } impl Dummy for TransactionInput { diff --git a/src/eth/rpc/rpc_middleware.rs b/src/eth/rpc/rpc_middleware.rs index 8c4e6df2e..c5f4d42a5 100644 --- a/src/eth/rpc/rpc_middleware.rs +++ b/src/eth/rpc/rpc_middleware.rs @@ -11,10 +11,8 @@ use jsonrpsee::types::Params; use jsonrpsee::MethodResponse; use pin_project::pin_project; -use crate::eth::codegen::{self}; use crate::eth::primitives::Bytes; use crate::eth::primitives::CallInput; -use crate::eth::primitives::Signature4Bytes; use crate::eth::primitives::SoliditySignature; use crate::eth::primitives::TransactionInput; use crate::eth::rpc::next_rpc_param; @@ -50,14 +48,14 @@ where tracing::info!( id = %request.id, %method, - function = %function.unwrap_or_default(), + function = %function.clone().unwrap_or_default(), params = ?request.params(), "rpc request" ); // metrify request #[cfg(feature = "metrics")] - metrics::inc_rpc_requests_started(method, function); + metrics::inc_rpc_requests_started(method, function.clone()); RpcResponse { id: request.id.to_string(), @@ -71,24 +69,13 @@ where fn extract_function_from_call(params: Params) -> Option { let (_, call) = next_rpc_param::(params.sequence()).ok()?; - let data = call.data; - extract_function_signature(data.get(..4)?.try_into().ok()?) + call.extract_function() } fn extract_function_from_transaction(params: Params) -> Option { let (_, data) = next_rpc_param::(params.sequence()).ok()?; let transaction = parse_rpc_rlp::(&data).ok()?; - if transaction.is_contract_deployment() { - return Some("contract_deployment"); - } - extract_function_signature(transaction.input.get(..4)?.try_into().ok()?) -} - -fn extract_function_signature(id: Signature4Bytes) -> Option { - match codegen::SIGNATURES_4_BYTES.get(&id) { - Some(signature) => Some(signature), - None => Some("unknown"), - } + transaction.extract_function() } // ----------------------------------------------------------------------------- @@ -123,7 +110,7 @@ impl> Future for RpcResponse { tracing::info!( id = %proj.id, method = %proj.method, - function = %proj.function.unwrap_or_default(), + function = %proj.function.clone().unwrap_or_default(), duration_ms = %elapsed.as_millis(), success = %response.is_success(), result = %response.as_result(), @@ -132,7 +119,7 @@ impl> Future for RpcResponse { // metrify response #[cfg(feature = "metrics")] - metrics::inc_rpc_requests_finished(elapsed, proj.method.clone(), *proj.function, response.is_success()); + metrics::inc_rpc_requests_finished(elapsed, proj.method.clone(), proj.function.clone(), response.is_success()); } response diff --git a/src/infra/metrics.rs b/src/infra/metrics.rs index 2d5977e0a..bc3829d1d 100644 --- a/src/infra/metrics.rs +++ b/src/infra/metrics.rs @@ -1,6 +1,7 @@ //! Metrics services. #![cfg(feature = "metrics")] +use std::borrow::Cow; use std::stringify; use std::time::Instant; @@ -174,7 +175,10 @@ metrics! { histogram_duration executor_external_block{} [], "Time to execute and persist temporary changes of a single transaction inside import_offline operation." - histogram_duration executor_external_transaction{} [], + histogram_duration executor_external_transaction{function} [], + + "Gas spent to execute a single transaction inside import_offline operation." + histogram_counter executor_external_transaction_gas{function} [], "Number of account reads when importing an external block." histogram_counter executor_external_block_account_reads{} [0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 20., 30., 40., 50., 60., 70., 80., 90., 100., 150., 200.], @@ -186,10 +190,16 @@ metrics! { histogram_counter executor_external_block_slot_reads_cached{} [0., 10., 20., 30., 40., 50., 60., 70., 80., 90., 100., 200., 300., 400., 500., 600., 700., 800., 900., 1000., 2000., 3000., 4000., 5000., 6000., 7000., 8000., 9000., 10000.], "Time to execute a transaction received with eth_sendRawTransaction." - histogram_duration executor_transact{success} [], + histogram_duration executor_transact{success, function} [], + + "Gas spent execute a transaction received with eth_sendRawTransaction." + histogram_counter executor_transact_gas{success, function} [], "Time to execute a transaction received with eth_call or eth_estimateGas." - histogram_duration executor_call{success} [] + histogram_duration executor_call{success, function} [], + + "Gas spent to execute a transaction received with eth_call or eth_estimateGas." + histogram_counter executor_call_gas{function} [] } metrics! { @@ -255,6 +265,15 @@ pub enum LabelValue { None, } +impl From>> for LabelValue { + fn from(value: Option>) -> Self { + match value { + Some(str) => Self::Some(str.into_owned()), + None => Self::None, + } + } +} + impl From<&str> for LabelValue { fn from(value: &str) -> Self { Self::Some(value.to_owned()) From e2399cdfac1a84dc808f87a83a0cf780b3d32575 Mon Sep 17 00:00:00 2001 From: Daniel Freire Date: Tue, 14 May 2024 12:51:43 -0300 Subject: [PATCH 2/5] signature enum --- src/eth/evm/evm.rs | 6 ++--- src/eth/executor.rs | 8 +++---- src/eth/primitives/alias.rs | 20 ---------------- src/eth/primitives/bytes.rs | 11 --------- src/eth/primitives/call_input.rs | 6 ++--- src/eth/primitives/mod.rs | 7 +++--- src/eth/primitives/signature.rs | 32 +++++++++++++++++++++++++ src/eth/primitives/transaction_input.rs | 8 +++---- 8 files changed, 49 insertions(+), 49 deletions(-) delete mode 100644 src/eth/primitives/alias.rs create mode 100644 src/eth/primitives/signature.rs diff --git a/src/eth/evm/evm.rs b/src/eth/evm/evm.rs index 5c4ba4c06..708a92fdc 100644 --- a/src/eth/evm/evm.rs +++ b/src/eth/evm/evm.rs @@ -11,7 +11,6 @@ use std::borrow::Cow; use display_json::DebugAsJson; use itertools::Itertools; -use crate::eth::primitives::bytes::extract_function_signature; use crate::eth::primitives::Address; use crate::eth::primitives::BlockNumber; use crate::eth::primitives::Bytes; @@ -24,6 +23,7 @@ use crate::eth::primitives::ExternalReceipt; use crate::eth::primitives::ExternalTransaction; use crate::eth::primitives::Gas; use crate::eth::primitives::Nonce; +use crate::eth::primitives::Signature; use crate::eth::primitives::SoliditySignature; use crate::eth::primitives::StoragePointInTime; use crate::eth::primitives::TransactionInput; @@ -139,9 +139,9 @@ impl EvmInput { if self.is_contract_deployment() { return Some(Cow::from("contract_deployment")); } - let id: [u8; 4] = self.data.get(..4)?.try_into().ok()?; + let sig = Signature::Function(self.data.get(..4)?.try_into().ok()?); - Some(extract_function_signature(id)) + Some(sig.extract()) } /// Creates from a transaction that was sent directly to Stratus with `eth_sendRawTransaction`. diff --git a/src/eth/executor.rs b/src/eth/executor.rs index 1f90edabb..eaccf5555 100644 --- a/src/eth/executor.rs +++ b/src/eth/executor.rs @@ -203,10 +203,10 @@ impl Executor { }; #[cfg(feature = "metrics")] - let gas_used = evm_result.execution.gas; - - #[cfg(feature = "metrics")] - metrics::inc_executor_external_transaction_gas(gas_used.as_u64() as usize, function.clone()); + { + let gas_used = evm_result.execution.gas; + metrics::inc_executor_external_transaction_gas(gas_used.as_u64() as usize, function.clone()); + } evm_result.execution.gas = match receipt.gas_used.unwrap_or_default().try_into() { Ok(gas) => gas, diff --git a/src/eth/primitives/alias.rs b/src/eth/primitives/alias.rs deleted file mode 100644 index d205f364e..000000000 --- a/src/eth/primitives/alias.rs +++ /dev/null @@ -1,20 +0,0 @@ -//! Alias Module -//! -//! This module defines convenient aliases for various Ethereum-specific -//! signatures and identifiers. It includes types like `Signature4Bytes` for -//! identifying function and error signatures, `Signature32Bytes` for event -//! signatures, and `SoliditySignature` for general Solidity function, error, -//! or event signatures. These aliases simplify code readability and -//! maintenance by providing clear, descriptive types in Ethereum-related -//! operations. - -use std::borrow::Cow; - -/// Alias for 4 byte signature used to identify functions and errors. -pub type Signature4Bytes = [u8; 4]; - -/// Alias for 32 byte signature used to identify events. -pub type Signature32Bytes = [u8; 32]; - -/// Alias for a Solidity function, error or event signature. -pub type SoliditySignature = Cow<'static, str>; diff --git a/src/eth/primitives/bytes.rs b/src/eth/primitives/bytes.rs index 1bce5ee7e..b85d1e678 100644 --- a/src/eth/primitives/bytes.rs +++ b/src/eth/primitives/bytes.rs @@ -7,7 +7,6 @@ //! various byte formats and Ethereum-specific types, playing a key role in //! data serialization and processing. -use std::borrow::Cow; use std::fmt::Debug; use std::fmt::Display; use std::ops::Deref; @@ -18,9 +17,6 @@ use revm::primitives::Bytecode as RevmBytecode; use revm::primitives::Bytes as RevmBytes; use revm::primitives::Output as RevmOutput; -use crate::eth::codegen; -use crate::eth::primitives::Signature4Bytes; -use crate::eth::primitives::SoliditySignature; use crate::gen_newtype_from; #[derive(Clone, Default, Eq, PartialEq, fake::Dummy, sqlx::Type)] @@ -143,10 +139,3 @@ impl From for RevmBytecode { to_analysed(RevmBytecode::new_raw(value.0.into())) } } - -pub fn extract_function_signature(id: Signature4Bytes) -> SoliditySignature { - match codegen::SIGNATURES_4_BYTES.get(&id) { - Some(signature) => Cow::from(*signature), - None => Cow::from(const_hex::encode_prefixed(id)), - } -} diff --git a/src/eth/primitives/call_input.rs b/src/eth/primitives/call_input.rs index 6252aa2ba..d11c0decb 100644 --- a/src/eth/primitives/call_input.rs +++ b/src/eth/primitives/call_input.rs @@ -6,7 +6,7 @@ //! the transaction data payload (`data`). It is crucial in constructing and //! interpreting transaction calls, especially for smart contract interactions. -use crate::eth::primitives::bytes::extract_function_signature; +use super::Signature; use crate::eth::primitives::Address; use crate::eth::primitives::Bytes; use crate::eth::primitives::SoliditySignature; @@ -26,7 +26,7 @@ pub struct CallInput { impl CallInput { pub fn extract_function(&self) -> Option { - let id: [u8; 4] = self.data.get(..4)?.try_into().ok()?; - Some(extract_function_signature(id)) + let sig = Signature::Function(self.data.get(..4)?.try_into().ok()?); + Some(sig.extract()) } } diff --git a/src/eth/primitives/mod.rs b/src/eth/primitives/mod.rs index 87d94e540..20c95ae91 100644 --- a/src/eth/primitives/mod.rs +++ b/src/eth/primitives/mod.rs @@ -76,7 +76,6 @@ mod account; mod address; -mod alias; mod block; mod block_header; mod block_number; @@ -111,6 +110,7 @@ pub mod logs_bloom; mod miner_nonce; mod nonce; mod pending_block; +mod signature; mod size; mod slot; mod slot_access; @@ -128,9 +128,6 @@ mod wei; pub use account::test_accounts; pub use account::Account; pub use address::Address; -pub use alias::Signature32Bytes; -pub use alias::Signature4Bytes; -pub use alias::SoliditySignature; pub use block::Block; pub use block_header::BlockHeader; pub use block_number::BlockNumber; @@ -168,6 +165,8 @@ pub use log_topic::LogTopic; pub use miner_nonce::MinerNonce; pub use nonce::Nonce; pub use pending_block::PendingBlock; +pub use signature::Signature; +pub use signature::SoliditySignature; pub use size::Size; pub use slot::Slot; pub use slot_access::SlotAccess; diff --git a/src/eth/primitives/signature.rs b/src/eth/primitives/signature.rs new file mode 100644 index 000000000..64eb21545 --- /dev/null +++ b/src/eth/primitives/signature.rs @@ -0,0 +1,32 @@ +use std::borrow::Cow; + +use crate::eth::codegen; + +/// Alias for 4 byte signature used to identify functions and errors. +pub type Signature4Bytes = [u8; 4]; + +/// Alias for 32 byte signature used to identify events. +pub type Signature32Bytes = [u8; 32]; + +/// Alias for a Solidity function, error or event signature. +pub type SoliditySignature = Cow<'static, str>; + +pub enum Signature { + Function(Signature4Bytes), + Event(Signature32Bytes), +} + +impl Signature { + pub fn extract(self) -> SoliditySignature { + match self { + Signature::Function(id) => match codegen::SIGNATURES_4_BYTES.get(&id) { + Some(signature) => Cow::from(*signature), + None => Cow::from(const_hex::encode_prefixed(id)), + }, + Signature::Event(id) => match codegen::SIGNATURES_32_BYTES.get(&id) { + Some(signature) => Cow::from(*signature), + None => Cow::from(const_hex::encode_prefixed(id)), + }, + } + } +} diff --git a/src/eth/primitives/transaction_input.rs b/src/eth/primitives/transaction_input.rs index 94df6398b..8388bbf66 100644 --- a/src/eth/primitives/transaction_input.rs +++ b/src/eth/primitives/transaction_input.rs @@ -18,7 +18,8 @@ use fake::Fake; use fake::Faker; use rlp::Decodable; -use crate::eth::primitives::bytes::extract_function_signature; +use super::signature::SoliditySignature; +use super::Signature; use crate::eth::primitives::Address; use crate::eth::primitives::Bytes; use crate::eth::primitives::ChainId; @@ -26,7 +27,6 @@ use crate::eth::primitives::ExternalTransaction; use crate::eth::primitives::Gas; use crate::eth::primitives::Hash; use crate::eth::primitives::Nonce; -use crate::eth::primitives::SoliditySignature; use crate::eth::primitives::Wei; use crate::ext::not; use crate::ext::OptionExt; @@ -63,9 +63,9 @@ impl TransactionInput { if self.is_contract_deployment() { return Some(Cow::from("contract_deployment")); } - let id: [u8; 4] = self.input.get(..4)?.try_into().ok()?; + let sig = Signature::Function(self.input.get(..4)?.try_into().ok()?); - Some(extract_function_signature(id)) + Some(sig.extract()) } } From 49ddc81740ba4a676cd903dcb26e7f2d0c02ab80 Mon Sep 17 00:00:00 2001 From: Daniel Freire Date: Tue, 14 May 2024 12:58:07 -0300 Subject: [PATCH 3/5] reafac --- src/eth/primitives/signature.rs | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/eth/primitives/signature.rs b/src/eth/primitives/signature.rs index 64eb21545..6a4a13172 100644 --- a/src/eth/primitives/signature.rs +++ b/src/eth/primitives/signature.rs @@ -17,16 +17,22 @@ pub enum Signature { } impl Signature { - pub fn extract(self) -> SoliditySignature { + pub fn encoded(self) -> String { match self { - Signature::Function(id) => match codegen::SIGNATURES_4_BYTES.get(&id) { - Some(signature) => Cow::from(*signature), - None => Cow::from(const_hex::encode_prefixed(id)), - }, - Signature::Event(id) => match codegen::SIGNATURES_32_BYTES.get(&id) { - Some(signature) => Cow::from(*signature), - None => Cow::from(const_hex::encode_prefixed(id)), - }, + Signature::Function(id) => const_hex::encode_prefixed(id), + Signature::Event(id) => const_hex::encode_prefixed(id), + } + } + + pub fn extract(self) -> SoliditySignature { + let sig = match self { + Signature::Function(id) => codegen::SIGNATURES_4_BYTES.get(&id), + Signature::Event(id) => codegen::SIGNATURES_32_BYTES.get(&id), + }; + + match sig { + Some(signature) => Cow::from(*signature), + None => Cow::from(self.encoded()), } } } From 29d354029aa4cc82035c1e7cfd2342f3fc3a42a0 Mon Sep 17 00:00:00 2001 From: Daniel Freire Date: Tue, 14 May 2024 13:06:56 -0300 Subject: [PATCH 4/5] cargo check each feature --- src/eth/storage/stratus_storage.rs | 1 + tests/test_import_external_snapshot_common.rs | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/eth/storage/stratus_storage.rs b/src/eth/storage/stratus_storage.rs index 4d3b55e7a..67b9476ed 100644 --- a/src/eth/storage/stratus_storage.rs +++ b/src/eth/storage/stratus_storage.rs @@ -362,6 +362,7 @@ impl StratusStorage { let start = metrics::now(); let result_result = self.temp.reset().await; + #[cfg(feature = "metrics")] let result_set = self.set_active_block_number_as_next().await; #[cfg(feature = "metrics")] diff --git a/tests/test_import_external_snapshot_common.rs b/tests/test_import_external_snapshot_common.rs index 79f4943b7..4ae11fc7f 100644 --- a/tests/test_import_external_snapshot_common.rs +++ b/tests/test_import_external_snapshot_common.rs @@ -4,6 +4,7 @@ use std::fs; use std::sync::Arc; use std::time::Duration; +#[cfg(feature = "dev")] use fancy_duration::AsFancyDuration; use itertools::Itertools; use stratus::config::IntegrationTestConfig; @@ -188,7 +189,10 @@ pub async fn execute_test( println!("{:<70} = {}", query, value); } else { let secs = Duration::from_secs_f64(value); + #[cfg(feature = "dev")] println!("{:<70} = {}", query, secs.fancy_duration().truncate(2)); + #[cfg(not(feature = "dev"))] + println!("{:<70} = {}", query, secs.as_millis()); } } } From 9e38a4aa5a536556cb98c0829487734faa2270ac Mon Sep 17 00:00:00 2001 From: Daniel Freire Date: Tue, 14 May 2024 13:39:38 -0300 Subject: [PATCH 5/5] remove rocks from default feature --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 12408986a..07396f5ea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -142,7 +142,7 @@ path = "src/bin/run_with_importer.rs" # ------------------------------------------------------------------------------ [features] -default = ["metrics", "rocks"] +default = ["metrics"] # Application is running in develoment mode. dev = []