feat: reth binary and parsing of eth chain tests (#38)

* Scaffolding for reth test binary. wip for blockchain tests

* wip models for chain json tests

* reth binary and chain test

* fmt,clippy

* Update bin/reth/src/lib.rs

Co-authored-by: Bjerg <onbjerg@users.noreply.github.com>

* Update bin/reth/src/lib.rs

Co-authored-by: Bjerg <onbjerg@users.noreply.github.com>

* Update bin/reth/src/test_eth_chain/mod.rs

Co-authored-by: Bjerg <onbjerg@users.noreply.github.com>

* Update bin/reth/src/test_eth_chain/mod.rs

Co-authored-by: Bjerg <onbjerg@users.noreply.github.com>

* Update bin/reth/src/test_eth_chain/mod.rs

Co-authored-by: Bjerg <onbjerg@users.noreply.github.com>

* Update bin/reth/src/test_eth_chain/models.rs

Co-authored-by: Bjerg <onbjerg@users.noreply.github.com>

* Update bin/reth/src/test_eth_chain/models.rs

Co-authored-by: Bjerg <onbjerg@users.noreply.github.com>

* Update bin/reth/src/test_eth_chain/mod.rs

Co-authored-by: Bjerg <onbjerg@users.noreply.github.com>

* Update bin/reth/src/test_eth_chain/runner.rs

Co-authored-by: Bjerg <onbjerg@users.noreply.github.com>

* Move JsonU256 to primitives

* fmt

* Use eyre

* nits

Co-authored-by: Bjerg <onbjerg@users.noreply.github.com>
This commit is contained in:
rakita
2022-10-12 17:43:01 +02:00
committed by GitHub
parent 08d8a7f030
commit ae5935e6b2
16 changed files with 789 additions and 18 deletions

130
Cargo.lock generated
View File

@ -73,6 +73,17 @@ dependencies = [
"syn",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "auto_impl"
version = "1.0.1"
@ -263,6 +274,43 @@ dependencies = [
"libloading",
]
[[package]]
name = "clap"
version = "4.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "385007cbbed899260395a4107435fead4cad80684461b3cc78238bdcb0bad58f"
dependencies = [
"atty",
"bitflags",
"clap_derive",
"clap_lex",
"once_cell",
"strsim",
"termcolor",
]
[[package]]
name = "clap_derive"
version = "4.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db342ce9fda24fb191e2ed4e102055a4d381c1086a06630174cd8da8d5d917ce"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
dependencies = [
"os_str_bytes",
]
[[package]]
name = "const-oid"
version = "0.9.0"
@ -526,6 +574,16 @@ version = "2.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
[[package]]
name = "eyre"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb"
dependencies = [
"indenter",
"once_cell",
]
[[package]]
name = "fastrand"
version = "1.8.0"
@ -965,6 +1023,12 @@ dependencies = [
"syn",
]
[[package]]
name = "indenter"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
[[package]]
name = "indexmap"
version = "1.9.1"
@ -1457,6 +1521,12 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "os_str_bytes"
version = "6.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff"
[[package]]
name = "page_size"
version = "0.4.2"
@ -1716,6 +1786,18 @@ dependencies = [
[[package]]
name = "reth"
version = "0.1.0"
dependencies = [
"clap",
"eyre",
"reth-primitives",
"serde",
"serde_json",
"thiserror",
"tokio",
"tracing",
"tracing-futures",
"walkdir",
]
[[package]]
name = "reth-crate-template"
@ -1751,8 +1833,8 @@ dependencies = [
name = "reth-executor"
version = "0.1.0"
dependencies = [
"anyhow",
"async-trait",
"eyre",
"reth-interfaces",
"reth-primitives",
"revm",
@ -1792,6 +1874,8 @@ dependencies = [
"bytes",
"ethers-core",
"fastrlp",
"serde",
"serde_json",
]
[[package]]
@ -2026,6 +2110,15 @@ version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]]
name = "schannel"
version = "0.1.20"
@ -2263,6 +2356,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "strum"
version = "0.24.1"
@ -2335,6 +2434,15 @@ dependencies = [
"winapi",
]
[[package]]
name = "termcolor"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
dependencies = [
"winapi-util",
]
[[package]]
name = "thiserror"
version = "1.0.37"
@ -2544,6 +2652,17 @@ version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "walkdir"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
dependencies = [
"same-file",
"winapi",
"winapi-util",
]
[[package]]
name = "want"
version = "0.3.0"
@ -2673,6 +2792,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"

View File

@ -1,10 +1,6 @@
[package]
name = "reth"
version = "0.1.0"
edition = "2021"
[workspace]
members = [
"bin/reth",
"crate-template",
"crates/db",
"crates/executor",
@ -19,9 +15,4 @@ members = [
"crates/transaction-pool",
"crates/db"
]
[dependencies]
[[bin]]
path = "bin/reth.rs"
name = "reth"
default-members = ["bin/reth"]

View File

@ -1,3 +0,0 @@
fn main() {
println!("Hello, world!");
}

19
bin/reth/Cargo.toml Normal file
View File

@ -0,0 +1,19 @@
[package]
name = "reth"
version = "0.1.0"
edition = "2021"
license = "MIT OR Apache-2.0"
repository = "https://github.com/foundry-rs/reth"
readme = "README.md"
[dependencies]
eyre = "0.6.8"
clap = { version = "4.0", features = ["derive"] }
thiserror = "1.0"
tracing = "0.1"
tracing-futures = "0.2"
tokio = { version = "1.21", features = ["sync", "macros", "rt-multi-thread"] }
serde = "1.0"
serde_json = "1.0"
reth-primitives = { path = "../../crates/primitives" }
walkdir = "2.3"

36
bin/reth/src/cli.rs Normal file
View File

@ -0,0 +1,36 @@
use clap::{ArgAction, Parser, Subcommand};
use crate::test_eth_chain;
/// main function that parses cli and runs command
pub async fn run() -> eyre::Result<()> {
let opt = Cli::parse();
match opt.command {
Commands::TestEthChain(command) => command.execute().await,
}
}
/// Commands to be executed
#[derive(Subcommand)]
pub enum Commands {
/// Runs Ethereum blockchain tests
#[command(name = "test-chain")]
TestEthChain(test_eth_chain::Command),
}
#[derive(Parser)]
#[command(author, version="0.1", about="Reth binary", long_about = None)]
struct Cli {
/// The command to run
#[clap(subcommand)]
command: Commands,
/// Use verbose output
#[clap(short, long, action = ArgAction::Count, global = true)]
verbose: u8,
/// Silence all output
#[clap(short, long, global = true)]
silent: bool,
}

17
bin/reth/src/lib.rs Normal file
View File

@ -0,0 +1,17 @@
#![warn(missing_docs, unreachable_pub)]
#![deny(unused_must_use, rust_2018_idioms)]
#![doc(test(
no_crate_inject,
attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables))
))]
//! Rust Ethereum (reth) binary executable.
/// CLI definition and entrypoint
pub mod cli;
/// Utility functions.
pub mod util;
/// Command for executing Ethereum blockchain tests
pub mod test_eth_chain;

