Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(anvil): port serde helpers, remove multiline jsons #6404

Merged
merged 1 commit into from
Nov 22, 2023
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
186 changes: 92 additions & 94 deletions crates/anvil/core/src/eth/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub mod state;
pub mod serde_helpers;

#[cfg(feature = "serde")]
use ethers_core::types::serde_helpers::*;
use ethers_core::types::serde_helpers::{deserialize_number, deserialize_number_opt, deserialize_number_seq};

#[cfg(feature = "serde")]
use self::serde_helpers::*;
Expand Down Expand Up @@ -87,7 +87,10 @@ pub enum EthRequest {
EthGetBlockByHash(B256, bool),

#[cfg_attr(feature = "serde", serde(rename = "eth_getBlockByNumber"))]
Copy link
Member

@DaniPopes DaniPopes Nov 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unrelated to this PR, is there a reason to feature-gate serde? It's not removing it from dependencies since it depends on serde_json and many more
@mattsse

EthGetBlockByNumber(BlockNumber, bool),
EthGetBlockByNumber(
#[cfg_attr(feature = "serde", serde(deserialize_with = "lenient_block_number::lenient_block_number"))]
BlockNumber,
bool),

#[cfg_attr(feature = "serde", serde(rename = "eth_getTransactionCount"))]
EthGetTransactionCount(Address, Option<BlockId>),
Expand All @@ -98,7 +101,13 @@ pub enum EthRequest {
)]
EthGetTransactionCountByHash(B256),

#[cfg_attr(feature = "serde", serde(rename = "eth_getBlockTransactionCountByNumber",))]
#[cfg_attr(
feature = "serde",
serde(
rename = "eth_getBlockTransactionCountByNumber",
deserialize_with = "lenient_block_number::lenient_block_number_seq"
)
)]
EthGetTransactionCountByNumber(BlockNumber),

#[cfg_attr(
Expand All @@ -107,7 +116,13 @@ pub enum EthRequest {
)]
EthGetUnclesCountByHash(B256),

#[cfg_attr(feature = "serde", serde(rename = "eth_getUncleCountByBlockNumber",))]
#[cfg_attr(
feature = "serde",
serde(
rename = "eth_getUncleCountByBlockNumber",
deserialize_with = "lenient_block_number::lenient_block_number_seq"
)
)]
EthGetUnclesCountByNumber(BlockNumber),

#[cfg_attr(feature = "serde", serde(rename = "eth_getCode"))]
Expand Down Expand Up @@ -175,7 +190,11 @@ pub enum EthRequest {
EthGetUncleByBlockHashAndIndex(B256, Index),

#[cfg_attr(feature = "serde", serde(rename = "eth_getUncleByBlockNumberAndIndex"))]
EthGetUncleByBlockNumberAndIndex(BlockNumber, Index),
EthGetUncleByBlockNumberAndIndex(
#[cfg_attr(feature = "serde", serde(deserialize_with = "lenient_block_number::lenient_block_number"))]
BlockNumber,
Index
),

#[cfg_attr(feature = "serde", serde(rename = "eth_getLogs", with = "sequence"))]
EthGetLogs(Filter),
Expand Down Expand Up @@ -248,6 +267,10 @@ pub enum EthRequest {
TraceTransaction(B256),

/// Trace transaction endpoint for parity's `trace_block`
#[cfg_attr(
feature = "serde",
serde(rename = "trace_block", deserialize_with = "lenient_block_number::lenient_block_number_seq")
)]
TraceBlock(BlockNumber),

