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

fix(eof): fixture 2 tests #1550

Merged
merged 9 commits into from
Jun 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 bins/revm-test/src/bin/burntpix/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ fn try_from_hex_to_u32(hex: &str) -> eyre::Result<u32> {
}

fn insert_account_info(cache_db: &mut CacheDB<EmptyDB>, addr: Address, code: Bytes) {
let code_hash = hex::encode(keccak256(code.clone()));
let code_hash = hex::encode(keccak256(&code));
let account_info = AccountInfo::new(
U256::from(0),
0,
Expand Down
2 changes: 2 additions & 0 deletions bins/revme/src/cmd/statetest/models/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub enum SpecName {
Shanghai,
Cancun,
Prague,
PragueEOF,
#[serde(other)]
Unknown,
}
Expand All @@ -46,6 +47,7 @@ impl SpecName {
Self::Shanghai => SpecId::SHANGHAI,
Self::Cancun => SpecId::CANCUN,
Self::Prague => SpecId::PRAGUE,
Self::PragueEOF => SpecId::PRAGUE_EOF,
Self::ByzantiumToConstantinopleAt5 | Self::Constantinople => {
panic!("Overridden with PETERSBURG")
}
Expand Down
58 changes: 45 additions & 13 deletions crates/interpreter/src/instruction_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ pub enum InstructionResult {
Revert = 0x10, // revert opcode
CallTooDeep,
OutOfFunds,
/// Revert if CREATE/CREATE2 starts with 0xEF00
CreateInitCodeStartingEF00,
/// Invalid EOF initcode,
InvalidEOFInitCode,

// Actions
CallOrCreate = 0x20,
Expand All @@ -29,7 +33,7 @@ pub enum InstructionResult {
OpcodeNotFound,
CallNotAllowedInsideStatic,
StateChangeDuringStaticCall,
InvalidFEOpcode,
InvalidEFOpcode,
InvalidJump,
NotActivated,
StackUnderflow,
Expand All @@ -53,6 +57,10 @@ pub enum InstructionResult {
EOFOpcodeDisabledInLegacy,
/// EOF function stack overflow
EOFFunctionStackOverflow,
/// Aux data overflow, new aux data is larger tha u16 max size.
EofAuxDataOverflow,
/// Aud data is smaller then already present data size.
EofAuxDataTooSmall,
}

impl From<SuccessReason> for InstructionResult {
Expand All @@ -77,7 +85,7 @@ impl From<HaltReason> for InstructionResult {
OutOfGasError::Precompile => Self::PrecompileOOG,
},
HaltReason::OpcodeNotFound => Self::OpcodeNotFound,
HaltReason::InvalidFEOpcode => Self::InvalidFEOpcode,
HaltReason::InvalidEFOpcode => Self::InvalidEFOpcode,
HaltReason::InvalidJump => Self::InvalidJump,
HaltReason::NotActivated => Self::NotActivated,
HaltReason::StackOverflow => Self::StackOverflow,
Expand All @@ -94,6 +102,9 @@ impl From<HaltReason> for InstructionResult {
HaltReason::CallNotAllowedInsideStatic => Self::CallNotAllowedInsideStatic,
HaltReason::OutOfFunds => Self::OutOfFunds,
HaltReason::CallTooDeep => Self::CallTooDeep,
HaltReason::EofAuxDataOverflow => Self::EofAuxDataOverflow,
HaltReason::EofAuxDataTooSmall => Self::EofAuxDataTooSmall,
HaltReason::EOFFunctionStackOverflow => Self::EOFFunctionStackOverflow,
#[cfg(feature = "optimism")]
HaltReason::FailedDeposit => Self::FatalExternalError,
}
Expand All @@ -114,7 +125,11 @@ macro_rules! return_ok {
#[macro_export]
macro_rules! return_revert {
() => {
InstructionResult::Revert | InstructionResult::CallTooDeep | InstructionResult::OutOfFunds
InstructionResult::Revert
| InstructionResult::CallTooDeep
| InstructionResult::OutOfFunds
| InstructionResult::InvalidEOFInitCode
| InstructionResult::CreateInitCodeStartingEF00
};
}

Expand All @@ -129,7 +144,7 @@ macro_rules! return_error {
| InstructionResult::OpcodeNotFound
| InstructionResult::CallNotAllowedInsideStatic
| InstructionResult::StateChangeDuringStaticCall
| InstructionResult::InvalidFEOpcode
| InstructionResult::InvalidEFOpcode
| InstructionResult::InvalidJump
| InstructionResult::NotActivated
| InstructionResult::StackUnderflow
Expand All @@ -146,6 +161,8 @@ macro_rules! return_error {
| InstructionResult::ReturnContractInNotInitEOF
| InstructionResult::EOFOpcodeDisabledInLegacy
| InstructionResult::EOFFunctionStackOverflow
| InstructionResult::EofAuxDataTooSmall
| InstructionResult::EofAuxDataOverflow
};
}

Expand All @@ -169,16 +186,24 @@ impl InstructionResult {
}
}

/// Internal result that are not ex
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum InternalResult {
/// Internal instruction that signals Interpreter should continue running.
InternalContinue,
/// Internal instruction that signals call or create.
InternalCallOrCreate,
/// Internal CREATE/CREATE starts with 0xEF00
CreateInitCodeStartingEF00,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum SuccessOrHalt {
Success(SuccessReason),
Revert,
Halt(HaltReason),
FatalExternalError,
/// Internal instruction that signals Interpreter should continue running.
InternalContinue,
/// Internal instruction that signals call or create.
InternalCallOrCreate,
Internal(InternalResult),
}

impl SuccessOrHalt {
Expand Down Expand Up @@ -222,12 +247,13 @@ impl SuccessOrHalt {
impl From<InstructionResult> for SuccessOrHalt {
fn from(result: InstructionResult) -> Self {
match result {
InstructionResult::Continue => Self::InternalContinue, // used only in interpreter loop
InstructionResult::Continue => Self::Internal(InternalResult::InternalContinue), // used only in interpreter loop
InstructionResult::Stop => Self::Success(SuccessReason::Stop),
InstructionResult::Return => Self::Success(SuccessReason::Return),
InstructionResult::SelfDestruct => Self::Success(SuccessReason::SelfDestruct),
InstructionResult::Revert => Self::Revert,
InstructionResult::CallOrCreate => Self::InternalCallOrCreate, // used only in interpreter loop
InstructionResult::CreateInitCodeStartingEF00 => Self::Revert,
InstructionResult::CallOrCreate => Self::Internal(InternalResult::InternalCallOrCreate), // used only in interpreter loop
InstructionResult::CallTooDeep => Self::Halt(HaltReason::CallTooDeep), // not gonna happen for first call
InstructionResult::OutOfFunds => Self::Halt(HaltReason::OutOfFunds), // Check for first call is done separately.
InstructionResult::OutOfGas => Self::Halt(HaltReason::OutOfGas(OutOfGasError::Basic)),
Expand All @@ -250,7 +276,7 @@ impl From<InstructionResult> for SuccessOrHalt {
InstructionResult::StateChangeDuringStaticCall => {
Self::Halt(HaltReason::StateChangeDuringStaticCall)
}
InstructionResult::InvalidFEOpcode => Self::Halt(HaltReason::InvalidFEOpcode),
InstructionResult::InvalidEFOpcode => Self::Halt(HaltReason::InvalidEFOpcode),
InstructionResult::InvalidJump => Self::Halt(HaltReason::InvalidJump),
InstructionResult::NotActivated => Self::Halt(HaltReason::NotActivated),
InstructionResult::StackUnderflow => Self::Halt(HaltReason::StackUnderflow),
Expand All @@ -267,10 +293,16 @@ impl From<InstructionResult> for SuccessOrHalt {
InstructionResult::CreateInitCodeSizeLimit => {
Self::Halt(HaltReason::CreateInitCodeSizeLimit)
}
// TODO (EOF) add proper Revert subtype.
InstructionResult::InvalidEOFInitCode => Self::Revert,
InstructionResult::FatalExternalError => Self::FatalExternalError,
InstructionResult::EOFOpcodeDisabledInLegacy => Self::Halt(HaltReason::OpcodeNotFound),
InstructionResult::EOFFunctionStackOverflow => Self::FatalExternalError,
InstructionResult::EOFFunctionStackOverflow => {
Self::Halt(HaltReason::EOFFunctionStackOverflow)
}
InstructionResult::ReturnContract => Self::Success(SuccessReason::EofReturnContract),
InstructionResult::EofAuxDataOverflow => Self::Halt(HaltReason::EofAuxDataOverflow),
InstructionResult::EofAuxDataTooSmall => Self::Halt(HaltReason::EofAuxDataTooSmall),
}
}
}
Expand Down Expand Up @@ -325,7 +357,7 @@ mod tests {
InstructionResult::OpcodeNotFound,
InstructionResult::CallNotAllowedInsideStatic,
InstructionResult::StateChangeDuringStaticCall,
InstructionResult::InvalidFEOpcode,
InstructionResult::InvalidEFOpcode,
InstructionResult::InvalidJump,
InstructionResult::NotActivated,
InstructionResult::StackUnderflow,
Expand Down
31 changes: 20 additions & 11 deletions crates/interpreter/src/instructions/contract.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
mod call_helpers;

pub use call_helpers::{calc_call_gas, get_memory_input_and_out_ranges, resize_memory};
use revm_primitives::{keccak256, BerlinSpec};

use crate::{
gas::{self, cost_per_word, EOF_CREATE_GAS, KECCAK256WORD},
interpreter::Interpreter,
primitives::{Address, Bytes, Eof, Spec, SpecId::*, U256},
primitives::{
eof::EofHeader, keccak256, Address, BerlinSpec, Bytes, Eof, Spec, SpecId::*, U256,
},
CallInputs, CallScheme, CallValue, CreateInputs, CreateScheme, EOFCreateInputs, Host,
InstructionResult, InterpreterAction, InterpreterResult, LoadAccountResult, MAX_INITCODE_SIZE,
};
Expand Down Expand Up @@ -67,7 +68,7 @@ pub fn eofcreate<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H)
// Send container for execution container is preverified.
interpreter.instruction_result = InstructionResult::CallOrCreate;
interpreter.next_action = InterpreterAction::EOFCreate {
inputs: Box::new(EOFCreateInputs::new(
inputs: Box::new(EOFCreateInputs::new_opcode(
interpreter.contract.target_address,
created_address,
value,
Expand All @@ -92,10 +93,11 @@ pub fn return_contract<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &
.body
.container_section
.get(deploy_container_index as usize)
.expect("EOF is checked");
.expect("EOF is checked")
.clone();

// convert to EOF so we can check data section size.
let new_eof = Eof::decode(container.clone()).expect("Container is verified");
let (eof_header, _) = EofHeader::decode(&container).expect("valid EOF header");

let aux_slice = if aux_data_size != 0 {
let aux_data_offset = as_usize_or_fail!(interpreter, aux_data_offset);
Expand All @@ -108,20 +110,27 @@ pub fn return_contract<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &
&[]
};

let new_data_size = new_eof.body.data_section.len() + aux_slice.len();
let static_aux_size = eof_header.eof_size() - container.len();

// data_size - static_aux_size give us current data `container` size.
// and with aux_slice len we can calculate new data size.
let new_data_size = eof_header.data_size as usize - static_aux_size + aux_slice.len();
if new_data_size > 0xFFFF {
// aux data is too big
interpreter.instruction_result = InstructionResult::FatalExternalError;
interpreter.instruction_result = InstructionResult::EofAuxDataOverflow;
return;
}
if new_data_size < new_eof.header.data_size as usize {
if new_data_size < eof_header.data_size as usize {
// aux data is too small
interpreter.instruction_result = InstructionResult::FatalExternalError;
interpreter.instruction_result = InstructionResult::EofAuxDataTooSmall;
return;
}
let new_data_size = (new_data_size as u16).to_be_bytes();

// append data bytes
let output = [new_eof.raw(), aux_slice].concat().into();
let mut output = [&container, aux_slice].concat();
// set new data size in eof bytes as we know exact index.
output[eof_header.data_size_raw_i()..][..2].clone_from_slice(&new_data_size);
let output: Bytes = output.into();

let result = InstructionResult::ReturnContract;
interpreter.instruction_result = result;
Expand Down
2 changes: 1 addition & 1 deletion crates/interpreter/src/instructions/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ pub fn stop<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {

/// Invalid opcode. This opcode halts the execution.
pub fn invalid<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
interpreter.instruction_result = InstructionResult::InvalidFEOpcode;
interpreter.instruction_result = InstructionResult::InvalidEFOpcode;
}

/// Unknown opcode. This opcode halts the execution.
Expand Down
8 changes: 5 additions & 3 deletions crates/interpreter/src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ pub use contract::Contract;
pub use shared_memory::{num_words, SharedMemory, EMPTY_SHARED_MEMORY};
pub use stack::{Stack, STACK_LIMIT};

use crate::EOFCreateOutcome;
use crate::{
gas, primitives::Bytes, push, push_b256, return_ok, return_revert, CallOutcome, CreateOutcome,
FunctionStack, Gas, Host, InstructionResult, InterpreterAction,
Expand Down Expand Up @@ -192,7 +191,7 @@ impl Interpreter {
}
}

pub fn insert_eofcreate_outcome(&mut self, create_outcome: EOFCreateOutcome) {
pub fn insert_eofcreate_outcome(&mut self, create_outcome: CreateOutcome) {
self.instruction_result = InstructionResult::Continue;
let instruction_result = create_outcome.instruction_result();

Expand All @@ -206,7 +205,10 @@ impl Interpreter {

match instruction_result {
InstructionResult::ReturnContract => {
push_b256!(self, create_outcome.address.into_word());
push_b256!(
self,
create_outcome.address.expect("EOF Address").into_word()
);
self.gas.erase_cost(create_outcome.gas().remaining());
self.gas.record_refund(create_outcome.gas().refunded());
}
Expand Down
4 changes: 1 addition & 3 deletions crates/interpreter/src/interpreter_action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@ mod call_outcome;
mod create_inputs;
mod create_outcome;
mod eof_create_inputs;
mod eof_create_outcome;

pub use call_inputs::{CallInputs, CallScheme, CallValue};
pub use call_outcome::CallOutcome;
pub use create_inputs::{CreateInputs, CreateScheme};
pub use create_outcome::CreateOutcome;
pub use eof_create_inputs::EOFCreateInputs;
pub use eof_create_outcome::EOFCreateOutcome;
pub use eof_create_inputs::{EOFCreateInputs, EOFCreateKind};

use crate::InterpreterResult;
use std::boxed::Box;
Expand Down
Loading
Loading