9
bin/reth/src/main.rs Normal file
View File

@ -0,0 +1,9 @@
use tracing::error;
#[tokio::main]
async fn main() {
if let Err(err) = reth::cli::run().await {
error!("Error: {:?}", err);
std::process::exit(1);
}
}

View File

@ -0,0 +1,52 @@
use crate::util;
use clap::Parser;
use std::path::PathBuf;
/// Models for parsing JSON blockchain tests
pub mod models;
/// Ethereum blockhain test runner
pub mod runner;
/// Execute Ethereum blockchain tests by specifying path to json files
#[derive(Debug, Parser)]
pub struct Command {
/// Path to Ethereum JSON test files
path: Vec<PathBuf>,
}
impl Command {
/// Execute the command
pub async fn execute(self) -> eyre::Result<()> {
// note the use of `into_iter()` to consume `items`
let task_group: Vec<_> = self
.path
.iter()
.map(|item| {
util::find_all_json_tests(item).into_iter().map(|file| {
let tfile = file.clone();
let join = tokio::spawn(async move { runner::run_test(tfile.as_path()).await });
(join, file)
})
})
.collect();
// await the tasks for resolve's to complete and give back our test results
let mut num_of_failed = 0;
let mut num_of_passed = 0;
for tasks in task_group {
for (join, file) in tasks {
match join.await.unwrap() {
Ok(_) => {
num_of_passed += 1;
}
Err(error) => {
num_of_failed += 1;
println!("Test {:?} failed:\n {error}\n", file);
}
}
}
}
println!("\nPASSED {num_of_passed}/{} tests\n", num_of_passed + num_of_failed);
Ok(())
}
}

