Skip to content

Commit

Permalink
refactor testing, 1229 tests now passing
Browse files Browse the repository at this point in the history
  • Loading branch information
max-wickham committed Mar 30, 2024
1 parent 1336710 commit 5df0391
Show file tree
Hide file tree
Showing 12 changed files with 867 additions and 466 deletions.
13 changes: 13 additions & 0 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
workspace = { members = ["util"] }
workspace = { members = [ "official_test_types","util"] }
[package]
name = "ethereum_evm"
version = "0.1.0"
Expand All @@ -8,6 +8,7 @@ edition = "2021"

[dependencies]
test_gen = { path = "./test_gen" }
official_test_types = { path = "./official_test_types" }
util = { path = "./util" }
array-init = "2.1.0"
ethereum = "0.15.0"
Expand Down
10 changes: 10 additions & 0 deletions official_test_types/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "official_test_types"
version = "0.1.0"
edition = "2021"

[dependencies]
hex = "0.4.3"
primitive-types = { version = "0.12", features = ["rlp", "serde"] }
serde = { version = "1", features = ["derive"] }
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
2 changes: 2 additions & 0 deletions official_test_types/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod types;
mod util;
217 changes: 217 additions & 0 deletions official_test_types/src/types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
// use ethereum_evm::util::{h256_to_u256, u256_to_h256};
use hex::FromHex;
use primitive_types::{H256, U256};
use serde::{Deserialize, Deserializer, Serialize};
use std::{collections::BTreeMap, fmt};
use crate::util::{Hex, u256_to_h256};

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize)]
struct WrappedU256(U256);

impl<'de> Deserialize<'de> for WrappedU256 {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct H256Visitor;

impl<'de> serde::de::Visitor<'de> for H256Visitor {
type Value = WrappedU256;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a string representing a hex-encoded H256 value")
}

fn visit_str<E>(self, value: &str) -> Result<WrappedU256, E>
where
E: serde::de::Error,
{
let fixed_length_str: String;
let mut value_without_prefix = if value.starts_with("0x") {
&value[2..] // Skip the first two characters (0x)
} else {
value
};
if value_without_prefix.len() % 2 == 1{
fixed_length_str = "0".to_string() + value_without_prefix;
value_without_prefix = fixed_length_str.as_str();

}
let hash_bytes: Vec<u8> = match Vec::<u8>::from_hex(value_without_prefix) {
Ok(bytes) => bytes,
Err(_) => return Err(serde::de::Error::invalid_value(serde::de::Unexpected::Str(value), &self)),
};

let mut hash = [0u8; 32];
let num_bytes_to_copy = hash_bytes.len().min(32);
// println!("num_bytes_to_copy: {}", num_bytes_to_copy);
// println!("hash_bytes: {:x?}", hash_bytes);
hash[32 - num_bytes_to_copy..32].copy_from_slice(&hash_bytes);
// println!("hash: {:x?}", hash);
Ok(WrappedU256(U256::from(hash)))
}
}

deserializer.deserialize_str(H256Visitor)
}
}


#[derive(Clone, Debug, Eq, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TestStateMulti {
#[serde(rename = "_info")]
pub info: TestInfo,
pub env: TestEnv,
pub post: BTreeMap<String, Vec<TestPost>>,
pub pre: BTreeMap<U256, TestContract>,
pub transaction: TestTransactionMulti,
}

impl TestStateMulti {
pub fn tests(&self) -> Vec<TestState> {
let mut tests = Vec::new();
for (fork, post_states) in &self.post {
if fork == "Berlin" {
let mut new_tests: Vec<TestState> = post_states
.iter()
.enumerate()
.map(|(index, post_state)| TestState {
info: self.info.clone(),
env: self.env.clone(),
fork: fork.clone(),
post: post_state.clone(),
pre: self.pre.clone(),
transaction: TestTransaction {
data: self.transaction.data[post_state.indexes.data].0.clone(),
gas_limit: self.transaction.gas_limit[post_state.indexes.gas],
gas_price: self.transaction.gas_price,
max_fee_per_gas: self.transaction.max_fee_per_gas,
max_priority_fee_per_gas: self.transaction.max_priority_fee_per_gas,
nonce: self.transaction.nonce,
secret_key: self.transaction.secret_key,
sender: self.transaction.sender,
to: self.transaction.to,
value: self.transaction.value[post_state.indexes.value],
},
})
.collect();
tests.append(&mut new_tests);
}
}
tests
}
}

#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TestState {
#[serde(rename = "_info")]
pub info: TestInfo,
pub env: TestEnv,
pub fork: String,
pub post: TestPost,
pub pre: BTreeMap<U256, TestContract>,
pub transaction: TestTransaction,
}

#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TestInfo {
pub comment: String,
#[serde(rename = "filling-rpc-server")]
pub filling_rpc_server: String,
#[serde(rename = "filling-tool-version")]
pub filling_tool_version: String,
pub labels: Option<BTreeMap<String, String>>,
pub generated_test_hash: String,
#[serde(rename = "lllcversion")]
pub lllc_version: String,
pub solidity: String,
pub source: String,
pub source_hash: String,
}

