Skip to content

Commit

Permalink
feat(interpreter): test Host object-safety, allow dyn Host in instr…
Browse files Browse the repository at this point in the history
…uctions
  • Loading branch information
DaniPopes committed Mar 29, 2024
1 parent 81b65dd commit 854e9a7
Show file tree
Hide file tree
Showing 13 changed files with 140 additions and 107 deletions.
13 changes: 13 additions & 0 deletions crates/interpreter/src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,16 @@ pub struct SStoreResult {
/// Is storage slot loaded from database
pub is_cold: bool,
}

#[cfg(test)]
mod tests {
use super::*;

fn assert_host<H: Host + ?Sized>() {}

#[test]
fn object_safety() {
assert_host::<DummyHost>();
assert_host::<dyn Host>();
}
}
22 changes: 11 additions & 11 deletions crates/interpreter/src/instructions/arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,67 +5,67 @@ use crate::{
Host, Interpreter,
};

pub fn wrapping_add<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn wrapping_add<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::VERYLOW);
pop_top!(interpreter, op1, op2);
*op2 = op1.wrapping_add(*op2);
}

pub fn wrapping_mul<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn wrapping_mul<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::LOW);
pop_top!(interpreter, op1, op2);
*op2 = op1.wrapping_mul(*op2);
}

pub fn wrapping_sub<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn wrapping_sub<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::VERYLOW);
pop_top!(interpreter, op1, op2);
*op2 = op1.wrapping_sub(*op2);
}

pub fn div<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn div<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::LOW);
pop_top!(interpreter, op1, op2);
if *op2 != U256::ZERO {
*op2 = op1.wrapping_div(*op2);
}
}

pub fn sdiv<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn sdiv<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::LOW);
pop_top!(interpreter, op1, op2);
*op2 = i256_div(op1, *op2);
}

pub fn rem<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn rem<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::LOW);
pop_top!(interpreter, op1, op2);
if *op2 != U256::ZERO {
*op2 = op1.wrapping_rem(*op2);
}
}

pub fn smod<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn smod<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::LOW);
pop_top!(interpreter, op1, op2);
if *op2 != U256::ZERO {
*op2 = i256_mod(op1, *op2)
}
}

pub fn addmod<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn addmod<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::MID);
pop_top!(interpreter, op1, op2, op3);
*op3 = op1.add_mod(op2, *op3)
}

pub fn mulmod<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn mulmod<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::MID);
pop_top!(interpreter, op1, op2, op3);
*op3 = op1.mul_mod(op2, *op3)
}

pub fn exp<H: Host, SPEC: Spec>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn exp<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, _host: &mut H) {
pop_top!(interpreter, op1, op2);
gas_or_fail!(interpreter, gas::exp_cost::<SPEC>(*op2));
*op2 = op1.pow(*op2);
Expand All @@ -86,7 +86,7 @@ pub fn exp<H: Host, SPEC: Spec>(interpreter: &mut Interpreter, _host: &mut H) {
/// `y | !mask` where `|` is the bitwise `OR` and `!` is bitwise negation. Similarly, if
/// `b == 0` then the yellow paper says the output should start with all zeros, then end with
/// bits from `b`; this is equal to `y & mask` where `&` is bitwise `AND`.
pub fn signextend<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn signextend<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::LOW);
pop_top!(interpreter, ext, x);
// For 31 we also don't need to do anything.
Expand Down
28 changes: 14 additions & 14 deletions crates/interpreter/src/instructions/bitwise.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,67 +6,67 @@ use crate::{
};
use core::cmp::Ordering;

pub fn lt<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn lt<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::VERYLOW);
pop_top!(interpreter, op1, op2);
*op2 = U256::from(op1 < *op2);
}

pub fn gt<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn gt<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::VERYLOW);
pop_top!(interpreter, op1, op2);
*op2 = U256::from(op1 > *op2);
}

pub fn slt<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn slt<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::VERYLOW);
pop_top!(interpreter, op1, op2);
*op2 = U256::from(i256_cmp(&op1, op2) == Ordering::Less);
}

