Skip to content

Commit

Permalink
Osaka Activation (release_49 branch) (#1835)
Browse files Browse the repository at this point in the history
* Osaka Activation

Accept Osaka in unit tests and eof validation tests.

* update test cases

* remove evmone (they are all Prague based)
* remove evmone exclusions
* use eip7692@v2.0.0 for eest
* port in EXTDELEGATE precompile fix

* fmt

* Leave space for arbitrary forks in eof validation

* only count validated tests

* remove references to test directories that are not valid with current specs

* refactor flow slightly

* clippy

* fmt
  • Loading branch information
shemnon authored Oct 28, 2024
1 parent b09b375 commit 346aa01
Show file tree
Hide file tree
Showing 676 changed files with 49,026 additions and 140,651 deletions.
6 changes: 1 addition & 5 deletions .github/workflows/ethereum-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,10 @@ jobs:
ethtests/EIPTests/StateTests/stEIP1153-transientStorage/ \
ethtests/EIPTests/StateTests/stEIP4844-blobtransactions/ \
ethtests/EIPTests/StateTests/stEIP2537/ \
ethtests/EIPTests/StateTests/stEOF \
tests/eof_suite/eest/state_tests \
tests/eof_suite/evmone/state_tests \
tests/prague_suite/state_tests
- name: Run EOF validation tests
run: |
cross run --target ${{matrix.target}} --profile ${{ matrix.profile }} -p revme -- eof-validation \
ethtests/EOFTests \
tests/eof_suite/eest/eof_tests/prague \
tests/eof_suite/evmone/eof_tests
tests/eof_suite/eest/eof_tests/osaka
12 changes: 9 additions & 3 deletions bins/revme/src/cmd/eofvalidation.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
mod test_suite;

pub use test_suite::{PragueTestResult, TestResult, TestSuite, TestUnit, TestVector};
pub use test_suite::{TestResult, TestSuite, TestUnit, TestVector};

use crate::{cmd::Error, dir_utils::find_all_json_tests};
use revm::interpreter::analysis::{validate_raw_eof_inner, CodeType, EofError};
Expand Down Expand Up @@ -81,13 +81,19 @@ pub fn run_test(path: &Path) -> Result<(), Error> {
} else {
Some(CodeType::ReturnOrStop)
};
// In future this can be generalized to cover multiple forks, Not just Osaka.
let Some(test_result) = test_vector.results.get("Osaka") else {
// if test does not have a result that we can compare to, we skip it
println!("Test without result: {} - {}", name, vector_name);
continue;
};
let res = validate_raw_eof_inner(test_vector.code.clone(), kind);
if res.is_ok() != test_vector.results.prague.result {
if test_result.result != res.is_ok() {
println!(
"\nTest failed: {} - {}\nresult:{:?}\nrevm err_result:{:#?}\nbytes:{:?}\n",
name,
vector_name,
test_vector.results.prague,
test_result.result,
res.as_ref().err(),
test_vector.code
);
Expand Down
9 changes: 1 addition & 8 deletions bins/revme/src/cmd/eofvalidation/test_suite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,7 @@ pub struct TestUnit {
pub struct TestVector {
pub code: Bytes,
pub container_kind: Option<String>,
pub results: PragueTestResult,
}

#[derive(Debug, PartialEq, Eq, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct PragueTestResult {
#[serde(rename = "Prague")]
pub prague: TestResult,
pub results: BTreeMap<String, TestResult>,
}

#[derive(Debug, PartialEq, Eq, Deserialize)]
Expand Down
2 changes: 1 addition & 1 deletion bins/revme/src/cmd/statetest/models/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ impl SpecName {
Self::Shanghai => SpecId::SHANGHAI,
Self::Cancun => SpecId::CANCUN,
Self::Prague => SpecId::PRAGUE,
Self::Osaka => SpecId::OSAKA,
Self::ByzantiumToConstantinopleAt5 | Self::Constantinople => {
panic!("Overridden with PETERSBURG")
}
Self::Osaka => panic!("Osaka is not implemented"),
Self::Unknown => panic!("Unknown spec"),
}
}
Expand Down
17 changes: 2 additions & 15 deletions bins/revme/src/cmd/statetest/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,15 +123,6 @@ fn skip_test(path: &Path) -> bool {
| "static_Call50000_sha256.json"
| "loopMul.json"
| "CALLBlake2f_MaxRounds.json"

// evmone statetest
| "initcode_transaction_before_prague.json"
| "invalid_tx_non_existing_sender.json"
| "tx_non_existing_sender.json"
| "block_apply_withdrawal.json"
| "block_apply_ommers_reward.json"
| "known_block_hash.json"
| "eip7516_blob_base_fee.json"
)
}

Expand Down Expand Up @@ -330,16 +321,12 @@ pub fn execute_test_suite(
// Constantinople was immediately extended by Petersburg.
// There isn't any production Constantinople transaction
// so we don't support it and skip right to Petersburg.
if spec_name == SpecName::Constantinople || spec_name == SpecName::Osaka {
if spec_name == SpecName::Constantinople {
continue;
}

// Enable EOF in Prague tests.
let spec_id = if spec_name == SpecName::Prague {
SpecId::OSAKA
} else {
spec_name.to_spec_id()
};
let spec_id = spec_name.to_spec_id();

if spec_id.is_enabled_in(SpecId::MERGE) && env.block.prevrandao.is_none() {
// if spec is merge and prevrandao is not set, set it to default
Expand Down
96 changes: 50 additions & 46 deletions crates/revm/src/context/evm_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use super::inner_evm_context::InnerEvmContext;
use crate::{
db::Database,
interpreter::{
analysis::validate_eof, return_ok, CallInputs, Contract, CreateInputs, EOFCreateInputs,
EOFCreateKind, Gas, InstructionResult, Interpreter, InterpreterResult,
analysis::validate_eof, CallInputs, Contract, CreateInputs, EOFCreateInputs, EOFCreateKind,
Gas, InstructionResult, Interpreter, InterpreterResult,
},
primitives::{
keccak256, Address, Bytecode, Bytes, CreateScheme, EVMError, Env, Eof,
Expand Down Expand Up @@ -205,57 +205,61 @@ impl<DB: Database> EvmContext<DB> {
_ => {}
};

if let Some(result) = self.call_precompile(&inputs.bytecode_address, &inputs.input, gas)? {
if matches!(result.result, return_ok!()) {
self.journaled_state.checkpoint_commit();
} else {
self.journaled_state.checkpoint_revert(checkpoint);
}
Ok(FrameOrResult::new_call_result(
result,
inputs.return_memory_offset.clone(),
))
} else {
let account = self
.inner
.journaled_state
.load_code(inputs.bytecode_address, &mut self.inner.db)?;
let is_ext_delegate = inputs.scheme.is_ext_delegate_call();

let code_hash = account.info.code_hash();
let mut bytecode = account.info.code.clone().unwrap_or_default();

// ExtDelegateCall is not allowed to call non-EOF contracts.
if inputs.scheme.is_ext_delegate_call()
&& !bytecode.bytes_slice().starts_with(&EOF_MAGIC_BYTES)
if !is_ext_delegate {
if let Some(result) =
self.call_precompile(&inputs.bytecode_address, &inputs.input, gas)?
{
return return_result(InstructionResult::InvalidExtDelegateCallTarget);
if result.result.is_ok() {
self.journaled_state.checkpoint_commit();
} else {
self.journaled_state.checkpoint_revert(checkpoint);
}
return Ok(FrameOrResult::new_call_result(
result,
inputs.return_memory_offset.clone(),
));
}
}
// load account and bytecode
let account = self
.inner
.journaled_state
.load_code(inputs.bytecode_address, &mut self.inner.db)?;

if bytecode.is_empty() {
self.journaled_state.checkpoint_commit();
return return_result(InstructionResult::Stop);
}
let code_hash = account.info.code_hash();
let mut bytecode = account.info.code.clone().unwrap_or_default();

if let Bytecode::Eip7702(eip7702_bytecode) = bytecode {
bytecode = self
.inner
.journaled_state
.load_code(eip7702_bytecode.delegated_address, &mut self.inner.db)?
.info
.code
.clone()
.unwrap_or_default();
}
// ExtDelegateCall is not allowed to call non-EOF contracts.
if is_ext_delegate && !bytecode.bytes_slice().starts_with(&EOF_MAGIC_BYTES) {
return return_result(InstructionResult::InvalidExtDelegateCallTarget);
}

let contract =
Contract::new_with_context(inputs.input.clone(), bytecode, Some(code_hash), inputs);
// Create interpreter and executes call and push new CallStackFrame.
Ok(FrameOrResult::new_call_frame(
inputs.return_memory_offset.clone(),
checkpoint,
Interpreter::new(contract, gas.limit(), inputs.is_static),
))
if bytecode.is_empty() {
self.journaled_state.checkpoint_commit();
return return_result(InstructionResult::Stop);
}

if let Bytecode::Eip7702(eip7702_bytecode) = bytecode {
bytecode = self
.inner
.journaled_state
.load_code(eip7702_bytecode.delegated_address, &mut self.inner.db)?
.info
.code
.clone()
.unwrap_or_default();
}

let contract =
Contract::new_with_context(inputs.input.clone(), bytecode, Some(code_hash), inputs);
// Create interpreter and executes call and push new CallStackFrame.
Ok(FrameOrResult::new_call_frame(
inputs.return_memory_offset.clone(),
checkpoint,
Interpreter::new(contract, gas.limit(), inputs.is_static),
))
}

/// Make create frame.
Expand Down
Loading

0 comments on commit 346aa01

Please sign in to comment.