evmjit homestead merge, compiles but tests do not pass yet
This commit is contained in:
		
							parent
							
								
									c5b81270a8
								
							
						
					
					
						commit
						3030b18683
					
				| @ -174,28 +174,37 @@ impl<'a> evmjit::Ext for ExtAdapter<'a> { | |||||||
| 	fn call(&mut self, | 	fn call(&mut self, | ||||||
| 				io_gas: *mut u64, | 				io_gas: *mut u64, | ||||||
| 				call_gas: u64, | 				call_gas: u64, | ||||||
|  | 				sender_address: *const evmjit::H256, | ||||||
| 				receive_address: *const evmjit::H256, | 				receive_address: *const evmjit::H256, | ||||||
| 				value: *const evmjit::I256, | 				code_address: *const evmjit::H256, | ||||||
|  | 				transfer_value: *const evmjit::I256, | ||||||
|  | 				_apparent_value: *const evmjit::I256, | ||||||
| 				in_beg: *const u8, | 				in_beg: *const u8, | ||||||
| 				in_size: u64, | 				in_size: u64, | ||||||
| 				out_beg: *mut u8, | 				out_beg: *mut u8, | ||||||
| 				out_size: u64, | 				out_size: u64) -> bool { | ||||||
| 				code_address: *const evmjit::H256) -> bool { |  | ||||||
| 
 | 
 | ||||||
| 		let mut gas = unsafe { U256::from(*io_gas) }; | 		let mut gas = unsafe { U256::from(*io_gas) }; | ||||||
| 		let mut call_gas = U256::from(call_gas); | 		let mut call_gas = U256::from(call_gas); | ||||||
| 		let mut gas_cost = 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 receive_address = unsafe { Address::from_jit(&*receive_address) }; | ||||||
| 		let code_address = unsafe { Address::from_jit(&*code_address) }; | 		let code_address = unsafe { Address::from_jit(&*code_address) }; | ||||||
| 		let value = unsafe { U256::from_jit(&*value) }; | 		let transfer_value = unsafe { U256::from_jit(&*transfer_value) }; | ||||||
|  | 		let mut value = Some(transfer_value); | ||||||
| 
 | 
 | ||||||
| 		// receive address and code address are the same in normal calls
 | 		// receive address and code address are the same in normal calls
 | ||||||
| 		let is_callcode = receive_address != code_address; | 		let is_callcode = receive_address != code_address; | ||||||
|  | 		if !is_callcode { | ||||||
|  | 			// it's a delegatecall... fix it better.
 | ||||||
|  | 			value = None; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		if !is_callcode && !self.ext.exists(&code_address) { | 		if !is_callcode && !self.ext.exists(&code_address) { | ||||||
| 			gas_cost = gas_cost + U256::from(self.ext.schedule().call_new_account_gas); | 			gas_cost = gas_cost + U256::from(self.ext.schedule().call_new_account_gas); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if value > U256::zero() { | 		if transfer_value > U256::zero() { | ||||||
| 			assert!(self.ext.schedule().call_value_transfer_gas > self.ext.schedule().call_stipend, "overflow possible"); | 			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); | 			gas_cost = gas_cost + U256::from(self.ext.schedule().call_value_transfer_gas); | ||||||
| 			call_gas = call_gas + U256::from(self.ext.schedule().call_stipend); | 			call_gas = call_gas + U256::from(self.ext.schedule().call_stipend); | ||||||
| @ -211,7 +220,7 @@ impl<'a> evmjit::Ext for ExtAdapter<'a> { | |||||||
| 		gas = gas - gas_cost; | 		gas = gas - gas_cost; | ||||||
| 
 | 
 | ||||||
| 		// check if balance is sufficient and we are not too deep
 | 		// 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 { | 		if self.ext.balance(&self.address) < transfer_value || self.ext.depth() >= self.ext.schedule().max_depth { | ||||||
| 			unsafe { | 			unsafe { | ||||||
| 				*io_gas = (gas + call_gas).low_u64(); | 				*io_gas = (gas + call_gas).low_u64(); | ||||||
| 				return false; | 				return false; | ||||||
| @ -220,9 +229,9 @@ impl<'a> evmjit::Ext for ExtAdapter<'a> { | |||||||
| 
 | 
 | ||||||
| 		match self.ext.call( | 		match self.ext.call( | ||||||
| 					  &call_gas, 
 | 					  &call_gas, 
 | ||||||
| 					  &self.address, | 					  &sender_address, | ||||||
| 					  &receive_address, 
 | 					  &receive_address, 
 | ||||||
| 					  Some(value), | 					  value, | ||||||
| 					  unsafe { slice::from_raw_parts(in_beg, in_size as usize) }, | 					  unsafe { slice::from_raw_parts(in_beg, in_size as usize) }, | ||||||
| 					  &code_address, | 					  &code_address, | ||||||
| 					  unsafe { slice::from_raw_parts_mut(out_beg, out_size as usize) }) { | 					  unsafe { slice::from_raw_parts_mut(out_beg, out_size as usize) }) { | ||||||
| @ -305,11 +314,20 @@ impl evm::Evm for JitEvm { | |||||||
| 		data.address = params.address.into_jit(); | 		data.address = params.address.into_jit(); | ||||||
| 		data.caller = params.sender.into_jit(); | 		data.caller = params.sender.into_jit(); | ||||||
| 		data.origin = params.origin.into_jit(); | 		data.origin = params.origin.into_jit(); | ||||||
| 		data.call_value = match params.value { | 		match params.value { | ||||||
| 			ActionValue::Transfer(val) => val.into_jit(), | 			ActionValue::Transfer(val) => { | ||||||
| 			ActionValue::Apparent(val) => val.into_jit() | 				data.transfer_value = val.into_jit(); | ||||||
|  | 				data.apparent_value = U256::zero().into_jit(); | ||||||
|  | 			}, | ||||||
|  | 			ActionValue::Apparent(val) => { | ||||||
|  | 				data.transfer_value = U256::zero().into_jit(); | ||||||
|  | 				data.apparent_value = val.into_jit(); | ||||||
|  | 			} | ||||||
| 		}; | 		}; | ||||||
| 
 | 
 | ||||||
|  | 		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.author = ext.env_info().author.clone().into_jit(); | ||||||
| 		data.difficulty = ext.env_info().difficulty.into_jit(); | 		data.difficulty = ext.env_info().difficulty.into_jit(); | ||||||
| 		data.gas_limit = ext.env_info().gas_limit.into_jit(); | 		data.gas_limit = ext.env_info().gas_limit.into_jit(); | ||||||
| @ -317,7 +335,7 @@ impl evm::Evm for JitEvm { | |||||||
| 		// don't really know why jit timestamp is int..
 | 		// don't really know why jit timestamp is int..
 | ||||||
| 		data.timestamp = ext.env_info().timestamp as i64; | 		data.timestamp = ext.env_info().timestamp as i64; | ||||||
| 
 | 
 | ||||||
| 		let mut context = unsafe { evmjit::ContextHandle::new(data, &mut ext_handle) }; | 		let mut context = unsafe { evmjit::ContextHandle::new(data, schedule, &mut ext_handle) }; | ||||||
| 		let res = context.exec(); | 		let res = context.exec(); | ||||||
| 		
 | 		
 | ||||||
| 		match res { | 		match res { | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| [package] | [package] | ||||||
| name = "evmjit" | name = "evmjit" | ||||||
| version = "0.1.0" | version = "0.9.0" | ||||||
| authors = ["debris <marek.kotewicz@gmail.com>"] | authors = ["debris <marek.kotewicz@gmail.com>"] | ||||||
| 
 | 
 | ||||||
| [lib] | [lib] | ||||||
|  | |||||||
| @ -42,10 +42,10 @@ pub use self::ffi::JitReturnCode as ReturnCode; | |||||||
| pub use self::ffi::JitI256 as I256; | pub use self::ffi::JitI256 as I256; | ||||||
| pub use self::ffi::JitH256 as H256; | pub use self::ffi::JitH256 as H256; | ||||||
| 
 | 
 | ||||||
| /// Takes care of  proper initialization and destruction of `RuntimeData`.
 | /// Takes care of proper initialization and destruction of `RuntimeData`.
 | ||||||
| ///
 | ///
 | ||||||
| /// This handle must be used to create runtime data,
 | /// This handle must be used to create runtime data,
 | ||||||
| /// cause underneath it's a `C++` structure. Incombatible with rust
 | /// cause underneath it's a `C++` structure. Incompatible with rust
 | ||||||
| /// structs.
 | /// structs.
 | ||||||
| pub struct RuntimeDataHandle { | pub struct RuntimeDataHandle { | ||||||
| 	runtime_data: *mut JitRuntimeData | 	runtime_data: *mut JitRuntimeData | ||||||
| @ -58,16 +58,6 @@ impl RuntimeDataHandle { | |||||||
| 			runtime_data: unsafe { evmjit_create_runtime_data() } | 			runtime_data: unsafe { evmjit_create_runtime_data() } | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 	/// Returns immutable reference to runtime data.
 |  | ||||||
| 	pub fn runtime_data(&self) -> &JitRuntimeData { |  | ||||||
| 		unsafe { &*self.runtime_data } |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	/// Returns mutable reference to runtime data.
 |  | ||||||
| 	pub fn mut_runtime_data(&mut self) -> &mut JitRuntimeData { |  | ||||||
| 		unsafe { &mut *self.runtime_data } |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Drop for RuntimeDataHandle { | impl Drop for RuntimeDataHandle { | ||||||
| @ -80,13 +70,51 @@ impl Deref for RuntimeDataHandle { | |||||||
| 	type Target = JitRuntimeData; | 	type Target = JitRuntimeData; | ||||||
| 
 | 
 | ||||||
| 	fn deref(&self) -> &Self::Target { | 	fn deref(&self) -> &Self::Target { | ||||||
| 		self.runtime_data() | 		unsafe { &*self.runtime_data } | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl DerefMut for RuntimeDataHandle { | impl DerefMut for RuntimeDataHandle { | ||||||
| 	fn deref_mut(&mut self) -> &mut Self::Target { | 	fn deref_mut(&mut self) -> &mut Self::Target { | ||||||
| 		self.mut_runtime_data() | 		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 } | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -98,6 +126,7 @@ impl DerefMut for RuntimeDataHandle { | |||||||
| pub struct ContextHandle { | pub struct ContextHandle { | ||||||
| 	context: *mut JitContext, | 	context: *mut JitContext, | ||||||
| 	data_handle: RuntimeDataHandle, | 	data_handle: RuntimeDataHandle, | ||||||
|  | 	schedule_handle: ScheduleHandle | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl ContextHandle { | impl ContextHandle { | ||||||
| @ -107,19 +136,20 @@ impl ContextHandle { | |||||||
| 	/// We also can't make ExtHandle a member of `ContextHandle` structure,
 | 	/// We also can't make ExtHandle a member of `ContextHandle` structure,
 | ||||||
| 	/// cause this would be a move operation or it would require a template 
 | 	/// cause this would be a move operation or it would require a template 
 | ||||||
| 	/// lifetime to a reference. Both solutions are not possible.
 | 	/// lifetime to a reference. Both solutions are not possible.
 | ||||||
| 	pub unsafe fn new(data_handle: RuntimeDataHandle, ext: &mut ExtHandle) -> Self { | 	pub unsafe fn new(data_handle: RuntimeDataHandle, schedule_handle: ScheduleHandle, ext: &mut ExtHandle) -> Self { | ||||||
| 		let mut handle = ContextHandle { | 		let mut handle = ContextHandle { | ||||||
| 			context: std::mem::uninitialized(), | 			context: std::mem::uninitialized(), | ||||||
|  | 			schedule_handle: schedule_handle, | ||||||
| 			data_handle: data_handle, | 			data_handle: data_handle, | ||||||
| 		}; | 		}; | ||||||
| 
 | 
 | ||||||
| 		handle.context = evmjit_create_context(handle.data_handle.mut_runtime_data(), ext); | 		handle.context = evmjit_create_context(handle.data_handle.deref_mut(), ext); | ||||||
| 		handle | 		handle | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/// Executes context.
 | 	/// Executes context.
 | ||||||
| 	pub fn exec(&mut self) -> JitReturnCode { | 	pub fn exec(&mut self) -> JitReturnCode { | ||||||
| 		unsafe { evmjit_exec(self.context) } | 		unsafe { evmjit_exec(self.context, self.schedule_handle.deref_mut()) } | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/// Returns output data.
 | 	/// Returns output data.
 | ||||||
| @ -162,13 +192,15 @@ pub trait Ext { | |||||||
| 	fn call(&mut self, | 	fn call(&mut self, | ||||||
| 				io_gas: *mut u64, | 				io_gas: *mut u64, | ||||||
| 				call_gas: u64, | 				call_gas: u64, | ||||||
|  | 				sender_address: *const JitH256, | ||||||
| 				receive_address: *const JitH256, | 				receive_address: *const JitH256, | ||||||
| 				value: *const JitI256, | 				code_address: *const JitH256, | ||||||
|  | 				transfer_value: *const JitI256, | ||||||
|  | 				apparent_value: *const JitI256, | ||||||
| 				in_beg: *const u8, | 				in_beg: *const u8, | ||||||
| 				in_size: u64, | 				in_size: u64, | ||||||
| 				out_beg: *mut u8, | 				out_beg: *mut u8, | ||||||
| 				out_size: u64, | 				out_size: u64) -> bool; | ||||||
| 				code_address: *const JitH256) -> bool; |  | ||||||
| 
 | 
 | ||||||
| 	fn log(&mut self, | 	fn log(&mut self, | ||||||
| 		   beg: *const u8, | 		   beg: *const u8, | ||||||
| @ -292,7 +324,8 @@ pub mod ffi { | |||||||
| 		pub address: JitI256, | 		pub address: JitI256, | ||||||
| 		pub caller: JitI256, | 		pub caller: JitI256, | ||||||
| 		pub origin: JitI256, | 		pub origin: JitI256, | ||||||
| 		pub call_value: JitI256, | 		pub transfer_value: JitI256, | ||||||
|  | 		pub apparent_value: JitI256, | ||||||
| 		pub author: JitI256, | 		pub author: JitI256, | ||||||
| 		pub difficulty: JitI256, | 		pub difficulty: JitI256, | ||||||
| 		pub gas_limit: JitI256, | 		pub gas_limit: JitI256, | ||||||
| @ -303,6 +336,13 @@ pub mod ffi { | |||||||
| 		pub code_hash: JitI256 | 		pub code_hash: JitI256 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	#[repr(C)] | ||||||
|  | 	#[derive(Debug)] | ||||||
|  | 	/// Configurable properties of git schedule.
 | ||||||
|  | 	pub struct JitSchedule { | ||||||
|  | 		pub have_delegate_call: bool | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	#[no_mangle] | 	#[no_mangle] | ||||||
| 	pub unsafe extern "C" fn env_sload(ext: *const ExtHandle, index: *const JitI256, out_value: *mut JitI256) { | 	pub unsafe extern "C" fn env_sload(ext: *const ExtHandle, index: *const JitI256, out_value: *mut JitI256) { | ||||||
| 		let ext = &*ext; | 		let ext = &*ext; | ||||||
| @ -342,15 +382,17 @@ pub mod ffi { | |||||||
| 	pub unsafe extern "C" fn env_call(ext: *mut ExtHandle, 
 | 	pub unsafe extern "C" fn env_call(ext: *mut ExtHandle, 
 | ||||||
| 						   io_gas: *mut u64, | 						   io_gas: *mut u64, | ||||||
| 						   call_gas: u64, | 						   call_gas: u64, | ||||||
|  | 						   sender_address: *const JitH256, | ||||||
| 						   receive_address: *const JitH256, | 						   receive_address: *const JitH256, | ||||||
| 						   value: *const JitI256, | 						   code_address: *const JitH256, | ||||||
|  | 						   transfer_value: *const JitI256, | ||||||
|  | 						   apparent_value: *const JitI256, | ||||||
| 						   in_beg: *const u8, | 						   in_beg: *const u8, | ||||||
| 						   in_size: u64, | 						   in_size: u64, | ||||||
| 						   out_beg: *mut u8, | 						   out_beg: *mut u8, | ||||||
| 						   out_size: u64, | 						   out_size: u64) -> bool { | ||||||
| 						   code_address: *const JitH256) -> bool { |  | ||||||
| 		let ext = &mut *ext; | 		let ext = &mut *ext; | ||||||
| 		ext.call(io_gas, call_gas, receive_address, value, in_beg, in_size, out_beg, out_size, code_address) | 		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] | 	#[no_mangle] | ||||||
| @ -385,10 +427,12 @@ pub mod ffi { | |||||||
| 
 | 
 | ||||||
| 	#[link(name="evmjit")] | 	#[link(name="evmjit")] | ||||||
| 	extern "C" { | 	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_create_runtime_data() -> *mut JitRuntimeData; | ||||||
| 		pub fn evmjit_destroy_runtime_data(data: *mut JitRuntimeData); | 		pub fn evmjit_destroy_runtime_data(data: *mut JitRuntimeData); | ||||||
| 		pub fn evmjit_destroy_context(context: *mut JitContext); | 		pub fn evmjit_destroy_context(context: *mut JitContext); | ||||||
| 		pub fn evmjit_exec(context: *mut JitContext) -> JitReturnCode; | 		pub fn evmjit_exec(context: *mut JitContext, schedule: *mut JitSchedule) -> JitReturnCode; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// ExtHandle is not a C type, so we need to allow "improper_ctypes" 
 | 	// ExtHandle is not a C type, so we need to allow "improper_ctypes" 
 | ||||||
| @ -403,11 +447,13 @@ pub mod ffi { | |||||||
| fn ffi_test() { | fn ffi_test() { | ||||||
| 	unsafe { | 	unsafe { | ||||||
| 		let data = evmjit_create_runtime_data(); | 		let data = evmjit_create_runtime_data(); | ||||||
|  | 		let schedule = evmjit_create_schedule(); | ||||||
| 		let context = evmjit_create_context(data, &mut ExtHandle::empty()); | 		let context = evmjit_create_context(data, &mut ExtHandle::empty()); | ||||||
| 
 | 
 | ||||||
| 		let code = evmjit_exec(context); | 		let code = evmjit_exec(context, schedule); | ||||||
| 		assert_eq!(code, JitReturnCode::Stop); | 		assert_eq!(code, JitReturnCode::Stop); | ||||||
| 
 | 
 | ||||||
|  | 		evmjit_destroy_schedule(schedule); | ||||||
| 		evmjit_destroy_runtime_data(data); | 		evmjit_destroy_runtime_data(data); | ||||||
| 		evmjit_destroy_context(context); | 		evmjit_destroy_context(context); | ||||||
| 	} | 	} | ||||||
| @ -416,7 +462,8 @@ fn ffi_test() { | |||||||
| #[test] | #[test] | ||||||
| fn handle_test() { | fn handle_test() { | ||||||
| 	unsafe { | 	unsafe { | ||||||
| 		let mut context = ContextHandle::new(RuntimeDataHandle::new(), &mut ExtHandle::empty()); | 		let mut ext = ExtHandle::empty(); | ||||||
|  | 		let mut context = ContextHandle::new(RuntimeDataHandle::new(), ScheduleHandle::new(), &mut ext); | ||||||
| 		assert_eq!(context.exec(), ReturnCode::Stop); | 		assert_eq!(context.exec(), ReturnCode::Stop); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user