#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TestEnv {
pub current_base_fee: U256,
pub current_coinbase: U256,
pub current_difficulty: U256,
pub current_excess_blob_gas: U256,
pub current_gas_limit: U256,
pub current_number: U256,
pub current_random: U256,
pub current_timestamp: U256,
}

#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TestPost {
pub hash: H256,
pub indexes: TestPostIndexes,
pub logs: U256,
#[serde(rename = "txbytes")]
pub tx_bytes: Hex,
}

#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TestPostIndexes {
pub data: usize,
pub gas: usize,
pub value: usize,
}

#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TestContract {
balance: WrappedU256,
pub code: Hex,
nonce: WrappedU256,
storage: BTreeMap<WrappedU256, WrappedU256>,
}

impl TestContract{
pub fn storage(&self) -> BTreeMap<H256, H256> {
self.storage.iter().map(|(k, v)| (u256_to_h256(k.0), u256_to_h256(v.0))).collect()
}

pub fn nonce(&self) -> U256 {
self.nonce.0
}

pub fn balance(&self) -> U256 {
self.balance.0
}
}

#[derive(Clone, Debug, Eq, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TestTransactionMulti {
pub data: Vec<Hex>,
pub gas_limit: Vec<U256>,
pub gas_price: Option<U256>,
pub max_fee_per_gas: Option<U256>,
pub max_priority_fee_per_gas: Option<U256>,
pub nonce: U256,
pub secret_key: U256,
pub to: U256,
pub sender: U256,
pub value: Vec<U256>,
}

#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TestTransaction {
pub data: Vec<u8>,
pub gas_limit: U256,
pub gas_price: Option<U256>,
pub max_fee_per_gas: Option<U256>,
pub max_priority_fee_per_gas: Option<U256>,
pub nonce: U256,
pub secret_key: U256,
pub sender: U256,
pub to: U256,
pub value: U256,
}
70 changes: 70 additions & 0 deletions official_test_types/src/util.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
use hex::FromHex;
use serde::{
de::{Error, Visitor}, ser::SerializeSeq, Deserialize, Deserializer, Serialize, Serializer
};
use primitive_types::{H256, U256};
use std::fmt;


pub fn u256_to_h256(v: U256) -> H256 {
let mut r = H256::default();
v.to_big_endian(&mut r[..]);
r
}


// TODO reimplement;

#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct Hex(#[serde(deserialize_with = "deserialize_hex_bytes", serialize_with = "serialize_hex_bytes")] pub Vec<u8>);

fn deserialize_hex_bytes<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
where
D: Deserializer<'de>,
{
struct HexStrVisitor;

impl<'de> Visitor<'de> for HexStrVisitor {
type Value = Vec<u8>;

fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "a hex encoded string")
}

fn visit_str<E>(self, data: &str) -> Result<Self::Value, E>
where
E: Error,
{
if &data[0..2] != "0x" {
return Err(Error::custom("should start with 0x"));
}

FromHex::from_hex(&data[2..]).map_err(Error::custom)
}

fn visit_borrowed_str<E>(self, data: &'de str) -> Result<Self::Value, E>
where
E: Error,
{
if &data[0..2] != "0x" {
return Err(Error::custom("should start with 0x"));
}

FromHex::from_hex(&data[2..]).map_err(Error::custom)
}
}

deserializer.deserialize_str(HexStrVisitor)
}

fn serialize_hex_bytes<S>(data: &Vec<u8>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let hex_string: String = data.iter()
.map(|byte| format!("{:02X}", byte))
.collect();
let hex_string = "0x".to_string() + &hex_string;

serializer.serialize_str(&hex_string)
}
12 changes: 6 additions & 6 deletions src/evm_logic/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ pub struct EVMContext {
}

impl EVMContext {

#[inline]
fn create_sub_context(
address: U256,
Expand Down Expand Up @@ -88,14 +87,15 @@ impl EVMContext {
#[inline]
fn execute_program(&mut self, runtime: &mut impl Runtime, debug: bool) -> ExecutionResult {
runtime.add_context();

let mut result;
if self.program.len() != 0 {
loop {
result = self.execute_next_instruction(runtime, debug);
match &result {
ExecutionResult::InProgress => {},
_ => {break;}
ExecutionResult::InProgress => {}
_ => {
break;
}
}
}
} else {
Expand Down Expand Up @@ -136,8 +136,7 @@ impl EVMContext {

#[inline]
fn check_gas_usage(&self) -> ExecutionResult {
match !self.gas_recorder.is_valid_with_refunds()
{
match !self.gas_recorder.is_valid_with_refunds() {
true => ExecutionResult::Error(ExecutionError::InsufficientGas),
false => ExecutionResult::InProgress,
}
Expand All @@ -164,6 +163,7 @@ pub fn execute_transaction(
value: value,
data: data.to_vec(),
};

let transaction = Transaction {
origin: origin,
gas_price: gas_price,
Expand Down
Loading

0 comments on commit 5df0391

Please sign in to comment.