// Custom endpoints, they're not extracted to a separate type out of serde convenience
Expand Down Expand Up @@ -582,7 +605,10 @@ pub enum EthRequest {
/// https://github.com/otterscan/otterscan/blob/071d8c55202badf01804f6f8d53ef9311d4a9e47/src/useProvider.ts#L71
/// Related upstream issue: https://github.com/otterscan/otterscan/issues/1081
#[cfg_attr(feature = "serde", serde(rename = "erigon_getHeaderByNumber"))]
ErigonGetHeaderByNumber(BlockNumber),
ErigonGetHeaderByNumber(
#[cfg_attr(feature = "serde", serde(deserialize_with = "lenient_block_number::lenient_block_number_seq"))]
BlockNumber
),

/// Otterscan's `ots_getApiLevel` endpoint
/// Used as a simple API versioning scheme for the ots_* namespace
Expand All @@ -598,7 +624,11 @@ pub enum EthRequest {
/// Otterscan's `ots_hasCode` endpoint
/// Check if an ETH address contains code at a certain block number.
#[cfg_attr(feature = "serde", serde(rename = "ots_hasCode"))]
OtsHasCode(Address, BlockNumber),
OtsHasCode(
Address,
#[cfg_attr(feature = "serde", serde(deserialize_with = "lenient_block_number::lenient_block_number", default))]
BlockNumber
),

/// Otterscan's `ots_traceTransaction` endpoint
/// Trace a transaction and generate a trace call tree.
Expand All @@ -615,7 +645,10 @@ pub enum EthRequest {
/// method, but can be optimized by excluding unnecessary data such as transactions and
/// logBloom
#[cfg_attr(feature = "serde", serde(rename = "ots_getBlockDetails"))]
OtsGetBlockDetails(BlockNumber),
OtsGetBlockDetails(
#[cfg_attr(feature = "serde", serde(deserialize_with = "lenient_block_number::lenient_block_number", default))]
BlockNumber
),

/// Otterscan's `ots_getBlockDetails` endpoint
/// Same as `ots_getBlockDetails`, but receiving a block hash instead of number
Expand Down Expand Up @@ -715,11 +748,10 @@ mod tests {

#[test]
fn test_eth_get_proof() {
let s =
r#"{"method":"eth_getProof","params":["0x7F0d15C7FAae65896648C8273B6d7E43f58Fa842",["
0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"],"latest"]}"#; let
value: serde_json::Value = serde_json::from_str(s).unwrap(); let _req =
serde_json::from_value::<EthRequest>(value).unwrap(); }
let s = r#"{"method":"eth_getProof","params":["0x7F0d15C7FAae65896648C8273B6d7E43f58Fa842",["0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"],"latest"]}"#;
let value: serde_json::Value = serde_json::from_str(s).unwrap();
let _req = serde_json::from_value::<EthRequest>(value).unwrap();
}

#[test]
fn test_eth_chain_id() {
Expand Down Expand Up @@ -1272,27 +1304,24 @@ serde_json::from_value::<EthRequest>(value).unwrap(); }

#[test]
fn test_eth_uncle_count_by_block_hash() {
let s =
r#"{"jsonrpc":"2.0","method":"eth_getUncleCountByBlockHash","params":["
0x4a3b0fce2cb9707b0baa68640cf2fe858c8bb4121b2a8cb904ff369d38a560ff"]}"#; let value:
serde_json::Value = serde_json::from_str(s).unwrap(); let _req =
serde_json::from_value::<EthRequest>(value).unwrap(); }
let s = r#"{"jsonrpc":"2.0","method":"eth_getUncleCountByBlockHash","params":["0x4a3b0fce2cb9707b0baa68640cf2fe858c8bb4121b2a8cb904ff369d38a560ff"]}"#;
let value: serde_json::Value = serde_json::from_str(s).unwrap();
let _req = serde_json::from_value::<EthRequest>(value).unwrap();
}

#[test]
fn test_eth_block_tx_count_by_block_hash() {
let s =
r#"{"jsonrpc":"2.0","method":"eth_getBlockTransactionCountByHash","params":["
0x4a3b0fce2cb9707b0baa68640cf2fe858c8bb4121b2a8cb904ff369d38a560ff"]}"#; let value:
serde_json::Value = serde_json::from_str(s).unwrap(); let _req =
serde_json::from_value::<EthRequest>(value).unwrap(); }
let s = r#"{"jsonrpc":"2.0","method":"eth_getBlockTransactionCountByHash","params":["0x4a3b0fce2cb9707b0baa68640cf2fe858c8bb4121b2a8cb904ff369d38a560ff"]}"#;
let value: serde_json::Value = serde_json::from_str(s).unwrap();
let _req = serde_json::from_value::<EthRequest>(value).unwrap();
}

#[test]
fn test_eth_get_logs() {
let s =
r#"{"jsonrpc":"2.0","method":"eth_getLogs","params":[{"topics":["
0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b"]}],"id":74}"#; let
value: serde_json::Value = serde_json::from_str(s).unwrap(); let _req =
serde_json::from_value::<EthRequest>(value).unwrap(); }
let s = r#"{"jsonrpc":"2.0","method":"eth_getLogs","params":[{"topics":["0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b"]}],"id":74}"#;
let value: serde_json::Value = serde_json::from_str(s).unwrap();
let _req = serde_json::from_value::<EthRequest>(value).unwrap();
}

#[test]
fn test_eth_new_filter() {
Expand Down Expand Up @@ -1348,36 +1377,26 @@ true}]}"#; let value: serde_json::Value = serde_json::from_str(s).unwrap
}

