Skip to content
Open
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
3 changes: 2 additions & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
[submodule "monad-cxx/monad-execution"]
path = monad-cxx/monad-execution
url = https://github.com/category-labs/monad.git
url = https://github.com/category-labs/monad
branch = dhil/replay-txs
225 changes: 225 additions & 0 deletions monad-ethcall/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,231 @@ pub fn decode_revert_message(output_data: &[u8]) -> Option<String> {
})
}

pub async fn eth_trace_block(
chain_id: u64,
block_header: Header,
block_number: u64,
block_id: Option<[u8; 32]>,
parent_id: Option<[u8; 32]>,
eth_call_executor: Arc<EthCallExecutor>,
tracer: MonadTracer,
) -> CallResult {
let chain_config = match chain_id {
ETHEREUM_MAINNET_CHAIN_ID => bindings::monad_chain_config_CHAIN_CONFIG_ETHEREUM_MAINNET,
MONAD_DEVNET_CHAIN_ID => bindings::monad_chain_config_CHAIN_CONFIG_MONAD_DEVNET,
MONAD_TESTNET_CHAIN_ID => bindings::monad_chain_config_CHAIN_CONFIG_MONAD_TESTNET,
MONAD_MAINNET_CHAIN_ID => bindings::monad_chain_config_CHAIN_CONFIG_MONAD_MAINNET,
MONAD_TESTNET2_CHAIN_ID => bindings::monad_chain_config_CHAIN_CONFIG_MONAD_TESTNET2,
_ => {
return CallResult::Failure(FailureCallResult {
error_code: EthCallResult::OtherError,
message: "unsupported chain id".to_string(),
data: Some(chain_id.to_string()),
});
}
};

let mut rlp_encoded_block_header = vec![];
block_header.encode(&mut rlp_encoded_block_header);

let rlp_encoded_block_id = alloy_rlp::encode(block_id.unwrap_or([0_u8; 32]));

let rlp_encoded_parent_id = alloy_rlp::encode(parent_id.unwrap_or([0_u8; 32]));

let (send, recv) = channel();
let sender_ctx = Box::new(SenderContext { sender: send });

unsafe {
let sender_ctx_ptr = Box::into_raw(sender_ctx);

bindings::monad_eth_trace_block_executor_submit(
eth_call_executor.eth_call_executor,
chain_config,
rlp_encoded_block_header.as_ptr(),
rlp_encoded_block_header.len(),
block_number,
rlp_encoded_block_id.as_ptr(),
rlp_encoded_block_id.len(),
rlp_encoded_parent_id.as_ptr(),
rlp_encoded_parent_id.len(),
Some(eth_call_submit_callback),
sender_ctx_ptr as *mut std::ffi::c_void,
tracer.into(),
)
};

let result = match recv.await {
Ok(r) => r,
Err(e) => {
warn!("callback from eth_trace_block_executor failed: {:?}", e);

return CallResult::Failure(FailureCallResult {
error_code: EthCallResult::OtherError,
message: "internal eth_trace_block error".to_string(),
data: None,
});
}
};

unsafe {
let status_code = (*result).status_code;

let call_result = match status_code {
ETH_CALL_SUCCESS => {
// TODO(dhil): I don't think these matter for the output of prestate tracing. Other providers don't seem to return them in prestate mode.
let gas_used = (*result).gas_used as u64;
let gas_refund = (*result).gas_refund as u64;

let output_data_len = (*result).encoded_trace_len;
let output_data = if output_data_len != 0 {
std::slice::from_raw_parts((*result).encoded_trace, output_data_len).to_vec()
} else {
vec![]
};

CallResult::Success(SuccessCallResult {
gas_used,
gas_refund,
output_data,
})
}
_ => {
let cstr_msg = CStr::from_ptr((*result).message.cast());
let message = match cstr_msg.to_str() {
Ok(str) => String::from(str),
Err(_) => String::from("execution error eth_trace_block message invalid utf-8"),
};

CallResult::Failure(FailureCallResult {
error_code: EthCallResult::OtherError,
message,
data: None,
})
}
};

bindings::monad_eth_call_result_release(result);

call_result
}
}

