Skip to content

Commit

Permalink
enha: simplify extraction of contract name and function signature (#1544
Browse files Browse the repository at this point in the history
)
  • Loading branch information
dinhani-cw authored Jul 25, 2024
1 parent db9fd53 commit 336b8af
Show file tree
Hide file tree
Showing 10 changed files with 74 additions and 143 deletions.
12 changes: 5 additions & 7 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,7 @@ fn generate_signature_module_content() -> String {
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 prefix = signature_file.filename.file_name().unwrap().to_str().unwrap().split('.').next().unwrap();
populate_signature_maps(&signature_file.content, &mut seen, &mut signatures_4_bytes, &mut signatures_32_bytes, prefix);
populate_signature_maps(&signature_file.content, &mut seen, &mut signatures_4_bytes, &mut signatures_32_bytes);
}

format!(
Expand All @@ -152,7 +151,6 @@ fn populate_signature_maps(
seen: &mut HashSet<Vec<u8>>,
signatures_4_bytes: &mut phf_codegen::Map<[u8; 4]>,
signatures_32_bytes: &mut phf_codegen::Map<[u8; 32]>,
prefix: &str,
) {
for line in file_content.lines() {
if let Ok((_, (id, signature))) = parse_signature(line) {
Expand All @@ -161,7 +159,7 @@ fn populate_signature_maps(
}
seen.insert(id.clone());

let signature = format!("\"{}::{}\"", prefix, signature);
let signature = format!("\"{}\"", signature);
match id.len() {
4 => {
signatures_4_bytes.entry(id.try_into().unwrap(), &signature);
Expand All @@ -188,7 +186,7 @@ fn parse_signature(input: &str) -> IResult<&str, (SolidityId, &SoliditySignature
// -----------------------------------------------------------------------------

struct InputFile {
filename: PathBuf,
_filename: PathBuf,
content: String,
}

Expand All @@ -202,15 +200,15 @@ fn list_files(pattern: &'static str) -> Vec<InputFile> {

// ensure at least one exists
if filenames.is_empty() {
panic!("No signature files found in \"{}\"", pattern);
panic!("No files found in \"{}\"", pattern);
}

// read file contents
let mut files = Vec::with_capacity(filenames.len());
for filename in filenames {
files.push(InputFile {
content: fs::read_to_string(&filename).expect("Reading file should not fail"),
filename,
_filename: filename,
});
}

Expand Down
19 changes: 16 additions & 3 deletions src/eth/codegen.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,29 @@
//! Auto-generated code.
use crate::eth::primitives::Address;
use crate::infra::metrics;

include!(concat!(env!("OUT_DIR"), "/contracts.rs"));
include!(concat!(env!("OUT_DIR"), "/signatures.rs"));

pub type SoliditySignature = &'static str;

pub type ContractName = &'static str;

/// Returns the contract name for a given address.
pub fn get_contract_name(address: &Address) -> ContractName {
/// Returns the contract name to be used in observability tasks.
pub fn contract_name_for_o11y(address: &Option<Address>) -> ContractName {
let Some(address) = address else { return metrics::LABEL_MISSING };
match CONTRACTS.get(address.as_bytes()) {
Some(contract_name) => contract_name,
None => "unknown",
None => metrics::LABEL_UNKNOWN,
}
}

/// Returns the function name to be used in observability tasks.
pub fn function_sig_for_o11y(bytes: impl AsRef<[u8]>) -> SoliditySignature {
let Some(id) = bytes.as_ref().get(..4) else { return metrics::LABEL_MISSING };
match SIGNATURES_4_BYTES.get(id) {
Some(signature) => signature,
None => metrics::LABEL_UNKNOWN,
}
}
29 changes: 16 additions & 13 deletions src/eth/executor/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use anyhow::anyhow;
use tracing::info_span;
use tracing::Span;

use crate::eth::codegen;
use crate::eth::executor::Evm;
use crate::eth::executor::EvmExecutionResult;
use crate::eth::executor::EvmInput;
Expand Down Expand Up @@ -333,16 +334,17 @@ impl Executor {
self.miner.save_execution(tx_execution.clone())?;

// track metrics

#[cfg(feature = "metrics")]
{
let evm_execution = tx_execution.execution();
let evm_metrics = tx_execution.metrics();
*block_metrics += *evm_metrics;

let function = tx.solidity_signature();
metrics::inc_executor_external_transaction(start.elapsed(), function.clone());
metrics::inc_executor_external_transaction_account_reads(evm_metrics.account_reads, function.clone());
metrics::inc_executor_external_transaction_slot_reads(evm_metrics.slot_reads, function.clone());
let function = codegen::function_sig_for_o11y(&tx.0.input);
metrics::inc_executor_external_transaction(start.elapsed(), function);
metrics::inc_executor_external_transaction_account_reads(evm_metrics.account_reads, function);
metrics::inc_executor_external_transaction_slot_reads(evm_metrics.slot_reads, function);
metrics::inc_executor_external_transaction_gas(evm_execution.gas.as_u64() as usize, function);
}

Expand Down Expand Up @@ -422,12 +424,12 @@ impl Executor {
// track metrics
#[cfg(feature = "metrics")]
{
let function = tx_input.solidity_signature();
let function = codegen::function_sig_for_o11y(&tx_input.input);
match &tx_execution {
Ok(tx_execution) => {
metrics::inc_executor_local_transaction(start.elapsed(), true, function.clone());
metrics::inc_executor_local_transaction_account_reads(tx_execution.metrics().account_reads, function.clone());
metrics::inc_executor_local_transaction_slot_reads(tx_execution.metrics().slot_reads, function.clone());
metrics::inc_executor_local_transaction(start.elapsed(), true, function);
metrics::inc_executor_local_transaction_account_reads(tx_execution.metrics().account_reads, function);
metrics::inc_executor_local_transaction_slot_reads(tx_execution.metrics().slot_reads, function);
metrics::inc_executor_local_transaction_gas(tx_execution.execution().gas.as_u64() as usize, true, function);
}
Err(_) => {
Expand Down Expand Up @@ -548,18 +550,19 @@ impl Executor {
};
let evm_result = self.evms.execute(evm_input, evm_route);

// track metrics
#[cfg(feature = "metrics")]
{
let function = call_input.solidity_signature();
let function = codegen::function_sig_for_o11y(&call_input.data);
match &evm_result {
Ok(evm_result) => {
metrics::inc_executor_local_call(start.elapsed(), true, function.clone());
metrics::inc_executor_local_call_account_reads(evm_result.metrics.account_reads, function.clone());
metrics::inc_executor_local_call_slot_reads(evm_result.metrics.slot_reads, function.clone());
metrics::inc_executor_local_call(start.elapsed(), true, function);
metrics::inc_executor_local_call_account_reads(evm_result.metrics.account_reads, function);
metrics::inc_executor_local_call_slot_reads(evm_result.metrics.slot_reads, function);
metrics::inc_executor_local_call_gas(evm_result.execution.gas.as_u64() as usize, function);
}
Err(_) => {
metrics::inc_executor_local_call(start.elapsed(), false, function.clone());
metrics::inc_executor_local_call(start.elapsed(), false, function);
}
}
}
Expand Down
12 changes: 0 additions & 12 deletions src/eth/primitives/call_input.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use super::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)]
Expand All @@ -15,13 +13,3 @@ pub struct CallInput {
#[serde(alias = "input", default)]
pub data: Bytes,
}

impl CallInput {
/// Parses the Solidity function being called.
///
/// TODO: unify and remove duplicate implementations.
pub fn solidity_signature(&self) -> Option<SoliditySignature> {
let sig = Signature::Function(self.data.get(..4)?.try_into().ok()?);
Some(sig.extract())
}
}
21 changes: 0 additions & 21 deletions src/eth/primitives/external_transaction.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
use std::borrow::Cow;

use crate::alias::EthersTransaction;
use crate::eth::primitives::BlockNumber;
use crate::eth::primitives::Hash;
use crate::eth::primitives::Signature;
use crate::eth::primitives::SoliditySignature;
use crate::ext::not;

#[derive(Debug, Clone, Default, derive_more:: Deref, serde::Deserialize, serde::Serialize)]
#[serde(transparent)]
Expand All @@ -21,22 +16,6 @@ impl ExternalTransaction {
pub fn hash(&self) -> Hash {
self.0.hash.into()
}

/// Checks if the current transaction is a contract deployment.
pub fn is_contract_deployment(&self) -> bool {
self.to.is_none() && not(self.input.is_empty())
}

/// Parses the Solidity function being called.
///
/// TODO: unify and remove duplicate implementations.
pub fn solidity_signature(&self) -> Option<SoliditySignature> {
if self.is_contract_deployment() {
return Some(Cow::from("contract_deployment"));
}
let sig = Signature::Function(self.input.get(..4)?.try_into().ok()?);
Some(sig.extract())
}
}

// -----------------------------------------------------------------------------
Expand Down
3 changes: 0 additions & 3 deletions src/eth/primitives/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ mod miner_nonce;
mod nonce;
mod now;
mod pending_block;
mod signature;
mod size;
mod slot;
mod slot_index;
Expand Down Expand Up @@ -87,8 +86,6 @@ pub use miner_nonce::MinerNonce;
pub use nonce::Nonce;
pub use now::DateTimeNow;
pub use pending_block::PendingBlock;
pub use signature::Signature;
pub use signature::SoliditySignature;
pub use size::Size;
pub use slot::Slot;
pub use slot_index::SlotIndex;
Expand Down
38 changes: 0 additions & 38 deletions src/eth/primitives/signature.rs

This file was deleted.

23 changes: 0 additions & 23 deletions src/eth/primitives/transaction_input.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::borrow::Cow;

use anyhow::anyhow;
use display_json::DebugAsJson;
use ethereum_types::U256;
Expand All @@ -20,10 +18,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::Signature;
use crate::eth::primitives::SoliditySignature;
use crate::eth::primitives::Wei;
use crate::ext::not;
use crate::ext::JsonValue;
use crate::ext::OptionExt;
use crate::log_and_err;
Expand Down Expand Up @@ -53,24 +48,6 @@ pub struct TransactionInput {
pub s: U256,
}

impl TransactionInput {
/// Checks if the current transaction is a contract deployment.
pub fn is_contract_deployment(&self) -> bool {
self.to.is_none() && not(self.input.is_empty())
}

/// Parses the Solidity function being called.
///
/// TODO: unify and remove duplicate implementations.
pub fn solidity_signature(&self) -> Option<SoliditySignature> {
if self.is_contract_deployment() {
return Some(Cow::from("contract_deployment"));
}
let sig = Signature::Function(self.input.get(..4)?.try_into().ok()?);
Some(sig.extract())
}
}

impl Dummy<Faker> for TransactionInput {
fn dummy_with_rng<R: ethers_core::rand::prelude::Rng + ?Sized>(faker: &Faker, rng: &mut R) -> Self {
Self {
Expand Down
Loading

0 comments on commit 336b8af

Please sign in to comment.