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 = [
|
||||
"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"
|
||||
|
@ -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"]
|
||||
|
@ -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
|
||||
|
@ -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" }
|
||||
|
||||
[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
|
||||
|
@ -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"]
|
||||
|
@ -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")]
|
||||
|
@ -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)]
|
||||
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))]
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
@ -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",
|
||||
"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()),
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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 {
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user