pub async fn eth_trace_transaction(
chain_id: u64,
block_header: Header,
block_number: u64,
block_id: Option<[u8; 32]>,
parent_id: Option<[u8; 32]>,
transaction_index: u64,
eth_call_executor: Arc<EthCallExecutor>,
tracer: MonadTracer,
) -> CallResult {
let chain_config = match chain_id {
ETHEREUM_MAINNET_CHAIN_ID => bindings::monad_chain_config_CHAIN_CONFIG_ETHEREUM_MAINNET,
MONAD_DEVNET_CHAIN_ID => bindings::monad_chain_config_CHAIN_CONFIG_MONAD_DEVNET,
MONAD_TESTNET_CHAIN_ID => bindings::monad_chain_config_CHAIN_CONFIG_MONAD_TESTNET,
MONAD_MAINNET_CHAIN_ID => bindings::monad_chain_config_CHAIN_CONFIG_MONAD_MAINNET,
MONAD_TESTNET2_CHAIN_ID => bindings::monad_chain_config_CHAIN_CONFIG_MONAD_TESTNET2,
_ => {
return CallResult::Failure(FailureCallResult {
error_code: EthCallResult::OtherError,
message: "unsupported chain id".to_string(),
data: Some(chain_id.to_string()),
});
}
};

let mut rlp_encoded_block_header = vec![];
block_header.encode(&mut rlp_encoded_block_header);

let rlp_encoded_block_id = alloy_rlp::encode(block_id.unwrap_or([0_u8; 32]));

let rlp_encoded_parent_id = alloy_rlp::encode(parent_id.unwrap_or([0_u8; 32]));

let (send, recv) = channel();
let sender_ctx = Box::new(SenderContext { sender: send });

unsafe {
let sender_ctx_ptr = Box::into_raw(sender_ctx);

bindings::monad_eth_trace_transaction_executor_submit(
eth_call_executor.eth_call_executor,
chain_config,
rlp_encoded_block_header.as_ptr(),
rlp_encoded_block_header.len(),
block_number,
rlp_encoded_block_id.as_ptr(),
rlp_encoded_block_id.len(),
rlp_encoded_parent_id.as_ptr(),
rlp_encoded_parent_id.len(),
transaction_index,
Some(eth_call_submit_callback),
sender_ctx_ptr as *mut std::ffi::c_void,
tracer.into(),
)
};

let result = match recv.await {
Ok(r) => r,
Err(e) => {
warn!(
"callback from eth_trace_transaction_executor failed: {:?}",
e
);

return CallResult::Failure(FailureCallResult {
error_code: EthCallResult::OtherError,
message: "internal eth_trace_transaction error".to_string(),
data: None,
});
}
};

unsafe {
let status_code = (*result).status_code;

let call_result = match status_code {
ETH_CALL_SUCCESS => {
// TODO(dhil): I don't think these matter for the output of prestate tracing. Other providers don't seem to return them in prestate mode.
let gas_used = (*result).gas_used as u64;
let gas_refund = (*result).gas_refund as u64;

let output_data_len = (*result).encoded_trace_len;
let output_data = if output_data_len != 0 {
std::slice::from_raw_parts((*result).encoded_trace, output_data_len).to_vec()
} else {
vec![]
};

CallResult::Success(SuccessCallResult {
gas_used,
gas_refund,
output_data,
})
}
_ => {
let cstr_msg = CStr::from_ptr((*result).message.cast());
let message = match cstr_msg.to_str() {
Ok(str) => String::from(str),
Err(_) => {
String::from("execution error eth_trace_transaction message invalid utf-8")
}
};

CallResult::Failure(FailureCallResult {
error_code: EthCallResult::OtherError,
message,
data: None,
})
}
};

bindings::monad_eth_call_result_release(result);

call_result
}
}

