Skip to content

feat: integrate revm + impl address recovery #73

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

Merged
merged 49 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
af59cf4
Draft
fmoletta Jun 26, 2024
9830005
Create BlockEnv from BlockHeader
fmoletta Jun 27, 2024
f568b4c
Add state cache
fmoletta Jun 27, 2024
19b47e1
Merge branch 'main' of https://github.com/lambdaclass/ethrex into add…
fmoletta Jun 27, 2024
4d82b04
Fill more tx env fields
fmoletta Jun 27, 2024
9c8f150
Move `Transaction` to its own module
fmoletta Jun 27, 2024
d48b3f6
Update crate name + add access list
fmoletta Jun 27, 2024
ff36e10
Merge branch 'main' of https://github.com/lambdaclass/ethrex into add…
fmoletta Jun 27, 2024
0423796
Add nonce and external handler
fmoletta Jun 27, 2024
0e7739e
Fill some todos
fmoletta Jun 27, 2024
e854ae5
Convert eftests header to ethrex block header
fmoletta Jun 27, 2024
639b74e
Convert eftests tx to ethrex tx
fmoletta Jun 27, 2024
ff7297f
Convert eftests account to ethrex account
fmoletta Jun 27, 2024
5e1d06b
Replace evm code in eftests with ethrex-evm import
fmoletta Jun 27, 2024
c1f7f53
WIP: add address recovery
fmoletta Jun 27, 2024
f29a030
Make ef tests run: Set chain id to mainnet + use current block instea…
fmoletta Jun 28, 2024
98b9edd
Update address calculation
fmoletta Jun 28, 2024
2d27e43
Use y parity
fmoletta Jun 28, 2024
f25208f
Fix parity calc
fmoletta Jun 28, 2024
890cff8
Fix parity calc
fmoletta Jun 28, 2024
937e1a9
Add another ef test example
fmoletta Jul 1, 2024
7c663df
Comment quick fix
fmoletta Jul 1, 2024
6ca3811
Differentiate between legacy and eip tx when converting from eftests …
fmoletta Jul 1, 2024
9748e86
Filter by tx_type
fmoletta Jul 1, 2024
f0b02a0
execute_tx return ExecutionResult
fmoletta Jul 1, 2024
fe64b2c
Handle y_parity in protected legacy txs
fmoletta Jul 1, 2024
3875895
Use rlp encoded tx fields instead of tx data to calc pub key
fmoletta Jul 1, 2024
5e52b86
Move quick fix for empty data
fmoletta Jul 1, 2024
184d56b
Add todo comment
fmoletta Jul 1, 2024
e8bd271
Fix tx data desrialization for eftests
fmoletta Jul 1, 2024
9e4b141
Remove comment
fmoletta Jul 1, 2024
1f2a194
Fix code deser
fmoletta Jul 1, 2024
9549014
Use correct data for EIP1555 addr calc too
fmoletta Jul 1, 2024
1dbc191
Remove unused dep
fmoletta Jul 1, 2024
4da9018
clippy
fmoletta Jul 1, 2024
69caf65
Remove uneeded feature
fmoletta Jul 1, 2024
625fc21
Remove dbg print
fmoletta Jul 1, 2024
08de5e2
Move evm crate inside core
fmoletta Jul 1, 2024
0908a4a
Fix desr
fmoletta Jul 1, 2024
87dab3d
map error
fmoletta Jul 1, 2024
6636cfc
Merge branch 'main' of https://github.com/lambdaclass/ethrex into add…
fmoletta Jul 2, 2024
54ffef5
Remove dbg print
fmoletta Jul 2, 2024
480a2fc
Merge branch 'main' of https://github.com/lambdaclass/ethrex into add…
fmoletta Jul 2, 2024
1aff2a4
Fix EOF
fmoletta Jul 2, 2024
d3fb8fc
Merge branch 'main' of https://github.com/lambdaclass/ethrex into add…
fmoletta Jul 2, 2024
d3f52b2
Add ExecutionResult type
fmoletta Jul 2, 2024
f4ced4a
Push fn
fmoletta Jul 2, 2024
4368db0
Move ExecutionResult to its own module
fmoletta Jul 2, 2024
769550f
Merge branch 'main' of https://github.com/lambdaclass/ethrex into add…
fmoletta Jul 2, 2024
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
4 changes: 1 addition & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ members = [
"ethrex",
"crates/consensus",
"crates/core",
"crates/evm",
"crates/net",
"crates/rpc",
"crates/storage",
Expand All @@ -18,7 +17,6 @@ edition = "2021"
[workspace.dependencies]
ethrex-consensus = { path = "./crates/consensus" }
ethrex-core = { path = "./crates/core" }
ethrex-evm = { path = "./crates/evm" }
ethrex-net = { path = "./crates/net" }
ethrex-rpc = { path = "./crates/rpc" }
ethrex-storage = { path = "./crates/storage" }
Expand All @@ -29,6 +27,6 @@ tracing-subscriber = "0.3.0"
serde = { version = "1.0.203", features = ["derive"] }
serde_json = "1.0.117"
libmdbx = { version = "0.5.0", features = ["orm"] }
bytes = "1.6.0"
tokio = { version = "1.38.0", features = ["full"] }
bytes = { version = "1.6.0", features = ["serde"] }
thiserror = "1.0.61"
7 changes: 6 additions & 1 deletion crates/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,13 @@ serde.workspace = true
serde_json.workspace = true
thiserror.workspace = true
keccak-hash = "0.10.0"
patricia-merkle-tree = { git = "https://github.com/lambdaclass/merkle_patricia_tree.git" }
sha3 = "0.10.8"
secp256k1 = { version = "0.29", default-features = false, features = [
"global-context",
"recovery",
] }
revm = { version = "10.0.0", features = ["serde", "std", "serde-json"] }
patricia-merkle-tree = { git = "https://github.com/lambdaclass/merkle_patricia_tree.git" }
bytes.workspace = true

[dev-dependencies]
Expand Down
86 changes: 86 additions & 0 deletions crates/core/src/evm/execution_result.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use bytes::Bytes;
use ethereum_types::Address;
use revm::primitives::result::Output as RevmOutput;
use revm::primitives::result::SuccessReason as RevmSuccessReason;
use revm::primitives::ExecutionResult as RevmExecutionResult;

pub enum ExecutionResult {
Success {
reason: SuccessReason,
gas_used: u64,
gas_refunded: u64,
output: Output,
},
/// Reverted by `REVERT` opcode
Revert { gas_used: u64, output: Bytes },
/// Reverted for other reasons, spends all gas.
Halt {
reason: String,
/// Halting will spend all the gas, which will be equal to gas_limit.
gas_used: u64,
},
}

pub enum SuccessReason {
Stop,
Return,
SelfDestruct,
EofReturnContract,
}

pub enum Output {
Call(Bytes),
Create(Bytes, Option<Address>),
}

impl From<RevmExecutionResult> for ExecutionResult {
fn from(val: RevmExecutionResult) -> Self {
match val {
RevmExecutionResult::Success {
reason,
gas_used,
gas_refunded,
logs: _,
output,
} => ExecutionResult::Success {
reason: match reason {
RevmSuccessReason::Stop => SuccessReason::Stop,
RevmSuccessReason::Return => SuccessReason::Return,
RevmSuccessReason::SelfDestruct => SuccessReason::SelfDestruct,
RevmSuccessReason::EofReturnContract => SuccessReason::EofReturnContract,
},
gas_used,
gas_refunded,
output: match output {
RevmOutput::Call(bytes) => Output::Call(bytes.0),
RevmOutput::Create(bytes, addr) => Output::Create(
bytes.0,
addr.map(|addr| Address::from_slice(addr.0.as_ref())),
),
},
},
RevmExecutionResult::Revert { gas_used, output } => ExecutionResult::Revert {
gas_used,
output: output.0,
},
RevmExecutionResult::Halt { reason, gas_used } => ExecutionResult::Halt {
reason: format!("{:?}", reason),
gas_used,
},
}
}
}

impl ExecutionResult {
pub fn is_success(&self) -> bool {
matches!(
self,
ExecutionResult::Success {
reason: _,
gas_used: _,
gas_refunded: _,
output: _
}
)
}
}
115 changes: 115 additions & 0 deletions crates/core/src/evm/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
mod execution_result;

use crate::types::TxKind;

use super::{
types::{Account, BlockHeader, Transaction},
Address,
};
use revm::{
inspector_handle_register,
inspectors::TracerEip3155,
primitives::{BlockEnv, Bytecode, TxEnv, U256},
CacheState, Evm,
};
use std::collections::HashMap;
// Rename imported types for clarity
use revm::primitives::AccountInfo as RevmAccountInfo;
use revm::primitives::Address as RevmAddress;
use revm::primitives::TxKind as RevmTxKind;
// Export needed types
pub use execution_result::*;
pub use revm::primitives::SpecId;

pub fn execute_tx(
tx: &Transaction,
header: &BlockHeader,
pre: &HashMap<Address, Account>, // TODO: Modify this type when we have a defined State structure
spec_id: SpecId,
) -> ExecutionResult {
let block_env = block_env(header);
let tx_env = tx_env(tx);
let cache_state = cache_state(pre);
let mut state = revm::db::State::builder()
.with_cached_prestate(cache_state)
.with_bundle_update()
.build();
let mut evm = Evm::builder()
.with_db(&mut state)
.with_block_env(block_env)
.with_tx_env(tx_env)
.with_spec_id(spec_id)
.reset_handler()
.with_external_context(TracerEip3155::new(Box::new(std::io::stderr())).without_summary())
.append_handler_register(inspector_handle_register)
.build();
let tx_result = evm.transact().unwrap();
tx_result.result.into()
}

fn cache_state(pre: &HashMap<Address, Account>) -> CacheState {
let mut cache_state = revm::CacheState::new(false);
for (address, account) in pre {
let acc_info = RevmAccountInfo {
balance: U256::from_limbs(account.info.balance.0),
code_hash: account.info.code_hash.0.into(),
code: Some(Bytecode::new_raw(account.code.clone().into())),
nonce: account.info.nonce,
};

let mut storage = HashMap::new();
for (k, v) in &account.storage {
storage.insert(U256::from_be_bytes(k.0), U256::from_be_bytes(v.0));
}

cache_state.insert_account_with_storage(address.to_fixed_bytes().into(), acc_info, storage);
}
cache_state
}

fn block_env(header: &BlockHeader) -> BlockEnv {
BlockEnv {
number: U256::from(header.number),
coinbase: RevmAddress(header.coinbase.0.into()),
timestamp: U256::from(header.timestamp),
gas_limit: U256::from(header.gas_limit),
basefee: U256::from(header.base_fee_per_gas),
difficulty: U256::from_limbs(header.difficulty.0),
prevrandao: Some(header.prev_randao.as_fixed_bytes().into()),
..Default::default()
}
}

fn tx_env(tx: &Transaction) -> TxEnv {
TxEnv {
caller: RevmAddress(tx.sender().0.into()),
gas_limit: tx.gas_limit(),
gas_price: U256::from(tx.gas_price()),
transact_to: tx.to().into(),
value: U256::from_limbs(tx.value().0),
data: tx.data().clone().into(),
nonce: Some(tx.nonce()),
chain_id: tx.chain_id(),
access_list: tx
.access_list()
.into_iter()
.map(|(addr, list)| {
(
RevmAddress(addr.0.into()),
list.into_iter().map(|a| U256::from_be_bytes(a.0)).collect(),
)
})
.collect(),
gas_priority_fee: tx.max_priority_fee().map(U256::from),
..Default::default()
}
}

impl From<TxKind> for RevmTxKind {
fn from(val: TxKind) -> Self {
match val {
TxKind::Call(address) => RevmTxKind::Call(address.0.into()),
TxKind::Create => RevmTxKind::Create,
}
}
}
1 change: 1 addition & 0 deletions crates/core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod rlp;
pub use ethereum_types::*;
pub mod evm;
pub mod serde_utils;
pub mod types;
2 changes: 1 addition & 1 deletion crates/core/src/types/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ impl From<GenesisAccount> for Account {
}
}

fn code_hash(code: &Bytes) -> H256 {
pub fn code_hash(code: &Bytes) -> H256 {
keccak_hash::keccak(code.as_ref())
}

Expand Down
Loading
Loading