View File

@ -0,0 +1,391 @@
use reth_primitives::{Address, Bloom, Bytes, JsonU256, H160, H256, H64};
use serde::{self, Deserialize};
use std::collections::BTreeMap;
/// Blockchain test deserializer.
#[derive(Debug, PartialEq, Eq, Deserialize)]
pub struct Test(pub BTreeMap<String, BlockchainTestData>);
/// Ethereum blockchain test data
#[derive(Debug, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BlockchainTestData {
/// Genesis block header.
pub genesis_block_header: Header,
/// Genesis rlp.
#[serde(rename = "genesisRLP")]
pub genesis_rlp: Option<Bytes>,
/// Blocks.
pub blocks: Vec<Block>,
/// Post state.
pub post_state: Option<State>,
/// Pre state.
pub pre: State,
/// Hash of best block.
pub lastblockhash: H256,
/// Network.
pub network: ForkSpec,
#[serde(default)]
/// Engine
pub self_engine: SealEngine,
}
/// Ethereum blockchain test data Header.
#[derive(Debug, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Header {
/// Bloom filter.
pub bloom: Bloom,
/// Coinbase.
pub coinbase: Address,
/// Difficulty.
pub difficulty: JsonU256,
/// Extra data.
pub extra_data: Bytes,
/// Gas limit.
pub gas_limit: JsonU256,
/// Gas used.
pub gas_used: JsonU256,
/// Block Hash.
pub hash: H256,
/// Mix hash.
pub mix_hash: H256,
/// Seal nonce.
pub nonce: H64,
/// Block number.
pub number: JsonU256,
/// Parent hash.
pub parent_hash: H256,
/// Receipt trie.
pub receipt_trie: H256,
/// State root.
pub state_root: H256,
/// Timestamp.
pub timestamp: JsonU256,
/// Transactions trie.
pub transactions_trie: H256,
/// Uncle hash.
pub uncle_hash: H256,
/// Base fee per gas.
pub base_fee_per_gas: Option<JsonU256>,
}
/// Ethereum blockchain test data Block.
#[derive(Debug, PartialEq, Eq, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct Block {
/// Block header.
pub block_header: Option<Header>,
/// Rlp block bytes
pub rlp: Bytes,
/// Transactions
pub transactions: Option<Vec<Transaction>>,
/// Uncle/Omner headers.
pub uncle_headers: Option<Vec<Header>>,
}
/// Ethereum blockchain test data State.
#[derive(Clone, Debug, Eq, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct State(pub RootOrState);
/// Merkle root hash or storage accounts.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
#[serde(untagged)]
pub enum RootOrState {
/// If state is too big, only state root is present
Root(H256),
/// Staet
State(BTreeMap<Address, Account>),
}
/// Spec account
#[derive(Debug, PartialEq, Eq, Deserialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct Account {
/// Balance.
pub balance: JsonU256,
/// Code.
pub code: Bytes,
/// Nonce.
pub nonce: JsonU256,
/// Storage.
pub storage: BTreeMap<JsonU256, JsonU256>,
}
/// Ethereum blockchain test data State.
#[derive(Debug, PartialEq, Eq, Deserialize)]
pub enum ForkSpec {
/// Fork EIP150.
EIP150,
/// Fork EIP158.
EIP158,
/// Fork Frontier.
Frontier,
/// Fork Homestead.
Homestead,
/// Fork Byzantium.
Byzantium,
/// Fork Constantinople.
Constantinople,
/// Fork ConstantinopleFix.
ConstantinopleFix,
/// Fork Istanbul.
Istanbul,
/// Fork EIP158ToByzantiumAt5.
EIP158ToByzantiumAt5,
/// Fork FrontierToHomesteadAt5.
FrontierToHomesteadAt5,
/// Fork HomesteadToDaoAt5.
HomesteadToDaoAt5,
/// Fork HomesteadToEIP150At5.
HomesteadToEIP150At5,
/// Fork ByzantiumToConstantinopleAt5.
ByzantiumToConstantinopleAt5,
/// Fork ByzantiumToConstantinopleFixAt5.
ByzantiumToConstantinopleFixAt5,
/// Fork Berlin.
Berlin,
/// Fork London.
London,
/// Fork BerlinToLondonAt5.
BerlinToLondonAt5,
/// Fork Merge,
Merge,
}
/// Json Block test possible engine kind.
#[derive(Debug, PartialEq, Eq, Default, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum SealEngine {
/// No consensus checks.
#[default]
NoProof,
}
/// Ethereum blockchain test transaction data.
#[derive(Debug, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Transaction {
/// Transaction type
#[serde(rename = "type")]
pub transaction_type: Option<JsonU256>,
/// Data.
pub data: Bytes,
/// Gas limit.
pub gas_limit: JsonU256,
/// Gas price.
pub gas_price: Option<JsonU256>,
/// Nonce.
pub nonce: JsonU256,
/// Signature r part.
pub r: JsonU256,
/// Signature s part.
pub s: JsonU256,
/// Parity bit.
pub v: JsonU256,
/// Transaction value.
pub value: JsonU256,
/// Chain ID.
pub chain_id: Option<JsonU256>,
/// Access list.
pub access_list: Option<AccessList>,
/// Max fee per gas.
pub max_fee_per_gas: Option<JsonU256>,
/// Max priority fee per gas
pub max_priority_fee_per_gas: Option<JsonU256>,
/// Transaction hash.
pub hash: Option<H256>,
}
/// Access list item
#[derive(Debug, PartialEq, Eq, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct AccessListItem {
/// Account address
pub address: H160,
/// Storage key.
pub storage_keys: Vec<H256>,
}
/// Access list.
pub type AccessList = Vec<AccessListItem>;
#[cfg(test)]
mod test {
use super::*;
use serde_json;
#[test]
fn blockchain_test_deserialize() {
let test = r#"{
"evmBytecode_d0g0v0_Berlin" : {
"_info" : {
"comment" : "",
"filling-rpc-server" : "evm version 1.10.18-unstable-53304ff6-20220503",
"filling-tool-version" : "retesteth-0.2.2-testinfo+commit.05e0b8ca.Linux.g++",
"generatedTestHash" : "0951de8d9e6b2a08e57234f57ef719a17aee9d7e9d7e852e454a641028b791a9",
"lllcversion" : "Version: 0.5.14-develop.2021.11.27+commit.401d5358.Linux.g++",
"solidity" : "Version: 0.8.5+commit.a4f2e591.Linux.g++",
"source" : "src/GeneralStateTestsFiller/stBugs/evmBytecodeFiller.json",
"sourceHash" : "6ced7b43100305d1cc5aee48344c0eab6002940358e2c126279ef8444c2dea5a"
},
"blocks" : [
{
"blockHeader" : {
"bloom" : "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "0x1000000000000000000000000000000000000000",
"difficulty" : "0x020000",
"extraData" : "0x00",
"gasLimit" : "0x54a60a4202e088",
"gasUsed" : "0x01d4c0",
"hash" : "0xb8152a06d2018ed9a1eb1eb6e1fe8c3478d8eae5b04d743bf4a1ec699510cfe5",
"mixHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce" : "0x0000000000000000",
"number" : "0x01",
"parentHash" : "0xb835c89a42605cfcc542381145b83c826caf10823b81af0f45091040a67e6601",
"receiptTrie" : "0x0ef77336cf7bfbd2c500dcefe7b48d0ef7896d38f6373fbeb301ea4dac3746a7",
"stateRoot" : "0x27bf1aca92967ecd83e11c52887203bbdcab73a27fe07e814cf749fa50483a53",
"timestamp" : "0x03e8",
"transactionsTrie" : "0x9008a2d4af552fea9b45675cd2af6d4117303b57da25b28438ccd1f6bad6828d",
"uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
},
"rlp" : "0xf90264f901fca0b835c89a42605cfcc542381145b83c826caf10823b81af0f45091040a67e6601a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347941000000000000000000000000000000000000000a027bf1aca92967ecd83e11c52887203bbdcab73a27fe07e814cf749fa50483a53a09008a2d4af552fea9b45675cd2af6d4117303b57da25b28438ccd1f6bad6828da00ef77336cf7bfbd2c500dcefe7b48d0ef7896d38f6373fbeb301ea4dac3746a7b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000018754a60a4202e0888301d4c08203e800a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f862f860800a8301d4c094b94f5374fce5edbc8e2a8697c15331677e6ebf0b80801ca0f3b41c283c02ed98318dc9cac3f0ddc3de2f2f7853a03299a46f22a7c6726c3aa0396ccb5968a532ea070924408625d3e36d4db21bfbd0cb070ba9e1fe9dba58abc0",
"transactions" : [
{
"data" : "0x",
"gasLimit" : "0x01d4c0",
"gasPrice" : "0x0a",
"nonce" : "0x00",
"r" : "0xf3b41c283c02ed98318dc9cac3f0ddc3de2f2f7853a03299a46f22a7c6726c3a",
"s" : "0x396ccb5968a532ea070924408625d3e36d4db21bfbd0cb070ba9e1fe9dba58ab",
"sender" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"to" : "0xb94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"v" : "0x1c",
"value" : "0x00"
}
],
"uncleHeaders" : [
]
}
],
"genesisBlockHeader" : {
"bloom" : "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "0x1000000000000000000000000000000000000000",
"difficulty" : "0x020000",
"extraData" : "0x00",
"gasLimit" : "0x54a60a4202e088",
"gasUsed" : "0x00",
"hash" : "0xb835c89a42605cfcc542381145b83c826caf10823b81af0f45091040a67e6601",
"mixHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce" : "0x0000000000000000",
"number" : "0x00",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"stateRoot" : "0x642a369a4a9dbf57d83ba05413910a5dd2cff93858c68e9e8293a8fffeae8660",
"timestamp" : "0x00",
"transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
},
"genesisRLP" : "0xf901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347941000000000000000000000000000000000000000a0642a369a4a9dbf57d83ba05413910a5dd2cff93858c68e9e8293a8fffeae8660a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000808754a60a4202e088808000a00000000000000000000000000000000000000000000000000000000000000000880000000000000000c0c0",
"lastblockhash" : "0xb8152a06d2018ed9a1eb1eb6e1fe8c3478d8eae5b04d743bf4a1ec699510cfe5",
"network" : "Berlin",
"postState" : {
"0x1000000000000000000000000000000000000000" : {
"balance" : "0x1bc16d674eda4f80",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x38beec8feeb7d618",
"code" : "0x",
"nonce" : "0x01",
"storage" : {
}
},
"0xb94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x00",
"code" : "0x67ffffffffffffffff600160006000fb",
"nonce" : "0x3f",
"storage" : {
}
}
},
"pre" : {
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x38beec8feeca2598",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"0xb94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x00",
"code" : "0x67ffffffffffffffff600160006000fb",
"nonce" : "0x3f",
"storage" : {
}
}
},
"sealEngine" : "NoProof"
}
}"#;
let res = serde_json::from_str::<Test>(test);
assert!(res.is_ok(), "Failed to deserialize BlockchainTestData with error: {:?}", res);
}
#[test]
fn header_deserialize() {
let test = r#"{
"baseFeePerGas" : "0x0a",
"bloom" : "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
"difficulty" : "0x020000",
"extraData" : "0x00",
"gasLimit" : "0x10000000000000",
"gasUsed" : "0x10000000000000",
"hash" : "0x7ebfee2a2c785fef181b8ffd92d4a48a0660ec000f465f309757e3f092d13882",
"mixHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce" : "0x0000000000000000",
"number" : "0x01",
"parentHash" : "0xa8f2eb2ea9dccbf725801eef5a31ce59bada431e888dfd5501677cc4365dc3be",
"receiptTrie" : "0xbdd943f5c62ae0299324244a0f65524337ada9817e18e1764631cc1424f3a293",
"stateRoot" : "0xc9c6306ee3e5acbaabe8e2fa28a10c12e27bad1d1aacc271665149f70519f8b0",
"timestamp" : "0x03e8",
"transactionsTrie" : "0xf5893b055ca05e4f14d1792745586a1376e218180bd56bd96b2b024e1dc78300",
"uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
}"#;
let res = serde_json::from_str::<Header>(test);
assert!(res.is_ok(), "Failed to deserialize Header with error: {:?}", res);
}
#[test]
fn transaction_deserialize() {
let test = r#"[
{
"accessList" : [
],
"chainId" : "0x01",
"data" : "0x693c61390000000000000000000000000000000000000000000000000000000000000000",
"gasLimit" : "0x10000000000000",
"maxFeePerGas" : "0x07d0",
"maxPriorityFeePerGas" : "0x00",
"nonce" : "0x01",
"r" : "0x5fecc3972a35c9e341b41b0c269d9a7325e13269fb01c2f64cbce1046b3441c8",
"s" : "0x7d4d0eda0e4ebd53c5d0b6fc35c600b317f8fa873b3963ab623ec9cec7d969bd",
"sender" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"to" : "0xcccccccccccccccccccccccccccccccccccccccc",
"type" : "0x02",
"v" : "0x01",
"value" : "0x00"
}
]"#;
let res = serde_json::from_str::<Vec<Transaction>>(test);
assert!(res.is_ok(), "Failed to deserialize transactin with error: {:?}", res);
}
}

