feat: populate gas cost for vm instructions (#4046)

This commit is contained in:
Matthias Seitz
2023-08-03 20:30:23 +02:00
committed by GitHub
parent 0d33585426
commit 6ceaad6af9
2 changed files with 31 additions and 12 deletions

View File

@ -7,7 +7,8 @@ use reth_primitives::{Address, U64};
use reth_rpc_types::{trace::parity::*, TransactionInfo};
use revm::{
db::DatabaseRef,
primitives::{AccountInfo, ExecutionResult, ResultAndState, KECCAK_EMPTY},
interpreter::opcode::spec_opcode_gas,
primitives::{AccountInfo, ExecutionResult, ResultAndState, SpecId, KECCAK_EMPTY},
};
use std::collections::{HashSet, VecDeque};
@ -18,6 +19,8 @@ use std::collections::{HashSet, VecDeque};
pub struct ParityTraceBuilder {
/// Recorded trace nodes
nodes: Vec<CallTraceNode>,
/// The spec id of the EVM.
spec_id: Option<SpecId>,
/// How the traces were recorded
_config: TracingInspectorConfig,
@ -25,8 +28,12 @@ pub struct ParityTraceBuilder {
impl ParityTraceBuilder {
/// Returns a new instance of the builder
pub(crate) fn new(nodes: Vec<CallTraceNode>, _config: TracingInspectorConfig) -> Self {
Self { nodes, _config }
pub(crate) fn new(
nodes: Vec<CallTraceNode>,
spec_id: Option<SpecId>,
_config: TracingInspectorConfig,
) -> Self {
Self { nodes, spec_id, _config }
}
/// Returns a list of all addresses that appeared as callers.
@ -306,7 +313,7 @@ impl ParityTraceBuilder {
None
};
instructions.push(Self::make_instruction(step, maybe_sub));
instructions.push(self.make_instruction(step, maybe_sub));
}
match current.parent {
@ -331,7 +338,7 @@ impl ParityTraceBuilder {
/// Creates a VM instruction from a [CallTraceStep] and a [VmTrace] for the subcall if there is
/// one
fn make_instruction(step: &CallTraceStep, maybe_sub: Option<VmTrace>) -> VmInstruction {
fn make_instruction(&self, step: &CallTraceStep, maybe_sub: Option<VmTrace>) -> VmInstruction {
let maybe_storage = step.storage_change.map(|storage_change| StorageDelta {
key: storage_change.key,
val: storage_change.value,
@ -351,12 +358,14 @@ impl ParityTraceBuilder {
store: maybe_storage,
});
VmInstruction {
pc: step.pc,
cost: 0, // TODO: use op gas cost
ex: maybe_execution,
sub: maybe_sub,
}
let cost = self
.spec_id
.and_then(|spec_id| {
spec_opcode_gas(spec_id).get(step.op.u8() as usize).map(|op| op.get_gas())
})
.unwrap_or_default();
VmInstruction { pc: step.pc, cost: cost as u64, ex: maybe_execution, sub: maybe_sub }
}
}

View File

@ -10,6 +10,7 @@ use revm::{
opcode, return_ok, CallInputs, CallScheme, CreateInputs, Gas, InstructionResult,
Interpreter, OpCode,
},
primitives::SpecId,
Database, EVMData, Inspector, JournalEntry,
};
use types::{CallTrace, CallTraceStep};
@ -59,6 +60,10 @@ pub struct TracingInspector {
last_call_return_data: Option<Bytes>,
/// The gas inspector used to track remaining gas.
gas_inspector: GasInspector,
/// The spec id of the EVM.
///
/// This is filled during execution.
spec_id: Option<SpecId>,
}
// === impl TracingInspector ===
@ -73,12 +78,13 @@ impl TracingInspector {
step_stack: vec![],
last_call_return_data: None,
gas_inspector: Default::default(),
spec_id: None,
}
}
/// Consumes the Inspector and returns a [ParityTraceBuilder].
pub fn into_parity_builder(self) -> ParityTraceBuilder {
ParityTraceBuilder::new(self.traces.arena, self.config)
ParityTraceBuilder::new(self.traces.arena, self.spec_id, self.config)
}
/// Consumes the Inspector and returns a [GethTraceBuilder].
@ -170,6 +176,10 @@ impl TracingInspector {
// this is the root call which should get the original gas limit of the transaction,
// because initialization costs are already subtracted from gas_limit
gas_limit = data.env.tx.gas_limit;
// we set the spec id here because we only need to do this once and this condition is
// hit exactly once
self.spec_id = Some(data.env.cfg.spec_id);
}
self.trace_stack.push(self.traces.push_trace(