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

feat(interpreter): test Host object-safety, allow dyn Host in instructions #1245

Merged
merged 1 commit into from
Apr 3, 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
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
Loading