diff --git a/rust-evmjit/src/lib.rs b/rust-evmjit/src/lib.rs index 58cb4a1f5..25c38fb04 100644 --- a/rust-evmjit/src/lib.rs +++ b/rust-evmjit/src/lib.rs @@ -69,21 +69,19 @@ impl DerefMut for RuntimeDataHandle { pub struct ContextHandle { context: *mut JitContext, data_handle: RuntimeDataHandle, - env: EnvHandle } impl ContextHandle { /// Creates new context handle. - pub fn new(data_handle: RuntimeDataHandle, env: EnvHandle) -> Self { + /// This function is unsafe cause env lifetime is not considered + pub unsafe fn new(data_handle: RuntimeDataHandle, env: &mut EnvHandle) -> Self { import_evmjit_abi(); let mut handle = ContextHandle { - context: unsafe {::std::mem::uninitialized()}, + context: std::mem::uninitialized(), data_handle: data_handle, - env: env }; - println!("env address: {:?}", &handle.env as *const _); - handle.context = unsafe { evmjit_create_context(handle.data_handle.mut_runtime_data(), &mut handle.env) }; + handle.context = evmjit_create_context(handle.data_handle.mut_runtime_data(), env); handle } @@ -263,32 +261,30 @@ pub mod ffi { #[no_mangle] pub unsafe extern "C" fn env_sload(env: *const EnvHandle, index: *const JitI256, out_value: *mut JitI256) { - println!("sload env address: {:?}", env); let env = &*env; env.sload(index, out_value); } #[no_mangle] pub unsafe extern "C" fn env_sstore(env: *mut EnvHandle, index: *mut JitI256, value: *mut JitI256) { - println!("sstore"); let env = &mut *env; env.sstore(index, value); } #[no_mangle] - pub unsafe extern fn env_balance(env: *const EnvHandle, address: *const JitI256, out_value: *mut JitI256) { + pub unsafe extern "C" fn env_balance(env: *const EnvHandle, address: *const JitI256, out_value: *mut JitI256) { let env = &*env; env.balance(address, out_value); } #[no_mangle] - pub unsafe extern fn env_blockhash(env: *const EnvHandle, number: *const JitI256, out_hash: *mut JitI256) { + pub unsafe extern "C" fn env_blockhash(env: *const EnvHandle, number: *const JitI256, out_hash: *mut JitI256) { let env = &*env; env.blockhash(number, out_hash); } #[no_mangle] - pub unsafe extern fn env_create(env: *mut EnvHandle, + pub unsafe extern "C" fn env_create(env: *mut EnvHandle, io_gas: *mut u64, endowment: *const JitI256, init_beg: *const u8, @@ -299,7 +295,7 @@ pub mod ffi { } #[no_mangle] - pub unsafe extern fn env_call(env: *mut EnvHandle, + pub unsafe extern "C" fn env_call(env: *mut EnvHandle, io_gas: *mut u64, call_gas: *const u64, receive_address: *const JitI256, @@ -314,7 +310,7 @@ pub mod ffi { } #[no_mangle] - pub unsafe extern fn env_sha3(begin: *const u8, size: u64, out_hash: *mut JitI256) { + pub unsafe extern "C" fn env_sha3(begin: *const u8, size: u64, out_hash: *mut JitI256) { // TODO: write tests // it may be incorrect due to endianess // if it is, don't use `from_raw_parts` @@ -328,13 +324,13 @@ pub mod ffi { } #[no_mangle] - pub unsafe extern fn env_extcode(env: *const EnvHandle, address: *const JitI256, size: *mut u64) -> *const u8 { + pub unsafe extern "C" fn env_extcode(env: *const EnvHandle, address: *const JitI256, size: *mut u64) -> *const u8 { let env = &*env; env.extcode(address, size) } #[no_mangle] - pub unsafe extern fn env_log(env: *mut EnvHandle, + pub unsafe extern "C" fn env_log(env: *mut EnvHandle, beg: *const u8, size: *const u64, topic1: *const JitI256, diff --git a/src/evm/env.rs b/src/evm/env.rs index 42d7031e3..2724159a4 100644 --- a/src/evm/env.rs +++ b/src/evm/env.rs @@ -8,13 +8,13 @@ impl Env { } pub fn sload(&self, _index: &H256) -> H256 { - println!("sload!"); + println!("sload!: {:?}", _index); //unimplemented!(); H256::new() } pub fn sstore(&self, _index: &H256, _value: &H256) { - println!("sstore!"); + println!("sstore!: {:?} , {:?}", _index, _value); //unimplemented!(); } diff --git a/src/evm/evm.rs b/src/evm/evm.rs new file mode 100644 index 000000000..b25eabc15 --- /dev/null +++ b/src/evm/evm.rs @@ -0,0 +1,16 @@ +//! EVM interface + +use evm::{RuntimeData, Env}; + +#[derive(Debug, Eq, PartialEq)] +pub enum ReturnCode { + Stop, + Return, + Suicide, + OutOfGas, + InternalError +} + +pub trait Evm { + fn exec(data: RuntimeData, env: &mut Env) -> ReturnCode; +} diff --git a/src/evm/jit.rs b/src/evm/jit.rs index e004c87fc..ac796e0f1 100644 --- a/src/evm/jit.rs +++ b/src/evm/jit.rs @@ -7,12 +7,12 @@ use util::sha3::*; use evm; /// Should be used to convert jit types to ethcore -pub trait FromJit: Sized { +trait FromJit: Sized { fn from_jit(input: T) -> Self; } /// Should be used to covert ethcore types to jit -pub trait IntoJit { +trait IntoJit { fn into_jit(self) -> T; } @@ -88,19 +88,19 @@ impl IntoJit for evm::RuntimeData { } } -pub struct EnvAdapter { - env: evm::Env +struct EnvAdapter<'a> { + env: &'a mut evm::Env } -impl EnvAdapter { - pub fn new() -> EnvAdapter { +impl<'a> EnvAdapter<'a> { + fn new(env: &'a mut evm::Env) -> Self { EnvAdapter { - env: evm::Env::new() + env: env } } } -impl evmjit::Env for EnvAdapter { +impl<'a> evmjit::Env for EnvAdapter<'a> { fn sload(&self, index: *const evmjit::I256, out_value: *mut evmjit::I256) { unsafe { let i = H256::from_jit(&*index); @@ -160,12 +160,35 @@ impl evmjit::Env for EnvAdapter { } } +impl From for evm::ReturnCode { + fn from(code: evmjit::ReturnCode) -> Self { + match code { + evmjit::ReturnCode::Stop => evm::ReturnCode::Stop, + evmjit::ReturnCode::Return => evm::ReturnCode::Return, + evmjit::ReturnCode::Suicide => evm::ReturnCode::Suicide, + evmjit::ReturnCode::OutOfGas => evm::ReturnCode::OutOfGas, + _ => evm::ReturnCode::InternalError + } + } +} + +pub struct JitEvm; + +impl evm::Evm for JitEvm { + fn exec(data: evm::RuntimeData, env: &mut evm::Env) -> evm::ReturnCode { + // Dirty hack. This is unsafe, but we interact with ffi, so it's justified. + let env_adapter: EnvAdapter<'static> = unsafe { ::std::mem::transmute(EnvAdapter::new(env)) }; + let mut env_handle = evmjit::EnvHandle::new(env_adapter); + let mut context = unsafe { evmjit::ContextHandle::new(data.into_jit(), &mut env_handle) }; + From::from(context.exec()) + } +} + #[cfg(test)] mod tests { use std::str::FromStr; use util::hash::*; use util::uint::*; - use evmjit::{ContextHandle, RuntimeDataHandle, EnvHandle, ReturnCode, ffi}; use evm::*; use evm::jit::{FromJit, IntoJit}; @@ -189,18 +212,9 @@ mod tests { assert_eq!(h, h2); } - #[test] - fn test_env_sload() { - let env = EnvHandle::new(EnvAdapter::new()); - let i = U256::from(0).into_jit(); - let mut o = U256::from(0).into_jit(); - unsafe { - ffi::env_sload(&env as *const _, &i as *const _, &mut o as *mut _); - } - } - #[test] fn test_env_adapter() { + let mut data = RuntimeData::new(); data.coinbase = Address::from_str("2adc25665018aa1fe0e6bc666dac8fc2697ff9ba").unwrap(); data.difficulty = U256::from(0x0100); @@ -215,11 +229,8 @@ mod tests { data.gas_price = 0x3b9aca00; data.origin = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap(); data.call_value = U256::from_str("0de0b6b3a7640000").unwrap(); - let env = EnvAdapter::new(); - let mut context = ContextHandle::new(data.into_jit(), EnvHandle::new(env)); - // crashes with signal 11 on env.sload - assert_eq!(context.exec(), ReturnCode::Stop); - assert!(false); + let mut env = Env::new(); + assert_eq!(JitEvm::exec(data, &mut env), ReturnCode::Stop); } } diff --git a/src/evm/mod.rs b/src/evm/mod.rs index a57e6bff4..095c47dd6 100644 --- a/src/evm/mod.rs +++ b/src/evm/mod.rs @@ -2,11 +2,13 @@ pub mod env; pub mod runtime_data; +pub mod evm; #[cfg(feature = "jit" )] pub mod jit; +pub use self::evm::{Evm, ReturnCode}; pub use self::env::Env; pub use self::runtime_data::RuntimeData; #[cfg(feature = "jit" )] -pub use self::jit::EnvAdapter; +pub use self::jit::JitEvm;