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

Add support for old forks. #191

Merged
merged 25 commits into from
Aug 29, 2022
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
db01eb5
Add all forks to revm
rakita Aug 16, 2022
38bfb6d
Add all hardforks
rakita Aug 17, 2022
f2ff107
Merge remote-tracking branch 'origin/main' into main
rakita Aug 17, 2022
84739f1
EXTCODESIZE and EXTCODEHASH old hardfork gas fix
rakita Aug 17, 2022
fc1a81e
EXTCODECOPY fix gas hardfork
rakita Aug 17, 2022
daadfa2
fmt
rakita Aug 17, 2022
25f06a0
cleanups
rakita Aug 17, 2022
d10dfdf
EIP-161 is in SPURIOUS_DRAGON hardfork
rakita Aug 18, 2022
6e97f92
EIP-161 create nonce increment for SPURIOUS_DRAGON
rakita Aug 18, 2022
175aee5
Enable SPURIOUS_DRAGON tests
rakita Aug 18, 2022
c25fc75
Change database traits to return Result<Option<>>
rakita Aug 18, 2022
b1de572
80perc done transition
rakita Aug 20, 2022
0d68e72
db result compiled and new forks passing
rakita Aug 21, 2022
588d99d
not_existing, precompile perf is_cold
rakita Aug 22, 2022
4222270
fix for not_existing
rakita Aug 22, 2022
1d532dc
passing most of legact tests
rakita Aug 22, 2022
94bc2be
Remove spurious precompile hotfix for old forks
rakita Aug 22, 2022
61eebc8
EIP-2 OOG if crate bytecode can't be paid
rakita Aug 23, 2022
4859b12
Merge remote-tracking branch 'origin/main' into forks
rakita Aug 26, 2022
c8171a7
Add legacy tests to github ci, fmt,clippy
rakita Aug 26, 2022
2d1edcf
Merge remote-tracking branch 'origin/main' into forks
rakita Aug 26, 2022
b5c65f9
fmt
rakita Aug 26, 2022
4317474
Propagate FatalExternalError
rakita Aug 26, 2022
431fe68
Add Error associated type to Database.
rakita Aug 27, 2022
44f6ec1
Small cleanup
rakita Aug 29, 2022
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
2 changes: 1 addition & 1 deletion .github/workflows/ethereum-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ jobs:
cache-on-failure: true