pub fn sgt<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn sgt<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::VERYLOW);
pop_top!(interpreter, op1, op2);
*op2 = U256::from(i256_cmp(&op1, op2) == Ordering::Greater);
}

pub fn eq<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn eq<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::VERYLOW);
pop_top!(interpreter, op1, op2);
*op2 = U256::from(op1 == *op2);
}

pub fn iszero<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn iszero<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::VERYLOW);
pop_top!(interpreter, op1);
*op1 = U256::from(*op1 == U256::ZERO);
}

pub fn bitand<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn bitand<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::VERYLOW);
pop_top!(interpreter, op1, op2);
*op2 = op1 & *op2;
}

pub fn bitor<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn bitor<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::VERYLOW);
pop_top!(interpreter, op1, op2);
*op2 = op1 | *op2;
}

pub fn bitxor<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn bitxor<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::VERYLOW);
pop_top!(interpreter, op1, op2);
*op2 = op1 ^ *op2;
}

pub fn not<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn not<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::VERYLOW);
pop_top!(interpreter, op1);
*op1 = !*op1;
}

pub fn byte<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn byte<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::VERYLOW);
pop_top!(interpreter, op1, op2);

Expand All @@ -80,23 +80,23 @@ pub fn byte<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
}

/// EIP-145: Bitwise shifting instructions in EVM
pub fn shl<H: Host, SPEC: Spec>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn shl<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, _host: &mut H) {
check!(interpreter, CONSTANTINOPLE);
gas!(interpreter, gas::VERYLOW);
pop_top!(interpreter, op1, op2);
*op2 <<= as_usize_saturated!(op1);
}

/// EIP-145: Bitwise shifting instructions in EVM
pub fn shr<H: Host, SPEC: Spec>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn shr<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, _host: &mut H) {
check!(interpreter, CONSTANTINOPLE);
gas!(interpreter, gas::VERYLOW);
pop_top!(interpreter, op1, op2);
*op2 >>= as_usize_saturated!(op1);
}

/// EIP-145: Bitwise shifting instructions in EVM
pub fn sar<H: Host, SPEC: Spec>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn sar<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, _host: &mut H) {
check!(interpreter, CONSTANTINOPLE);
gas!(interpreter, gas::VERYLOW);
pop_top!(interpreter, op1, op2);
Expand Down
18 changes: 9 additions & 9 deletions crates/interpreter/src/instructions/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ use crate::{
Host, InstructionResult, Interpreter, InterpreterResult,
};

pub fn jump<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn jump<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::MID);
pop!(interpreter, dest);
jump_inner(interpreter, dest);
}

pub fn jumpi<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn jumpi<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::HIGH);
pop!(interpreter, dest, value);
if value != U256::ZERO {
Expand All @@ -29,11 +29,11 @@ fn jump_inner(interpreter: &mut Interpreter, dest: U256) {
interpreter.instruction_pointer = unsafe { interpreter.contract.bytecode.as_ptr().add(dest) };
}

pub fn jumpdest<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn jumpdest<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::JUMPDEST);
}

pub fn pc<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn pc<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::BASE);
// - 1 because we have already advanced the instruction pointer in `Interpreter::step`
push!(interpreter, U256::from(interpreter.program_counter() - 1));
Expand Down Expand Up @@ -63,27 +63,27 @@ fn return_inner(interpreter: &mut Interpreter, instruction_result: InstructionRe
};
}

pub fn ret<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn ret<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
return_inner(interpreter, InstructionResult::Return);
}

/// EIP-140: REVERT instruction
pub fn revert<H: Host, SPEC: Spec>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn revert<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, _host: &mut H) {
check!(interpreter, BYZANTIUM);
return_inner(interpreter, InstructionResult::Revert);
}

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

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

/// Unknown opcode. This opcode halts the execution.
pub fn unknown<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
pub fn unknown<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
interpreter.instruction_result = InstructionResult::OpcodeNotFound;
}
Loading

0 comments on commit 854e9a7

Please sign in to comment.