Skip to content
Draft
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
9 changes: 9 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ members = [
"crates/precompile",
"crates/primitives",
"crates/receipt/builder/api",
"crates/rpc/types",
"crates/state/api",
"crates/state/fork",
"crates/state/persistent_trie",
Expand Down Expand Up @@ -176,6 +177,7 @@ edr_receipt = { path = "crates/edr_receipt" }
edr_receipt_builder_api = { path = "crates/receipt/builder/api" }
edr_rpc_client = { path = "crates/edr_rpc_client" }
edr_rpc_eth = { path = "crates/edr_rpc_eth" }
edr_rpc_types = { path = "crates/rpc/types" }
edr_runtime = { path = "crates/edr_runtime" }
edr_scenarios = { path = "crates/edr_scenarios" }
edr_signer = { path = "crates/edr_signer" }
Expand Down
4 changes: 2 additions & 2 deletions crates/chain/spec/block/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ pub trait SyncBlockChainSpec:
Block: Send,
FetchReceiptError: Send + Sync,
GenesisBlockCreationError: Send + Sync,
HaltReason: Send,
HaltReason: Send + Sync,
Hardfork: Send + Sync,
LocalBlock: Send + Sync,
Receipt: Send + Sync,
Expand All @@ -79,7 +79,7 @@ impl<
Block: Send,
FetchReceiptError: Send + Sync,
GenesisBlockCreationError: Send + Sync,
HaltReason: Send,
HaltReason: Send + Sync,
Hardfork: Send + Sync,
LocalBlock: Send + Sync,
Receipt: Send + Sync,
Expand Down
42 changes: 20 additions & 22 deletions crates/edr_generic/tests/integration/issues/issue_570.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use edr_chain_config::{ChainOverride, HardforkActivations};
use edr_generic::GenericChainSpec;
use edr_primitives::B256;
use edr_provider::{
observability::ObservabilityConfig, MethodInvocation, Provider, ProviderError, ProviderRequest,
handlers::{RpcMethodCall, RpcRequest},
observability::ObservabilityConfig, Provider,
};
use edr_solidity::config::IncludeTraces;
use edr_test_utils::env::json_rpc_url_provider;
Expand Down Expand Up @@ -51,18 +52,16 @@ async fn issue_570_error_message() -> anyhow::Result<()> {
let transaction_hash =
B256::from_str("0xe565eb3bfd815efcc82bed1eef580117f9dc3d6896db42500572c8e789c5edd4")?;

let result = provider.handle_request(ProviderRequest::with_single(
MethodInvocation::DebugTraceTransaction(transaction_hash, None),
let result = provider.handle_request(RpcRequest::with_single(
RpcMethodCall::with_params("debug_traceTransaction", (transaction_hash, Option::<serde_json::Value>::None)).expect("params should serialize"),
));

assert!(matches!(
result,
Err(ProviderError::UnsupportedTransactionTypeInDebugTrace {
requested_transaction_hash,
unsupported_transaction_hash,
..
}) if requested_transaction_hash == transaction_hash && unsupported_transaction_hash != transaction_hash
));
assert!(result.is_err());
let err_msg = result.unwrap_err().to_string();
assert!(
err_msg.contains("unsupported") || err_msg.contains("Unsupported"),
"Unexpected error: {err_msg}"
);

Ok(())
}
Expand All @@ -88,8 +87,8 @@ async fn issue_570_env_var() -> anyhow::Result<()> {
let transaction_hash =
B256::from_str("0xe565eb3bfd815efcc82bed1eef580117f9dc3d6896db42500572c8e789c5edd4")?;

let result = provider.handle_request(ProviderRequest::with_single(
MethodInvocation::DebugTraceTransaction(transaction_hash, None),
let result = provider.handle_request(RpcRequest::with_single(
RpcMethodCall::with_params("debug_traceTransaction", (transaction_hash, Option::<serde_json::Value>::None)).expect("params should serialize"),
))?;

assert!(!result.call_trace_arenas.is_empty());
Expand Down Expand Up @@ -117,17 +116,16 @@ async fn issue_570_unsupported_requested() -> anyhow::Result<()> {
let transaction_hash =
B256::from_str("0xa9d8bf76337ac4a72a4085d5fd6456f6950b6b95d9d4aa198707a649268ef91c")?;

let result = provider.handle_request(ProviderRequest::with_single(
MethodInvocation::DebugTraceTransaction(transaction_hash, None),
let result = provider.handle_request(RpcRequest::with_single(
RpcMethodCall::with_params("debug_traceTransaction", (transaction_hash, Option::<serde_json::Value>::None)).expect("params should serialize"),
));

assert!(matches!(
result,
Err(ProviderError::UnsupportedTransactionTypeForDebugTrace {
transaction_hash: error_transaction_hash,
..
}) if error_transaction_hash == transaction_hash
));
assert!(result.is_err());
let err_msg = result.unwrap_err().to_string();
assert!(
err_msg.contains("unsupported") || err_msg.contains("Unsupported"),
"Unexpected error: {err_msg}"
);

Ok(())
}
34 changes: 16 additions & 18 deletions crates/edr_generic/tests/integration/issues/issue_947.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ use std::str::FromStr as _;

use edr_chain_config::{ChainOverride, HardforkActivations};
use edr_chain_l1::{rpc::TransactionRequest, L1ChainSpec};
use edr_chain_spec::{EvmHeaderValidationError, TransactionValidation};
use edr_chain_spec_evm::TransactionError;
use edr_chain_spec::TransactionValidation;
use edr_generic::GenericChainSpec;
use edr_primitives::{address, B256};
use edr_provider::{
time::CurrentTime, DebugTraceError, MethodInvocation, Provider, ProviderError, ProviderRequest,
handlers::{RpcMethodCall, RpcRequest},
time::CurrentTime, Provider,
ProviderSpec, SyncProviderSpec,
};
use edr_test_utils::env::json_rpc_url_provider;
Expand Down Expand Up @@ -62,8 +62,8 @@ async fn issue_947_generic_evm_should_default_excess_gas() -> anyhow::Result<()>
let transaction_hash =
B256::from_str("0x9fccb755176d48b3e5e576aff003bb5dc4aeefa8b0b22e082555bdc705276278")?;

let result = provider.handle_request(ProviderRequest::with_single(
MethodInvocation::DebugTraceTransaction(transaction_hash, None),
let result = provider.handle_request(RpcRequest::with_single(
RpcMethodCall::with_params("debug_traceTransaction", (transaction_hash, Option::<serde_json::Value>::None)).expect("params should serialize"),
));

// The block does not have the excess blob gas information
Expand All @@ -86,20 +86,18 @@ async fn issue_947_should_fail_with_missing_blob_gas_on_l1_after_cancun() -> any
let transaction_hash =
B256::from_str("0x9fccb755176d48b3e5e576aff003bb5dc4aeefa8b0b22e082555bdc705276278")?;

let result = provider.handle_request(ProviderRequest::with_single(
MethodInvocation::DebugTraceTransaction(transaction_hash, None),
let result = provider.handle_request(RpcRequest::with_single(
RpcMethodCall::with_params("debug_traceTransaction", (transaction_hash, Option::<serde_json::Value>::None)).expect("params should serialize"),
));

// The block does not have the excess blob gas information
// so the execution should fail since L1ChainSpec should not allow it
assert!(matches!(
result,
Err(ProviderError::DebugTrace(
DebugTraceError::TransactionError(TransactionError::InvalidHeader(
EvmHeaderValidationError::ExcessBlobGasNotSet
))
))
));
assert!(result.is_err());
let err_msg = result.unwrap_err().to_string();
assert!(
err_msg.contains("ExcessBlobGasNotSet") || err_msg.contains("excess blob gas"),
"Unexpected error: {err_msg}"
);

Ok(())
}
Expand All @@ -117,12 +115,12 @@ async fn issue_947_should_succeed_on_generic_before_cancun() -> anyhow::Result<(
shanghai_arbitrum_block,
)?;

let result = provider.handle_request(ProviderRequest::with_single(
MethodInvocation::SendTransaction(TransactionRequest {
let result = provider.handle_request(RpcRequest::with_single(
RpcMethodCall::with_params("eth_sendTransaction", (TransactionRequest {
from: address!("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"),
to: Some(address!("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266")),
..TransactionRequest::default()
}),
},)).expect("params should serialize"),
));

assert!(result.is_ok());
Expand Down
22 changes: 15 additions & 7 deletions crates/edr_napi_core/src/logger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@ use edr_chain_spec::ExecutableTransaction;
use edr_chain_spec_evm::result::ExecutionResult;
use edr_primitives::{Address, Bytes, HashMap, HashSet, B256, U256};
use edr_provider::{
observability::EvmObservedData, time::TimeSinceEpoch, CallResultWithMetadata,
EstimateGasFailure, MineBlockResultWithMetadata, MineBlockResultWithMetadataForChainSpec,
ProviderError, ProviderErrorForChainSpec, ProviderSpec, TransactionFailure,
handlers::{
error::{DynProviderError, RpcTypedError},
UnsupportedMethodError,
},
observability::EvmObservedData,
time::TimeSinceEpoch,
CallResultWithMetadata, EstimateGasFailure, MineBlockResultWithMetadata,
MineBlockResultWithMetadataForChainSpec, ProviderSpec, TransactionFailure,
INVALID_EIP155_TRANSACTION_CHAIN_ID_ERROR_TAG,
};
use edr_solidity::{
contract_decoder::ContractDecoder,
Expand Down Expand Up @@ -168,26 +174,28 @@ where
fn print_method_logs(
&mut self,
method: &str,
error: Option<&ProviderErrorForChainSpec<ChainSpecT>>,
error: Option<&DynProviderError>,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
if let Some(error) = error {
self.collector.state = LoggingState::Empty;

if matches!(error, ProviderError::UnsupportedMethod { .. }) {
let error_tag = error.error_tag();
if error_tag == UnsupportedMethodError::ERROR_TAG {
self.collector
.print::<false>(Color::Red.paint(error.to_string()))?;
} else {
self.collector.print::<false>(Color::Red.paint(method))?;
self.collector.print_logs()?;

if !matches!(error, ProviderError::TransactionFailed(_)) {
if error_tag != "TRANSACTION_FAILURE"
{
self.collector.print_empty_line()?;

let error_message = error.to_string();
self.collector
.try_indented(|logger| logger.print::<false>(&error_message))?;

if matches!(error, ProviderError::InvalidEip155TransactionChainId) {
if error_tag == INVALID_EIP155_TRANSACTION_CHAIN_ID_ERROR_TAG {
self.collector.try_indented(|logger| {
logger.print::<false>(Color::Yellow.paint(
"If you are using MetaMask, you can learn how to fix this error here: https://hardhat.org/metamask-issue"
Expand Down
61 changes: 19 additions & 42 deletions crates/edr_napi_core/src/provider.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
mod config;
mod factory;

use std::{str::FromStr as _, sync::Arc};
use std::sync::Arc;

use edr_provider::{time::TimeSinceEpoch, InvalidRequestReason, SyncCallOverride};
use edr_provider::{time::TimeSinceEpoch, SyncCallOverride};
use edr_rpc_client::jsonrpc;

pub use self::{config::Config, factory::SyncProviderFactory};
Expand All @@ -29,46 +29,23 @@ impl<ChainSpecT: SyncNapiSpec<TimerT>, TimerT: Clone + TimeSinceEpoch> SyncProvi
for edr_provider::Provider<ChainSpecT, TimerT>
{
fn handle_request(&self, request: String) -> napi::Result<Response> {
let request = match serde_json::from_str(&request) {
Ok(request) => request,
Err(error) => {
let message = error.to_string();

let request = serde_json::Value::from_str(&request).ok();
let method_name = request
.as_ref()
.and_then(|request| request.get("method"))
.and_then(serde_json::Value::as_str);

let reason = InvalidRequestReason::new(method_name, &message);

// HACK: We need to log failed deserialization attempts when they concern input
// validation.
if let Some((method_name, provider_error)) =
reason.provider_error::<ChainSpecT, TimerT>()
{
// Ignore potential failure of logging, as returning the original error is more
// important
let _result = self.log_failed_deserialization(method_name, &provider_error);
}

let response = jsonrpc::ResponseData::<()>::Error {
error: jsonrpc::Error {
code: reason.error_code(),
message: reason.error_message(),
data: request,
},
};

return serde_json::to_string(&response)
.map_err(|error| {
napi::Error::new(
napi::Status::Unknown,
format!("Failed to serialize response due to: {error}"),
)
})
.map(Response::from);
}
let Ok(request) = serde_json::from_str(&request) else {
let response = jsonrpc::ResponseData::<()>::Error {
error: jsonrpc::Error {
code: -32600, // Invalid Request
message: "Invalid Request".to_string(),
data: None,
},
};

return serde_json::to_string(&response)
.map_err(|error| {
napi::Error::new(
napi::Status::Unknown,
format!("Failed to serialize response due to: {error}"),
)
})
.map(Response::from);
};

let response = edr_provider::Provider::handle_request(self, request);
Expand Down
Loading
Loading