Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ schemars = "0.8.21"
scrypt = { version = "0.11", default-features = false }
secp256k1 = "0.26"
serde = "1.0"
serde_cbor = "0.11.2"
serde_json = "1.0"
serde_test = "1.0.177"
sha2 = "0.10"
Expand Down
43 changes: 31 additions & 12 deletions monad-ethcall/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,26 @@ pub struct StateOverrideObject {
pub storage_override: Option<StorageOverride>,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(u32)]
pub enum MonadTracer {
NoopTracer = 0,
CallTracer,
PreStateTracer,
StateDiffTracer,
}

impl From<MonadTracer> for u32 {
fn from(tracer: MonadTracer) -> u32 {
match tracer {
MonadTracer::NoopTracer => 0,
MonadTracer::CallTracer => 1,
MonadTracer::PreStateTracer => 2,
MonadTracer::StateDiffTracer => 3,
}
}
}

pub const ETH_CALL_SUCCESS: i32 = 0;
pub const EVMC_OUT_OF_GAS: i32 = 3;

Expand Down Expand Up @@ -143,7 +163,7 @@ pub struct FailureCallResult {

#[derive(Clone, Debug, Default)]
pub struct RevertCallResult {
pub call_frame: Vec<u8>,
pub trace: Vec<u8>,
}

pub struct SenderContext {
Expand Down Expand Up @@ -175,7 +195,7 @@ pub async fn eth_call(
block_id: Option<[u8; 32]>,
eth_call_executor: Arc<Mutex<EthCallExecutor>>,
state_override_set: &StateOverrideSet,
trace: bool,
tracer: MonadTracer,
gas_specified: bool,
) -> CallResult {
// upper bound gas limit of transaction to block gas limit to prevent abuse of eth_call
Expand Down Expand Up @@ -312,7 +332,7 @@ pub async fn eth_call(
override_ctx,
Some(eth_call_submit_callback),
sender_ctx_ptr as *mut std::ffi::c_void,
trace,
tracer.into(),
gas_specified,
)
};
Expand All @@ -337,13 +357,14 @@ pub async fn eth_call(

unsafe {
let status_code = (*result).status_code;
let tracer_cval: u32 = tracer.into();

let call_result = match status_code {
ETH_CALL_SUCCESS => {
let gas_used = (*result).gas_used as u64;
let gas_refund = (*result).gas_refund as u64;

if !trace {
if tracer_cval == bindings::monad_tracer_config_NOOP_TRACER {
let output_data_len = (*result).output_data_len;
let output_data = if output_data_len != 0 {
std::slice::from_raw_parts((*result).output_data, output_data_len).to_vec()
Expand All @@ -357,9 +378,9 @@ pub async fn eth_call(
output_data,
})
} else {
let output_data_len = (*result).rlp_call_frames_len;
let output_data_len = (*result).encoded_trace_len;
let output_data = if output_data_len != 0 {
std::slice::from_raw_parts((*result).rlp_call_frames, output_data_len)
std::slice::from_raw_parts((*result).encoded_trace, output_data_len)
.to_vec()
} else {
vec![]
Expand All @@ -375,7 +396,7 @@ pub async fn eth_call(
_ => {
if (*result).message.is_null() {
// This means execution reverted, not a validation error
if !trace {
if tracer_cval == bindings::monad_tracer_config_NOOP_TRACER {
let output_data_len = (*result).output_data_len;
let output_data = if output_data_len != 0 {
std::slice::from_raw_parts((*result).output_data, output_data_len)
Expand All @@ -400,16 +421,14 @@ pub async fn eth_call(
data: Some(format!("0x{}", hex::encode(&output_data))),
})
} else {
let output_data_len = (*result).rlp_call_frames_len;
let output_data_len = (*result).encoded_trace_len;
let output_data = if output_data_len != 0 {
std::slice::from_raw_parts((*result).rlp_call_frames, output_data_len)
std::slice::from_raw_parts((*result).encoded_trace, output_data_len)
.to_vec()
} else {
vec![]
};
CallResult::Revert(RevertCallResult {
call_frame: output_data,
})
CallResult::Revert(RevertCallResult { trace: output_data })
}
} else {
// This means we hit a validation error (execution not started)
Expand Down
1 change: 1 addition & 0 deletions monad-rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ rayon = { workspace = true }
reqwest = { workspace = true }
schemars = { workspace = true, features = ["preserve_order", "raw_value"] }
serde = { workspace = true, features = ["derive", "rc"] }
serde_cbor = { workspace = true }
serde_json = { workspace = true, features = ["raw_value"] }
tokio = { workspace = true, features = [
"net",
Expand Down
6 changes: 1 addition & 5 deletions monad-rpc/monad-rpc-docs/monad-rpc-docs-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,12 +258,8 @@ fn extract_output_info(output: ReturnType) -> Option<(String, Type, TokenStream2
fn generate_schema_expr(ty: &Type) -> TokenStream2 {
match ty {
Type::Path(type_path) => {
let type_ident = match &type_path.path.segments.last() {
Some(segment) => &segment.ident,
None => return quote! { None },
};
quote! {
Some(schemars::schema_for!(#type_ident))
Some(schemars::schema_for!(#type_path))
}
}
Type::Reference(type_reference) => {
Expand Down
26 changes: 21 additions & 5 deletions monad-rpc/src/handlers/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,17 +235,30 @@ impl Decodable for CallFrame {
#[serde(rename_all = "camelCase")]
pub struct TracerObject {
#[serde(default)]
tracer: Tracer,
only_top_call: Option<bool>,
pub tracer: Tracer,
#[serde(default, rename = "tracerConfig")]
pub config: TracerConfig,
}

#[derive(Deserialize, Debug, Default, schemars::JsonSchema, Clone)]
#[derive(Deserialize, Debug, Default, schemars::JsonSchema, Clone, PartialEq, Eq)]
pub enum Tracer {
#[default]
#[serde(rename = "callTracer")]
CallTracer,
#[serde(rename = "prestateTracer")]
PreStateTracer, // TODO: implement prestate tracer
PreStateTracer,
}

#[derive(Clone, Debug, Deserialize, Default, schemars::JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct TracerConfig {
/// onlyTopCall for callTracer, ignored for prestateTracer
#[serde(default)]
pub only_top_call: bool,

/// diff mode for prestateTracer, ignored for callTracer
#[serde(default)]
pub diff_mode: bool,
}

#[derive(Deserialize, Debug, schemars::JsonSchema)]
Expand Down Expand Up @@ -556,7 +569,10 @@ pub async fn decode_call_frame<T: Triedb>(

match tracer.tracer {
Tracer::CallTracer => {
if let Some(true) = tracer.only_top_call {
// Diff mode is supported only by the prestate tracer
if tracer.config.diff_mode {
Err(JsonRpcError::method_not_supported())
} else if tracer.config.only_top_call {
if call_frames.is_empty() {
Ok(None)
} else {
Expand Down
Loading