View File

@ -0,0 +1,13 @@
use super::models::Test;
use std::path::Path;
/// Run one JSON-encoded Ethereum blockchain test at the specified path.
pub async fn run_test(path: &Path) -> eyre::Result<()> {
let json_file = std::fs::read(path)?;
let suits: Test = serde_json::from_reader(&*json_file)?;
for suit in suits.0 {
println!("TODO:{:?}", suit.0);
}
Ok(())
}

11
bin/reth/src/util/mod.rs Normal file
View File

@ -0,0 +1,11 @@
use std::path::{Path, PathBuf};
use walkdir::{DirEntry, WalkDir};
pub(crate) fn find_all_json_tests(path: &Path) -> Vec<PathBuf> {
WalkDir::new(path)
.into_iter()
.filter_map(|e| e.ok())
.filter(|e| e.file_name().to_string_lossy().ends_with(".json"))
.map(DirEntry::into_path)
.collect::<Vec<PathBuf>>()
}

View File

@ -12,4 +12,4 @@ reth-primitives = { path = "../primitives" }
reth-interfaces = { path = "../interfaces" }
async-trait = "0.1.57"
thiserror = "1.0.37"
anyhow = "1.0"
eyre = "0.6.8"

View File

@ -10,4 +10,8 @@ description = "Commonly used types in reth."
[dependencies]
fastrlp = { version = "0.1.3" }
ethers-core = { git = "https://github.com/gakonst/ethers-rs", default-features = false }
bytes = "1.2"
bytes = "1.2"
serde = "1.0"
[dev-dependencies]
serde_json = "1.0"