#[test]
#[test]
fn test_serde_debug_trace_call() {
let s = r#"{"method": "debug_traceCall", "params":
[{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"
0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"}]}"#; let value: serde_json::Value =
serde_json::from_str(s).unwrap(); let _req =
serde_json::from_value::<EthRequest>(value).unwrap();
let s = r#"{"method": "debug_traceCall", "params": [{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"}]}"#;
let value: serde_json::Value = serde_json::from_str(s).unwrap();
let _req = serde_json::from_value::<EthRequest>(value).unwrap();

let s = r#"{"method": "debug_traceCall", "params":
[{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"
0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"}, { "blockNumber": "latest" }]}"#; let value:
serde_json::Value = serde_json::from_str(s).unwrap(); let _req =
serde_json::from_value::<EthRequest>(value).unwrap();
let s = r#"{"method": "debug_traceCall", "params": [{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"}, { "blockNumber": "latest" }]}"#;
let value: serde_json::Value = serde_json::from_str(s).unwrap();
let _req = serde_json::from_value::<EthRequest>(value).unwrap();

let s = r#"{"method": "debug_traceCall", "params":
[{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"
0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"}, { "blockNumber": "0x0" }]}"#; let value:
serde_json::Value = serde_json::from_str(s).unwrap(); let _req =
serde_json::from_value::<EthRequest>(value).unwrap();
let s = r#"{"method": "debug_traceCall", "params": [{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"}, { "blockNumber": "0x0" }]}"#;
let value: serde_json::Value = serde_json::from_str(s).unwrap();
let _req = serde_json::from_value::<EthRequest>(value).unwrap();

let s = r#"{"method": "debug_traceCall", "params":
[{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"
0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"}, { "blockHash":
"0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" }]}"#; let value:
serde_json::Value = serde_json::from_str(s).unwrap(); let _req =
serde_json::from_value::<EthRequest>(value).unwrap();
let s = r#"{"method": "debug_traceCall", "params": [{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"}, { "blockHash": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" }]}"#;
let value: serde_json::Value = serde_json::from_str(s).unwrap();
let _req = serde_json::from_value::<EthRequest>(value).unwrap();

let s = r#"{"method": "debug_traceCall", "params":
[{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"
0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"}, { "blockNumber": "0x0" }, {"disableStorage":
true}]}"#; let value: serde_json::Value = serde_json::from_str(s).unwrap();
let s = r#"{"method": "debug_traceCall", "params": [{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"}, { "blockNumber": "0x0" }, {"disableStorage": true}]}"#;
let value: serde_json::Value = serde_json::from_str(s).unwrap();
let _req = serde_json::from_value::<EthRequest>(value).unwrap();
}

Expand All @@ -1390,36 +1409,24 @@ serde_json::from_value::<EthRequest>(value).unwrap(); }

#[test]
fn test_eth_call() {
let req =
r#"{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"
0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"}"#; let _req =
serde_json::from_str::<TransactionRequest>(req).unwrap();

let s = r#"{"method": "eth_call", "params":
[{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"
0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"},"latest"]}"#; let _req =
serde_json::from_str::<EthRequest>(s).unwrap();

let s = r#"{"method": "eth_call", "params":
[{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"
0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"}]}"#; let _req =
serde_json::from_str::<EthRequest>(s).unwrap();

let s = r#"{"method": "eth_call", "params":
[{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"
0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"}, { "blockNumber": "latest" }]}"#; let _req =
serde_json::from_str::<EthRequest>(s).unwrap();

let s = r#"{"method": "eth_call", "params":
[{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"
0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"}, { "blockNumber": "0x0" }]}"#; let _req =
serde_json::from_str::<EthRequest>(s).unwrap();

let s = r#"{"method": "eth_call", "params":
[{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"
0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"}, { "blockHash":
"0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" }]}"#; let _req =
serde_json::from_str::<EthRequest>(s).unwrap(); }
let req = r#"{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"}"#;
let _req =serde_json::from_str::<CallRequest>(req).unwrap();

let s = r#"{"method": "eth_call", "params":[{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"},"latest"]}"#;
let _req = serde_json::from_str::<EthRequest>(s).unwrap();

let s = r#"{"method": "eth_call", "params":[{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"}]}"#;
let _req = serde_json::from_str::<EthRequest>(s).unwrap();

let s = r#"{"method": "eth_call", "params":[{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"}, { "blockNumber": "latest" }]}"#;
let _req = serde_json::from_str::<EthRequest>(s).unwrap();

let s = r#"{"method": "eth_call", "params":[{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"}, { "blockNumber": "0x0" }]}"#;
let _req = serde_json::from_str::<EthRequest>(s).unwrap();

let s = r#"{"method": "eth_call", "params":[{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"}, { "blockHash":"0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" }]}"#;
let _req = serde_json::from_str::<EthRequest>(s).unwrap();
}

#[test]
fn test_serde_eth_balance() {
Expand Down Expand Up @@ -1453,17 +1460,8 @@ serde_json::from_str::<EthRequest>(s).unwrap(); }

#[test]
fn test_eth_sign_typed_data() {
let s =
r#"{"method":"eth_signTypedData_v4","params":["0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826",
{"types":{"EIP712Domain":[{"name":"name","type":"string"},{"name":"version","type":"string"},{"
name":"chainId","type":"uint256"},{"name":"verifyingContract","type":"address"}],"Person":[{"
name":"name","type":"string"},{"name":"wallet","type":"address"}],"Mail":[{"name":"from","type":"
Person"},{"name":"to","type":"Person"},{"name":"contents","type":"string"}]},"primaryType":"Mail"
,"domain":{"name":"Ether
Mail","version":"1","chainId":1,"verifyingContract":"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"
},"message":{"from":{"name":"Cow","wallet":"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826"},"to":{"
name":"Bob","wallet":"0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB"},"contents":"Hello,
Bob!"}}]}"#; let value: serde_json::Value = serde_json::from_str(s).unwrap();
let s = r#"{"method":"eth_signTypedData_v4","params":["0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826", {"types":{"EIP712Domain":[{"name":"name","type":"string"},{"name":"version","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","type":"address"}],"Person":[{"name":"name","type":"string"},{"name":"wallet","type":"address"}],"Mail":[{"name":"from","type":"Person"},{"name":"to","type":"Person"},{"name":"contents","type":"string"}]},"primaryType":"Mail","domain":{"name":"Ether Mail","version":"1","chainId":1,"verifyingContract":"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"},"message":{"from":{"name":"Cow","wallet":"0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826"},"to":{"name":"Bob","wallet":"0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB"},"contents":"Hello, Bob!"}}]}"#;
let value: serde_json::Value = serde_json::from_str(s).unwrap();
let _req = serde_json::from_value::<EthRequest>(value).unwrap();
}
}
57 changes: 57 additions & 0 deletions crates/anvil/core/src/eth/serde_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,60 @@ pub mod empty_params {
Ok(())
}
}

/// A module that deserializes either a BlockNumberOrTag, or a simple number.
pub mod lenient_block_number {
use alloy_rpc_types::BlockNumberOrTag;
use serde::{Deserializer, Deserialize};
/// Following the spec the block parameter is either:
///
/// > HEX String - an integer block number
/// > String "earliest" for the earliest/genesis block
/// > String "latest" - for the latest mined block
/// > String "pending" - for the pending state/transactions
///
/// and with EIP-1898:
/// > blockNumber: QUANTITY - a block number
/// > blockHash: DATA - a block hash
///
/// <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1898.md>
///
/// EIP-1898 does not all calls that use `BlockNumber` like `eth_getBlockByNumber` and doesn't list
/// raw integers as supported.
///
/// However, there are dev node implementations that support integers, such as ganache: <https://github.com/foundry-rs/foundry/issues/1868>
///
/// N.B.: geth does not support ints in `eth_getBlockByNumber`
pub fn lenient_block_number<'de, D>(deserializer: D) -> Result<BlockNumberOrTag, D::Error>
where
D: Deserializer<'de>,
{
LenientBlockNumber::deserialize(deserializer).map(Into::into)
}

/// Same as `lenient_block_number` but requires to be `[num; 1]`
pub fn lenient_block_number_seq<'de, D>(deserializer: D) -> Result<BlockNumberOrTag, D::Error>
where
D: Deserializer<'de>,
{
let num = <[LenientBlockNumber; 1]>::deserialize(deserializer)?[0].into();
Ok(num)
}

/// Various block number representations, See [`lenient_block_number()`]
#[derive(Clone, Copy, Deserialize)]
#[serde(untagged)]
pub enum LenientBlockNumber {
BlockNumber(BlockNumberOrTag),
Num(u64),
}

impl From<LenientBlockNumber> for BlockNumberOrTag {
fn from(b: LenientBlockNumber) -> Self {
match b {
LenientBlockNumber::BlockNumber(b) => b,
LenientBlockNumber::Num(b) => b.into(),
}
}
}
}
Loading