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

feat: State with account status #499

Merged
merged 76 commits into from
Aug 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
7f609d8
wip separate initial checks
rakita May 5, 2023
57504a9
tests passing, consolidate some checks
rakita May 8, 2023
9d58056
test
rakita May 9, 2023
150447e
feat: add transfer test
rakita May 9, 2023
410d768
Merge remote-tracking branch 'origin/transfer_test' into separate_ini…
rakita May 9, 2023
25b317f
temp
rakita May 9, 2023
ec78f21
Update crates/interpreter/src/gas/calc.rs
rakita May 9, 2023
9f82d05
/ Initial gas that is deducted from the transaction gas limit.
rakita May 9, 2023
1dc3307
fmt
rakita May 9, 2023
feecd77
account states
rakita May 11, 2023
03be593
temp
rakita May 11, 2023
a745b6f
Global account BlockState. wip
rakita May 15, 2023
88af756
few comments
rakita May 16, 2023
3609ad2
Merge remote-tracking branch 'origin/main' into v330
rakita May 16, 2023
1f12387
wip
rakita May 16, 2023
84f2b6b
Tests working
rakita May 16, 2023
49ab258
wip changes
rakita May 19, 2023
72df0de
work on update and revert
rakita May 19, 2023
b5e8e6b
AccountState as a simple enum flag
rakita May 21, 2023
0c4dfe7
Add storage for EmptyEip161 account
rakita May 22, 2023
3332689
split state to component files
rakita May 23, 2023
3c5a0a6
continue spliting, wip State
rakita May 24, 2023
4e6750b
feat: Add initcode limit to be double of bytecode limit (#491)
rakita May 25, 2023
0ecfb8a
bigger cleanup, structure it
rakita May 26, 2023
5fb0de0
wip reverts and the flow
rakita May 26, 2023
e24991b
increments balance and some wip on reverts
rakita Jun 5, 2023
1ccfb1a
feat: Run CI on release branches (#506)
rakita Jun 5, 2023
0a97b73
feat: Add initcode limit to be double of bytecode limit (#503)
rakita Jun 5, 2023
65387e4
chore: Move Precompiles to EVMData so Inspector can access it (#504)
rakita Jun 5, 2023
8833792
fix previous commit (#507)
rakita Jun 5, 2023
104c820
wip cache account, changeset and revert
rakita Jun 6, 2023
6743208
plain state wip, reverts compiles now
rakita Jun 8, 2023
361a303
working changes
rakita Jun 13, 2023
6dbed63
working and, added timestamps and println
rakita Jun 13, 2023
e200b13
Add reverts
rakita Jun 14, 2023
9400d4e
clippy happy, some cleanup, work on reverts
rakita Jun 17, 2023
ec6e2a2
Merge remote-tracking branch 'origin/main' into account_state
rakita Jun 19, 2023
7bbf70a
wip on spliting and creating BundleState
rakita Jun 21, 2023
7fd5da7
needed things for integration
rakita Jun 26, 2023
f194dd5
Few utilities, emptydb with typed error
rakita Jun 28, 2023
111aca2
wip
rakita Jun 29, 2023
166a20c
fix some things
rakita Jun 30, 2023
dc3f1fb
cleanup
rakita Jul 10, 2023
2fb0967
Merge remote-tracking branch 'origin/release/v25' into account_state
rakita Jul 10, 2023
592ba46
refactoring
rakita Jul 11, 2023
0a2ae8a
clippy and some cleanup
rakita Jul 11, 2023
d519c2f
Merge remote-tracking branch 'origin/main' into account_state
rakita Jul 11, 2023
4d05b99
add state clear flag
rakita Jul 12, 2023
a19e226
bugs fixes
rakita Jul 13, 2023
117dcb5
add state builder
rakita Jul 17, 2023
bccc964
some cleanup and being more strict
rakita Jul 18, 2023
8020109
cleanup, and simplification
rakita Jul 25, 2023
ed7f8f4
check nonce for account
rakita Jul 26, 2023
54caddf
make storage was_destroyed
rakita Jul 26, 2023
9568034
dont store storage when not needed
rakita Jul 26, 2023
0df3aa3
dont ask db for destroyed accounts
rakita Jul 26, 2023
c0ac192
debug logs
rakita Jul 26, 2023
454970c
test account
rakita Jul 26, 2023
d0de0d5
more debug
rakita Jul 26, 2023
efd9c9c
save previous state on double touch
rakita Jul 26, 2023
285e379
check if pre eip161 touched account is already empty
rakita Jul 26, 2023
318d39d
Changr address
rakita Jul 27, 2023
abbac49
diferent debug account
rakita Jul 27, 2023
99b38e6
set wipe flag for destroyed
rakita Jul 27, 2023
28f9a91
remove some test clones
rakita Aug 1, 2023
d57562a
Merge remote-tracking branch 'origin/main' into revm_state
rakita Aug 3, 2023
e1e8108
nit
rakita Aug 4, 2023
76a2ff3
Merge remote-tracking branch 'origin/main' into revm_state
rakita Aug 6, 2023
da66dd4
clippy
rakita Aug 6, 2023
92029b5
make state behind std
rakita Aug 8, 2023
5985c2d
Merge remote-tracking branch 'origin/main' into revm_state
rakita Aug 8, 2023
e679493
lto
rakita Aug 8, 2023
c4016e4
cleanup
rakita Aug 8, 2023
d8e557f
Merge remote-tracking branch 'origin/main' into revm_state
rakita Aug 8, 2023
935b1d4
set bigger stack size in tests
rakita Aug 8, 2023
2004b76
fmt
rakita Aug 8, 2023
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
12 changes: 12 additions & 0 deletions Cargo.lock

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

11 changes: 7 additions & 4 deletions bins/revme/src/statetest/merkle_trie.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use hash_db::Hasher;
use plain_hasher::PlainHasher;
use primitive_types::{H160, H256};
use revm::{
db::DbAccount,
db::PlainAccount,
primitives::{keccak256, Log, B160, B256, U256},
};
use rlp::RlpStream;
Expand All @@ -30,10 +30,13 @@ pub fn log_rlp_hash(logs: Vec<Log>) -> B256 {
keccak256(&out)
}

pub fn state_merkle_trie_root(accounts: impl Iterator<Item = (B160, DbAccount)>) -> B256 {
pub fn state_merkle_trie_root<'a>(
accounts: impl IntoIterator<Item = (B160, &'a PlainAccount)>,
) -> B256 {
let vec = accounts
.into_iter()
.map(|(address, info)| {
let acc_root = trie_account_rlp(&info);
let acc_root = trie_account_rlp(info);
(H160::from(address.0), acc_root)
})
.collect();
Expand All @@ -42,7 +45,7 @@ pub fn state_merkle_trie_root(accounts: impl Iterator<Item = (B160, DbAccount)>)
}

/// Returns the RLP for this account.
pub fn trie_account_rlp(acc: &DbAccount) -> Bytes {
pub fn trie_account_rlp(acc: &PlainAccount) -> Bytes {
let mut stream = RlpStream::new_list(4);
stream.append(&acc.info.nonce);
stream.append(&acc.info.balance);
Expand Down
4 changes: 2 additions & 2 deletions bins/revme/src/statetest/models/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use bytes::Bytes;
use revm::primitives::{B160, B256, U256};
use std::collections::{BTreeMap, HashMap};
use revm::primitives::{HashMap, B160, B256, U256};
use std::collections::BTreeMap;
mod deserializer;
mod spec;

Expand Down
95 changes: 52 additions & 43 deletions bins/revme/src/statetest/runner.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,26 @@
use std::io::stdout;
use std::{
collections::HashMap,
ffi::OsStr,
path::{Path, PathBuf},
sync::{atomic::AtomicBool, Arc, Mutex},
time::{Duration, Instant},
};

use indicatif::ProgressBar;

use revm::inspectors::TracerEip3155;
use revm::{
db::AccountState,
interpreter::CreateScheme,
primitives::{Bytecode, Env, ExecutionResult, SpecId, TransactTo, B160, B256, U256},
};
use std::sync::atomic::Ordering;
use walkdir::{DirEntry, WalkDir};

use super::{
merkle_trie::{log_rlp_hash, state_merkle_trie_root},
models::{SpecName, TestSuit},
};
use hex_literal::hex;
use indicatif::ProgressBar;
use revm::inspectors::TracerEip3155;
use revm::primitives::keccak256;
use revm::{
interpreter::CreateScheme,
primitives::{Bytecode, Env, ExecutionResult, HashMap, SpecId, TransactTo, B160, B256, U256},
};
use std::sync::atomic::Ordering;
use thiserror::Error;
use walkdir::{DirEntry, WalkDir};

#[derive(Debug, Error)]
pub enum TestError {
Expand Down Expand Up @@ -62,10 +58,19 @@ pub fn execute_test_suit(
if path.file_name() == Some(OsStr::new("ValueOverflow.json")) {
return Ok(());
}

// precompiles having storage is not possible
if path.file_name() == Some(OsStr::new("RevertPrecompiledTouch_storage.json"))
|| path.file_name() == Some(OsStr::new("RevertPrecompiledTouch.json"))
{
return Ok(());
}

// txbyte is of type 02 and we dont parse tx bytes for this test to fail.
if path.file_name() == Some(OsStr::new("typeTwoBerlin.json")) {
return Ok(());
}

// Test checks if nonce overflows. We are handling this correctly but we are not parsing exception in testsuite
// There are more nonce overflow tests that are in internal call/create, and those tests are passing and are enabled.
if path.file_name() == Some(OsStr::new("CreateTransactionHighNonce.json")) {
Expand All @@ -78,7 +83,10 @@ pub fn execute_test_suit(
}

// Test check if gas price overflows, we handle this correctly but does not match tests specific exception.
if path.file_name() == Some(OsStr::new("HighGasPrice.json")) {
if path.file_name() == Some(OsStr::new("HighGasPrice.json"))
|| path.file_name() == Some(OsStr::new("CREATE_HighNonce.json"))
|| path.file_name() == Some(OsStr::new("CREATE_HighNonceMinus1.json"))
{
return Ok(());
}

Expand Down Expand Up @@ -153,19 +161,15 @@ pub fn execute_test_suit(

for (name, unit) in suit.0.into_iter() {
// Create database and insert cache
let mut database = revm::InMemoryDB::default();
for (address, info) in unit.pre.iter() {
let mut cache_state = revm::CacheState::new(false);
for (address, info) in unit.pre.into_iter() {
let acc_info = revm::primitives::AccountInfo {
balance: info.balance,
code_hash: keccak256(&info.code), // try with dummy hash.
code: Some(Bytecode::new_raw(info.code.clone())),
nonce: info.nonce,
};
database.insert_account_info(*address, acc_info);
// insert storage:
for (&slot, &value) in info.storage.iter() {
let _ = database.insert_account_storage(*address, slot, value);
}
cache_state.insert_account_with_storage(address, acc_info, info.storage.clone());
}
let mut env = Env::default();
// cfg env. SpecId is set down the road
Expand Down Expand Up @@ -247,9 +251,16 @@ pub fn execute_test_suit(
};
env.tx.transact_to = to;

let mut database_cloned = database.clone();
let mut cache = cache_state.clone();
cache.set_state_clear_flag(SpecId::enabled(
env.cfg.spec_id,
revm::primitives::SpecId::SPURIOUS_DRAGON,
));
let mut state = revm::db::StateBuilder::default()
.with_cached_prestate(cache)
.build();
let mut evm = revm::new();
evm.database(&mut database_cloned);
evm.database(&mut state);
evm.env = env.clone();
// do the deed

Expand All @@ -264,22 +275,8 @@ pub fn execute_test_suit(

*elapsed.lock().unwrap() += timer;

let is_legacy = !SpecId::enabled(
evm.env.cfg.spec_id,
revm::primitives::SpecId::SPURIOUS_DRAGON,
);
let db = evm.db().unwrap();
let state_root = state_merkle_trie_root(
db.accounts
.iter()
.filter(|(_address, acc)| {
(is_legacy && !matches!(acc.account_state, AccountState::NotExisting))
|| (!is_legacy
&& (!(acc.info.is_empty())
|| matches!(acc.account_state, AccountState::None)))
})
.map(|(k, v)| (*k, v.clone())),
);
let state_root = state_merkle_trie_root(db.cache.trie_account());
let logs = match &exec_result {
Ok(ExecutionResult::Success { logs, .. }) => logs.clone(),
_ => Vec::new(),
Expand All @@ -290,8 +287,16 @@ pub fn execute_test_suit(
"Roots did not match:\nState root: wanted {:?}, got {state_root:?}\nLogs root: wanted {:?}, got {logs_root:?}",
test.hash, test.logs
);
let mut database_cloned = database.clone();
evm.database(&mut database_cloned);

let mut cache = cache_state.clone();
cache.set_state_clear_flag(SpecId::enabled(
env.cfg.spec_id,
revm::primitives::SpecId::SPURIOUS_DRAGON,
));
let mut state = revm::db::StateBuilder::default()
.with_cached_prestate(cache)
.build();
evm.database(&mut state);
let _ =
evm.inspect_commit(TracerEip3155::new(Box::new(stdout()), false, false));
let db = evm.db().unwrap();
Expand Down Expand Up @@ -319,8 +324,12 @@ pub fn execute_test_suit(
println!("Output: {out:?} {path:?} UNIT_TEST:{name}\n");
}
}
println!("\nApplied state:\n{db:#?}\n");
println!(" TEST NAME: {:?}", name);
println!("\nApplied state:\n{:#?}\n", db.cache);
println!("\nState root: {state_root:?}\n");
println!("env.tx: {:?}\n", env.tx);
println!("env.block: {:?}\n", env.block);
println!("env.cfg: {:?}\n", env.cfg);
return Err(TestError::RootMismatch {
spec_id: env.cfg.spec_id,
id,
Expand Down Expand Up @@ -358,9 +367,9 @@ pub fn run(
let mut thread = std::thread::Builder::new();

// Allow bigger stack in debug mode to prevent stack overflow errors
if cfg!(debug_assertions) {
thread = thread.stack_size(4 * 1024 * 1024);
}
//if cfg!(debug_assertions) {
thread = thread.stack_size(4 * 1024 * 1024);
//}

joins.push(
thread
Expand Down
4 changes: 2 additions & 2 deletions crates/interpreter/src/instructions/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,8 +255,8 @@ pub fn selfdestruct<SPEC: Spec>(interpreter: &mut Interpreter, host: &mut dyn Ho

pub fn prepare_create_inputs<const IS_CREATE2: bool, SPEC: Spec>(
interpreter: &mut Interpreter,
create_inputs: &mut Option<Box<CreateInputs>>,
host: &mut dyn Host,
create_inputs: &mut Option<Box<CreateInputs>>,
) {
check_staticcall!(interpreter);
if IS_CREATE2 {
Expand Down Expand Up @@ -328,7 +328,7 @@ pub fn create<const IS_CREATE2: bool, SPEC: Spec>(
host: &mut dyn Host,
) {
let mut create_input: Option<Box<CreateInputs>> = None;
prepare_create_inputs::<IS_CREATE2, SPEC>(interpreter, &mut create_input, host);
prepare_create_inputs::<IS_CREATE2, SPEC>(interpreter, host, &mut create_input);

let Some(mut create_input) = create_input else {
return;
Expand Down
11 changes: 1 addition & 10 deletions crates/interpreter/src/interpreter/analysis.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::opcode;
use crate::primitives::{Bytecode, BytecodeState, Bytes, B256};
use crate::primitives::{Bytecode, BytecodeState, Bytes};
use alloc::sync::Arc;
// use bitvec::order::Lsb0;
// use bitvec::prelude::bitvec;
Expand All @@ -15,7 +15,6 @@ use revm_primitives::{
///
/// If the bytecode is already analyzed, it is returned as-is.
pub fn to_analysed(bytecode: Bytecode) -> Bytecode {
let hash = bytecode.hash;
let (bytecode, len) = match bytecode.state {
BytecodeState::Raw => {
let len = bytecode.bytecode.len();
Expand All @@ -29,7 +28,6 @@ pub fn to_analysed(bytecode: Bytecode) -> Bytecode {

Bytecode {
bytecode,
hash,
state: BytecodeState::Analysed { len, jump_map },
}
}
Expand Down Expand Up @@ -67,7 +65,6 @@ fn analyze(code: &[u8]) -> JumpMap {
pub struct BytecodeLocked {
bytecode: Bytes,
len: usize,
hash: B256,
jump_map: JumpMap,
}

Expand All @@ -87,7 +84,6 @@ impl TryFrom<Bytecode> for BytecodeLocked {
Ok(BytecodeLocked {
bytecode: bytecode.bytecode,
len,
hash: bytecode.hash,
jump_map,
})
} else {
Expand All @@ -104,18 +100,13 @@ impl BytecodeLocked {
self.len
}

pub fn hash(&self) -> B256 {
self.hash
}

pub fn is_empty(&self) -> bool {
self.len == 0
}

pub fn unlock(self) -> Bytecode {
Bytecode {
bytecode: self.bytecode,
hash: self.hash,
state: BytecodeState::Analysed {
len: self.len,
jump_map: self.jump_map,
Expand Down
4 changes: 3 additions & 1 deletion crates/interpreter/src/interpreter/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ pub struct Memory {

impl Default for Memory {
fn default() -> Self {
Memory::new()
Self {
data: Vec::with_capacity(4 * 1024), // took it from evmone
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion crates/primitives/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ readme = "../../README.md"
[dependencies]
bytes = { version = "1.4", default-features = false }
hashbrown = { version = "0.14" }
hex = { version = "0.4", default-features = false }
primitive-types = { version = "0.12", default-features = false }
rlp = { version = "0.5", default-features = false } # used for create2 address calculation
ruint = { version = "1.8.0", features = ["primitive-types", "rlp"] }
Expand All @@ -28,6 +27,8 @@ fixed-hash = { version = "0.8", default-features = false, features = [

#utility
hex-literal = "0.4"
hex = { version = "0.4", default-features = false }
to-binary = "0.4"
derive_more = "0.99"
enumn = "0.1"

Expand Down
Loading