#[cfg(test)]
mod tests {
use alloy_primitives::hex;
Expand Down
4 changes: 2 additions & 2 deletions monad-rpc/src/chainstate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ impl<T: Triedb> ChainState<T> {
};

let block_key = match &block {
BlockTagOrHash::BlockTags(tag) => get_block_key_from_tag(&self.triedb_env, tag.clone()),
BlockTagOrHash::BlockTags(tag) => get_block_key_from_tag(&self.triedb_env, *tag),
BlockTagOrHash::Hash(hash) => {
let latest_block_key = get_latest_block_key(&self.triedb_env);

Expand Down Expand Up @@ -394,7 +394,7 @@ impl<T: Triedb> ChainState<T> {
}

let block_key = match &block {
BlockTagOrHash::BlockTags(tag) => get_block_key_from_tag(&self.triedb_env, tag.clone()),
BlockTagOrHash::BlockTags(tag) => get_block_key_from_tag(&self.triedb_env, *tag),
BlockTagOrHash::Hash(hash) => {
let latest_block_key = get_latest_block_key(&self.triedb_env);

Expand Down
2 changes: 1 addition & 1 deletion monad-rpc/src/eth_json_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ impl<'de, const N: usize> Deserialize<'de> for FixedData<N> {
}
}

#[derive(Clone, Debug, Default, PartialEq, Eq)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub enum BlockTags {
Number(Quantity), // voted or finalized
#[default]
Expand Down
22 changes: 11 additions & 11 deletions monad-rpc/src/handlers/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ impl Decodable for CallFrame {
}
}

#[derive(Deserialize, Debug, Default, schemars::JsonSchema, Clone)]
#[derive(Deserialize, Debug, Default, schemars::JsonSchema, Clone, Copy)]
#[serde(rename_all = "camelCase")]
pub struct TracerObject {
#[serde(default)]
Expand All @@ -253,7 +253,7 @@ pub struct TracerObject {
pub config: TracerConfig,
}

#[derive(Deserialize, Debug, Default, schemars::JsonSchema, Clone, PartialEq, Eq)]
#[derive(Deserialize, Debug, Default, schemars::JsonSchema, Clone, Copy, PartialEq, Eq)]
pub enum Tracer {
#[default]
#[serde(rename = "callTracer")]
Expand All @@ -262,7 +262,7 @@ pub enum Tracer {
PreStateTracer,
}

#[derive(Clone, Debug, Deserialize, Default, schemars::JsonSchema)]
#[derive(Clone, Copy, Debug, Deserialize, Default, schemars::JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct TracerConfig {
/// onlyTopCall for callTracer, ignored for prestateTracer
Expand All @@ -278,11 +278,11 @@ pub struct TracerConfig {
pub with_log: bool,
}

#[derive(Deserialize, Debug, schemars::JsonSchema)]
#[derive(Clone, Copy, Deserialize, Debug, schemars::JsonSchema)]
pub struct MonadDebugTraceTransactionParams {
tx_hash: EthHash,
pub tx_hash: EthHash,
#[serde(default)]
tracer: TracerObject,
pub tracer: TracerObject,
}

#[derive(Serialize, Debug, schemars::JsonSchema)]
Expand Down Expand Up @@ -394,9 +394,9 @@ pub enum CallKind {

#[derive(Deserialize, Debug, schemars::JsonSchema)]
pub struct MonadDebugTraceBlockByHashParams {
block_hash: EthHash,
pub block_hash: EthHash,
#[serde(default)]
tracer: TracerObject,
pub tracer: TracerObject,
}

#[rpc(method = "debug_traceBlockByHash")]
Expand Down Expand Up @@ -463,11 +463,11 @@ pub async fn monad_debug_traceBlockByHash<T: Triedb>(
Err(JsonRpcError::internal_error("block not found".into()))
}

#[derive(Deserialize, Debug, schemars::JsonSchema)]
#[derive(Clone, Copy, Deserialize, Debug, schemars::JsonSchema)]
pub struct MonadDebugTraceBlockByNumberParams {
block_number: BlockTags,
pub block_number: BlockTags,
#[serde(default)]
tracer: TracerObject,
pub tracer: TracerObject,
}

#[derive(Serialize, Debug, schemars::JsonSchema)]
Expand Down
Loading
Loading