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:
Marek Kotewicz 2018-04-04 18:07:49 +09:00 committed by GitHub
parent 679d6c6f2b
commit ea6b0ec164
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 57 additions and 1179 deletions

8
Cargo.lock generated
View File

@ -908,7 +908,6 @@ version = "0.1.0"
dependencies = [
"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)",
"evmjit 1.11.0",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.0",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -939,13 +938,6 @@ dependencies = [
"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]]
name = "fdlimit"
version = "0.1.1"

View File

@ -100,7 +100,6 @@ ui-precompiled = [
]
ui-enabled = ["dapps"]
dapps = ["parity-dapps"]
jit = ["ethcore/jit"]
json-tests = ["ethcore/json-tests"]
test-heavy = ["ethcore/test-heavy"]
evm-debug = ["ethcore/evm-debug"]

View File

@ -27,20 +27,7 @@ RUN apt-get update && \
libudev-dev \
pkg-config \
dpkg-dev \
# evmjit dependencies
zlib1g-dev \
libedit-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
curl https://sh.rustup.rs -sSf | sh -s -- -y && \
# rustup directory
@ -73,10 +60,6 @@ cd /build&&git clone https://github.com/paritytech/parity && \
file \
pkg-config \
dpkg-dev \
# evmjit dependencies
zlib1g-dev \
libedit-dev \
cmake llvm-3.7-dev&&\
rm -rf /var/lib/apt/lists/*
# setup ENTRYPOINT
EXPOSE 8080 8545 8180

View File

@ -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"]

View File

@ -76,7 +76,6 @@ tempdir = "0.3"
trie-standardmap = { path = "../util/trie-standardmap" }
[features]
jit = ["evm/jit"]
evm-debug = ["slow-blocks"]
evm-debug-tests = ["evm-debug", "evm/evm-debug-tests"]
slow-blocks = [] # Use SLOW_TX_DURATION="50" (compile time!) to track transactions over 50ms

View File

@ -6,7 +6,6 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
bit-set = "0.4"
ethereum-types = "0.3"
evmjit = { path = "../../evmjit", optional = true }
heapsize = "0.4"
lazy_static = "1.0"
log = "0.3"
@ -19,6 +18,5 @@ memory-cache = { path = "../../util/memory_cache" }
rustc-hex = "1.0"
[features]
jit = ["evmjit"]
evm-debug = []
evm-debug-tests = ["evm-debug"]

View File

@ -32,23 +32,6 @@ pub struct Factory {
impl Factory {
/// Create fresh instance of VM
/// 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> {
match self.evm {
VMType::Interpreter => if Self::can_fit_in_usize(gas) {
@ -74,17 +57,7 @@ impl 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
#[cfg(any(not(feature = "jit"), test))]
fn default() -> Factory {
Factory {
evm: VMType::Interpreter,
@ -101,24 +74,7 @@ fn test_create_vm() {
/// Create tests by injecting different VM factories
#[macro_export]
macro_rules! evm_test(
(ignorejit => $name_test: ident: $name_jit: 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));
}
($name_test: ident: $name_int: ident) => {
#[test]
fn $name_int() {
$name_test(Factory::new(VMType::Interpreter, 1024 * 32));
@ -129,14 +85,7 @@ macro_rules! evm_test(
/// Create ignored tests by injecting different VM factories
#[macro_export]
macro_rules! evm_test_ignore(
($name_test: ident: $name_jit: ident, $name_int: ident) => {
#[test]
#[ignore]
#[cfg(feature = "jit")]
#[cfg(feature = "ignored-tests")]
fn $name_jit() {
$name_test(Factory::new(VMType::Jit, 1024 * 32));
}
($name_test: ident: $name_int: ident) => {
#[test]
#[ignore]
#[cfg(feature = "ignored-tests")]

View File

@ -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);
}

View File

@ -30,9 +30,6 @@ extern crate lazy_static;
#[cfg_attr(feature = "evm-debug", macro_use)]
extern crate log;
#[cfg(feature = "jit")]
extern crate evmjit;
#[cfg(test)]
extern crate rustc_hex;
@ -44,9 +41,6 @@ pub mod factory;
mod vmtype;
mod instructions;
#[cfg(feature = "jit" )]
mod jit;
#[cfg(test)]
mod tests;
#[cfg(all(feature="benches", test))]

View File

@ -26,7 +26,7 @@ use vm::tests::{FakeExt, FakeCall, FakeCallType, test_finalize};
use factory::Factory;
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) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01600055".from_hex().unwrap();
@ -46,7 +46,7 @@ fn test_add(factory: super::Factory) {
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) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "6000600020600055".from_hex().unwrap();
@ -66,7 +66,7 @@ fn test_sha3(factory: super::Factory) {
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) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "30600055".from_hex().unwrap();
@ -86,7 +86,7 @@ fn test_address(factory: super::Factory) {
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) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let origin = Address::from_str("cd1722f2947def4cf144679da39c4c32bdc35681").unwrap();
@ -108,7 +108,7 @@ fn test_origin(factory: super::Factory) {
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) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let sender = Address::from_str("cd1722f2947def4cf144679da39c4c32bdc35681").unwrap();
@ -130,7 +130,7 @@ fn test_sender(factory: super::Factory) {
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) {
// 33 - sender
// 3b - extcodesize
@ -165,7 +165,7 @@ fn test_extcodecopy(factory: super::Factory) {
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) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").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());
}
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) {
// 60 ff - push ff
// 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());
}
evm_test!{test_blockhash: test_blockhash_jit, test_blockhash_int}
evm_test!{test_blockhash: test_blockhash_int}
fn test_blockhash(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").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);
}
evm_test!{test_calldataload: test_calldataload_jit, test_calldataload_int}
evm_test!{test_calldataload: test_calldataload_int}
fn test_calldataload(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").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) {
let author = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let code = "41600055".from_hex().unwrap();
@ -285,7 +285,7 @@ fn test_author(factory: super::Factory) {
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) {
let timestamp = 0x1234;
let code = "42600055".from_hex().unwrap();
@ -305,7 +305,7 @@ fn test_timestamp(factory: super::Factory) {
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) {
let number = 0x1234;
let code = "43600055".from_hex().unwrap();
@ -325,7 +325,7 @@ fn test_number(factory: super::Factory) {
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) {
let difficulty = U256::from(0x1234);
let code = "44600055".from_hex().unwrap();
@ -345,7 +345,7 @@ fn test_difficulty(factory: super::Factory) {
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) {
let gas_limit = U256::from(0x1234);
let code = "45600055".from_hex().unwrap();
@ -365,7 +365,7 @@ fn test_gas_limit(factory: super::Factory) {
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) {
let code = "65012365124623626543219002600055".from_hex().unwrap();
@ -383,7 +383,7 @@ fn test_mul(factory: super::Factory) {
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) {
let code = "65012365124623626543219003600055".from_hex().unwrap();
@ -401,7 +401,7 @@ fn test_sub(factory: super::Factory) {
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) {
let code = "65012365124623626543219004600055".from_hex().unwrap();
@ -419,7 +419,7 @@ fn test_div(factory: super::Factory) {
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) {
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));
}
evm_test!{test_mod: test_mod_jit, test_mod_int}
evm_test!{test_mod: test_mod_int}
fn test_mod(factory: super::Factory) {
let code = "650123651246236265432290066000556501236512462360009006600155".from_hex().unwrap();
@ -456,7 +456,7 @@ fn test_mod(factory: super::Factory) {
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) {
let code = "650123651246236265432290076000556501236512462360009007600155".from_hex().unwrap();
@ -475,7 +475,7 @@ fn test_smod(factory: super::Factory) {
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) {
let code = "650123651246236265432290056000556501236512462360009005600155".from_hex().unwrap();
@ -494,7 +494,7 @@ fn test_sdiv(factory: super::Factory) {
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) {
let code = "6016650123651246230a6000556001650123651246230a6001556000650123651246230a600255".from_hex().unwrap();
@ -514,7 +514,7 @@ fn test_exp(factory: super::Factory) {
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) {
let code = "601665012365124623818181811060005511600155146002556415235412358014600355".from_hex().unwrap();
@ -535,7 +535,7 @@ fn test_comparison(factory: super::Factory) {
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) {
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));
}
evm_test!{test_bitops: test_bitops_jit, test_bitops_int}
evm_test!{test_bitops: test_bitops_int}
fn test_bitops(factory: super::Factory) {
let code = "60ff610ff08181818116600055176001551860025560008015600355198015600455600555".from_hex().unwrap();
@ -579,7 +579,7 @@ fn test_bitops(factory: super::Factory) {
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) {
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));
}
evm_test!{test_byte: test_byte_jit, test_byte_int}
evm_test!{test_byte: test_byte_int}
fn test_byte(factory: super::Factory) {
let code = "60f061ffff1a600055610fff601f1a600155".from_hex().unwrap();
@ -619,7 +619,7 @@ fn test_byte(factory: super::Factory) {
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) {
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) {
let code = "60f060aa50600055".from_hex().unwrap();
@ -677,7 +677,7 @@ fn test_pop(factory: super::Factory) {
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) {
let code = "5a6001555836553a600255386003553460045560016001526016590454600555".from_hex().unwrap();
@ -702,7 +702,7 @@ fn test_extops(factory: super::Factory) {
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) {
let code = "600160015560066000555b60016000540380806000551560245760015402600155600a565b".from_hex().unwrap();
@ -722,7 +722,7 @@ fn test_jumps(factory: super::Factory) {
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) {
let code = "600054602d57600160005560006000600060006050610998610100f160006000600060006050610998610100f25b".from_hex().unwrap();
@ -766,7 +766,7 @@ fn test_calls(factory: super::Factory) {
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) {
let code = "600060006064f000".from_hex().unwrap();

View File

@ -19,22 +19,11 @@ use std::fmt;
/// Type of EVM to use.
#[derive(Debug, PartialEq, Clone)]
pub enum VMType {
/// JIT EVM
#[cfg(feature = "jit")]
Jit,
/// RUST EVM
Interpreter
}
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 {
write!(f, "{}", match *self {
VMType::Interpreter => "INT"
@ -49,27 +38,8 @@ impl Default for 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)
#[cfg(not(feature = "jit"))]
pub fn all() -> Vec<VMType> {
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)
}
}

View File

@ -721,7 +721,7 @@ mod tests {
}
// 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) {
let sender = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &[]).0;
@ -752,7 +752,7 @@ mod tests {
// 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) {
// code:
//
@ -1083,7 +1083,7 @@ mod tests {
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) {
// code:
//
@ -1135,7 +1135,7 @@ mod tests {
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) {
// code:
//
@ -1188,7 +1188,7 @@ mod tests {
// test is incorrect, mk
// 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) {
// 60 00 - push 0
// 60 00 - push 0
@ -1248,7 +1248,7 @@ mod tests {
// test is incorrect, mk
// 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) {
// 60 01 - push 1
// 60 00 - push 0
@ -1293,7 +1293,7 @@ mod tests {
// test is incorrect, mk
// 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) {
let keypair = Random.generate().unwrap();
let t = Transaction {
@ -1331,7 +1331,7 @@ mod tests {
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) {
let keypair = Random.generate().unwrap();
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) {
let keypair = Random.generate().unwrap();
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) {
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) {
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) {
let contract_address = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap();
let sender = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();

View File

@ -130,9 +130,6 @@ extern crate trace_time;
#[cfg_attr(test, macro_use)]
extern crate evm;
#[cfg(feature = "jit" )]
extern crate evmjit;
pub extern crate ethstore;
pub mod account_provider;

View File

@ -31,7 +31,7 @@ use rustc_hex::FromHex;
use ethereum_types::{H256, Address};
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) {
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());

View File

@ -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"

View File

@ -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);
}

View File

@ -857,11 +857,6 @@ usage! {
"--no-periodic-snapshot",
"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"]
FLAG flag_whisper: (bool) = false, or |c: &Config| c.whisper.as_ref()?.enabled,
"--whisper",
@ -1023,7 +1018,6 @@ struct Config {
mining: Option<Mining>,
footprint: Option<Footprint>,
snapshots: Option<Snapshots>,
vm: Option<VM>,
misc: Option<Misc>,
stratum: Option<Stratum>,
whisper: Option<Whisper>,
@ -1240,12 +1234,6 @@ struct Snapshots {
disable_periodic: Option<bool>,
}
#[derive(Default, Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
struct VM {
jit: Option<bool>,
}
#[derive(Default, Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
struct Misc {
@ -1269,7 +1257,7 @@ mod tests {
use super::{
Args, ArgsError,
Config, Operating, Account, Ui, Network, Ws, Rpc, Ipc, Dapps, Ipfs, Mining, Footprint,
Snapshots, VM, Misc, Whisper, SecretStore,
Snapshots, Misc, Whisper, SecretStore,
};
use toml;
use clap::{ErrorKind as ClapErrorKind};
@ -1660,9 +1648,6 @@ mod tests {
arg_snapshot_at: "latest".into(),
flag_no_periodic_snapshot: false,
// -- Virtual Machine Options
flag_jitvm: false,
// -- Whisper options.
flag_whisper: false,
arg_whisper_pool_size: 20,
@ -1906,9 +1891,6 @@ mod tests {
snapshots: Some(Snapshots {
disable_periodic: Some(true),
}),
vm: Some(VM {
jit: Some(false),
}),
misc: Some(Misc {
ntp_servers: Some(vec!["0.parity.pool.ntp.org:123".into()]),
logging: Some("own_tx=trace".into()),

View File

@ -147,9 +147,6 @@ num_verifiers = 6
[snapshots]
disable_periodic = false
[vm]
jit = false
[misc]
logging = "own_tx=trace"
log_file = "/var/log/parity.log"

View File

@ -74,9 +74,6 @@ scale_verifiers = false
[snapshots]
disable_periodic = true
[vm]
jit = false
[misc]
ntp_servers = ["0.parity.pool.ntp.org:123"]
logging = "own_tx=trace"

View File

@ -403,12 +403,8 @@ impl Configuration {
}
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)
}
}
fn miner_extras(&self) -> Result<MinerExtras, String> {
let extras = MinerExtras {

View File

@ -12,7 +12,7 @@
### Running coverage
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_FLAGS="--verify"
EXCLUDE="/usr/lib,/usr/include,$HOME/.cargo,$HOME/.multirust,rocksdb,secp256k1"

View File

@ -1,5 +1,5 @@
#!/bin/sh
# 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

View File

@ -7,6 +7,6 @@ echo "set -e" >> $FILE
# Run release build
echo "cargo build --features dev" >> $FILE
# 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
chmod +x $FILE

View File

@ -43,5 +43,5 @@ fi
# Running test's
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