mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 19:09:54 +00:00
perf: improve debug_traceBlock performance (#11979)
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
committed by
GitHub
parent
cecdf611e9
commit
ac329bfce1
@ -112,6 +112,7 @@ where
|
||||
let mut results = Vec::with_capacity(transactions.len());
|
||||
let mut db = CacheDB::new(StateProviderDatabase::new(state));
|
||||
let mut transactions = transactions.into_iter().enumerate().peekable();
|
||||
let mut inspector = None;
|
||||
while let Some((index, tx)) = transactions.next() {
|
||||
let tx_hash = tx.hash;
|
||||
|
||||
@ -124,7 +125,7 @@ where
|
||||
handler_cfg: cfg.handler_cfg,
|
||||
};
|
||||
let (result, state_changes) = this.trace_transaction(
|
||||
opts.clone(),
|
||||
&opts,
|
||||
env,
|
||||
&mut db,
|
||||
Some(TransactionContext {
|
||||
@ -132,8 +133,11 @@ where
|
||||
tx_hash: Some(tx_hash),
|
||||
tx_index: Some(index),
|
||||
}),
|
||||
&mut inspector,
|
||||
)?;
|
||||
|
||||
inspector = inspector.map(|insp| insp.fused());
|
||||
|
||||
results.push(TraceResult::Success { result, tx_hash: Some(tx_hash) });
|
||||
if transactions.peek().is_some() {
|
||||
// need to apply the state changes of this transaction before executing the
|
||||
@ -295,7 +299,7 @@ where
|
||||
};
|
||||
|
||||
this.trace_transaction(
|
||||
opts,
|
||||
&opts,
|
||||
env,
|
||||
&mut db,
|
||||
Some(TransactionContext {
|
||||
@ -303,6 +307,7 @@ where
|
||||
tx_index: Some(index),
|
||||
tx_hash: Some(tx.hash),
|
||||
}),
|
||||
&mut None,
|
||||
)
|
||||
.map(|(trace, _)| trace)
|
||||
})
|
||||
@ -573,6 +578,7 @@ where
|
||||
let Bundle { transactions, block_override } = bundle;
|
||||
|
||||
let block_overrides = block_override.map(Box::new);
|
||||
let mut inspector = None;
|
||||
|
||||
let mut transactions = transactions.into_iter().peekable();
|
||||
while let Some(tx) = transactions.next() {
|
||||
@ -588,8 +594,15 @@ where
|
||||
overrides,
|
||||
)?;
|
||||
|
||||
let (trace, state) =
|
||||
this.trace_transaction(tracing_options.clone(), env, &mut db, None)?;
|
||||
let (trace, state) = this.trace_transaction(
|
||||
&tracing_options,
|
||||
env,
|
||||
&mut db,
|
||||
None,
|
||||
&mut inspector,
|
||||
)?;
|
||||
|
||||
inspector = inspector.map(|insp| insp.fused());
|
||||
|
||||
// If there is more transactions, commit the database
|
||||
// If there is no transactions, but more bundles, commit to the database too
|
||||
@ -692,6 +705,13 @@ where
|
||||
|
||||
/// Executes the configured transaction with the environment on the given database.
|
||||
///
|
||||
/// It optionally takes fused inspector ([`TracingInspector::fused`]) to avoid re-creating the
|
||||
/// inspector for each transaction. This is useful when tracing multiple transactions in a
|
||||
/// block. This is only useful for block tracing which uses the same tracer for all transactions
|
||||
/// in the block.
|
||||
///
|
||||
/// Caution: If the inspector is provided then `opts.tracer_config` is ignored.
|
||||
///
|
||||
/// Returns the trace frame and the state that got updated after executing the transaction.
|
||||
///
|
||||
/// Note: this does not apply any state overrides if they're configured in the `opts`.
|
||||
@ -699,10 +719,11 @@ where
|
||||
/// Caution: this is blocking and should be performed on a blocking task.
|
||||
fn trace_transaction(
|
||||
&self,
|
||||
opts: GethDebugTracingOptions,
|
||||
opts: &GethDebugTracingOptions,
|
||||
env: EnvWithHandlerCfg,
|
||||
db: &mut StateCacheDb<'_>,
|
||||
transaction_context: Option<TransactionContext>,
|
||||
fused_inspector: &mut Option<TracingInspector>,
|
||||
) -> Result<(GethTrace, revm_primitives::EvmState), Eth::Error> {
|
||||
let GethDebugTracingOptions { config, tracer, tracer_config, .. } = opts;
|
||||
|
||||
@ -716,35 +737,42 @@ where
|
||||
}
|
||||
GethDebugBuiltInTracerType::CallTracer => {
|
||||
let call_config = tracer_config
|
||||
.clone()
|
||||
.into_call_config()
|
||||
.map_err(|_| EthApiError::InvalidTracerConfig)?;
|
||||
|
||||
let mut inspector = TracingInspector::new(
|
||||
TracingInspectorConfig::from_geth_call_config(&call_config),
|
||||
);
|
||||
let mut inspector = fused_inspector.get_or_insert_with(|| {
|
||||
TracingInspector::new(TracingInspectorConfig::from_geth_call_config(
|
||||
&call_config,
|
||||
))
|
||||
});
|
||||
|
||||
let (res, env) = self.eth_api().inspect(db, env, &mut inspector)?;
|
||||
|
||||
inspector.set_transaction_gas_limit(env.tx.gas_limit);
|
||||
|
||||
let frame = inspector
|
||||
.with_transaction_gas_limit(env.tx.gas_limit)
|
||||
.into_geth_builder()
|
||||
.geth_builder()
|
||||
.geth_call_traces(call_config, res.result.gas_used());
|
||||
|
||||
return Ok((frame.into(), res.state))
|
||||
}
|
||||
GethDebugBuiltInTracerType::PreStateTracer => {
|
||||
let prestate_config = tracer_config
|
||||
.clone()
|
||||
.into_pre_state_config()
|
||||
.map_err(|_| EthApiError::InvalidTracerConfig)?;
|
||||
|
||||
let mut inspector = TracingInspector::new(
|
||||
TracingInspectorConfig::from_geth_prestate_config(&prestate_config),
|
||||
);
|
||||
let mut inspector = fused_inspector.get_or_insert_with(|| {
|
||||
TracingInspector::new(
|
||||
TracingInspectorConfig::from_geth_prestate_config(&prestate_config),
|
||||
)
|
||||
});
|
||||
let (res, env) = self.eth_api().inspect(&mut *db, env, &mut inspector)?;
|
||||
|
||||
inspector.set_transaction_gas_limit(env.tx.gas_limit);
|
||||
let frame = inspector
|
||||
.with_transaction_gas_limit(env.tx.gas_limit)
|
||||
.into_geth_builder()
|
||||
.geth_builder()
|
||||
.geth_prestate_traces(&res, &prestate_config, db)
|
||||
.map_err(Eth::Error::from_eth_err)?;
|
||||
|
||||
@ -755,6 +783,7 @@ where
|
||||
}
|
||||
GethDebugBuiltInTracerType::MuxTracer => {
|
||||
let mux_config = tracer_config
|
||||
.clone()
|
||||
.into_mux_config()
|
||||
.map_err(|_| EthApiError::InvalidTracerConfig)?;
|
||||
|
||||
@ -769,6 +798,7 @@ where
|
||||
}
|
||||
GethDebugBuiltInTracerType::FlatCallTracer => {
|
||||
let flat_call_config = tracer_config
|
||||
.clone()
|
||||
.into_flat_call_config()
|
||||
.map_err(|_| EthApiError::InvalidTracerConfig)?;
|
||||
|
||||
@ -799,10 +829,10 @@ where
|
||||
}
|
||||
#[cfg(feature = "js-tracer")]
|
||||
GethDebugTracerType::JsTracer(code) => {
|
||||
let config = tracer_config.into_json();
|
||||
let config = tracer_config.clone().into_json();
|
||||
let mut inspector =
|
||||
revm_inspectors::tracing::js::JsInspector::with_transaction_context(
|
||||
code,
|
||||
code.clone(),
|
||||
config,
|
||||
transaction_context.unwrap_or_default(),
|
||||
)
|
||||
@ -818,17 +848,15 @@ where
|
||||
}
|
||||
|
||||
// default structlog tracer
|
||||
let inspector_config = TracingInspectorConfig::from_geth_config(&config);
|
||||
|
||||
let mut inspector = TracingInspector::new(inspector_config);
|
||||
|
||||
let mut inspector = fused_inspector.get_or_insert_with(|| {
|
||||
let inspector_config = TracingInspectorConfig::from_geth_config(config);
|
||||
TracingInspector::new(inspector_config)
|
||||
});
|
||||
let (res, env) = self.eth_api().inspect(db, env, &mut inspector)?;
|
||||
let gas_used = res.result.gas_used();
|
||||
let return_value = res.result.into_output().unwrap_or_default();
|
||||
let frame = inspector
|
||||
.with_transaction_gas_limit(env.tx.gas_limit)
|
||||
.into_geth_builder()
|
||||
.geth_traces(gas_used, return_value, config);
|
||||
inspector.set_transaction_gas_limit(env.tx.gas_limit);
|
||||
let frame = inspector.geth_builder().geth_traces(gas_used, return_value, *config);
|
||||
|
||||
Ok((frame.into(), res.state))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user