remove evmjit (#8229)
* removed not working evmjit, closes #8192 closes #6205 * removed evmjit from build scripts * fixed parity compile error * removed evmjit cli options * fixed invalid test config files
This commit is contained in:
parent
679d6c6f2b
commit
ea6b0ec164
8
Cargo.lock
generated
8
Cargo.lock
generated
@ -908,7 +908,6 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ethereum-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ethereum-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"evmjit 1.11.0",
|
|
||||||
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"keccak-hash 0.1.0",
|
"keccak-hash 0.1.0",
|
||||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -939,13 +938,6 @@ dependencies = [
|
|||||||
"vm 0.1.0",
|
"vm 0.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "evmjit"
|
|
||||||
version = "1.11.0"
|
|
||||||
dependencies = [
|
|
||||||
"tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fdlimit"
|
name = "fdlimit"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
@ -100,7 +100,6 @@ ui-precompiled = [
|
|||||||
]
|
]
|
||||||
ui-enabled = ["dapps"]
|
ui-enabled = ["dapps"]
|
||||||
dapps = ["parity-dapps"]
|
dapps = ["parity-dapps"]
|
||||||
jit = ["ethcore/jit"]
|
|
||||||
json-tests = ["ethcore/json-tests"]
|
json-tests = ["ethcore/json-tests"]
|
||||||
test-heavy = ["ethcore/test-heavy"]
|
test-heavy = ["ethcore/test-heavy"]
|
||||||
evm-debug = ["ethcore/evm-debug"]
|
evm-debug = ["ethcore/evm-debug"]
|
||||||
|
@ -27,20 +27,7 @@ RUN apt-get update && \
|
|||||||
libudev-dev \
|
libudev-dev \
|
||||||
pkg-config \
|
pkg-config \
|
||||||
dpkg-dev \
|
dpkg-dev \
|
||||||
# evmjit dependencies
|
|
||||||
zlib1g-dev \
|
|
||||||
libedit-dev \
|
|
||||||
libudev-dev &&\
|
libudev-dev &&\
|
||||||
# cmake and llvm ppa's. then update ppa's
|
|
||||||
add-apt-repository -y "ppa:george-edison55/cmake-3.x" && \
|
|
||||||
add-apt-repository "deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.7 main" && \
|
|
||||||
apt-get update && \
|
|
||||||
apt-get install -y --force-yes cmake llvm-3.7-dev && \
|
|
||||||
# install evmjit
|
|
||||||
git clone https://github.com/debris/evmjit && \
|
|
||||||
cd evmjit && \
|
|
||||||
mkdir build && cd build && \
|
|
||||||
cmake .. && make && make install && cd && \
|
|
||||||
# install rustup
|
# install rustup
|
||||||
curl https://sh.rustup.rs -sSf | sh -s -- -y && \
|
curl https://sh.rustup.rs -sSf | sh -s -- -y && \
|
||||||
# rustup directory
|
# rustup directory
|
||||||
@ -73,10 +60,6 @@ cd /build&&git clone https://github.com/paritytech/parity && \
|
|||||||
file \
|
file \
|
||||||
pkg-config \
|
pkg-config \
|
||||||
dpkg-dev \
|
dpkg-dev \
|
||||||
# evmjit dependencies
|
|
||||||
zlib1g-dev \
|
|
||||||
libedit-dev \
|
|
||||||
cmake llvm-3.7-dev&&\
|
|
||||||
rm -rf /var/lib/apt/lists/*
|
rm -rf /var/lib/apt/lists/*
|
||||||
# setup ENTRYPOINT
|
# setup ENTRYPOINT
|
||||||
EXPOSE 8080 8545 8180
|
EXPOSE 8080 8545 8180
|
||||||
|
@ -1,58 +0,0 @@
|
|||||||
FROM ubuntu:14.04
|
|
||||||
WORKDIR /build
|
|
||||||
|
|
||||||
# install tools and dependencies
|
|
||||||
RUN apt-get update && \
|
|
||||||
apt-get install -y \
|
|
||||||
# make
|
|
||||||
build-essential \
|
|
||||||
# add-apt-repository
|
|
||||||
software-properties-common \
|
|
||||||
curl \
|
|
||||||
wget \
|
|
||||||
git \
|
|
||||||
g++ \
|
|
||||||
binutils \
|
|
||||||
file \
|
|
||||||
# evmjit dependencies
|
|
||||||
zlib1g-dev \
|
|
||||||
libedit-dev
|
|
||||||
|
|
||||||
# cmake and llvm ppas. then update ppas
|
|
||||||
RUN add-apt-repository -y "ppa:george-edison55/cmake-3.x" && \
|
|
||||||
add-apt-repository "deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.7 main" && \
|
|
||||||
apt-get update && \
|
|
||||||
apt-get install -y --force-yes cmake llvm-3.7-dev
|
|
||||||
|
|
||||||
# install evmjit
|
|
||||||
RUN git clone https://github.com/debris/evmjit && \
|
|
||||||
cd evmjit && \
|
|
||||||
mkdir build && cd build && \
|
|
||||||
cmake .. && make && make install && cd
|
|
||||||
|
|
||||||
# install rustup
|
|
||||||
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y
|
|
||||||
|
|
||||||
# rustup directory
|
|
||||||
ENV PATH /root/.cargo/bin:$PATH
|
|
||||||
|
|
||||||
# show backtraces
|
|
||||||
ENV RUST_BACKTRACE 1
|
|
||||||
|
|
||||||
# show tools
|
|
||||||
RUN rustc -vV && \
|
|
||||||
cargo -V && \
|
|
||||||
gcc -v &&\
|
|
||||||
g++ -v
|
|
||||||
|
|
||||||
# build parity
|
|
||||||
ADD . /build/parity
|
|
||||||
RUN cd parity && \
|
|
||||||
cargo build --release --features ethcore/jit --verbose && \
|
|
||||||
ls /build/parity/target/release/parity && \
|
|
||||||
strip /build/parity/target/release/parity
|
|
||||||
|
|
||||||
RUN file /build/parity/target/release/parity
|
|
||||||
|
|
||||||
EXPOSE 8080 8545 8180
|
|
||||||
ENTRYPOINT ["/build/parity/target/release/parity"]
|
|
@ -76,7 +76,6 @@ tempdir = "0.3"
|
|||||||
trie-standardmap = { path = "../util/trie-standardmap" }
|
trie-standardmap = { path = "../util/trie-standardmap" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
jit = ["evm/jit"]
|
|
||||||
evm-debug = ["slow-blocks"]
|
evm-debug = ["slow-blocks"]
|
||||||
evm-debug-tests = ["evm-debug", "evm/evm-debug-tests"]
|
evm-debug-tests = ["evm-debug", "evm/evm-debug-tests"]
|
||||||
slow-blocks = [] # Use SLOW_TX_DURATION="50" (compile time!) to track transactions over 50ms
|
slow-blocks = [] # Use SLOW_TX_DURATION="50" (compile time!) to track transactions over 50ms
|
||||||
|
@ -6,7 +6,6 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
bit-set = "0.4"
|
bit-set = "0.4"
|
||||||
ethereum-types = "0.3"
|
ethereum-types = "0.3"
|
||||||
evmjit = { path = "../../evmjit", optional = true }
|
|
||||||
heapsize = "0.4"
|
heapsize = "0.4"
|
||||||
lazy_static = "1.0"
|
lazy_static = "1.0"
|
||||||
log = "0.3"
|
log = "0.3"
|
||||||
@ -19,6 +18,5 @@ memory-cache = { path = "../../util/memory_cache" }
|
|||||||
rustc-hex = "1.0"
|
rustc-hex = "1.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
jit = ["evmjit"]
|
|
||||||
evm-debug = []
|
evm-debug = []
|
||||||
evm-debug-tests = ["evm-debug"]
|
evm-debug-tests = ["evm-debug"]
|
||||||
|
@ -32,23 +32,6 @@ pub struct Factory {
|
|||||||
impl Factory {
|
impl Factory {
|
||||||
/// Create fresh instance of VM
|
/// Create fresh instance of VM
|
||||||
/// Might choose implementation depending on supplied gas.
|
/// Might choose implementation depending on supplied gas.
|
||||||
#[cfg(feature = "jit")]
|
|
||||||
pub fn create(&self, gas: &U256) -> Box<Vm> {
|
|
||||||
match self.evm {
|
|
||||||
VMType::Jit => {
|
|
||||||
Box::new(super::jit::JitEvm::default())
|
|
||||||
},
|
|
||||||
VMType::Interpreter => if Self::can_fit_in_usize(gas) {
|
|
||||||
Box::new(super::interpreter::Interpreter::<usize>::new(self.evm_cache.clone()))
|
|
||||||
} else {
|
|
||||||
Box::new(super::interpreter::Interpreter::<U256>::new(self.evm_cache.clone()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create fresh instance of VM
|
|
||||||
/// Might choose implementation depending on supplied gas.
|
|
||||||
#[cfg(not(feature = "jit"))]
|
|
||||||
pub fn create(&self, gas: &U256) -> Box<Vm> {
|
pub fn create(&self, gas: &U256) -> Box<Vm> {
|
||||||
match self.evm {
|
match self.evm {
|
||||||
VMType::Interpreter => if Self::can_fit_in_usize(gas) {
|
VMType::Interpreter => if Self::can_fit_in_usize(gas) {
|
||||||
@ -74,17 +57,7 @@ impl Factory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Factory {
|
impl Default for Factory {
|
||||||
/// Returns jitvm factory
|
|
||||||
#[cfg(all(feature = "jit", not(test)))]
|
|
||||||
fn default() -> Factory {
|
|
||||||
Factory {
|
|
||||||
evm: VMType::Jit,
|
|
||||||
evm_cache: Arc::new(SharedCache::default()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns native rust evm factory
|
/// Returns native rust evm factory
|
||||||
#[cfg(any(not(feature = "jit"), test))]
|
|
||||||
fn default() -> Factory {
|
fn default() -> Factory {
|
||||||
Factory {
|
Factory {
|
||||||
evm: VMType::Interpreter,
|
evm: VMType::Interpreter,
|
||||||
@ -101,24 +74,7 @@ fn test_create_vm() {
|
|||||||
/// Create tests by injecting different VM factories
|
/// Create tests by injecting different VM factories
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! evm_test(
|
macro_rules! evm_test(
|
||||||
(ignorejit => $name_test: ident: $name_jit: ident, $name_int: ident) => {
|
($name_test: ident: $name_int: ident) => {
|
||||||
#[test]
|
|
||||||
#[ignore]
|
|
||||||
#[cfg(feature = "jit")]
|
|
||||||
fn $name_jit() {
|
|
||||||
$name_test(Factory::new(VMType::Jit, 1024 * 32));
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
fn $name_int() {
|
|
||||||
$name_test(Factory::new(VMType::Interpreter, 1024 * 32));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
($name_test: ident: $name_jit: ident, $name_int: ident) => {
|
|
||||||
#[test]
|
|
||||||
#[cfg(feature = "jit")]
|
|
||||||
fn $name_jit() {
|
|
||||||
$name_test(Factory::new(VMType::Jit, 1024 * 32));
|
|
||||||
}
|
|
||||||
#[test]
|
#[test]
|
||||||
fn $name_int() {
|
fn $name_int() {
|
||||||
$name_test(Factory::new(VMType::Interpreter, 1024 * 32));
|
$name_test(Factory::new(VMType::Interpreter, 1024 * 32));
|
||||||
@ -129,14 +85,7 @@ macro_rules! evm_test(
|
|||||||
/// Create ignored tests by injecting different VM factories
|
/// Create ignored tests by injecting different VM factories
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! evm_test_ignore(
|
macro_rules! evm_test_ignore(
|
||||||
($name_test: ident: $name_jit: ident, $name_int: ident) => {
|
($name_test: ident: $name_int: ident) => {
|
||||||
#[test]
|
|
||||||
#[ignore]
|
|
||||||
#[cfg(feature = "jit")]
|
|
||||||
#[cfg(feature = "ignored-tests")]
|
|
||||||
fn $name_jit() {
|
|
||||||
$name_test(Factory::new(VMType::Jit, 1024 * 32));
|
|
||||||
}
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
#[cfg(feature = "ignored-tests")]
|
#[cfg(feature = "ignored-tests")]
|
||||||
|
@ -1,414 +0,0 @@
|
|||||||
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
|
||||||
// This file is part of Parity.
|
|
||||||
|
|
||||||
// Parity is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
|
|
||||||
// Parity is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
//! Just in time compiler execution environment.
|
|
||||||
use bigint::prelude::U256;
|
|
||||||
use bigint::hash::H256;
|
|
||||||
use util::*;
|
|
||||||
use evmjit;
|
|
||||||
use evm::{self, GasLeft};
|
|
||||||
use evm::CallType;
|
|
||||||
use vm::{self, Vm};
|
|
||||||
|
|
||||||
/// Should be used to convert jit types to ethcore
|
|
||||||
trait FromJit<T>: Sized {
|
|
||||||
fn from_jit(input: T) -> Self;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Should be used to covert ethcore types to jit
|
|
||||||
trait IntoJit<T> {
|
|
||||||
fn into_jit(self) -> T;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> FromJit<&'a evmjit::I256> for U256 {
|
|
||||||
fn from_jit(input: &'a evmjit::I256) -> Self {
|
|
||||||
unsafe {
|
|
||||||
let mut res: U256 = mem::uninitialized();
|
|
||||||
ptr::copy(input.words.as_ptr(), res.0.as_mut_ptr(), 4);
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> FromJit<&'a evmjit::I256> for H256 {
|
|
||||||
fn from_jit(input: &'a evmjit::I256) -> Self {
|
|
||||||
let u = U256::from_jit(input);
|
|
||||||
H256::from(&u)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> FromJit<&'a evmjit::I256> for Address {
|
|
||||||
fn from_jit(input: &'a evmjit::I256) -> Self {
|
|
||||||
Address::from(H256::from_jit(input))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> FromJit<&'a evmjit::H256> for H256 {
|
|
||||||
fn from_jit(input: &'a evmjit::H256) -> Self {
|
|
||||||
H256::from_jit(&evmjit::I256::from(input.clone()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> FromJit<&'a evmjit::H256> for Address {
|
|
||||||
fn from_jit(input: &'a evmjit::H256) -> Self {
|
|
||||||
Address::from(H256::from_jit(input))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IntoJit<evmjit::I256> for U256 {
|
|
||||||
fn into_jit(self) -> evmjit::I256 {
|
|
||||||
unsafe {
|
|
||||||
let mut res: evmjit::I256 = mem::uninitialized();
|
|
||||||
ptr::copy(self.0.as_ptr(), res.words.as_mut_ptr(), 4);
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IntoJit<evmjit::I256> for H256 {
|
|
||||||
fn into_jit(self) -> evmjit::I256 {
|
|
||||||
let mut ret = [0; 4];
|
|
||||||
let len = self.len();
|
|
||||||
for i in 0..len {
|
|
||||||
let rev = len - 1 - i;
|
|
||||||
let pos = rev / 8;
|
|
||||||
ret[pos] += (self[i] as u64) << ((rev % 8) * 8);
|
|
||||||
}
|
|
||||||
evmjit::I256 { words: ret }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IntoJit<evmjit::H256> for H256 {
|
|
||||||
fn into_jit(self) -> evmjit::H256 {
|
|
||||||
let i: evmjit::I256 = self.into_jit();
|
|
||||||
From::from(i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IntoJit<evmjit::I256> for Address {
|
|
||||||
fn into_jit(self) -> evmjit::I256 {
|
|
||||||
H256::from(self).into_jit()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IntoJit<evmjit::H256> for Address {
|
|
||||||
fn into_jit(self) -> evmjit::H256 {
|
|
||||||
H256::from(self).into_jit()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Externalities adapter. Maps callbacks from evmjit to externalities trait.
|
|
||||||
///
|
|
||||||
/// Evmjit doesn't have to know about children execution failures.
|
|
||||||
/// This adapter 'catches' them and moves upstream.
|
|
||||||
struct ExtAdapter<'a> {
|
|
||||||
ext: &'a mut evm::Ext,
|
|
||||||
address: Address
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> ExtAdapter<'a> {
|
|
||||||
fn new(ext: &'a mut evm::Ext, address: Address) -> Self {
|
|
||||||
ExtAdapter {
|
|
||||||
ext: ext,
|
|
||||||
address: address
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> evmjit::Ext for ExtAdapter<'a> {
|
|
||||||
fn sload(&self, key: *const evmjit::I256, out_value: *mut evmjit::I256) {
|
|
||||||
unsafe {
|
|
||||||
let i = H256::from_jit(&*key);
|
|
||||||
let o = self.ext.storage_at(&i);
|
|
||||||
*out_value = o.into_jit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sstore(&mut self, key: *const evmjit::I256, value: *const evmjit::I256) {
|
|
||||||
let key = unsafe { H256::from_jit(&*key) };
|
|
||||||
let value = unsafe { H256::from_jit(&*value) };
|
|
||||||
let old_value = self.ext.storage_at(&key);
|
|
||||||
// if SSTORE nonzero -> zero, increment refund count
|
|
||||||
if !old_value.is_zero() && value.is_zero() {
|
|
||||||
self.ext.inc_sstore_clears();
|
|
||||||
}
|
|
||||||
self.ext.set_storage(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn balance(&self, address: *const evmjit::H256, out_value: *mut evmjit::I256) {
|
|
||||||
unsafe {
|
|
||||||
let a = Address::from_jit(&*address);
|
|
||||||
let o = self.ext.balance(&a);
|
|
||||||
*out_value = o.into_jit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn blockhash(&self, number: *const evmjit::I256, out_hash: *mut evmjit::H256) {
|
|
||||||
unsafe {
|
|
||||||
let n = U256::from_jit(&*number);
|
|
||||||
let o = self.ext.blockhash(&n);
|
|
||||||
*out_hash = o.into_jit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create(&mut self,
|
|
||||||
io_gas: *mut u64,
|
|
||||||
value: *const evmjit::I256,
|
|
||||||
init_beg: *const u8,
|
|
||||||
init_size: u64,
|
|
||||||
address: *mut evmjit::H256) {
|
|
||||||
|
|
||||||
let gas = unsafe { U256::from(*io_gas) };
|
|
||||||
let value = unsafe { U256::from_jit(&*value) };
|
|
||||||
let code = unsafe { slice::from_raw_parts(init_beg, init_size as usize) };
|
|
||||||
|
|
||||||
// check if balance is sufficient and we are not too deep
|
|
||||||
if self.ext.balance(&self.address) >= value && self.ext.depth() < self.ext.schedule().max_depth {
|
|
||||||
match self.ext.create(&gas, &value, code) {
|
|
||||||
evm::ContractCreateResult::Created(new_address, gas_left) => unsafe {
|
|
||||||
*address = new_address.into_jit();
|
|
||||||
*io_gas = gas_left.low_u64();
|
|
||||||
},
|
|
||||||
evm::ContractCreateResult::Failed => unsafe {
|
|
||||||
*address = Address::new().into_jit();
|
|
||||||
*io_gas = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unsafe { *address = Address::new().into_jit(); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call(&mut self,
|
|
||||||
io_gas: *mut u64,
|
|
||||||
call_gas: u64,
|
|
||||||
sender_address: *const evmjit::H256,
|
|
||||||
receive_address: *const evmjit::H256,
|
|
||||||
code_address: *const evmjit::H256,
|
|
||||||
transfer_value: *const evmjit::I256,
|
|
||||||
// We are ignoring apparent value - it's handled in externalities.
|
|
||||||
_apparent_value: *const evmjit::I256,
|
|
||||||
in_beg: *const u8,
|
|
||||||
in_size: u64,
|
|
||||||
out_beg: *mut u8,
|
|
||||||
out_size: u64) -> bool {
|
|
||||||
|
|
||||||
let mut gas = unsafe { U256::from(*io_gas) };
|
|
||||||
let mut call_gas = U256::from(call_gas);
|
|
||||||
let mut gas_cost = call_gas;
|
|
||||||
let sender_address = unsafe { Address::from_jit(&*sender_address) };
|
|
||||||
let receive_address = unsafe { Address::from_jit(&*receive_address) };
|
|
||||||
let code_address = unsafe { Address::from_jit(&*code_address) };
|
|
||||||
let transfer_value = unsafe { U256::from_jit(&*transfer_value) };
|
|
||||||
|
|
||||||
// receive address and code address are the same in normal calls
|
|
||||||
let is_callcode = receive_address != code_address;
|
|
||||||
let is_delegatecall = is_callcode && sender_address != receive_address;
|
|
||||||
|
|
||||||
let value = if is_delegatecall { None } else { Some(transfer_value) };
|
|
||||||
|
|
||||||
if !is_callcode && !self.ext.exists(&code_address) {
|
|
||||||
gas_cost = gas_cost + U256::from(self.ext.schedule().call_new_account_gas);
|
|
||||||
}
|
|
||||||
|
|
||||||
if transfer_value > U256::zero() {
|
|
||||||
assert!(self.ext.schedule().call_value_transfer_gas > self.ext.schedule().call_stipend, "overflow possible");
|
|
||||||
gas_cost = gas_cost + U256::from(self.ext.schedule().call_value_transfer_gas);
|
|
||||||
call_gas = call_gas + U256::from(self.ext.schedule().call_stipend);
|
|
||||||
}
|
|
||||||
|
|
||||||
if gas_cost > gas {
|
|
||||||
unsafe {
|
|
||||||
*io_gas = -1i64 as u64;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gas = gas - gas_cost;
|
|
||||||
|
|
||||||
// check if balance is sufficient and we are not too deep
|
|
||||||
if self.ext.balance(&self.address) < transfer_value || self.ext.depth() >= self.ext.schedule().max_depth {
|
|
||||||
unsafe {
|
|
||||||
*io_gas = (gas + call_gas).low_u64();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let call_type = match (is_callcode, is_delegatecall) {
|
|
||||||
(_, true) => CallType::DelegateCall,
|
|
||||||
(true, false) => CallType::CallCode,
|
|
||||||
(false, false) => CallType::Call,
|
|
||||||
};
|
|
||||||
|
|
||||||
match self.ext.call(
|
|
||||||
&call_gas,
|
|
||||||
&sender_address,
|
|
||||||
&receive_address,
|
|
||||||
value,
|
|
||||||
unsafe { slice::from_raw_parts(in_beg, in_size as usize) },
|
|
||||||
&code_address,
|
|
||||||
unsafe { slice::from_raw_parts_mut(out_beg, out_size as usize) },
|
|
||||||
call_type,
|
|
||||||
) {
|
|
||||||
evm::MessageCallResult::Success(gas_left) => unsafe {
|
|
||||||
*io_gas = (gas + gas_left).low_u64();
|
|
||||||
true
|
|
||||||
},
|
|
||||||
evm::MessageCallResult::Failed => unsafe {
|
|
||||||
*io_gas = gas.low_u64();
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn log(&mut self,
|
|
||||||
beg: *const u8,
|
|
||||||
size: u64,
|
|
||||||
topic1: *const evmjit::H256,
|
|
||||||
topic2: *const evmjit::H256,
|
|
||||||
topic3: *const evmjit::H256,
|
|
||||||
topic4: *const evmjit::H256) {
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
let mut topics = vec![];
|
|
||||||
if !topic1.is_null() {
|
|
||||||
topics.push(H256::from_jit(&*topic1));
|
|
||||||
}
|
|
||||||
|
|
||||||
if !topic2.is_null() {
|
|
||||||
topics.push(H256::from_jit(&*topic2));
|
|
||||||
}
|
|
||||||
|
|
||||||
if !topic3.is_null() {
|
|
||||||
topics.push(H256::from_jit(&*topic3));
|
|
||||||
}
|
|
||||||
|
|
||||||
if !topic4.is_null() {
|
|
||||||
topics.push(H256::from_jit(&*topic4));
|
|
||||||
}
|
|
||||||
|
|
||||||
let bytes_ref: &[u8] = slice::from_raw_parts(beg, size as usize);
|
|
||||||
self.ext.log(topics, bytes_ref);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn extcode(&self, address: *const evmjit::H256, size: *mut u64) -> *const u8 {
|
|
||||||
unsafe {
|
|
||||||
let code = self.ext.extcode(&Address::from_jit(&*address));
|
|
||||||
*size = code.len() as u64;
|
|
||||||
let ptr = code.as_ptr();
|
|
||||||
mem::forget(code);
|
|
||||||
ptr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct JitEvm {
|
|
||||||
context: Option<evmjit::ContextHandle>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl vm::Vm for JitEvm {
|
|
||||||
fn exec(&mut self, params: ActionParams, ext: &mut evm::Ext) -> evm::Result<GasLeft> {
|
|
||||||
// Dirty hack. This is unsafe, but we interact with ffi, so it's justified.
|
|
||||||
let ext_adapter: ExtAdapter<'static> = unsafe { ::std::mem::transmute(ExtAdapter::new(ext, params.address.clone())) };
|
|
||||||
let mut ext_handle = evmjit::ExtHandle::new(ext_adapter);
|
|
||||||
assert!(params.gas <= U256::from(i64::max_value() as u64), "evmjit max gas is 2 ^ 63");
|
|
||||||
assert!(params.gas_price <= U256::from(i64::max_value() as u64), "evmjit max gas is 2 ^ 63");
|
|
||||||
|
|
||||||
let call_data = params.data.unwrap_or_else(Vec::new);
|
|
||||||
let code = params.code.unwrap_or_else(Vec::new);
|
|
||||||
|
|
||||||
let mut data = evmjit::RuntimeDataHandle::new();
|
|
||||||
data.gas = params.gas.low_u64() as i64;
|
|
||||||
data.gas_price = params.gas_price.low_u64() as i64;
|
|
||||||
data.call_data = call_data.as_ptr();
|
|
||||||
data.call_data_size = call_data.len() as u64;
|
|
||||||
mem::forget(call_data);
|
|
||||||
data.code = code.as_ptr();
|
|
||||||
data.code_size = code.len() as u64;
|
|
||||||
data.code_hash = code.sha3().into_jit();
|
|
||||||
mem::forget(code);
|
|
||||||
data.address = params.address.into_jit();
|
|
||||||
data.caller = params.sender.into_jit();
|
|
||||||
data.origin = params.origin.into_jit();
|
|
||||||
data.transfer_value = match params.value {
|
|
||||||
ActionValue::Transfer(val) => val.into_jit(),
|
|
||||||
ActionValue::Apparent(val) => val.into_jit()
|
|
||||||
};
|
|
||||||
data.apparent_value = data.transfer_value;
|
|
||||||
|
|
||||||
let mut schedule = evmjit::ScheduleHandle::new();
|
|
||||||
schedule.have_delegate_call = ext.schedule().have_delegate_call;
|
|
||||||
|
|
||||||
data.author = ext.env_info().author.clone().into_jit();
|
|
||||||
data.difficulty = ext.env_info().difficulty.into_jit();
|
|
||||||
data.gas_limit = ext.env_info().gas_limit.into_jit();
|
|
||||||
data.number = ext.env_info().number;
|
|
||||||
// don't really know why jit timestamp is int..
|
|
||||||
data.timestamp = ext.env_info().timestamp as i64;
|
|
||||||
|
|
||||||
self.context = Some(unsafe { evmjit::ContextHandle::new(data, schedule, &mut ext_handle) });
|
|
||||||
let mut context = self.context.as_mut().expect("context handle set on the prior line; qed");
|
|
||||||
let res = context.exec();
|
|
||||||
|
|
||||||
match res {
|
|
||||||
evmjit::ReturnCode::Stop => Ok(GasLeft::Known(U256::from(context.gas_left()))),
|
|
||||||
evmjit::ReturnCode::Return =>
|
|
||||||
Ok(GasLeft::NeedsReturn(U256::from(context.gas_left()), context.output_data())),
|
|
||||||
evmjit::ReturnCode::Suicide => {
|
|
||||||
ext.suicide(&Address::from_jit(&context.suicide_refund_address()));
|
|
||||||
Ok(GasLeft::Known(U256::from(context.gas_left())))
|
|
||||||
},
|
|
||||||
evmjit::ReturnCode::OutOfGas => Err(vm::Error::OutOfGas),
|
|
||||||
_err => Err(vm::Error::Internal)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_to_and_from_u256() {
|
|
||||||
let u = U256::from_str("d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3").unwrap();
|
|
||||||
let j = u.into_jit();
|
|
||||||
let u2 = U256::from_jit(&j);
|
|
||||||
assert_eq!(u, u2);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_to_and_from_h256() {
|
|
||||||
let h = H256::from_str("d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3").unwrap();
|
|
||||||
let j: ::evmjit::I256 = h.clone().into_jit();
|
|
||||||
let h2 = H256::from_jit(&j);
|
|
||||||
|
|
||||||
assert_eq!(h, h2);
|
|
||||||
|
|
||||||
let j: ::evmjit::H256 = h.clone().into_jit();
|
|
||||||
let h2 = H256::from_jit(&j);
|
|
||||||
assert_eq!(h, h2);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_to_and_from_address() {
|
|
||||||
let a = Address::from_str("2adc25665018aa1fe0e6bc666dac8fc2697ff9ba").unwrap();
|
|
||||||
let j: ::evmjit::I256 = a.clone().into_jit();
|
|
||||||
let a2 = Address::from_jit(&j);
|
|
||||||
|
|
||||||
assert_eq!(a, a2);
|
|
||||||
|
|
||||||
let j: ::evmjit::H256 = a.clone().into_jit();
|
|
||||||
let a2 = Address::from_jit(&j);
|
|
||||||
assert_eq!(a, a2);
|
|
||||||
}
|
|
@ -30,9 +30,6 @@ extern crate lazy_static;
|
|||||||
#[cfg_attr(feature = "evm-debug", macro_use)]
|
#[cfg_attr(feature = "evm-debug", macro_use)]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
||||||
#[cfg(feature = "jit")]
|
|
||||||
extern crate evmjit;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
extern crate rustc_hex;
|
extern crate rustc_hex;
|
||||||
|
|
||||||
@ -44,9 +41,6 @@ pub mod factory;
|
|||||||
mod vmtype;
|
mod vmtype;
|
||||||
mod instructions;
|
mod instructions;
|
||||||
|
|
||||||
#[cfg(feature = "jit" )]
|
|
||||||
mod jit;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
#[cfg(all(feature="benches", test))]
|
#[cfg(all(feature="benches", test))]
|
||||||
|
@ -26,7 +26,7 @@ use vm::tests::{FakeExt, FakeCall, FakeCallType, test_finalize};
|
|||||||
use factory::Factory;
|
use factory::Factory;
|
||||||
use vmtype::VMType;
|
use vmtype::VMType;
|
||||||
|
|
||||||
evm_test!{test_add: test_add_jit, test_add_int}
|
evm_test!{test_add: test_add_int}
|
||||||
fn test_add(factory: super::Factory) {
|
fn test_add(factory: super::Factory) {
|
||||||
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
||||||
let code = "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01600055".from_hex().unwrap();
|
let code = "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01600055".from_hex().unwrap();
|
||||||
@ -46,7 +46,7 @@ fn test_add(factory: super::Factory) {
|
|||||||
assert_store(&ext, 0, "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe");
|
assert_store(&ext, 0, "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe");
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_sha3: test_sha3_jit, test_sha3_int}
|
evm_test!{test_sha3: test_sha3_int}
|
||||||
fn test_sha3(factory: super::Factory) {
|
fn test_sha3(factory: super::Factory) {
|
||||||
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
||||||
let code = "6000600020600055".from_hex().unwrap();
|
let code = "6000600020600055".from_hex().unwrap();
|
||||||
@ -66,7 +66,7 @@ fn test_sha3(factory: super::Factory) {
|
|||||||
assert_store(&ext, 0, "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470");
|
assert_store(&ext, 0, "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470");
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_address: test_address_jit, test_address_int}
|
evm_test!{test_address: test_address_int}
|
||||||
fn test_address(factory: super::Factory) {
|
fn test_address(factory: super::Factory) {
|
||||||
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
||||||
let code = "30600055".from_hex().unwrap();
|
let code = "30600055".from_hex().unwrap();
|
||||||
@ -86,7 +86,7 @@ fn test_address(factory: super::Factory) {
|
|||||||
assert_store(&ext, 0, "0000000000000000000000000f572e5295c57f15886f9b263e2f6d2d6c7b5ec6");
|
assert_store(&ext, 0, "0000000000000000000000000f572e5295c57f15886f9b263e2f6d2d6c7b5ec6");
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_origin: test_origin_jit, test_origin_int}
|
evm_test!{test_origin: test_origin_int}
|
||||||
fn test_origin(factory: super::Factory) {
|
fn test_origin(factory: super::Factory) {
|
||||||
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
||||||
let origin = Address::from_str("cd1722f2947def4cf144679da39c4c32bdc35681").unwrap();
|
let origin = Address::from_str("cd1722f2947def4cf144679da39c4c32bdc35681").unwrap();
|
||||||
@ -108,7 +108,7 @@ fn test_origin(factory: super::Factory) {
|
|||||||
assert_store(&ext, 0, "000000000000000000000000cd1722f2947def4cf144679da39c4c32bdc35681");
|
assert_store(&ext, 0, "000000000000000000000000cd1722f2947def4cf144679da39c4c32bdc35681");
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_sender: test_sender_jit, test_sender_int}
|
evm_test!{test_sender: test_sender_int}
|
||||||
fn test_sender(factory: super::Factory) {
|
fn test_sender(factory: super::Factory) {
|
||||||
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
||||||
let sender = Address::from_str("cd1722f2947def4cf144679da39c4c32bdc35681").unwrap();
|
let sender = Address::from_str("cd1722f2947def4cf144679da39c4c32bdc35681").unwrap();
|
||||||
@ -130,7 +130,7 @@ fn test_sender(factory: super::Factory) {
|
|||||||
assert_store(&ext, 0, "000000000000000000000000cd1722f2947def4cf144679da39c4c32bdc35681");
|
assert_store(&ext, 0, "000000000000000000000000cd1722f2947def4cf144679da39c4c32bdc35681");
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_extcodecopy: test_extcodecopy_jit, test_extcodecopy_int}
|
evm_test!{test_extcodecopy: test_extcodecopy_int}
|
||||||
fn test_extcodecopy(factory: super::Factory) {
|
fn test_extcodecopy(factory: super::Factory) {
|
||||||
// 33 - sender
|
// 33 - sender
|
||||||
// 3b - extcodesize
|
// 3b - extcodesize
|
||||||
@ -165,7 +165,7 @@ fn test_extcodecopy(factory: super::Factory) {
|
|||||||
assert_store(&ext, 0, "6005600055000000000000000000000000000000000000000000000000000000");
|
assert_store(&ext, 0, "6005600055000000000000000000000000000000000000000000000000000000");
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_log_empty: test_log_empty_jit, test_log_empty_int}
|
evm_test!{test_log_empty: test_log_empty_int}
|
||||||
fn test_log_empty(factory: super::Factory) {
|
fn test_log_empty(factory: super::Factory) {
|
||||||
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
||||||
let code = "60006000a0".from_hex().unwrap();
|
let code = "60006000a0".from_hex().unwrap();
|
||||||
@ -187,7 +187,7 @@ fn test_log_empty(factory: super::Factory) {
|
|||||||
assert!(ext.logs[0].data.is_empty());
|
assert!(ext.logs[0].data.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_log_sender: test_log_sender_jit, test_log_sender_int}
|
evm_test!{test_log_sender: test_log_sender_int}
|
||||||
fn test_log_sender(factory: super::Factory) {
|
fn test_log_sender(factory: super::Factory) {
|
||||||
// 60 ff - push ff
|
// 60 ff - push ff
|
||||||
// 60 00 - push 00
|
// 60 00 - push 00
|
||||||
@ -220,7 +220,7 @@ fn test_log_sender(factory: super::Factory) {
|
|||||||
assert_eq!(ext.logs[0].data, "ff00000000000000000000000000000000000000000000000000000000000000".from_hex().unwrap());
|
assert_eq!(ext.logs[0].data, "ff00000000000000000000000000000000000000000000000000000000000000".from_hex().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_blockhash: test_blockhash_jit, test_blockhash_int}
|
evm_test!{test_blockhash: test_blockhash_int}
|
||||||
fn test_blockhash(factory: super::Factory) {
|
fn test_blockhash(factory: super::Factory) {
|
||||||
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
||||||
let code = "600040600055".from_hex().unwrap();
|
let code = "600040600055".from_hex().unwrap();
|
||||||
@ -242,7 +242,7 @@ fn test_blockhash(factory: super::Factory) {
|
|||||||
assert_eq!(ext.store.get(&H256::new()).unwrap(), &blockhash);
|
assert_eq!(ext.store.get(&H256::new()).unwrap(), &blockhash);
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_calldataload: test_calldataload_jit, test_calldataload_int}
|
evm_test!{test_calldataload: test_calldataload_int}
|
||||||
fn test_calldataload(factory: super::Factory) {
|
fn test_calldataload(factory: super::Factory) {
|
||||||
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
||||||
let code = "600135600055".from_hex().unwrap();
|
let code = "600135600055".from_hex().unwrap();
|
||||||
@ -265,7 +265,7 @@ fn test_calldataload(factory: super::Factory) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_author: test_author_jit, test_author_int}
|
evm_test!{test_author: test_author_int}
|
||||||
fn test_author(factory: super::Factory) {
|
fn test_author(factory: super::Factory) {
|
||||||
let author = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
let author = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
||||||
let code = "41600055".from_hex().unwrap();
|
let code = "41600055".from_hex().unwrap();
|
||||||
@ -285,7 +285,7 @@ fn test_author(factory: super::Factory) {
|
|||||||
assert_store(&ext, 0, "0000000000000000000000000f572e5295c57f15886f9b263e2f6d2d6c7b5ec6");
|
assert_store(&ext, 0, "0000000000000000000000000f572e5295c57f15886f9b263e2f6d2d6c7b5ec6");
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_timestamp: test_timestamp_jit, test_timestamp_int}
|
evm_test!{test_timestamp: test_timestamp_int}
|
||||||
fn test_timestamp(factory: super::Factory) {
|
fn test_timestamp(factory: super::Factory) {
|
||||||
let timestamp = 0x1234;
|
let timestamp = 0x1234;
|
||||||
let code = "42600055".from_hex().unwrap();
|
let code = "42600055".from_hex().unwrap();
|
||||||
@ -305,7 +305,7 @@ fn test_timestamp(factory: super::Factory) {
|
|||||||
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000001234");
|
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000001234");
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_number: test_number_jit, test_number_int}
|
evm_test!{test_number: test_number_int}
|
||||||
fn test_number(factory: super::Factory) {
|
fn test_number(factory: super::Factory) {
|
||||||
let number = 0x1234;
|
let number = 0x1234;
|
||||||
let code = "43600055".from_hex().unwrap();
|
let code = "43600055".from_hex().unwrap();
|
||||||
@ -325,7 +325,7 @@ fn test_number(factory: super::Factory) {
|
|||||||
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000001234");
|
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000001234");
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_difficulty: test_difficulty_jit, test_difficulty_int}
|
evm_test!{test_difficulty: test_difficulty_int}
|
||||||
fn test_difficulty(factory: super::Factory) {
|
fn test_difficulty(factory: super::Factory) {
|
||||||
let difficulty = U256::from(0x1234);
|
let difficulty = U256::from(0x1234);
|
||||||
let code = "44600055".from_hex().unwrap();
|
let code = "44600055".from_hex().unwrap();
|
||||||
@ -345,7 +345,7 @@ fn test_difficulty(factory: super::Factory) {
|
|||||||
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000001234");
|
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000001234");
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_gas_limit: test_gas_limit_jit, test_gas_limit_int}
|
evm_test!{test_gas_limit: test_gas_limit_int}
|
||||||
fn test_gas_limit(factory: super::Factory) {
|
fn test_gas_limit(factory: super::Factory) {
|
||||||
let gas_limit = U256::from(0x1234);
|
let gas_limit = U256::from(0x1234);
|
||||||
let code = "45600055".from_hex().unwrap();
|
let code = "45600055".from_hex().unwrap();
|
||||||
@ -365,7 +365,7 @@ fn test_gas_limit(factory: super::Factory) {
|
|||||||
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000001234");
|
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000001234");
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_mul: test_mul_jit, test_mul_int}
|
evm_test!{test_mul: test_mul_int}
|
||||||
fn test_mul(factory: super::Factory) {
|
fn test_mul(factory: super::Factory) {
|
||||||
let code = "65012365124623626543219002600055".from_hex().unwrap();
|
let code = "65012365124623626543219002600055".from_hex().unwrap();
|
||||||
|
|
||||||
@ -383,7 +383,7 @@ fn test_mul(factory: super::Factory) {
|
|||||||
assert_eq!(gas_left, U256::from(79_983));
|
assert_eq!(gas_left, U256::from(79_983));
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_sub: test_sub_jit, test_sub_int}
|
evm_test!{test_sub: test_sub_int}
|
||||||
fn test_sub(factory: super::Factory) {
|
fn test_sub(factory: super::Factory) {
|
||||||
let code = "65012365124623626543219003600055".from_hex().unwrap();
|
let code = "65012365124623626543219003600055".from_hex().unwrap();
|
||||||
|
|
||||||
@ -401,7 +401,7 @@ fn test_sub(factory: super::Factory) {
|
|||||||
assert_eq!(gas_left, U256::from(79_985));
|
assert_eq!(gas_left, U256::from(79_985));
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_div: test_div_jit, test_div_int}
|
evm_test!{test_div: test_div_int}
|
||||||
fn test_div(factory: super::Factory) {
|
fn test_div(factory: super::Factory) {
|
||||||
let code = "65012365124623626543219004600055".from_hex().unwrap();
|
let code = "65012365124623626543219004600055".from_hex().unwrap();
|
||||||
|
|
||||||
@ -419,7 +419,7 @@ fn test_div(factory: super::Factory) {
|
|||||||
assert_eq!(gas_left, U256::from(79_983));
|
assert_eq!(gas_left, U256::from(79_983));
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_div_zero: test_div_zero_jit, test_div_zero_int}
|
evm_test!{test_div_zero: test_div_zero_int}
|
||||||
fn test_div_zero(factory: super::Factory) {
|
fn test_div_zero(factory: super::Factory) {
|
||||||
let code = "6501236512462360009004600055".from_hex().unwrap();
|
let code = "6501236512462360009004600055".from_hex().unwrap();
|
||||||
|
|
||||||
@ -437,7 +437,7 @@ fn test_div_zero(factory: super::Factory) {
|
|||||||
assert_eq!(gas_left, U256::from(94_983));
|
assert_eq!(gas_left, U256::from(94_983));
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_mod: test_mod_jit, test_mod_int}
|
evm_test!{test_mod: test_mod_int}
|
||||||
fn test_mod(factory: super::Factory) {
|
fn test_mod(factory: super::Factory) {
|
||||||
let code = "650123651246236265432290066000556501236512462360009006600155".from_hex().unwrap();
|
let code = "650123651246236265432290066000556501236512462360009006600155".from_hex().unwrap();
|
||||||
|
|
||||||
@ -456,7 +456,7 @@ fn test_mod(factory: super::Factory) {
|
|||||||
assert_eq!(gas_left, U256::from(74_966));
|
assert_eq!(gas_left, U256::from(74_966));
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_smod: test_smod_jit, test_smod_int}
|
evm_test!{test_smod: test_smod_int}
|
||||||
fn test_smod(factory: super::Factory) {
|
fn test_smod(factory: super::Factory) {
|
||||||
let code = "650123651246236265432290076000556501236512462360009007600155".from_hex().unwrap();
|
let code = "650123651246236265432290076000556501236512462360009007600155".from_hex().unwrap();
|
||||||
|
|
||||||
@ -475,7 +475,7 @@ fn test_smod(factory: super::Factory) {
|
|||||||
assert_eq!(gas_left, U256::from(74_966));
|
assert_eq!(gas_left, U256::from(74_966));
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_sdiv: test_sdiv_jit, test_sdiv_int}
|
evm_test!{test_sdiv: test_sdiv_int}
|
||||||
fn test_sdiv(factory: super::Factory) {
|
fn test_sdiv(factory: super::Factory) {
|
||||||
let code = "650123651246236265432290056000556501236512462360009005600155".from_hex().unwrap();
|
let code = "650123651246236265432290056000556501236512462360009005600155".from_hex().unwrap();
|
||||||
|
|
||||||
@ -494,7 +494,7 @@ fn test_sdiv(factory: super::Factory) {
|
|||||||
assert_eq!(gas_left, U256::from(74_966));
|
assert_eq!(gas_left, U256::from(74_966));
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_exp: test_exp_jit, test_exp_int}
|
evm_test!{test_exp: test_exp_int}
|
||||||
fn test_exp(factory: super::Factory) {
|
fn test_exp(factory: super::Factory) {
|
||||||
let code = "6016650123651246230a6000556001650123651246230a6001556000650123651246230a600255".from_hex().unwrap();
|
let code = "6016650123651246230a6000556001650123651246230a6001556000650123651246230a600255".from_hex().unwrap();
|
||||||
|
|
||||||
@ -514,7 +514,7 @@ fn test_exp(factory: super::Factory) {
|
|||||||
assert_eq!(gas_left, U256::from(39_923));
|
assert_eq!(gas_left, U256::from(39_923));
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_comparison: test_comparison_jit, test_comparison_int}
|
evm_test!{test_comparison: test_comparison_int}
|
||||||
fn test_comparison(factory: super::Factory) {
|
fn test_comparison(factory: super::Factory) {
|
||||||
let code = "601665012365124623818181811060005511600155146002556415235412358014600355".from_hex().unwrap();
|
let code = "601665012365124623818181811060005511600155146002556415235412358014600355".from_hex().unwrap();
|
||||||
|
|
||||||
@ -535,7 +535,7 @@ fn test_comparison(factory: super::Factory) {
|
|||||||
assert_eq!(gas_left, U256::from(49_952));
|
assert_eq!(gas_left, U256::from(49_952));
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_signed_comparison: test_signed_comparison_jit, test_signed_comparison_int}
|
evm_test!{test_signed_comparison: test_signed_comparison_int}
|
||||||
fn test_signed_comparison(factory: super::Factory) {
|
fn test_signed_comparison(factory: super::Factory) {
|
||||||
let code = "60106000036010818112600055136001556010601060000381811260025513600355".from_hex().unwrap();
|
let code = "60106000036010818112600055136001556010601060000381811260025513600355".from_hex().unwrap();
|
||||||
|
|
||||||
@ -556,7 +556,7 @@ fn test_signed_comparison(factory: super::Factory) {
|
|||||||
assert_eq!(gas_left, U256::from(49_940));
|
assert_eq!(gas_left, U256::from(49_940));
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_bitops: test_bitops_jit, test_bitops_int}
|
evm_test!{test_bitops: test_bitops_int}
|
||||||
fn test_bitops(factory: super::Factory) {
|
fn test_bitops(factory: super::Factory) {
|
||||||
let code = "60ff610ff08181818116600055176001551860025560008015600355198015600455600555".from_hex().unwrap();
|
let code = "60ff610ff08181818116600055176001551860025560008015600355198015600455600555".from_hex().unwrap();
|
||||||
|
|
||||||
@ -579,7 +579,7 @@ fn test_bitops(factory: super::Factory) {
|
|||||||
assert_eq!(gas_left, U256::from(44_937));
|
assert_eq!(gas_left, U256::from(44_937));
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_addmod_mulmod: test_addmod_mulmod_jit, test_addmod_mulmod_int}
|
evm_test!{test_addmod_mulmod: test_addmod_mulmod_int}
|
||||||
fn test_addmod_mulmod(factory: super::Factory) {
|
fn test_addmod_mulmod(factory: super::Factory) {
|
||||||
let code = "60ff60f060108282820860005509600155600060f0601082828208196002550919600355".from_hex().unwrap();
|
let code = "60ff60f060108282820860005509600155600060f0601082828208196002550919600355".from_hex().unwrap();
|
||||||
|
|
||||||
@ -600,7 +600,7 @@ fn test_addmod_mulmod(factory: super::Factory) {
|
|||||||
assert_eq!(gas_left, U256::from(19_914));
|
assert_eq!(gas_left, U256::from(19_914));
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_byte: test_byte_jit, test_byte_int}
|
evm_test!{test_byte: test_byte_int}
|
||||||
fn test_byte(factory: super::Factory) {
|
fn test_byte(factory: super::Factory) {
|
||||||
let code = "60f061ffff1a600055610fff601f1a600155".from_hex().unwrap();
|
let code = "60f061ffff1a600055610fff601f1a600155".from_hex().unwrap();
|
||||||
|
|
||||||
@ -619,7 +619,7 @@ fn test_byte(factory: super::Factory) {
|
|||||||
assert_eq!(gas_left, U256::from(74_976));
|
assert_eq!(gas_left, U256::from(74_976));
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_signextend: test_signextend_jit, test_signextend_int}
|
evm_test!{test_signextend: test_signextend_int}
|
||||||
fn test_signextend(factory: super::Factory) {
|
fn test_signextend(factory: super::Factory) {
|
||||||
let code = "610fff60020b60005560ff60200b600155".from_hex().unwrap();
|
let code = "610fff60020b60005560ff60200b600155".from_hex().unwrap();
|
||||||
|
|
||||||
@ -659,7 +659,7 @@ fn test_badinstruction_int() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_pop: test_pop_jit, test_pop_int}
|
evm_test!{test_pop: test_pop_int}
|
||||||
fn test_pop(factory: super::Factory) {
|
fn test_pop(factory: super::Factory) {
|
||||||
let code = "60f060aa50600055".from_hex().unwrap();
|
let code = "60f060aa50600055".from_hex().unwrap();
|
||||||
|
|
||||||
@ -677,7 +677,7 @@ fn test_pop(factory: super::Factory) {
|
|||||||
assert_eq!(gas_left, U256::from(79_989));
|
assert_eq!(gas_left, U256::from(79_989));
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_extops: test_extops_jit, test_extops_int}
|
evm_test!{test_extops: test_extops_int}
|
||||||
fn test_extops(factory: super::Factory) {
|
fn test_extops(factory: super::Factory) {
|
||||||
let code = "5a6001555836553a600255386003553460045560016001526016590454600555".from_hex().unwrap();
|
let code = "5a6001555836553a600255386003553460045560016001526016590454600555".from_hex().unwrap();
|
||||||
|
|
||||||
@ -702,7 +702,7 @@ fn test_extops(factory: super::Factory) {
|
|||||||
assert_eq!(gas_left, U256::from(29_898));
|
assert_eq!(gas_left, U256::from(29_898));
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_jumps: test_jumps_jit, test_jumps_int}
|
evm_test!{test_jumps: test_jumps_int}
|
||||||
fn test_jumps(factory: super::Factory) {
|
fn test_jumps(factory: super::Factory) {
|
||||||
let code = "600160015560066000555b60016000540380806000551560245760015402600155600a565b".from_hex().unwrap();
|
let code = "600160015560066000555b60016000540380806000551560245760015402600155600a565b".from_hex().unwrap();
|
||||||
|
|
||||||
@ -722,7 +722,7 @@ fn test_jumps(factory: super::Factory) {
|
|||||||
assert_eq!(gas_left, U256::from(54_117));
|
assert_eq!(gas_left, U256::from(54_117));
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_calls: test_calls_jit, test_calls_int}
|
evm_test!{test_calls: test_calls_int}
|
||||||
fn test_calls(factory: super::Factory) {
|
fn test_calls(factory: super::Factory) {
|
||||||
let code = "600054602d57600160005560006000600060006050610998610100f160006000600060006050610998610100f25b".from_hex().unwrap();
|
let code = "600054602d57600160005560006000600060006050610998610100f160006000600060006050610998610100f25b".from_hex().unwrap();
|
||||||
|
|
||||||
@ -766,7 +766,7 @@ fn test_calls(factory: super::Factory) {
|
|||||||
assert_eq!(ext.calls.len(), 2);
|
assert_eq!(ext.calls.len(), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_create_in_staticcall: test_create_in_staticcall_jit, test_create_in_staticcall_int}
|
evm_test!{test_create_in_staticcall: test_create_in_staticcall_int}
|
||||||
fn test_create_in_staticcall(factory: super::Factory) {
|
fn test_create_in_staticcall(factory: super::Factory) {
|
||||||
let code = "600060006064f000".from_hex().unwrap();
|
let code = "600060006064f000".from_hex().unwrap();
|
||||||
|
|
||||||
|
@ -19,22 +19,11 @@ use std::fmt;
|
|||||||
/// Type of EVM to use.
|
/// Type of EVM to use.
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum VMType {
|
pub enum VMType {
|
||||||
/// JIT EVM
|
|
||||||
#[cfg(feature = "jit")]
|
|
||||||
Jit,
|
|
||||||
/// RUST EVM
|
/// RUST EVM
|
||||||
Interpreter
|
Interpreter
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for VMType {
|
impl fmt::Display for VMType {
|
||||||
#[cfg(feature="jit")]
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(f, "{}", match *self {
|
|
||||||
VMType::Jit => "JIT",
|
|
||||||
VMType::Interpreter => "INT"
|
|
||||||
})
|
|
||||||
}
|
|
||||||
#[cfg(not(feature="jit"))]
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "{}", match *self {
|
write!(f, "{}", match *self {
|
||||||
VMType::Interpreter => "INT"
|
VMType::Interpreter => "INT"
|
||||||
@ -49,27 +38,8 @@ impl Default for VMType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl VMType {
|
impl VMType {
|
||||||
/// Return all possible VMs (JIT, Interpreter)
|
|
||||||
#[cfg(feature = "jit")]
|
|
||||||
pub fn all() -> Vec<VMType> {
|
|
||||||
vec![VMType::Jit, VMType::Interpreter]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return all possible VMs (Interpreter)
|
/// Return all possible VMs (Interpreter)
|
||||||
#[cfg(not(feature = "jit"))]
|
|
||||||
pub fn all() -> Vec<VMType> {
|
pub fn all() -> Vec<VMType> {
|
||||||
vec![VMType::Interpreter]
|
vec![VMType::Interpreter]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return new jit if it's possible
|
|
||||||
#[cfg(not(feature = "jit"))]
|
|
||||||
pub fn jit() -> Option<Self> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return new jit if it's possible
|
|
||||||
#[cfg(feature = "jit")]
|
|
||||||
pub fn jit() -> Option<Self> {
|
|
||||||
Some(VMType::Jit)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -721,7 +721,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: replace params with transactions!
|
// TODO: replace params with transactions!
|
||||||
evm_test!{test_sender_balance: test_sender_balance_jit, test_sender_balance_int}
|
evm_test!{test_sender_balance: test_sender_balance_int}
|
||||||
fn test_sender_balance(factory: Factory) {
|
fn test_sender_balance(factory: Factory) {
|
||||||
let sender = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
let sender = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
||||||
let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &[]).0;
|
let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &[]).0;
|
||||||
@ -752,7 +752,7 @@ mod tests {
|
|||||||
// TODO: just test state root.
|
// TODO: just test state root.
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_create_contract_out_of_depth: test_create_contract_out_of_depth_jit, test_create_contract_out_of_depth_int}
|
evm_test!{test_create_contract_out_of_depth: test_create_contract_out_of_depth_int}
|
||||||
fn test_create_contract_out_of_depth(factory: Factory) {
|
fn test_create_contract_out_of_depth(factory: Factory) {
|
||||||
// code:
|
// code:
|
||||||
//
|
//
|
||||||
@ -1083,7 +1083,7 @@ mod tests {
|
|||||||
assert_eq!(vm_tracer.drain().unwrap(), expected_vm_trace);
|
assert_eq!(vm_tracer.drain().unwrap(), expected_vm_trace);
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_create_contract_value_too_high: test_create_contract_value_too_high_jit, test_create_contract_value_too_high_int}
|
evm_test!{test_create_contract_value_too_high: test_create_contract_value_too_high_int}
|
||||||
fn test_create_contract_value_too_high(factory: Factory) {
|
fn test_create_contract_value_too_high(factory: Factory) {
|
||||||
// code:
|
// code:
|
||||||
//
|
//
|
||||||
@ -1135,7 +1135,7 @@ mod tests {
|
|||||||
assert_eq!(substate.contracts_created.len(), 0);
|
assert_eq!(substate.contracts_created.len(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_create_contract_without_max_depth: test_create_contract_without_max_depth_jit, test_create_contract_without_max_depth_int}
|
evm_test!{test_create_contract_without_max_depth: test_create_contract_without_max_depth_int}
|
||||||
fn test_create_contract_without_max_depth(factory: Factory) {
|
fn test_create_contract_without_max_depth(factory: Factory) {
|
||||||
// code:
|
// code:
|
||||||
//
|
//
|
||||||
@ -1188,7 +1188,7 @@ mod tests {
|
|||||||
|
|
||||||
// test is incorrect, mk
|
// test is incorrect, mk
|
||||||
// TODO: fix (preferred) or remove
|
// TODO: fix (preferred) or remove
|
||||||
evm_test_ignore!{test_aba_calls: test_aba_calls_jit, test_aba_calls_int}
|
evm_test_ignore!{test_aba_calls: test_aba_calls_int}
|
||||||
fn test_aba_calls(factory: Factory) {
|
fn test_aba_calls(factory: Factory) {
|
||||||
// 60 00 - push 0
|
// 60 00 - push 0
|
||||||
// 60 00 - push 0
|
// 60 00 - push 0
|
||||||
@ -1248,7 +1248,7 @@ mod tests {
|
|||||||
|
|
||||||
// test is incorrect, mk
|
// test is incorrect, mk
|
||||||
// TODO: fix (preferred) or remove
|
// TODO: fix (preferred) or remove
|
||||||
evm_test_ignore!{test_recursive_bomb1: test_recursive_bomb1_jit, test_recursive_bomb1_int}
|
evm_test_ignore!{test_recursive_bomb1: test_recursive_bomb1_int}
|
||||||
fn test_recursive_bomb1(factory: Factory) {
|
fn test_recursive_bomb1(factory: Factory) {
|
||||||
// 60 01 - push 1
|
// 60 01 - push 1
|
||||||
// 60 00 - push 0
|
// 60 00 - push 0
|
||||||
@ -1293,7 +1293,7 @@ mod tests {
|
|||||||
|
|
||||||
// test is incorrect, mk
|
// test is incorrect, mk
|
||||||
// TODO: fix (preferred) or remove
|
// TODO: fix (preferred) or remove
|
||||||
evm_test_ignore!{test_transact_simple: test_transact_simple_jit, test_transact_simple_int}
|
evm_test_ignore!{test_transact_simple: test_transact_simple_int}
|
||||||
fn test_transact_simple(factory: Factory) {
|
fn test_transact_simple(factory: Factory) {
|
||||||
let keypair = Random.generate().unwrap();
|
let keypair = Random.generate().unwrap();
|
||||||
let t = Transaction {
|
let t = Transaction {
|
||||||
@ -1331,7 +1331,7 @@ mod tests {
|
|||||||
assert_eq!(state.storage_at(&contract, &H256::new()).unwrap(), H256::from(&U256::from(1)));
|
assert_eq!(state.storage_at(&contract, &H256::new()).unwrap(), H256::from(&U256::from(1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_transact_invalid_nonce: test_transact_invalid_nonce_jit, test_transact_invalid_nonce_int}
|
evm_test!{test_transact_invalid_nonce: test_transact_invalid_nonce_int}
|
||||||
fn test_transact_invalid_nonce(factory: Factory) {
|
fn test_transact_invalid_nonce(factory: Factory) {
|
||||||
let keypair = Random.generate().unwrap();
|
let keypair = Random.generate().unwrap();
|
||||||
let t = Transaction {
|
let t = Transaction {
|
||||||
@ -1363,7 +1363,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_transact_gas_limit_reached: test_transact_gas_limit_reached_jit, test_transact_gas_limit_reached_int}
|
evm_test!{test_transact_gas_limit_reached: test_transact_gas_limit_reached_int}
|
||||||
fn test_transact_gas_limit_reached(factory: Factory) {
|
fn test_transact_gas_limit_reached(factory: Factory) {
|
||||||
let keypair = Random.generate().unwrap();
|
let keypair = Random.generate().unwrap();
|
||||||
let t = Transaction {
|
let t = Transaction {
|
||||||
@ -1396,7 +1396,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_not_enough_cash: test_not_enough_cash_jit, test_not_enough_cash_int}
|
evm_test!{test_not_enough_cash: test_not_enough_cash_int}
|
||||||
fn test_not_enough_cash(factory: Factory) {
|
fn test_not_enough_cash(factory: Factory) {
|
||||||
|
|
||||||
let keypair = Random.generate().unwrap();
|
let keypair = Random.generate().unwrap();
|
||||||
@ -1429,7 +1429,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_keccak: test_keccak_jit, test_keccak_int}
|
evm_test!{test_keccak: test_keccak_int}
|
||||||
fn test_keccak(factory: Factory) {
|
fn test_keccak(factory: Factory) {
|
||||||
let code = "6064640fffffffff20600055".from_hex().unwrap();
|
let code = "6064640fffffffff20600055".from_hex().unwrap();
|
||||||
|
|
||||||
@ -1461,7 +1461,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_revert: test_revert_jit, test_revert_int}
|
evm_test!{test_revert: test_revert_int}
|
||||||
fn test_revert(factory: Factory) {
|
fn test_revert(factory: Factory) {
|
||||||
let contract_address = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap();
|
let contract_address = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap();
|
||||||
let sender = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
let sender = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
|
||||||
|
@ -130,9 +130,6 @@ extern crate trace_time;
|
|||||||
#[cfg_attr(test, macro_use)]
|
#[cfg_attr(test, macro_use)]
|
||||||
extern crate evm;
|
extern crate evm;
|
||||||
|
|
||||||
#[cfg(feature = "jit" )]
|
|
||||||
extern crate evmjit;
|
|
||||||
|
|
||||||
pub extern crate ethstore;
|
pub extern crate ethstore;
|
||||||
|
|
||||||
pub mod account_provider;
|
pub mod account_provider;
|
||||||
|
@ -31,7 +31,7 @@ use rustc_hex::FromHex;
|
|||||||
use ethereum_types::{H256, Address};
|
use ethereum_types::{H256, Address};
|
||||||
use bytes::BytesRef;
|
use bytes::BytesRef;
|
||||||
|
|
||||||
evm_test!{test_blockhash_eip210: test_blockhash_eip210_jit, test_blockhash_eip210_int}
|
evm_test!{test_blockhash_eip210: test_blockhash_eip210_int}
|
||||||
fn test_blockhash_eip210(factory: Factory) {
|
fn test_blockhash_eip210(factory: Factory) {
|
||||||
let get_prev_hash_code = Arc::new("600143034060205260206020f3".from_hex().unwrap()); // this returns previous block hash
|
let get_prev_hash_code = Arc::new("600143034060205260206020f3".from_hex().unwrap()); // this returns previous block hash
|
||||||
let get_prev_hash_code_hash = keccak(get_prev_hash_code.as_ref());
|
let get_prev_hash_code_hash = keccak(get_prev_hash_code.as_ref());
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "evmjit"
|
|
||||||
version = "1.11.0"
|
|
||||||
authors = ["Parity Technologies <admin@parity.io>"]
|
|
||||||
|
|
||||||
[lib]
|
|
||||||
crate-type = ["dylib"]
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
tiny-keccak = "1.3"
|
|
@ -1,493 +0,0 @@
|
|||||||
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
|
||||||
// This file is part of Parity.
|
|
||||||
|
|
||||||
// Parity is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
|
|
||||||
// Parity is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
//! Bare rust wrapper around evmjit.
|
|
||||||
//!
|
|
||||||
//! Requires latest version of Ethereum EVM JIT. https://github.com/debris/evmjit
|
|
||||||
//!
|
|
||||||
//! ```
|
|
||||||
//! extern crate evmjit;
|
|
||||||
//! use evmjit::*;
|
|
||||||
//!
|
|
||||||
//! fn main() {
|
|
||||||
//! let mut context = ContextHandle::new(RuntimeDataHandle::new(), ExtHandle::empty());
|
|
||||||
//! assert_eq!(context.exec(), ReturnCode::Stop);
|
|
||||||
//! }
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//!
|
|
||||||
//! To verify that c abi is "imported" correctly, run:
|
|
||||||
//!
|
|
||||||
//! ```bash
|
|
||||||
//! nm your_executable -g | grep ext
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! It should give the following output:
|
|
||||||
//!
|
|
||||||
//! ```bash
|
|
||||||
//! 00000001000779e0 T _ext_balance
|
|
||||||
//! 0000000100077a10 T _ext_blockhash
|
|
||||||
//! 0000000100077a90 T _ext_call
|
|
||||||
//! 0000000100077a40 T _ext_create
|
|
||||||
//! 0000000100077b50 T _ext_extcode
|
|
||||||
//! 0000000100077b80 T _ext_log
|
|
||||||
//! 0000000100077b20 T _ext_sha3
|
|
||||||
//! 0000000100077980 T _ext_sload
|
|
||||||
//! 00000001000779b0 T _ext_sstore
|
|
||||||
//! ```
|
|
||||||
|
|
||||||
extern crate tiny_keccak;
|
|
||||||
|
|
||||||
use std::ops::{Deref, DerefMut};
|
|
||||||
use self::ffi::*;
|
|
||||||
|
|
||||||
pub use self::ffi::JitReturnCode as ReturnCode;
|
|
||||||
pub use self::ffi::JitI256 as I256;
|
|
||||||
pub use self::ffi::JitH256 as H256;
|
|
||||||
|
|
||||||
/// Takes care of proper initialization and destruction of `RuntimeData`.
|
|
||||||
///
|
|
||||||
/// This handle must be used to create runtime data,
|
|
||||||
/// cause underneath it's a `C++` structure. Incompatible with rust
|
|
||||||
/// structs.
|
|
||||||
pub struct RuntimeDataHandle {
|
|
||||||
runtime_data: *mut JitRuntimeData
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RuntimeDataHandle {
|
|
||||||
/// Creates new `RuntimeData` handle.
|
|
||||||
pub fn new() -> Self {
|
|
||||||
RuntimeDataHandle {
|
|
||||||
runtime_data: unsafe { evmjit_create_runtime_data() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for RuntimeDataHandle {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
unsafe { evmjit_destroy_runtime_data(self.runtime_data) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for RuntimeDataHandle {
|
|
||||||
type Target = JitRuntimeData;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
unsafe { &*self.runtime_data }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DerefMut for RuntimeDataHandle {
|
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
||||||
unsafe { &mut *self.runtime_data }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Takes care of proper initilization and destruction of `JitSchedule`.
|
|
||||||
///
|
|
||||||
/// This handle must be used to jit schedule,
|
|
||||||
/// cause underneath it's a `C++` structure. Incompatible with rust
|
|
||||||
/// structs.
|
|
||||||
pub struct ScheduleHandle {
|
|
||||||
schedule: *mut JitSchedule
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ScheduleHandle {
|
|
||||||
/// Creates new `Schedule` handle.
|
|
||||||
pub fn new() -> Self {
|
|
||||||
ScheduleHandle {
|
|
||||||
schedule: unsafe { evmjit_create_schedule() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for ScheduleHandle {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
unsafe { evmjit_destroy_schedule(self.schedule) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for ScheduleHandle {
|
|
||||||
type Target = JitSchedule;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
unsafe { &*self.schedule }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DerefMut for ScheduleHandle {
|
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
||||||
unsafe { &mut *self.schedule }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Takes care of proper initialization and destruction of jit context.
|
|
||||||
///
|
|
||||||
/// This handle must be used to create context,
|
|
||||||
/// cause underneath it's a `C++` structure. Incombatible with rust
|
|
||||||
/// structs.
|
|
||||||
pub struct ContextHandle {
|
|
||||||
context: *mut JitContext,
|
|
||||||
data_handle: RuntimeDataHandle,
|
|
||||||
schedule_handle: ScheduleHandle
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ContextHandle {
|
|
||||||
/// Creates new context handle.
|
|
||||||
///
|
|
||||||
/// This function is unsafe cause ext lifetime is not considered
|
|
||||||
/// We also can't make ExtHandle a member of `ContextHandle` structure,
|
|
||||||
/// cause this would be a move operation or it would require a template
|
|
||||||
/// lifetime to a reference. Both solutions are not possible.
|
|
||||||
pub unsafe fn new(data_handle: RuntimeDataHandle, schedule_handle: ScheduleHandle, ext: &mut ExtHandle) -> Self {
|
|
||||||
let mut handle = ContextHandle {
|
|
||||||
context: std::mem::uninitialized(),
|
|
||||||
schedule_handle: schedule_handle,
|
|
||||||
data_handle: data_handle,
|
|
||||||
};
|
|
||||||
|
|
||||||
handle.context = evmjit_create_context(handle.data_handle.deref_mut(), ext);
|
|
||||||
handle
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Executes context.
|
|
||||||
pub fn exec(&mut self) -> JitReturnCode {
|
|
||||||
unsafe { evmjit_exec(self.context, self.schedule_handle.deref_mut()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns output data.
|
|
||||||
pub fn output_data(&self) -> &[u8] {
|
|
||||||
unsafe { std::slice::from_raw_parts(self.data_handle.call_data, self.data_handle.call_data_size as usize) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns address to which funds should be transfered after suicide.
|
|
||||||
pub fn suicide_refund_address(&self) -> JitI256 {
|
|
||||||
// evmjit reuses data_handle address field to store suicide address
|
|
||||||
self.data_handle.address
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns gas left.
|
|
||||||
pub fn gas_left(&self) -> u64 {
|
|
||||||
self.data_handle.gas as u64
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for ContextHandle {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
unsafe { evmjit_destroy_context(self.context); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Component oriented wrapper around jit ext c interface.
|
|
||||||
pub trait Ext {
|
|
||||||
fn sload(&self, index: *const JitI256, out_value: *mut JitI256);
|
|
||||||
fn sstore(&mut self, index: *const JitI256, value: *const JitI256);
|
|
||||||
fn balance(&self, address: *const JitH256, out_value: *mut JitI256);
|
|
||||||
fn blockhash(&self, number: *const JitI256, out_hash: *mut JitH256);
|
|
||||||
|
|
||||||
fn create(&mut self,
|
|
||||||
io_gas: *mut u64,
|
|
||||||
endowment: *const JitI256,
|
|
||||||
init_beg: *const u8,
|
|
||||||
init_size: u64,
|
|
||||||
address: *mut JitH256);
|
|
||||||
|
|
||||||
fn call(&mut self,
|
|
||||||
io_gas: *mut u64,
|
|
||||||
call_gas: u64,
|
|
||||||
sender_address: *const JitH256,
|
|
||||||
receive_address: *const JitH256,
|
|
||||||
code_address: *const JitH256,
|
|
||||||
transfer_value: *const JitI256,
|
|
||||||
apparent_value: *const JitI256,
|
|
||||||
in_beg: *const u8,
|
|
||||||
in_size: u64,
|
|
||||||
out_beg: *mut u8,
|
|
||||||
out_size: u64) -> bool;
|
|
||||||
|
|
||||||
fn log(&mut self,
|
|
||||||
beg: *const u8,
|
|
||||||
size: u64,
|
|
||||||
topic1: *const JitH256,
|
|
||||||
topic2: *const JitH256,
|
|
||||||
topic3: *const JitH256,
|
|
||||||
topic4: *const JitH256);
|
|
||||||
|
|
||||||
fn extcode(&self, address: *const JitH256, size: *mut u64) -> *const u8;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// C abi compatible wrapper for jit ext implementers.
|
|
||||||
pub struct ExtHandle {
|
|
||||||
ext_impl: Option<Box<Ext>>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ExtHandle {
|
|
||||||
/// Creates new extironment wrapper for given implementation
|
|
||||||
pub fn new<T>(ext_impl: T) -> Self where T: Ext + 'static {
|
|
||||||
ExtHandle { ext_impl: Some(Box::new(ext_impl)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates empty extironment.
|
|
||||||
/// It can be used to for any operations.
|
|
||||||
pub fn empty() -> Self {
|
|
||||||
ExtHandle { ext_impl: None }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for ExtHandle {
|
|
||||||
type Target = Box<Ext>;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
match self.ext_impl {
|
|
||||||
Some(ref ext) => ext,
|
|
||||||
None => { panic!("Handle is empty!"); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DerefMut for ExtHandle {
|
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
||||||
match self.ext_impl {
|
|
||||||
Some(ref mut ext) => ext,
|
|
||||||
None => { panic!("Handle is empty!"); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ffi functions
|
|
||||||
pub mod ffi {
|
|
||||||
use std::slice;
|
|
||||||
use std::mem;
|
|
||||||
use tiny_keccak::Keccak;
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
/// Jit context struct declaration.
|
|
||||||
pub enum JitContext {}
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
|
||||||
/// Jit context execution return code.
|
|
||||||
pub enum JitReturnCode {
|
|
||||||
Stop = 0,
|
|
||||||
Return = 1,
|
|
||||||
Suicide = 2,
|
|
||||||
|
|
||||||
OutOfGas = -1,
|
|
||||||
|
|
||||||
LLVMError = -101,
|
|
||||||
UnexpectedError = -111
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
/// Signed 256 bit integer.
|
|
||||||
pub struct JitI256 {
|
|
||||||
pub words: [u64; 4]
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
/// Jit Hash
|
|
||||||
pub struct JitH256 {
|
|
||||||
pub words: [u64; 4]
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<JitH256> for JitI256 {
|
|
||||||
fn from(mut hash: JitH256) -> JitI256 {
|
|
||||||
unsafe {
|
|
||||||
{
|
|
||||||
let bytes: &mut [u8] = slice::from_raw_parts_mut(hash.words.as_mut_ptr() as *mut u8, 32);
|
|
||||||
bytes.reverse();
|
|
||||||
}
|
|
||||||
mem::transmute(hash)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<JitI256> for JitH256 {
|
|
||||||
fn from(mut i: JitI256) -> JitH256 {
|
|
||||||
unsafe {
|
|
||||||
{
|
|
||||||
let bytes: &mut [u8] = slice::from_raw_parts_mut(i.words.as_mut_ptr() as *mut u8, 32);
|
|
||||||
bytes.reverse();
|
|
||||||
}
|
|
||||||
mem::transmute(i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug)]
|
|
||||||
/// Jit runtime data.
|
|
||||||
pub struct JitRuntimeData {
|
|
||||||
pub gas: i64,
|
|
||||||
pub gas_price: i64,
|
|
||||||
pub call_data: *const u8,
|
|
||||||
pub call_data_size: u64,
|
|
||||||
pub address: JitI256,
|
|
||||||
pub caller: JitI256,
|
|
||||||
pub origin: JitI256,
|
|
||||||
pub transfer_value: JitI256,
|
|
||||||
pub apparent_value: JitI256,
|
|
||||||
pub author: JitI256,
|
|
||||||
pub difficulty: JitI256,
|
|
||||||
pub gas_limit: JitI256,
|
|
||||||
pub number: u64,
|
|
||||||
pub timestamp: i64,
|
|
||||||
pub code: *const u8,
|
|
||||||
pub code_size: u64,
|
|
||||||
pub code_hash: JitI256
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(C)]
|
|
||||||
#[derive(Debug)]
|
|
||||||
/// Configurable properties of git schedule.
|
|
||||||
pub struct JitSchedule {
|
|
||||||
pub have_delegate_call: bool
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn env_sload(ext: *const ExtHandle, index: *const JitI256, out_value: *mut JitI256) {
|
|
||||||
let ext = &*ext;
|
|
||||||
ext.sload(index, out_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn env_sstore(ext: *mut ExtHandle, index: *mut JitI256, value: *mut JitI256) {
|
|
||||||
let ext = &mut *ext;
|
|
||||||
ext.sstore(index, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn env_balance(ext: *const ExtHandle, address: *const JitH256, out_value: *mut JitI256) {
|
|
||||||
let ext = &*ext;
|
|
||||||
ext.balance(address, out_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn env_blockhash(ext: *const ExtHandle, number: *const JitI256, out_hash: *mut JitH256) {
|
|
||||||
let ext = &*ext;
|
|
||||||
ext.blockhash(number, out_hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn env_create(ext: *mut ExtHandle,
|
|
||||||
io_gas: *mut u64,
|
|
||||||
endowment: *const JitI256,
|
|
||||||
init_beg: *const u8,
|
|
||||||
init_size: u64,
|
|
||||||
address: *mut JitH256) {
|
|
||||||
let ext = &mut *ext;
|
|
||||||
ext.create(io_gas, endowment, init_beg, init_size, address);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn env_call(ext: *mut ExtHandle,
|
|
||||||
io_gas: *mut u64,
|
|
||||||
call_gas: u64,
|
|
||||||
sender_address: *const JitH256,
|
|
||||||
receive_address: *const JitH256,
|
|
||||||
code_address: *const JitH256,
|
|
||||||
transfer_value: *const JitI256,
|
|
||||||
apparent_value: *const JitI256,
|
|
||||||
in_beg: *const u8,
|
|
||||||
in_size: u64,
|
|
||||||
out_beg: *mut u8,
|
|
||||||
out_size: u64) -> bool {
|
|
||||||
let ext = &mut *ext;
|
|
||||||
ext.call(io_gas, call_gas, sender_address, receive_address, code_address, transfer_value, apparent_value, in_beg, in_size, out_beg, out_size)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn env_sha3(begin: *const u8, size: u64, out_hash: *mut JitH256) {
|
|
||||||
let out_hash = &mut *out_hash;
|
|
||||||
let input = slice::from_raw_parts(begin, size as usize);
|
|
||||||
let outlen = out_hash.words.len() * 8;
|
|
||||||
let output = slice::from_raw_parts_mut(out_hash.words.as_mut_ptr() as *mut u8, outlen);
|
|
||||||
let mut sha3 = Keccak::new_keccak256();
|
|
||||||
sha3.update(input);
|
|
||||||
sha3.finalize(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn env_extcode(ext: *const ExtHandle, address: *const JitH256, size: *mut u64) -> *const u8 {
|
|
||||||
let ext = &*ext;
|
|
||||||
ext.extcode(address, size)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub unsafe extern "C" fn env_log(ext: *mut ExtHandle,
|
|
||||||
beg: *const u8,
|
|
||||||
size: u64,
|
|
||||||
topic1: *const JitH256,
|
|
||||||
topic2: *const JitH256,
|
|
||||||
topic3: *const JitH256,
|
|
||||||
topic4: *const JitH256) {
|
|
||||||
let ext = &mut *ext;
|
|
||||||
ext.log(beg, size, topic1, topic2, topic3, topic4);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[link(name="evmjit")]
|
|
||||||
extern "C" {
|
|
||||||
pub fn evmjit_create_schedule() -> *mut JitSchedule;
|
|
||||||
pub fn evmjit_destroy_schedule(schedule: *mut JitSchedule);
|
|
||||||
pub fn evmjit_create_runtime_data() -> *mut JitRuntimeData;
|
|
||||||
pub fn evmjit_destroy_runtime_data(data: *mut JitRuntimeData);
|
|
||||||
pub fn evmjit_destroy_context(context: *mut JitContext);
|
|
||||||
pub fn evmjit_exec(context: *mut JitContext, schedule: *mut JitSchedule) -> JitReturnCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExtHandle is not a C type, so we need to allow "improper_ctypes"
|
|
||||||
#[link(name="evmjit")]
|
|
||||||
#[allow(improper_ctypes)]
|
|
||||||
extern "C" {
|
|
||||||
pub fn evmjit_create_context(data: *mut JitRuntimeData, ext: *mut ExtHandle) -> *mut JitContext;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn ffi_test() {
|
|
||||||
unsafe {
|
|
||||||
let data = evmjit_create_runtime_data();
|
|
||||||
let schedule = evmjit_create_schedule();
|
|
||||||
let context = evmjit_create_context(data, &mut ExtHandle::empty());
|
|
||||||
|
|
||||||
let code = evmjit_exec(context, schedule);
|
|
||||||
assert_eq!(code, JitReturnCode::Stop);
|
|
||||||
|
|
||||||
evmjit_destroy_schedule(schedule);
|
|
||||||
evmjit_destroy_runtime_data(data);
|
|
||||||
evmjit_destroy_context(context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn handle_test() {
|
|
||||||
unsafe {
|
|
||||||
let mut ext = ExtHandle::empty();
|
|
||||||
let mut context = ContextHandle::new(RuntimeDataHandle::new(), ScheduleHandle::new(), &mut ext);
|
|
||||||
assert_eq!(context.exec(), ReturnCode::Stop);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn hash_to_int() {
|
|
||||||
let h = H256 { words:[0x0123456789abcdef, 0, 0, 0] };
|
|
||||||
let i = I256::from(h);
|
|
||||||
assert_eq!([0u64, 0, 0, 0xefcdab8967452301], i.words);
|
|
||||||
assert_eq!(H256::from(i).words, h.words);
|
|
||||||
}
|
|
@ -857,11 +857,6 @@ usage! {
|
|||||||
"--no-periodic-snapshot",
|
"--no-periodic-snapshot",
|
||||||
"Disable automated snapshots which usually occur once every 10000 blocks.",
|
"Disable automated snapshots which usually occur once every 10000 blocks.",
|
||||||
|
|
||||||
["Virtual Machine options"]
|
|
||||||
FLAG flag_jitvm: (bool) = false, or |c: &Config| c.vm.as_ref()?.jit.clone(),
|
|
||||||
"--jitvm",
|
|
||||||
"Enable the JIT VM.",
|
|
||||||
|
|
||||||
["Whisper options"]
|
["Whisper options"]
|
||||||
FLAG flag_whisper: (bool) = false, or |c: &Config| c.whisper.as_ref()?.enabled,
|
FLAG flag_whisper: (bool) = false, or |c: &Config| c.whisper.as_ref()?.enabled,
|
||||||
"--whisper",
|
"--whisper",
|
||||||
@ -1023,7 +1018,6 @@ struct Config {
|
|||||||
mining: Option<Mining>,
|
mining: Option<Mining>,
|
||||||
footprint: Option<Footprint>,
|
footprint: Option<Footprint>,
|
||||||
snapshots: Option<Snapshots>,
|
snapshots: Option<Snapshots>,
|
||||||
vm: Option<VM>,
|
|
||||||
misc: Option<Misc>,
|
misc: Option<Misc>,
|
||||||
stratum: Option<Stratum>,
|
stratum: Option<Stratum>,
|
||||||
whisper: Option<Whisper>,
|
whisper: Option<Whisper>,
|
||||||
@ -1240,12 +1234,6 @@ struct Snapshots {
|
|||||||
disable_periodic: Option<bool>,
|
disable_periodic: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, PartialEq, Deserialize)]
|
|
||||||
#[serde(deny_unknown_fields)]
|
|
||||||
struct VM {
|
|
||||||
jit: Option<bool>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Debug, PartialEq, Deserialize)]
|
#[derive(Default, Debug, PartialEq, Deserialize)]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
struct Misc {
|
struct Misc {
|
||||||
@ -1269,7 +1257,7 @@ mod tests {
|
|||||||
use super::{
|
use super::{
|
||||||
Args, ArgsError,
|
Args, ArgsError,
|
||||||
Config, Operating, Account, Ui, Network, Ws, Rpc, Ipc, Dapps, Ipfs, Mining, Footprint,
|
Config, Operating, Account, Ui, Network, Ws, Rpc, Ipc, Dapps, Ipfs, Mining, Footprint,
|
||||||
Snapshots, VM, Misc, Whisper, SecretStore,
|
Snapshots, Misc, Whisper, SecretStore,
|
||||||
};
|
};
|
||||||
use toml;
|
use toml;
|
||||||
use clap::{ErrorKind as ClapErrorKind};
|
use clap::{ErrorKind as ClapErrorKind};
|
||||||
@ -1660,9 +1648,6 @@ mod tests {
|
|||||||
arg_snapshot_at: "latest".into(),
|
arg_snapshot_at: "latest".into(),
|
||||||
flag_no_periodic_snapshot: false,
|
flag_no_periodic_snapshot: false,
|
||||||
|
|
||||||
// -- Virtual Machine Options
|
|
||||||
flag_jitvm: false,
|
|
||||||
|
|
||||||
// -- Whisper options.
|
// -- Whisper options.
|
||||||
flag_whisper: false,
|
flag_whisper: false,
|
||||||
arg_whisper_pool_size: 20,
|
arg_whisper_pool_size: 20,
|
||||||
@ -1906,9 +1891,6 @@ mod tests {
|
|||||||
snapshots: Some(Snapshots {
|
snapshots: Some(Snapshots {
|
||||||
disable_periodic: Some(true),
|
disable_periodic: Some(true),
|
||||||
}),
|
}),
|
||||||
vm: Some(VM {
|
|
||||||
jit: Some(false),
|
|
||||||
}),
|
|
||||||
misc: Some(Misc {
|
misc: Some(Misc {
|
||||||
ntp_servers: Some(vec!["0.parity.pool.ntp.org:123".into()]),
|
ntp_servers: Some(vec!["0.parity.pool.ntp.org:123".into()]),
|
||||||
logging: Some("own_tx=trace".into()),
|
logging: Some("own_tx=trace".into()),
|
||||||
|
@ -147,9 +147,6 @@ num_verifiers = 6
|
|||||||
[snapshots]
|
[snapshots]
|
||||||
disable_periodic = false
|
disable_periodic = false
|
||||||
|
|
||||||
[vm]
|
|
||||||
jit = false
|
|
||||||
|
|
||||||
[misc]
|
[misc]
|
||||||
logging = "own_tx=trace"
|
logging = "own_tx=trace"
|
||||||
log_file = "/var/log/parity.log"
|
log_file = "/var/log/parity.log"
|
||||||
|
@ -74,9 +74,6 @@ scale_verifiers = false
|
|||||||
[snapshots]
|
[snapshots]
|
||||||
disable_periodic = true
|
disable_periodic = true
|
||||||
|
|
||||||
[vm]
|
|
||||||
jit = false
|
|
||||||
|
|
||||||
[misc]
|
[misc]
|
||||||
ntp_servers = ["0.parity.pool.ntp.org:123"]
|
ntp_servers = ["0.parity.pool.ntp.org:123"]
|
||||||
logging = "own_tx=trace"
|
logging = "own_tx=trace"
|
||||||
|
@ -403,12 +403,8 @@ impl Configuration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn vm_type(&self) -> Result<VMType, String> {
|
fn vm_type(&self) -> Result<VMType, String> {
|
||||||
if self.args.flag_jitvm {
|
|
||||||
VMType::jit().ok_or("Parity is built without the JIT EVM.".into())
|
|
||||||
} else {
|
|
||||||
Ok(VMType::Interpreter)
|
Ok(VMType::Interpreter)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn miner_extras(&self) -> Result<MinerExtras, String> {
|
fn miner_extras(&self) -> Result<MinerExtras, String> {
|
||||||
let extras = MinerExtras {
|
let extras = MinerExtras {
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
### Running coverage
|
### Running coverage
|
||||||
|
|
||||||
set -x
|
set -x
|
||||||
RUSTFLAGS="-C link-dead-code" cargo test --all --exclude evmjit --no-run || exit $?
|
RUSTFLAGS="-C link-dead-code" cargo test --all --no-run || exit $?
|
||||||
KCOV_TARGET="target/cov"
|
KCOV_TARGET="target/cov"
|
||||||
KCOV_FLAGS="--verify"
|
KCOV_FLAGS="--verify"
|
||||||
EXCLUDE="/usr/lib,/usr/include,$HOME/.cargo,$HOME/.multirust,rocksdb,secp256k1"
|
EXCLUDE="/usr/lib,/usr/include,$HOME/.cargo,$HOME/.multirust,rocksdb,secp256k1"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# generate documentation only for partiy and ethcore libraries
|
# generate documentation only for partiy and ethcore libraries
|
||||||
|
|
||||||
cargo doc --no-deps --verbose --all --exclude parity-ipfs-api --exclude evmjit &&
|
cargo doc --no-deps --verbose --all --exclude parity-ipfs-api &&
|
||||||
echo '<meta http-equiv=refresh content=0;url=ethcore/index.html>' > target/doc/index.html
|
echo '<meta http-equiv=refresh content=0;url=ethcore/index.html>' > target/doc/index.html
|
||||||
|
@ -7,6 +7,6 @@ echo "set -e" >> $FILE
|
|||||||
# Run release build
|
# Run release build
|
||||||
echo "cargo build --features dev" >> $FILE
|
echo "cargo build --features dev" >> $FILE
|
||||||
# Build tests
|
# Build tests
|
||||||
echo "cargo test --no-run --features dev --all --exclude parity-ipfs-api --exclude evmjit" >> $FILE
|
echo "cargo test --no-run --features dev --all --exclude parity-ipfs-api" >> $FILE
|
||||||
echo "" >> $FILE
|
echo "" >> $FILE
|
||||||
chmod +x $FILE
|
chmod +x $FILE
|
||||||
|
2
test.sh
2
test.sh
@ -43,5 +43,5 @@ fi
|
|||||||
# Running test's
|
# Running test's
|
||||||
echo "________Running Parity Full Test Suite________"
|
echo "________Running Parity Full Test Suite________"
|
||||||
|
|
||||||
cargo test -j 8 $OPTIONS --features "$FEATURES" --all --exclude evmjit $1
|
cargo test -j 8 $OPTIONS --features "$FEATURES" --all $1
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user