Skip to content

Commit

Permalink
replace const u8 with meaningful trait
Browse files Browse the repository at this point in the history
  • Loading branch information
joonazan committed Aug 19, 2024
1 parent bf5866e commit 139f486
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 71 deletions.
86 changes: 47 additions & 39 deletions eravm-stable-interface/src/tracer_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,44 @@ macro_rules! pub_struct {

pub mod opcodes {
forall_simple_opcodes!(pub_struct);
pub struct FarCall<const M: u8>;
pub struct Ret<const M: u8>;
pub struct FarCall<M: TypeLevelCallingMode>(M);
pub struct Ret<T: TypeLevelReturnType>(T);

pub struct Normal;
pub struct Delegate;
pub struct Mimic;
pub struct Revert;
pub struct Panic;

use super::{CallingMode, ReturnType};

pub trait TypeLevelCallingMode {
const VALUE: CallingMode;
}

impl TypeLevelCallingMode for Normal {
const VALUE: CallingMode = CallingMode::Normal;
}
impl TypeLevelCallingMode for Delegate {
const VALUE: CallingMode = CallingMode::Delegate;
}
impl TypeLevelCallingMode for Mimic {
const VALUE: CallingMode = CallingMode::Mimic;
}

pub trait TypeLevelReturnType {
const VALUE: ReturnType;
}

impl TypeLevelReturnType for Normal {
const VALUE: ReturnType = ReturnType::Normal;
}
impl TypeLevelReturnType for Revert {
const VALUE: ReturnType = ReturnType::Revert;
}
impl TypeLevelReturnType for Panic {
const VALUE: ReturnType = ReturnType::Panic;
}
}

#[derive(PartialEq, Eq)]
Expand Down Expand Up @@ -106,28 +142,15 @@ pub enum Opcode {
}

#[derive(PartialEq, Eq)]
#[repr(u8)]
pub enum CallingMode {
Normal = 0,
Normal,
Delegate,
Mimic,
}

impl CallingMode {
pub const fn from_u8(value: u8) -> Self {
match value {
0 => CallingMode::Normal,
1 => CallingMode::Delegate,
2 => CallingMode::Mimic,
_ => unreachable!(),
}
}
}

#[repr(u8)]
#[derive(PartialEq, Eq)]
pub enum ReturnType {
Normal = 0,
Normal,
Revert,
Panic,
}
Expand All @@ -136,15 +159,6 @@ impl ReturnType {
pub fn is_failure(&self) -> bool {
*self != ReturnType::Normal
}

pub const fn from_u8(value: u8) -> Self {
match value {
0 => ReturnType::Normal,
1 => ReturnType::Revert,
2 => ReturnType::Panic,
_ => unreachable!(),
}
}
}

pub trait OpcodeType {
Expand All @@ -161,12 +175,12 @@ macro_rules! impl_opcode {

forall_simple_opcodes!(impl_opcode);

impl<const M: u8> OpcodeType for opcodes::FarCall<M> {
const VALUE: Opcode = Opcode::FarCall(CallingMode::from_u8(M));
impl<M: opcodes::TypeLevelCallingMode> OpcodeType for opcodes::FarCall<M> {
const VALUE: Opcode = Opcode::FarCall(M::VALUE);
}

impl<const M: u8> OpcodeType for opcodes::Ret<M> {
const VALUE: Opcode = Opcode::Ret(ReturnType::from_u8(M));
impl<T: opcodes::TypeLevelReturnType> OpcodeType for opcodes::Ret<T> {
const VALUE: Opcode = Opcode::Ret(T::VALUE);
}

/// Implement this for a type that holds the state of your tracer.
Expand Down Expand Up @@ -232,14 +246,10 @@ mod tests {
tracer.before_instruction::<opcodes::Nop, _>(&mut DummyState);
assert_eq!(tracer.0, 0);

tracer.before_instruction::<opcodes::FarCall<{ CallingMode::Normal as u8 }>, _>(
&mut DummyState,
);
tracer.before_instruction::<opcodes::FarCall<opcodes::Normal>, _>(&mut DummyState);
assert_eq!(tracer.0, 1);

tracer.before_instruction::<opcodes::FarCall<{ CallingMode::Delegate as u8 }>, _>(
&mut DummyState,
);
tracer.before_instruction::<opcodes::FarCall<opcodes::Mimic>, _>(&mut DummyState);
assert_eq!(tracer.0, 1);
}

Expand All @@ -252,9 +262,7 @@ mod tests {
assert_eq!(tracer.1 .0 .0, 0);
assert_eq!(tracer.1 .1 .0, 0);

tracer.before_instruction::<opcodes::FarCall<{ CallingMode::Normal as u8 }>, _>(
&mut DummyState,
);
tracer.before_instruction::<opcodes::FarCall<opcodes::Normal>, _>(&mut DummyState);
assert_eq!(tracer.0 .0, 1);
assert_eq!(tracer.1 .0 .0, 1);
assert_eq!(tracer.1 .1 .0, 1);
Expand Down
8 changes: 4 additions & 4 deletions src/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::{
mode_requirements::ModeRequirements,
Instruction, Predicate, VirtualMachine, World,
};
use eravm_stable_interface::{CallingMode, Tracer};
use eravm_stable_interface::{opcodes, Tracer};
use zkevm_opcode_defs::{
decoding::{EncodingModeProduction, VmEncodingMode},
ImmMemHandlerFlags, Opcode,
Expand Down Expand Up @@ -210,13 +210,13 @@ pub(crate) fn decode<T: Tracer>(raw: u64, is_bootloader: bool) -> Instruction<T>
zkevm_opcode_defs::Opcode::FarCall(kind) => {
let constructor = match kind {
zkevm_opcode_defs::FarCallOpcode::Normal => {
Instruction::from_far_call::<{ CallingMode::Normal as u8 }>
Instruction::from_far_call::<opcodes::Normal>
}
zkevm_opcode_defs::FarCallOpcode::Delegate => {
Instruction::from_far_call::<{ CallingMode::Delegate as u8 }>
Instruction::from_far_call::<opcodes::Delegate>
}
zkevm_opcode_defs::FarCallOpcode::Mimic => {
Instruction::from_far_call::<{ CallingMode::Mimic as u8 }>
Instruction::from_far_call::<opcodes::Mimic>
}
};
constructor(
Expand Down
15 changes: 9 additions & 6 deletions src/instruction_handlers/far_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ use crate::{
predication::Flags,
Instruction, VirtualMachine, World,
};
use eravm_stable_interface::{opcodes::FarCall, Tracer};
use eravm_stable_interface::{
opcodes::{FarCall, TypeLevelCallingMode},
Tracer,
};
use u256::U256;
use zkevm_opcode_defs::{
system_params::{EVM_SIMULATOR_STIPEND, MSG_VALUE_SIMULATOR_ADDITIVE_COST},
Expand All @@ -29,12 +32,12 @@ use zkevm_opcode_defs::{
///
/// Even though all errors happen before the new stack frame, they cause a panic in the new frame,
/// not in the caller!
fn far_call<T: Tracer, const CALLING_MODE: u8, const IS_STATIC: bool, const IS_SHARD: bool>(
fn far_call<T: Tracer, M: TypeLevelCallingMode, const IS_STATIC: bool, const IS_SHARD: bool>(
vm: &mut VirtualMachine<T>,
world: &mut dyn World<T>,
tracer: &mut T,
) -> ExecutionStatus {
instruction_boilerplate::<FarCall<CALLING_MODE>, _>(vm, world, tracer, |vm, args, world| {
instruction_boilerplate::<FarCall<M>, _>(vm, world, tracer, |vm, args, world| {
let (raw_abi, raw_abi_is_pointer) = Register1::get_with_pointer_flag(args, &mut vm.state);

let address_mask: U256 = U256::MAX >> (256 - 160);
Expand Down Expand Up @@ -111,7 +114,7 @@ fn far_call<T: Tracer, const CALLING_MODE: u8, const IS_STATIC: bool, const IS_S
.expect("stipend must not cause overflow");

let new_frame_is_static = IS_STATIC || vm.state.current_frame.is_static;
vm.push_frame::<CALLING_MODE>(
vm.push_frame::<M>(
u256_into_address(destination_address),
program,
new_frame_gas,
Expand Down Expand Up @@ -253,7 +256,7 @@ impl FatPointer {
use super::monomorphization::*;

impl<T: Tracer> Instruction<T> {
pub fn from_far_call<const MODE: u8>(
pub fn from_far_call<M: TypeLevelCallingMode>(
src1: Register1,
src2: Register2,
error_handler: Immediate1,
Expand All @@ -262,7 +265,7 @@ impl<T: Tracer> Instruction<T> {
arguments: Arguments,
) -> Self {
Self {
handler: monomorphize!(far_call [T MODE] match_boolean is_static match_boolean is_shard),
handler: monomorphize!(far_call [T M] match_boolean is_static match_boolean is_shard),
arguments: arguments
.write_source(&src1)
.write_source(&src2)
Expand Down
25 changes: 13 additions & 12 deletions src/instruction_handlers/ret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,19 @@ use crate::{
predication::Flags,
Instruction, Predicate, VirtualMachine, World,
};
use eravm_stable_interface::{opcodes, ReturnType, Tracer};
use eravm_stable_interface::{
opcodes::{self, TypeLevelReturnType},
ReturnType, Tracer,
};
use u256::U256;

fn ret<T: Tracer, const RETURN_TYPE: u8, const TO_LABEL: bool>(
fn ret<T: Tracer, RT: TypeLevelReturnType, const TO_LABEL: bool>(
vm: &mut VirtualMachine<T>,
world: &mut dyn World<T>,
tracer: &mut T,
) -> ExecutionStatus {
instruction_boilerplate_ext::<opcodes::Ret<RETURN_TYPE>, _>(vm, world, tracer, |vm, args, _| {
let mut return_type = ReturnType::from_u8(RETURN_TYPE);
instruction_boilerplate_ext::<opcodes::Ret<RT>, _>(vm, world, tracer, |vm, args, _| {
let mut return_type = RT::VALUE;
let near_call_leftover_gas = vm.state.current_frame.gas;

let (snapshot, leftover_gas) = if let Some(FrameRemnant {
Expand Down Expand Up @@ -155,41 +158,39 @@ pub(crate) fn free_panic<T: Tracer>(
world: &mut dyn World<T>,
tracer: &mut T,
) -> ExecutionStatus {
ret::<T, { ReturnType::Panic as u8 }, false>(vm, world, tracer)
ret::<T, opcodes::Panic, false>(vm, world, tracer)
}

use super::monomorphization::*;
use eravm_stable_interface::opcodes::{Normal, Panic, Revert};

impl<T: Tracer> Instruction<T> {
pub fn from_ret(src1: Register1, label: Option<Immediate1>, arguments: Arguments) -> Self {
let to_label = label.is_some();
const RETURN_TYPE: u8 = ReturnType::Normal as u8;
Self {
handler: monomorphize!(ret [T RETURN_TYPE] match_boolean to_label),
handler: monomorphize!(ret [T Normal] match_boolean to_label),
arguments: arguments.write_source(&src1).write_source(&label),
}
}
pub fn from_revert(src1: Register1, label: Option<Immediate1>, arguments: Arguments) -> Self {
let to_label = label.is_some();
const RETURN_TYPE: u8 = ReturnType::Revert as u8;
Self {
handler: monomorphize!(ret [T RETURN_TYPE] match_boolean to_label),
handler: monomorphize!(ret [T Revert] match_boolean to_label),
arguments: arguments.write_source(&src1).write_source(&label),
}
}
pub fn from_panic(label: Option<Immediate1>, arguments: Arguments) -> Self {
let to_label = label.is_some();
const RETURN_TYPE: u8 = ReturnType::Panic as u8;
Self {
handler: monomorphize!(ret [T RETURN_TYPE] match_boolean to_label),
handler: monomorphize!(ret [T Panic] match_boolean to_label),
arguments: arguments.write_source(&label),
}
}

pub const fn from_invalid() -> Self {
Self {
// This field is never read because the instruction fails at the gas cost stage.
handler: ret::<T, { ReturnType::Panic as u8 }, false>,
handler: ret::<T, Panic, false>,
arguments: Arguments::new(
Predicate::Always,
INVALID_INSTRUCTION_COST,
Expand Down
18 changes: 8 additions & 10 deletions src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::{
ExecutionEnd, Program, World,
};
use crate::{Instruction, ModeRequirements, Predicate};
use eravm_stable_interface::opcodes::TypeLevelCallingMode;
use eravm_stable_interface::{opcodes, CallingMode, HeapId, Tracer};
use u256::H160;

Expand Down Expand Up @@ -202,7 +203,7 @@ impl<T: Tracer> VirtualMachine<T> {
}

#[allow(clippy::too_many_arguments)]
pub(crate) fn push_frame<const CALLING_MODE: u8>(
pub(crate) fn push_frame<M: TypeLevelCallingMode>(
&mut self,
code_address: H160,
program: Program<T>,
Expand All @@ -214,19 +215,16 @@ impl<T: Tracer> VirtualMachine<T> {
world_before_this_frame: Snapshot,
) {
let mut new_frame = Callframe::new(
if CALLING_MODE == CallingMode::Delegate as u8 {
if M::VALUE == CallingMode::Delegate {
self.state.current_frame.address
} else {
code_address
},
code_address,
if CALLING_MODE == CallingMode::Normal as u8 {
self.state.current_frame.address
} else if CALLING_MODE == CallingMode::Delegate as u8 {
self.state.current_frame.caller
} else {
// Mimic call
u256_into_address(self.state.registers[15])
match M::VALUE {
CallingMode::Normal => self.state.current_frame.address,
CallingMode::Delegate => self.state.current_frame.caller,
CallingMode::Mimic => u256_into_address(self.state.registers[15]),
},
program,
self.stack_pool.get(),
Expand All @@ -236,7 +234,7 @@ impl<T: Tracer> VirtualMachine<T> {
gas,
stipend,
exception_handler,
if CALLING_MODE == CallingMode::Delegate as u8 {
if M::VALUE == CallingMode::Delegate {
self.state.current_frame.context_u128
} else {
self.state.context_u128
Expand Down

0 comments on commit 139f486

Please sign in to comment.