- name: Run Ethereum tests
run: cargo run --profile ethtests -p revme -- statetest ethtests/GeneralStateTests
run: cargo run --profile ethtests -p revme -- statetest ethtests/GeneralStateTests ethtests/LegacyTests/Constantinople/GeneralStateTests/
1 change: 1 addition & 0 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,6 @@ run tests with command: `cargo run --release -- statetest tests/GeneralStateTest

There is public telegram group: https://t.me/+Ig4WDWOzikA3MzA0

Or you can contact me directly on email: dragan0rakita@gmail.com
Or if you want to hire me or contact me directly, here is my email: dragan0rakita@gmail.com and telegram: https://t.me/draganrakita


11 changes: 7 additions & 4 deletions bins/revme/src/statetest/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ use structopt::StructOpt;
#[derive(StructOpt, Debug)]
pub struct Cmd {
#[structopt(required = true)]
path: PathBuf,
path: Vec<PathBuf>,
}

impl Cmd {
pub fn run(&self) -> Result<(), TestError> {
let test_files = find_all_json_tests(&self.path);
println!("Start running tests on: {:?}", self.path);
run(test_files)
for path in &self.path {
println!("Start running tests on: {:?}", path);
let test_files = find_all_json_tests(path);
run(test_files)?
}
Ok(())
}
}
11 changes: 11 additions & 0 deletions bins/revme/src/statetest/models/deserializer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,14 @@ where
.map_err(D::Error::custom)?
.into())
}

pub fn deserialize_opt_str_as_bytes<'de, D>(deserializer: D) -> Result<Option<Bytes>, D::Error>
where
D: de::Deserializer<'de>,
{
#[derive(Debug, Deserialize)]
struct WrappedValue(#[serde(deserialize_with = "deserialize_str_as_bytes")] Bytes);

Option::<WrappedValue>::deserialize(deserializer)
.map(|opt_wrapped: Option<WrappedValue>| opt_wrapped.map(|wrapped: WrappedValue| wrapped.0))
}
5 changes: 3 additions & 2 deletions bins/revme/src/statetest/models/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ pub struct Test {
pub indexes: TxPartIndices,
// logs
pub logs: H256,
#[serde(deserialize_with = "deserialize_str_as_bytes")]
pub txbytes: Bytes,
#[serde(default)]
#[serde(deserialize_with = "deserialize_opt_str_as_bytes")]
pub txbytes: Option<Bytes>,
}

#[derive(Debug, PartialEq, Eq, Deserialize)]
Expand Down
64 changes: 47 additions & 17 deletions bins/revme/src/statetest/models/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,64 @@ use serde_derive::*;

#[derive(Debug, PartialEq, Eq, PartialOrd, Hash, Ord, Deserialize)]
pub enum SpecName {
EIP150,
EIP158,
Frontier,
Homestead,
Byzantium,
Constantinople,
ConstantinopleFix,
Istanbul,
EIP158ToByzantiumAt5,
FrontierToHomesteadAt5,
Homestead,
HomesteadToDaoAt5,
HomesteadToEIP150At5,
ByzantiumToConstantinopleAt5,
EIP150,
EIP158, // EIP-161: State trie clearing
EIP158ToByzantiumAt5,
Byzantium, // done
ByzantiumToConstantinopleAt5, // SKIPPED
ByzantiumToConstantinopleFixAt5,
Berlin,
London,
BerlinToLondonAt5,
Merge,
Constantinople, // SKIPPED
ConstantinopleFix,
Istanbul,
Berlin, //done
BerlinToLondonAt5, // done
London, // done
Merge, //done
}

impl SpecName {
pub fn to_spec_id(&self) -> SpecId {
match self {
Self::Merge => SpecId::MERGE,
Self::London => SpecId::LONDON,
Self::Berlin => SpecId::BERLIN,
Self::Frontier => SpecId::FRONTIER,
Self::Homestead | Self::FrontierToHomesteadAt5 => SpecId::HOMESTEAD,
Self::EIP150 | Self::HomesteadToDaoAt5 | Self::HomesteadToEIP150At5 => {
SpecId::TANGERINE
}
Self::EIP158 => SpecId::SPURIOUS_DRAGON,
Self::Byzantium | Self::EIP158ToByzantiumAt5 => SpecId::BYZANTIUM,
Self::ConstantinopleFix | Self::ByzantiumToConstantinopleFixAt5 => SpecId::PETERSBURG,
Self::Istanbul => SpecId::ISTANBUL,
_ => panic!("Conversion failed"),
Self::Berlin => SpecId::BERLIN,
Self::London | Self::BerlinToLondonAt5 => SpecId::LONDON,
Self::Merge => SpecId::MERGE,
Self::ByzantiumToConstantinopleAt5 | Self::Constantinople => {
panic!("Overriden with PETERSBURG")
} //_ => panic!("Conversion failed"),
}
}
}

/*
spec!(FRONTIER);
// FRONTIER_THAWING no EVM spec change
spec!(HOMESTEAD);
// DAO_FORK no EVM spec change
spec!(TANGERINE);
spec!(SPURIOUS_DRAGON);
spec!(BYZANTIUM);
// CONSTANTINOPLE was overriden with PETERSBURG
spec!(PETERSBURG);
spec!(ISTANBUL);
// MUIR_GLACIER no EVM spec change
spec!(BERLIN);
spec!(LONDON);
// ARROW_GLACIER no EVM spec change
// GRAT_GLACIER no EVM spec change
spec!(MERGE);
spec!(LATEST);
*/
34 changes: 24 additions & 10 deletions bins/revme/src/statetest/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ pub enum TestError {
SerdeDeserialize(#[from] serde_json::Error),
#[error("Internal system error")]
SystemError,
#[error("Unknown private key: {private_key:?}")]
UnknownPrivateKey { private_key: H256 },
}

pub fn find_all_json_tests(path: &Path) -> Vec<PathBuf> {
Expand Down Expand Up @@ -112,6 +114,11 @@ pub fn execute_test_suit(path: &Path, elapsed: &Arc<Mutex<Duration>>) -> Result<
.unwrap(),
H160::from_str("0x3fb1cd2cd96c6d5c0b5eb3322d807b34482481d4").unwrap(),
),
(
H256::from_str("0xfe13266ff57000135fb9aa854bbfe455d8da85b21f626307bf3263a0c2a8e7fe")
.unwrap(),
H160::from_str("0xdcc5ba93a1ed7e045690d722f2bf460a51c61415").unwrap(),
),
]
.into_iter()
.collect();
Expand All @@ -129,7 +136,7 @@ pub fn execute_test_suit(path: &Path, elapsed: &Arc<Mutex<Duration>>) -> Result<
database.insert_account_info(*address, acc_info);
// insert storage:
for (&slot, &value) in info.storage.iter() {
database.insert_account_storage(*address, slot, value)
let _ = database.insert_account_storage(*address, slot, value);
}
}
let mut env = Env::default();
Expand All @@ -145,9 +152,13 @@ pub fn execute_test_suit(path: &Path, elapsed: &Arc<Mutex<Duration>>) -> Result<
env.block.difficulty = unit.env.current_difficulty;

//tx env
env.tx.caller = *map_caller_keys
.get(&unit.transaction.secret_key.unwrap())
.unwrap();
env.tx.caller =
if let Some(caller) = map_caller_keys.get(&unit.transaction.secret_key.unwrap()) {
*caller
} else {
let private_key = unit.transaction.secret_key.unwrap();
return Err(TestError::UnknownPrivateKey { private_key });
};
env.tx.gas_price = unit
.transaction
.gas_price
Expand All @@ -156,9 +167,9 @@ pub fn execute_test_suit(path: &Path, elapsed: &Arc<Mutex<Duration>>) -> Result<

// post and execution
for (spec_name, tests) in unit.post {
if !matches!(
if matches!(
spec_name,
SpecName::Merge | SpecName::London | SpecName::Berlin | SpecName::Istanbul
SpecName::ByzantiumToConstantinopleAt5 | SpecName::Constantinople
) {
continue;
}
Expand Down Expand Up @@ -226,13 +237,16 @@ pub fn execute_test_suit(path: &Path, elapsed: &Arc<Mutex<Duration>>) -> Result<

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

let is_legacy = !SpecId::enabled(evm.env.cfg.spec_id, SpecId::SPURIOUS_DRAGON);
let db = evm.db().unwrap();
let state_root = state_merkle_trie_root(
db.accounts
.iter()
.filter(|(_address, acc)| {
!(acc.info.is_empty())
|| matches!(acc.account_state, AccountState::None)
(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())),
);
Expand Down Expand Up @@ -269,10 +283,10 @@ pub fn execute_test_suit(path: &Path, elapsed: &Arc<Mutex<Duration>>) -> Result<
pub fn run(test_files: Vec<PathBuf>) -> Result<(), TestError> {
let endjob = Arc::new(AtomicBool::new(false));
let console_bar = Arc::new(ProgressBar::new(test_files.len() as u64));
let mut joins = Vec::new();
let mut joins: Vec<std::thread::JoinHandle<Result<(), TestError>>> = Vec::new();
let queue = Arc::new(Mutex::new((0, test_files)));
let elapsed = Arc::new(Mutex::new(std::time::Duration::ZERO));
for _ in 0..10 {
for _ in 0..1 {
let queue = queue.clone();
let endjob = endjob.clone();
let console_bar = console_bar.clone();
Expand Down
8 changes: 4 additions & 4 deletions bins/revme/src/statetest/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ impl<DB: Database> Inspector<DB> for CustomPrintTracer {
let gas_remaining = interp.gas.remaining() + self.full_gas_block - self.reduced_gas_block;

println!(
"depth:{}, PC:{}, gas:{:#x}({}), OPCODE: {:?}({:?}) refund:{:#x}({}) Stack:{:?}, Data:",
"depth:{}, PC:{}, gas:{:#x}({}), OPCODE: {:?}({:?}) refund:{:#x}({}) Stack:{:?}, Data size:{}",
data.journaled_state.depth(),
interp.program_counter(),
gas_remaining,
Expand All @@ -68,7 +68,7 @@ impl<DB: Database> Inspector<DB> for CustomPrintTracer {
interp.gas.refunded(),
interp.gas.refunded(),
interp.stack.data(),
//hex::encode(interp.memory.data()),
interp.memory.data().len(),
);

let pc = interp.program_counter();
Expand Down Expand Up @@ -141,12 +141,12 @@ impl<DB: Database> Inspector<DB> for CustomPrintTracer {
is_static: bool,
) -> (Return, Gas, Bytes) {
println!(
"SM CALL: {:?},context:{:?}, is_static:{:?}, transfer:{:?}, input:{:?}",
"SM CALL: {:?},context:{:?}, is_static:{:?}, transfer:{:?}, input:", //{:?}",
inputs.contract,
inputs.context,
is_static,
inputs.transfer,
hex::encode(&inputs.input),
//hex::encode(&inputs.input),
);
(Return::Continue, Gas::new(0), Bytes::new())
}
Expand Down
24 changes: 12 additions & 12 deletions crates/revm/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ use auto_impl::auto_impl;
#[auto_impl(& mut, Box)]
pub trait Database {
/// Get basic account information.
fn basic(&mut self, address: H160) -> AccountInfo;
fn basic(&mut self, address: H160) -> Result<Option<AccountInfo>, &'static str>;
/// Get account code by its hash
fn code_by_hash(&mut self, code_hash: H256) -> Bytecode;
fn code_by_hash(&mut self, code_hash: H256) -> Result<Bytecode, &'static str>;
/// Get storage value of address at index.
fn storage(&mut self, address: H160, index: U256) -> U256;
fn storage(&mut self, address: H160, index: U256) -> Result<U256, &'static str>;

// History related
fn block_hash(&mut self, number: U256) -> H256;
fn block_hash(&mut self, number: U256) -> Result<H256, &'static str>;
}

#[auto_impl(& mut, Box)]
Expand All @@ -37,14 +37,14 @@ pub trait DatabaseRef {
/// Whether account at address exists.
//fn exists(&self, address: H160) -> Option<AccountInfo>;
/// Get basic account information.
fn basic(&self, address: H160) -> AccountInfo;
fn basic(&self, address: H160) -> Result<Option<AccountInfo>, &'static str>;
/// Get account code by its hash
fn code_by_hash(&self, code_hash: H256) -> Bytecode;
fn code_by_hash(&self, code_hash: H256) -> Result<Bytecode, &'static str>;
/// Get storage value of address at index.
fn storage(&self, address: H160, index: U256) -> U256;
fn storage(&self, address: H160, index: U256) -> Result<U256, &'static str>;

// History related
fn block_hash(&self, number: U256) -> H256;
fn block_hash(&self, number: U256) -> Result<H256, &'static str>;
}

pub struct RefDBWrapper<'a> {
Expand All @@ -63,20 +63,20 @@ impl<'a> Database for RefDBWrapper<'a> {
// self.db.exists(address)
// }
/// Get basic account information.
fn basic(&mut self, address: H160) -> AccountInfo {
fn basic(&mut self, address: H160) -> Result<Option<AccountInfo>, &'static str> {
self.db.basic(address)
}
/// Get account code by its hash
fn code_by_hash(&mut self, code_hash: H256) -> Bytecode {
fn code_by_hash(&mut self, code_hash: H256) -> Result<Bytecode, &'static str> {
self.db.code_by_hash(code_hash)
}
/// Get storage value of address at index.
fn storage(&mut self, address: H160, index: U256) -> U256 {
fn storage(&mut self, address: H160, index: U256) -> Result<U256, &'static str> {
self.db.storage(address, index)
}

// History related
fn block_hash(&mut self, number: U256) -> H256 {
fn block_hash(&mut self, number: U256) -> Result<H256, &'static str> {
self.db.block_hash(number)
}
}
Loading