Skip to content

Commit

Permalink
EIP-6206: JUMPF
Browse files Browse the repository at this point in the history
  • Loading branch information
mrLSD committed Dec 13, 2024
1 parent bd982ea commit 20b2bc3
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 9 deletions.
3 changes: 3 additions & 0 deletions gasometer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -896,6 +896,9 @@ pub fn dynamic_opcode_cost<H: Handler>(
Opcode::RETF if config.has_eof => GasCost::VeryLow,
Opcode::RETF => GasCost::Invalid(opcode),

Opcode::JUMPF if config.has_eof => GasCost::Low,
Opcode::JUMPF => GasCost::Invalid(opcode),

_ => GasCost::Invalid(opcode),
};

Expand Down
2 changes: 1 addition & 1 deletion runtime/src/eval/eof/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ pub fn retf<H: Handler>(runtime: &mut Runtime, _handler: &mut H) -> Control<H> {
};
// Set machine code to target code section
runtime.machine.set_code(code_section);
// Set PC to position 0
// Set PC to position
runtime.machine.set_pc(function_return_state.pc);

Control::Continue
Expand Down
42 changes: 42 additions & 0 deletions runtime/src/eval/eof/jump.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//! # EIP-6206: EOF - JUMPF and non-returning functions
//!
//! Introduces instruction for chaining function calls.
//! [EIP-6206](https://eips.ethereum.org/EIPS/eip-6206)
use crate::eval::Control;
use crate::{Handler, Runtime};
use evm_core::{ExitError, ExitFatal};

pub fn jumpf<H: Handler>(runtime: &mut Runtime, _handler: &mut H) -> Control<H> {
let eof = require_eof!(runtime);
// Immediate value after the instruction.
// 16-bit unsigned big-endian value
let raw_offset = try_or_fail!(runtime.machine.get_code_and_inc_pc(2));
let target_section_index = usize::from(crate::eof::get_u16(raw_offset, 0));

// Get target types
let Some(types) = eof.body.types_section.get(target_section_index) else {
return Control::Exit(ExitFatal::CallErrorAsFatal(ExitError::EOFUnexpectedCall).into());
};

// Check max stack height for target code section. It's safe to subtract
// as max_stack_height is always more than inputs.
if runtime.machine.stack().len() + usize::from(types.max_stack_size - u16::from(types.inputs))
> 1024
{
return Control::Exit(ExitError::StackOverflow.into());
}

runtime
.context
.eof_function_stack
.set_current_code_index(target_section_index);
let Some(code_section) = eof.body.code_section.get(target_section_index) else {
return Control::Exit(ExitFatal::CallErrorAsFatal(ExitError::EOFUnexpectedCall).into());
};
// Set machine code to target code section
runtime.machine.set_code(code_section);
// Set PC to position 0
runtime.machine.set_pc(0);

Control::Continue
}
1 change: 1 addition & 0 deletions runtime/src/eval/eof/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub mod contract;
pub mod control;
pub mod data;
pub mod ext;
pub mod jump;
#[cfg(test)]
mod mock;
pub mod stack;
2 changes: 1 addition & 1 deletion runtime/src/eval/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ pub fn eval<H: Handler>(state: &mut Runtime, opcode: Opcode, handler: &mut H) ->
Opcode::RJUMPV => eof::control::rjumpv(state, handler),
Opcode::CALLF => eof::call::callf(state, handler),
Opcode::RETF => eof::call::retf(state, handler),
Opcode::JUMPF => system::jumpf(state, handler),
Opcode::JUMPF => eof::jump::jumpf(state, handler),
Opcode::DUPN => eof::stack::dupn(state),
Opcode::SWAPN => eof::stack::swapn(state),
Opcode::EXCHANGE => eof::stack::exchange(state),
Expand Down
5 changes: 0 additions & 5 deletions runtime/src/eval/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -586,11 +586,6 @@ pub fn call<H: Handler>(runtime: &mut Runtime, scheme: CallScheme, handler: &mut
//===========================
// EOF related functions

#[allow(dead_code)]
pub fn jumpf<H: Handler>(_runtime: &mut Runtime, _handler: &mut H) -> Control<H> {
todo!()
}

#[allow(dead_code)]
pub fn return_contract<H: Handler>(_runtime: &mut Runtime, _handler: &mut H) -> Control<H> {
todo!()
Expand Down
10 changes: 8 additions & 2 deletions src/executor/stack/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1299,10 +1299,16 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet>
Ok(eof) => {
// Set EOF
context.eof = Some(eof.clone());
// If code section doesn't exist, return `EOFUnexpectedCall`
let Some(code) = eof.body.code_section.first().cloned() else {
return Capture::Exit((
ExitFatal::CallErrorAsFatal(ExitError::EOFUnexpectedCall).into(),
Vec::new(),
));
};
(
// Get first code section
eof.body.code_section.first().cloned().unwrap_or_default(),
context,
code, context,
)
}
Err(err) => {
Expand Down

0 comments on commit 20b2bc3

Please sign in to comment.