fix: exclude calls to precompiles in parity tracers (#2987)

This commit is contained in:
Matthias Seitz
2023-06-06 20:20:49 +02:00
committed by GitHub
parent 1a4f407c4a
commit 8f4e37e8ff
6 changed files with 57 additions and 9 deletions

14
Cargo.lock generated
View File

@ -5538,8 +5538,7 @@ dependencies = [
[[package]]
name = "revm"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f293f351c4c203d321744e54ed7eed3d2b6eef4c140228910dde3ac9a5ea8031"
source = "git+https://github.com/bluealloy/revm/?branch=release/v25#88337924f4d16ed1f5e4cde12a03d0cb755cd658"
dependencies = [
"auto_impl",
"revm-interpreter",
@ -5549,8 +5548,7 @@ dependencies = [
[[package]]
name = "revm-interpreter"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a53980a26f9b5a66d13511c35074d4b53631e157850a1d7cf1af4efc2c2b72c9"
source = "git+https://github.com/bluealloy/revm/?branch=release/v25#88337924f4d16ed1f5e4cde12a03d0cb755cd658"
dependencies = [
"derive_more",
"enumn",
@ -5560,9 +5558,8 @@ dependencies = [
[[package]]
name = "revm-precompile"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10a3eabf08ea9e4063f5531b8735e29344d9d6eaebaa314c58253f6c17fcdf2d"
version = "2.0.3"
source = "git+https://github.com/bluealloy/revm/?branch=release/v25#88337924f4d16ed1f5e4cde12a03d0cb755cd658"
dependencies = [
"k256 0.13.1",
"num",
@ -5578,8 +5575,7 @@ dependencies = [
[[package]]
name = "revm-primitives"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "304d998f466ffef72d76c7f20b05bf08a96801736a6fb1fdef47d49a292618df"
source = "git+https://github.com/bluealloy/revm/?branch=release/v25#88337924f4d16ed1f5e4cde12a03d0cb755cd658"
dependencies = [
"arbitrary",
"auto_impl",

View File

@ -73,6 +73,9 @@ incremental = false
# patched for quantity U256 responses <https://github.com/recmo/uint/issues/224>
ruint = { git = "https://github.com/paradigmxyz/uint" }
revm = { git = "https://github.com/bluealloy/revm/", branch = "release/v25" }
revm-primitives = { git = "https://github.com/bluealloy/revm/", branch = "release/v25" }
[workspace.dependencies]
## eth
revm = { version = "3" }

View File

@ -124,6 +124,11 @@ impl ParityTraceBuilder {
let mut diff = StateDiff::default();
for (node, trace_address) in self.nodes.iter().zip(trace_addresses) {
// skip precompiles
if node.is_precompile() {
continue
}
if with_traces {
let trace = node.parity_transaction_trace(trace_address);
traces.push(trace);
@ -145,6 +150,7 @@ impl ParityTraceBuilder {
self.nodes
.into_iter()
.zip(trace_addresses)
.filter(|(node, _)| !node.is_precompile())
.map(|(node, trace_address)| node.parity_transaction_trace(trace_address))
}

View File

@ -14,6 +14,8 @@ pub struct TracingInspectorConfig {
pub record_stack_snapshots: bool,
/// Whether to record state diffs.
pub record_state_diff: bool,
/// Whether to ignore precompile calls.
pub exclude_precompile_calls: bool,
}
impl TracingInspectorConfig {
@ -24,6 +26,7 @@ impl TracingInspectorConfig {
record_memory_snapshots: true,
record_stack_snapshots: true,
record_state_diff: false,
exclude_precompile_calls: false,
}
}
@ -36,6 +39,7 @@ impl TracingInspectorConfig {
record_memory_snapshots: false,
record_stack_snapshots: false,
record_state_diff: false,
exclude_precompile_calls: true,
}
}
@ -48,6 +52,7 @@ impl TracingInspectorConfig {
record_memory_snapshots: true,
record_stack_snapshots: true,
record_state_diff: true,
exclude_precompile_calls: false,
}
}
@ -61,6 +66,14 @@ impl TracingInspectorConfig {
}
}
/// Configure whether calls to precompiles should be ignored.
///
/// If set to `true`, calls to precompiles without value transfers will be ignored.
pub fn set_exclude_precompile_calls(mut self, exclude_precompile_calls: bool) -> Self {
self.exclude_precompile_calls = exclude_precompile_calls;
self
}
/// Configure whether individual opcode level steps should be recorded
pub fn set_steps(mut self, record_steps: bool) -> Self {
self.record_steps = record_steps;

View File

@ -101,6 +101,7 @@ impl TracingInspector {
/// Starts tracking a new trace.
///
/// Invoked on [Inspector::call].
#[allow(clippy::too_many_arguments)]
fn start_trace_on_call(
&mut self,
depth: usize,
@ -109,6 +110,7 @@ impl TracingInspector {
value: U256,
kind: CallKind,
caller: Address,
maybe_precompile: Option<bool>,
) {
self.trace_stack.push(self.traces.push_trace(
0,
@ -121,6 +123,7 @@ impl TracingInspector {
status: InstructionResult::Continue,
caller,
last_call_return_value: self.last_call_return_data.clone(),
maybe_precompile,
..Default::default()
},
));
@ -318,6 +321,12 @@ where
_ => (inputs.context.caller, inputs.context.address),
};
// if calls to precompiles should be excluded, check whether this is a call to a precompile
let maybe_precompile = self
.config
.exclude_precompile_calls
.then(|| is_precompile_call(data, &to, inputs.transfer.value));
self.start_trace_on_call(
data.journaled_state.depth() as usize,
to,
@ -325,6 +334,7 @@ where
inputs.transfer.value,
inputs.context.scheme.into(),
from,
maybe_precompile,
);
(InstructionResult::Continue, Gas::new(0), Bytes::new())
@ -367,6 +377,7 @@ where
inputs.value,
inputs.scheme.into(),
inputs.caller,
Some(false),
);
(InstructionResult::Continue, None, Gas::new(inputs.gas_limit), Bytes::default())
@ -421,3 +432,12 @@ struct StackStep {
trace_idx: usize,
step_idx: usize,
}
/// Returns true if this a call to a precompile contract with `depth > 0 && value == 0`.
#[inline]
fn is_precompile_call<DB: Database>(data: &EVMData<'_, DB>, to: &Address, value: U256) -> bool {
if data.precompiles.contains(to) {
return data.journaled_state.depth() > 0 && value == U256::ZERO
}
false
}

View File

@ -121,6 +121,10 @@ pub(crate) struct CallTrace {
/// In other words, this is the callee if the [CallKind::Call] or the address of the created
/// contract if [CallKind::Create].
pub(crate) address: Address,
/// Whether this is a call to a precompile
///
/// Note: This is an Option because not all tracers make use of this
pub(crate) maybe_precompile: Option<bool>,
/// Holds the target for the selfdestruct refund target if `status` is
/// [InstructionResult::SelfDestruct]
pub(crate) selfdestruct_refund_target: Option<Address>,
@ -168,6 +172,7 @@ impl Default for CallTrace {
kind: Default::default(),
value: Default::default(),
data: Default::default(),
maybe_precompile: None,
output: Default::default(),
last_call_return_value: None,
gas_used: Default::default(),
@ -233,6 +238,11 @@ impl CallTraceNode {
stack
}
/// Returns true if this is a call to a precompile
pub(crate) fn is_precompile(&self) -> bool {
self.trace.maybe_precompile.unwrap_or(false)
}
/// Returns the kind of call the trace belongs to
pub(crate) fn kind(&self) -> CallKind {
self.trace.kind