openethereum/ethcore/evm/src/jit.rs

413 lines
12 KiB
Rust
Raw Normal View History

// Copyright 2015-2017 Parity Technologies (UK) Ltd.
2016-02-05 13:40:41 +01:00
// 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/>.
2016-01-11 02:42:02 +01:00
//! Just in time compiler execution environment.
use util::*;
2015-12-23 13:02:01 +01:00
use evmjit;
2016-06-23 14:46:31 +02:00
use evm::{self, GasLeft};
use evm::CallType;
use vm::{self, Vm};
2015-12-23 13:02:01 +01:00
2015-12-23 13:49:45 +01:00
/// Should be used to convert jit types to ethcore
2015-12-28 22:37:15 +01:00
trait FromJit<T>: Sized {
2015-12-23 13:49:45 +01:00
fn from_jit(input: T) -> Self;
2015-12-23 13:02:01 +01:00
}
2015-12-23 13:49:45 +01:00
/// Should be used to covert ethcore types to jit
2015-12-28 22:37:15 +01:00
trait IntoJit<T> {
2015-12-23 13:49:45 +01:00
fn into_jit(self) -> T;
2015-12-23 13:02:01 +01:00
}
2015-12-23 13:49:45 +01:00
impl<'a> FromJit<&'a evmjit::I256> for U256 {
fn from_jit(input: &'a evmjit::I256) -> Self {
2015-12-30 12:03:40 +01:00
unsafe {
let mut res: U256 = mem::uninitialized();
ptr::copy(input.words.as_ptr(), res.0.as_mut_ptr(), 4);
res
}
2015-12-23 13:02:01 +01:00
}
}
2015-12-23 13:49:45 +01:00
impl<'a> FromJit<&'a evmjit::I256> for H256 {
fn from_jit(input: &'a evmjit::I256) -> Self {
2015-12-23 13:02:01 +01:00
let u = U256::from_jit(input);
H256::from(&u)
}
}
2015-12-29 12:04:03 +01:00
impl<'a> FromJit<&'a evmjit::I256> for Address {
fn from_jit(input: &'a evmjit::I256) -> Self {
Address::from(H256::from_jit(input))
}
}
2016-01-06 13:00:14 +01:00
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 {
2016-01-06 13:00:14 +01:00
Address::from(H256::from_jit(input))
}
}
2015-12-23 13:49:45 +01:00
impl IntoJit<evmjit::I256> for U256 {
2015-12-23 13:02:01 +01:00
fn into_jit(self) -> evmjit::I256 {
2015-12-30 12:03:40 +01:00
unsafe {
let mut res: evmjit::I256 = mem::uninitialized();
ptr::copy(self.0.as_ptr(), res.words.as_mut_ptr(), 4);
res
}
2015-12-23 13:02:01 +01:00
}
}
2015-12-23 13:49:45 +01:00
impl IntoJit<evmjit::I256> for H256 {
2015-12-23 13:02:01 +01:00
fn into_jit(self) -> evmjit::I256 {
let mut ret = [0; 4];
2016-09-26 18:38:54 +02:00
let len = self.len();
for i in 0..len {
let rev = len - 1 - i;
2015-12-30 12:03:40 +01:00
let pos = rev / 8;
2016-09-26 18:38:54 +02:00
ret[pos] += (self[i] as u64) << ((rev % 8) * 8);
2015-12-23 13:02:01 +01:00
}
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)
}
}
2015-12-24 01:07:46 +01:00
impl IntoJit<evmjit::I256> for Address {
fn into_jit(self) -> evmjit::I256 {
H256::from(self).into_jit()
}
}
2016-01-06 20:00:32 +01:00
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.
2016-01-07 19:20:23 +01:00
struct ExtAdapter<'a> {
2016-01-11 14:08:03 +01:00
ext: &'a mut evm::Ext,
2016-01-16 07:46:36 +01:00
address: Address
2015-12-23 13:02:01 +01:00
}
2016-01-07 19:20:23 +01:00
impl<'a> ExtAdapter<'a> {
2016-01-16 07:46:36 +01:00
fn new(ext: &'a mut evm::Ext, address: Address) -> Self {
2016-01-07 19:20:23 +01:00
ExtAdapter {
2016-01-11 14:08:03 +01:00
ext: ext,
2016-01-16 07:46:36 +01:00
address: address
2015-12-23 13:02:01 +01:00
}
}
}
2016-01-07 19:20:23 +01:00
impl<'a> evmjit::Ext for ExtAdapter<'a> {
2016-01-16 07:46:36 +01:00
fn sload(&self, key: *const evmjit::I256, out_value: *mut evmjit::I256) {
2015-12-23 13:02:01 +01:00
unsafe {
2016-01-16 07:46:36 +01:00
let i = H256::from_jit(&*key);
2016-01-15 18:56:28 +01:00
let o = self.ext.storage_at(&i);
2015-12-23 13:02:01 +01:00
*out_value = o.into_jit();
}
}
2016-01-16 07:46:36 +01:00
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();
2015-12-23 13:02:01 +01:00
}
2016-01-16 07:46:36 +01:00
self.ext.set_storage(key, value);
2015-12-23 13:02:01 +01:00
}
fn balance(&self, address: *const evmjit::H256, out_value: *mut evmjit::I256) {
2015-12-29 12:04:03 +01:00
unsafe {
let a = Address::from_jit(&*address);
2016-01-07 19:20:23 +01:00
let o = self.ext.balance(&a);
2015-12-29 12:04:03 +01:00
*out_value = o.into_jit();
}
2015-12-23 13:02:01 +01:00
}
fn blockhash(&self, number: *const evmjit::I256, out_hash: *mut evmjit::H256) {
2015-12-29 12:04:03 +01:00
unsafe {
let n = U256::from_jit(&*number);
2016-01-07 19:20:23 +01:00
let o = self.ext.blockhash(&n);
2015-12-29 12:04:03 +01:00
*out_hash = o.into_jit();
}
2015-12-23 13:02:01 +01:00
}
fn create(&mut self,
2016-01-06 20:00:32 +01:00
io_gas: *mut u64,
2016-01-16 07:46:36 +01:00
value: *const evmjit::I256,
2016-01-06 20:00:32 +01:00
init_beg: *const u8,
init_size: u64,
address: *mut evmjit::H256) {
2016-01-16 07:46:36 +01:00
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 {
2016-01-16 07:46:36 +01:00
*address = new_address.into_jit();
*io_gas = gas_left.low_u64();
},
evm::ContractCreateResult::Failed => unsafe {
*address = Address::new().into_jit();
*io_gas = 0;
2016-01-16 07:46:36 +01:00
}
}
} else {
unsafe { *address = Address::new().into_jit(); }
2016-01-06 20:00:32 +01:00
}
2015-12-23 13:02:01 +01:00
}
fn call(&mut self,
2016-01-06 20:00:32 +01:00
io_gas: *mut u64,
call_gas: u64,
sender_address: *const evmjit::H256,
2016-01-06 20:00:32 +01:00
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,
2016-01-06 20:00:32 +01:00
in_beg: *const u8,
in_size: u64,
2016-01-11 16:05:21 +01:00
out_beg: *mut u8,
out_size: u64) -> bool {
2016-01-16 07:46:36 +01:00
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) };
2016-01-16 07:46:36 +01:00
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) };
2016-01-16 07:46:36 +01:00
// 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) };
2016-01-16 07:46:36 +01:00
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() {
2016-01-16 07:46:36 +01:00
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 {
2016-01-16 07:46:36 +01:00
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,
2016-09-26 18:38:54 +02:00
};
match self.ext.call(
&call_gas,
&sender_address,
&receive_address,
value,
2016-01-16 07:46:36 +01:00
unsafe { slice::from_raw_parts(in_beg, in_size as usize) },
&code_address,
2016-09-26 18:38:54 +02:00
unsafe { slice::from_raw_parts_mut(out_beg, out_size as usize) },
call_type,
) {
2016-01-16 07:46:36 +01:00
evm::MessageCallResult::Success(gas_left) => unsafe {
*io_gas = (gas + gas_left).low_u64();
true
},
evm::MessageCallResult::Failed => unsafe {
*io_gas = gas.low_u64();
false
2016-01-06 20:00:32 +01:00
}
}
2015-12-23 13:02:01 +01:00
}
fn log(&mut self,
2016-01-06 13:00:14 +01:00
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));
}
2016-01-06 13:00:14 +01:00
let bytes_ref: &[u8] = slice::from_raw_parts(beg, size as usize);
self.ext.log(topics, bytes_ref);
2016-01-06 13:00:14 +01:00
}
2015-12-23 13:02:01 +01:00
}
fn extcode(&self, address: *const evmjit::H256, size: *mut u64) -> *const u8 {
2016-01-05 18:43:46 +01:00
unsafe {
2016-01-07 19:20:23 +01:00
let code = self.ext.extcode(&Address::from_jit(&*address));
2016-01-05 18:43:46 +01:00
*size = code.len() as u64;
let ptr = code.as_ptr();
mem::forget(code);
ptr
}
2015-12-23 13:02:01 +01:00
}
}
#[derive(Default)]
pub struct JitEvm {
2016-06-23 14:46:31 +02:00
context: Option<evmjit::ContextHandle>,
}
2015-12-28 22:37:15 +01:00
impl vm::Vm for JitEvm {
fn exec(&mut self, params: ActionParams, ext: &mut evm::Ext) -> evm::Result<GasLeft> {
2015-12-28 22:37:15 +01:00
// Dirty hack. This is unsafe, but we interact with ffi, so it's justified.
2016-01-16 07:46:36 +01:00
let ext_adapter: ExtAdapter<'static> = unsafe { ::std::mem::transmute(ExtAdapter::new(ext, params.address.clone())) };
2016-01-07 19:20:23 +01:00
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");
2016-01-11 14:08:03 +01:00
let res = context.exec();
2016-01-11 14:08:03 +01:00
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 => {
2016-01-13 16:16:21 +01:00
ext.suicide(&Address::from_jit(&context.suicide_refund_address()));
Ok(GasLeft::Known(U256::from(context.gas_left())))
2016-01-11 02:17:29 +01:00
},
evmjit::ReturnCode::OutOfGas => Err(vm::Error::OutOfGas),
_err => Err(vm::Error::Internal)
2016-01-09 18:25:18 +01:00
}
2015-12-28 22:37:15 +01:00
}
}
#[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);
}