View File

@ -1,4 +1,4 @@
use crate::{Header, HeaderLocked, Receipt, Transaction, TransactionSigned};
use crate::{Header, HeaderLocked, Receipt, Transaction, TransactionSigned, H256};
use std::ops::Deref;
/// Ethereum full block.
@ -30,6 +30,13 @@ pub struct BlockLocked {
pub receipts: Vec<Receipt>,
}
impl BlockLocked {
/// Header hash.
pub fn hash(&self) -> H256 {
self.header.hash()
}
}
impl Deref for BlockLocked {
type Target = Header;
fn deref(&self) -> &Self::Target {

View File

@ -0,0 +1,94 @@
use crate::U256;
use serde::{
de::{Error, Visitor},
Deserialize, Deserializer, Serialize, Serializer,
};
use std::{fmt, str::FromStr};
/// Wrapper around primitive U256 type to handle edge cases of json parser
#[derive(Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
pub struct JsonU256(pub U256);
impl Serialize for JsonU256 {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.to_string().serialize(serializer)
}
}
impl<'a> Deserialize<'a> for JsonU256 {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'a>,
{
deserializer.deserialize_any(JsonU256Visitor)
}
}
struct JsonU256Visitor;
impl<'a> Visitor<'a> for JsonU256Visitor {
type Value = JsonU256;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "a hex encoding or decimal number")
}
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
where
E: Error,
{
Ok(JsonU256(U256::from(value)))
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: Error,
{
let value = match value.len() {
0 => U256::from(0),
2 if value.starts_with("0x") => U256::zero(),
_ if value.starts_with("0x") => U256::from_str(&value[2..]).map_err(|e| {
Error::custom(format!("Parsin JsonU256 as hex failed {}: {}", value, e))
})?,
_ => U256::from_dec_str(value).map_err(|e| {
Error::custom(format!("Parsin JsonU256 as decimal failed {}: {:?}", value, e))
})?,
};
Ok(JsonU256(value))
}
fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
where
E: Error,
{
self.visit_str(value.as_ref())
}
}
#[cfg(test)]
mod test {
use super::JsonU256;
use crate::U256;
use serde_json;
#[test]
fn jsonu256_deserialize() {
let deserialized: Vec<JsonU256> =
serde_json::from_str(r#"["","0", "0x","10",10,"0x10"]"#).unwrap();
assert_eq!(
deserialized,
vec![
JsonU256(U256::from(0)),
JsonU256(U256::from(0)),
JsonU256(U256::from(0)),
JsonU256(U256::from(10)),
JsonU256(U256::from(10)),
JsonU256(U256::from(16)),
]
);
}
}

View File

@ -11,6 +11,7 @@ mod account;
mod block;
mod chain;
mod header;
mod jsonu256;
mod log;
mod receipt;
mod transaction;
@ -19,6 +20,7 @@ pub use account::Account;
pub use block::{Block, BlockLocked};
pub use chain::Chain;
pub use header::{Header, HeaderLocked};
pub use jsonu256::JsonU256;
pub use log::Log;
pub use receipt::Receipt;
pub use transaction::{AccessList, AccessListItem, Transaction, TransactionSigned, TxType};