Skip to content

Commit

Permalink
Add gas_used & gas_limit to trace
Browse files Browse the repository at this point in the history
  • Loading branch information
pgherveou committed Dec 23, 2024
1 parent e85fcb7 commit ac3d117
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 123 deletions.

This file was deleted.

This file was deleted.

33 changes: 0 additions & 33 deletions substrate/frame/revive/fixtures/contracts/debug_message_works.rs

This file was deleted.

34 changes: 22 additions & 12 deletions substrate/frame/revive/src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub use crate::{
primitives::ExecReturnValue,
BalanceOf,
};
use crate::{Config, Weight, LOG_TARGET};
use crate::{Config, GasMeter, LOG_TARGET};
use alloc::vec::Vec;
use sp_core::{H160, U256};

Expand All @@ -47,25 +47,29 @@ pub trait Tracing<T: Config>: Default {
is_delegate_call: bool,
is_read_only: bool,
value: &U256,
gas_limit: &Weight,
input: &[u8],
gas_meter: &GasMeter<T>,
nested_gas_meter: &GasMeter<T>,
);

fn exit_child_span(&mut self, output: &ExecReturnValue);
fn exit_child_span(&mut self, output: &ExecReturnValue, gas_left: &GasMeter<T>);
}

impl Tracer {
/// Creates a new [`Tracer::CallTracer`].
pub fn new_call_tracer() -> Self {
Tracer::CallTracer(CallTracer::default())
}

/// Returns the call tracer if it is enabled.
pub fn as_call_tracer(self) -> Option<CallTracer> {
match self {
Tracer::CallTracer(tracer) => Some(tracer),
_ => None,
}
}

/// Returns the traces collected by the tracer.
pub fn traces(self) -> Traces {
return match self {
Tracer::CallTracer(tracer) => Traces::CallTraces(tracer.traces),
Expand All @@ -85,8 +89,9 @@ where
is_delegate_call: bool,
is_read_only: bool,
value: &U256,
gas_limit: &Weight,
input: &[u8],
gas_meter: &GasMeter<T>,
nested_gas_meter: &GasMeter<T>,
) {
match self {
Tracer::CallTracer(tracer) => {
Expand All @@ -97,21 +102,22 @@ where
is_delegate_call,
is_read_only,
value,
gas_limit,
input,
gas_meter,
nested_gas_meter,
);
},
Tracer::Disabled => {
log::trace!(target: LOG_TARGET, "call (delegate: {is_delegate_call:?}, read_only: {is_read_only:?}) from: {from:?}, to: {to:?} value: {value:?} gas_limit: {gas_limit:?} input_data: {input:?}");
log::trace!(target: LOG_TARGET, "call (delegate: {is_delegate_call:?}, read_only: {is_read_only:?}) from: {from:?}, to: {to:?} value: {value:?} input_data: {input:?}");
},
}
}

//fn after_call(&mut self, output: &ExecReturnValue);
fn exit_child_span(&mut self, output: &ExecReturnValue) {
fn exit_child_span(&mut self, output: &ExecReturnValue, gas_left: &GasMeter<T>) {
match self {
Tracer::CallTracer(tracer) => {
<CallTracer as Tracing<T>>::exit_child_span(tracer, output);
<CallTracer as Tracing<T>>::exit_child_span(tracer, output, gas_left);
},
Tracer::Disabled => {
log::trace!(target: LOG_TARGET, "call result {output:?}")
Expand Down Expand Up @@ -139,10 +145,10 @@ where
is_delegate_call: bool,
is_read_only: bool,
value: &U256,
gas_limit: &Weight,
input: &[u8],
gas_meter: &GasMeter<T>,
nested_gas_meter: &GasMeter<T>,
) {
log::info!(target: LOG_TARGET, "call (delegate: {is_delegate_call:?}, read_only: {is_read_only:?}) from: {from:?}, to: {to:?} value: {value:?} gas_limit: {gas_limit:?} input_data: {input:?}");
let call_type = if is_read_only {
CallType::StaticCall
} else if is_delegate_call {
Expand All @@ -157,16 +163,20 @@ where
value: (*value).into(),
call_type,
input: input.to_vec(),
gas: nested_gas_meter.gas_left(),
gas_used: gas_meter.gas_left(),
..Default::default()
});

// Push the index onto the stack of the current active trace
self.current_stack.push(self.traces.len() - 1);
}
fn exit_child_span(&mut self, output: &ExecReturnValue) {
fn exit_child_span(&mut self, output: &ExecReturnValue, gas_meter: &GasMeter<T>) {
// Set the output of the current trace
let current_index = self.current_stack.pop().unwrap();
self.traces[current_index].output = output.data.clone();
let trace = &mut self.traces[current_index];
trace.output = output.data.clone();
trace.gas_used = trace.gas_used.saturating_sub(gas_meter.gas_left());

// move the current trace into its parent
if let Some(parent_index) = self.current_stack.last() {
Expand Down
47 changes: 41 additions & 6 deletions substrate/frame/revive/src/evm/api/debug_rpc_types.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#![allow(missing_docs)]
use crate::Weight;
use alloc::vec::Vec;
use codec::{Decode, Encode};
use scale_info::TypeInfo;
Expand All @@ -23,16 +24,30 @@ pub enum CallType {
DelegateCall,
}

/// The traces of a transaction.
#[derive(TypeInfo, Encode, Decode, Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
pub enum Traces {
CallTraces(Vec<CallTrace>),
pub enum Traces<Gas = Weight> {
CallTraces(Vec<CallTrace<Gas>>),
}

impl<Gas> Traces<Gas> {
/// Return mapped traces with the given gas mapper.
pub fn map<F, T>(self, gas_mapper: F) -> Traces<T>
where
F: Fn(Gas) -> T + Copy,
{
match self {
Traces::CallTraces(traces) =>
Traces::CallTraces(traces.into_iter().map(|trace| trace.map(gas_mapper)).collect()),
}
}
}

/// A smart contract execution call trace.
#[derive(
TypeInfo, Default, Encode, Decode, Serialize, Deserialize, Clone, Debug, Eq, PartialEq,
)]
pub struct CallTrace {
pub struct CallTrace<Gas = Weight> {
/// Address of the sender.
pub from: H160,
/// Address of the receiver.
Expand All @@ -46,17 +61,37 @@ pub struct CallTrace {
#[serde(rename = "type")]
pub call_type: CallType,
/// Gas limit.
pub gas: U256,
pub gas: Gas,
/// Amount of gas used.
#[serde(rename = "gasUsed")]
pub gas_used: U256,
pub gas_used: Gas,
/// Return data.
#[serde(skip_serializing_if = "Vec::is_empty")]
pub output: Vec<u8>,
/// Amount of gas provided for the call.
/// List of sub-calls.
#[serde(skip_serializing_if = "Vec::is_empty")]
pub calls: Vec<CallTrace>,
pub calls: Vec<CallTrace<Gas>>,
}

impl<Gas> CallTrace<Gas> {
/// Return a new call gas with a mapped gas value.
pub fn map<F, T>(self, gas_mapper: F) -> CallTrace<T>
where
F: Fn(Gas) -> T + Copy,
{
CallTrace {
from: self.from,
to: self.to,
input: self.input,
value: self.value,
call_type: self.call_type,
gas: gas_mapper(self.gas),
gas_used: gas_mapper(self.gas_used),
output: self.output,
calls: self.calls.into_iter().map(|call| call.map(gas_mapper)).collect(),
}
}
}

/// A transaction trace
Expand Down
10 changes: 5 additions & 5 deletions substrate/frame/revive/src/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1056,7 +1056,6 @@ where
let frame = top_frame_mut!(self);
let read_only = frame.read_only;
let value_transferred = frame.value_transferred.clone();
let gas_limit = frame.nested_gas.gas_left();
let account_id = &frame.account_id.clone();

// We need to charge the storage deposit before the initial transfer so that
Expand Down Expand Up @@ -1090,8 +1089,8 @@ where
)?;
}

let contract_address = T::AddressMapper::to_address(&top_frame!(self).account_id);
let maybe_caller_address = self.caller().account_id().map(T::AddressMapper::to_address);
let contract_address = T::AddressMapper::to_address(account_id);
let maybe_caller_address = caller.account_id().map(T::AddressMapper::to_address);

<Tracer as Tracing<T>>::enter_child_span(
self.tracer,
Expand All @@ -1100,15 +1099,16 @@ where
is_delegate_call,
read_only,
&value_transferred,
&gas_limit,
&input_data,
&self.gas_meter,
&frame.nested_gas,
);

let output = T::Debug::intercept_call(&contract_address, entry_point, &input_data)
.unwrap_or_else(|| executable.execute(self, entry_point, input_data))
.map_err(|e| ExecError { error: e.error, origin: ErrorOrigin::Callee })?;

<Tracer as Tracing<T>>::exit_child_span(self.tracer, &output);
<Tracer as Tracing<T>>::exit_child_span(self.tracer, &output, &self.gas_meter);

// Avoid useless work that would be reverted anyways.
if output.did_revert() {
Expand Down
2 changes: 1 addition & 1 deletion substrate/frame/revive/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4845,7 +4845,7 @@ fn tracing_works() {
let result = builder::bare_call(addr).data((3u32, addr_callee).encode()).build();

assert_eq!(
result.traces,
result.traces.map(|_| Weight::default()),
Traces::CallTraces(vec![CallTrace {
from: ALICE_ADDR,
to: addr,
Expand Down

0 comments on commit ac3d117

Please sign in to comment.