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

switch vm stack to little endian representation #7

Merged
merged 5 commits into from
Feb 15, 2022
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
18 changes: 10 additions & 8 deletions core/src/eval/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@ macro_rules! try_or_fail {
};
}

macro_rules! pop {
macro_rules! pop_h256 {
( $machine:expr, $( $x:ident ),* ) => (
$(
let $x = match $machine.stack.pop() {
Ok(value) => value,
Ok(value) => {
let mut res = H256([0; 32]);
value.to_big_endian(&mut res[..]);
res
},
Err(e) => return Control::Exit(e.into()),
};
)*
Expand All @@ -22,17 +26,17 @@ macro_rules! pop_u256 {
( $machine:expr, $( $x:ident ),* ) => (
$(
let $x = match $machine.stack.pop() {
Ok(value) => U256::from_big_endian(&value[..]),
Ok(value) => value,
Err(e) => return Control::Exit(e.into()),
};
)*
);
}

macro_rules! push {
macro_rules! push_h256 {
( $machine:expr, $( $x:expr ),* ) => (
$(
match $machine.stack.push($x) {
match $machine.stack.push(U256::from_big_endian(&$x[..])) {
Ok(()) => (),
Err(e) => return Control::Exit(e.into()),
}
Expand All @@ -43,9 +47,7 @@ macro_rules! push {
macro_rules! push_u256 {
( $machine:expr, $( $x:expr ),* ) => (
$(
let mut value = H256::default();
$x.to_big_endian(&mut value[..]);
match $machine.stack.push(value) {
match $machine.stack.push($x) {
Ok(()) => (),
Err(e) => return Control::Exit(e.into()),
}
Expand Down
21 changes: 10 additions & 11 deletions core/src/eval/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub fn calldataload(state: &mut Machine) -> Control {
}
}

push!(state, H256::from(load));
push_h256!(state, H256::from(load));
Control::Continue(1)
}

Expand Down Expand Up @@ -72,7 +72,7 @@ pub fn calldatacopy(state: &mut Machine) -> Control {

#[inline]
pub fn pop(state: &mut Machine) -> Control {
pop!(state, _val);
pop_u256!(state, _val);
Control::Continue(1)
}

Expand All @@ -81,15 +81,15 @@ pub fn mload(state: &mut Machine) -> Control {
pop_u256!(state, index);
try_or_fail!(state.memory.resize_offset(index, U256::from(32)));
let index = as_usize_or_fail!(index);
let value = H256::from_slice(&state.memory.get(index, 32)[..]);
push!(state, value);
let value = state.memory.get_h256(index);
push_h256!(state, value);
Control::Continue(1)
}

#[inline]
pub fn mstore(state: &mut Machine) -> Control {
pop_u256!(state, index);
pop!(state, value);
pop_h256!(state, value);
try_or_fail!(state.memory.resize_offset(index, U256::from(32)));
let index = as_usize_or_fail!(index);
match state.memory.set(index, &value[..], Some(32)) {
Expand Down Expand Up @@ -125,9 +125,9 @@ pub fn jump(state: &mut Machine) -> Control {
#[inline]
pub fn jumpi(state: &mut Machine) -> Control {
pop_u256!(state, dest);
pop!(state, value);
pop_u256!(state, value);

if value != H256::zero() {
if value != U256::zero() {
let dest = as_usize_or_fail!(dest, ExitError::InvalidJump);
if state.valids.is_valid(dest) {
Control::Jump(dest)
Expand Down Expand Up @@ -155,10 +155,9 @@ pub fn msize(state: &mut Machine) -> Control {
pub fn push(state: &mut Machine, n: usize, position: usize) -> Control {
let end = min(position + 1 + n, state.code.len());
let slice = &state.code[(position + 1)..end];
let mut val = [0u8; 32];
val[(32 - slice.len())..32].copy_from_slice(slice);
let val = U256::from_big_endian(slice);

push!(state, H256(val));
push_u256!(state, val);
Control::Continue(1 + n)
}

Expand All @@ -168,7 +167,7 @@ pub fn dup(state: &mut Machine, n: usize) -> Control {
Ok(value) => value,
Err(e) => return Control::Exit(e.into()),
};
push!(state, value);
push_u256!(state, value);
Control::Continue(1)
}

Expand Down
2 changes: 1 addition & 1 deletion core/src/eval/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ mod misc;

use crate::{ExitError, ExitReason, ExitSucceed, Machine, Opcode};
use core::ops::{BitAnd, BitOr, BitXor};
use primitive_types::{H256, U256};
use primitive_types::U256;

#[derive(Clone, Eq, PartialEq, Debug)]
pub enum Control {
Expand Down
19 changes: 18 additions & 1 deletion core/src/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{ExitError, ExitFatal};
use alloc::vec::Vec;
use core::cmp::min;
use core::ops::{BitAnd, Not};
use primitive_types::U256;
use primitive_types::{H256, U256};

/// A sequencial memory. It uses Rust's `Vec` for internal
/// representation.
Expand Down Expand Up @@ -96,6 +96,23 @@ impl Memory {
ret
}

/// Get `H256` from a specific offset in memory.
pub fn get_h256(&self, offset: usize) -> H256 {
let mut ret = [0; 32];

#[allow(clippy::needless_range_loop)]
for index in 0..32 {
let position = offset + index;
if position >= self.data.len() {
break;
}

ret[index] = self.data[position];
}

H256(ret)
}

/// Set memory region at given offset. The offset and value is considered
/// untrusted.
pub fn set(
Expand Down
35 changes: 28 additions & 7 deletions core/src/stack.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use crate::ExitError;
use alloc::vec::Vec;
use primitive_types::H256;
use primitive_types::{H256, U256};

/// EVM stack.
#[derive(Clone, Debug)]
pub struct Stack {
data: Vec<H256>,
data: Vec<U256>,
limit: usize,
}

Expand Down Expand Up @@ -38,21 +38,30 @@ impl Stack {

#[inline]
/// Stack data.
pub fn data(&self) -> &Vec<H256> {
pub fn data(&self) -> &Vec<U256> {
&self.data
}

#[inline]
/// Pop a value from the stack. If the stack is already empty, returns the
/// `StackUnderflow` error.
pub fn pop(&mut self) -> Result<H256, ExitError> {
pub fn pop(&mut self) -> Result<U256, ExitError> {
self.data.pop().ok_or(ExitError::StackUnderflow)
}

#[inline]
pub fn pop_h256(&mut self) -> Result<H256, ExitError> {
self.pop().map(|it| {
let mut res = H256([0; 32]);
it.to_big_endian(&mut res.0);
res
})
}

#[inline]
/// Push a new value into the stack. If it will exceed the stack limit,
/// returns `StackOverflow` error and leaves the stack unchanged.
pub fn push(&mut self, value: H256) -> Result<(), ExitError> {
pub fn push(&mut self, value: U256) -> Result<(), ExitError> {
if self.data.len() + 1 > self.limit {
return Err(ExitError::StackOverflow);
}
Expand All @@ -64,19 +73,31 @@ impl Stack {
/// Peek a value at given index for the stack, where the top of
/// the stack is at index `0`. If the index is too large,
/// `StackError::Underflow` is returned.
pub fn peek(&self, no_from_top: usize) -> Result<H256, ExitError> {
pub fn peek(&self, no_from_top: usize) -> Result<U256, ExitError> {
if self.data.len() > no_from_top {
Ok(self.data[self.data.len() - no_from_top - 1])
} else {
Err(ExitError::StackUnderflow)
}
}

#[inline]
/// Peek a value at given index for the stack, where the top of
/// the stack is at index `0`. If the index is too large,
/// `StackError::Underflow` is returned.
pub fn peek_h256(&self, no_from_top: usize) -> Result<H256, ExitError> {
self.peek(no_from_top).map(|it| {
let mut res = H256([0; 32]);
it.to_big_endian(&mut res.0);
res
})
}

#[inline]
/// Set a value at given index for the stack, where the top of the
/// stack is at index `0`. If the index is too large,
/// `StackError::Underflow` is returned.
pub fn set(&mut self, no_from_top: usize, val: H256) -> Result<(), ExitError> {
pub fn set(&mut self, no_from_top: usize, val: U256) -> Result<(), ExitError> {
if self.data.len() > no_from_top {
let len = self.data.len();
self.data[len - no_from_top - 1] = val;
Expand Down
Loading