ext call refactored
This commit is contained in:
		
							parent
							
								
									777ac4dc87
								
							
						
					
					
						commit
						6fb580f621
					
				@ -6,6 +6,20 @@ use util::bytes::*;
 | 
				
			|||||||
use evm::{Schedule, Error};
 | 
					use evm::{Schedule, Error};
 | 
				
			||||||
use env_info::*;
 | 
					use env_info::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct CallResult {
 | 
				
			||||||
 | 
						pub gas_left: U256,
 | 
				
			||||||
 | 
						pub success: bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl CallResult {
 | 
				
			||||||
 | 
						pub fn new(gas_left: U256, success: bool) -> Self {
 | 
				
			||||||
 | 
							CallResult {
 | 
				
			||||||
 | 
								gas_left: gas_left,
 | 
				
			||||||
 | 
								success: success
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub trait Ext {
 | 
					pub trait Ext {
 | 
				
			||||||
	/// Returns a value for given key.
 | 
						/// Returns a value for given key.
 | 
				
			||||||
	fn sload(&self, key: &H256) -> H256;
 | 
						fn sload(&self, key: &H256) -> H256;
 | 
				
			||||||
@ -26,8 +40,9 @@ pub trait Ext {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	/// Message call.
 | 
						/// Message call.
 | 
				
			||||||
	/// 
 | 
						/// 
 | 
				
			||||||
	/// If call is successfull, returns gas left.
 | 
						/// Returns None, if we run out of gas.
 | 
				
			||||||
	/// otherwise `Error`.
 | 
						/// Otherwise returns call_result which contains gas left 
 | 
				
			||||||
 | 
						/// and true if subcall was successfull.
 | 
				
			||||||
	fn call(&mut self, 
 | 
						fn call(&mut self, 
 | 
				
			||||||
			gas: &U256, 
 | 
								gas: &U256, 
 | 
				
			||||||
			call_gas: &U256, 
 | 
								call_gas: &U256, 
 | 
				
			||||||
@ -35,7 +50,7 @@ pub trait Ext {
 | 
				
			|||||||
			value: &U256, 
 | 
								value: &U256, 
 | 
				
			||||||
			data: &[u8], 
 | 
								data: &[u8], 
 | 
				
			||||||
			code_address: &Address, 
 | 
								code_address: &Address, 
 | 
				
			||||||
			output: &mut [u8]) -> Result<U256, Error>;
 | 
								output: &mut [u8]) -> Option<CallResult>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// Returns code at given address
 | 
						/// Returns code at given address
 | 
				
			||||||
	fn extcode(&self, address: &Address) -> Vec<u8>;
 | 
						fn extcode(&self, address: &Address) -> Vec<u8>;
 | 
				
			||||||
 | 
				
			|||||||
@ -229,30 +229,21 @@ impl<'a> evmjit::Ext for ExtAdapter<'a> {
 | 
				
			|||||||
				out_size: u64,
 | 
									out_size: u64,
 | 
				
			||||||
				code_address: *const evmjit::H256) -> bool {
 | 
									code_address: *const evmjit::H256) -> bool {
 | 
				
			||||||
		unsafe {
 | 
							unsafe {
 | 
				
			||||||
			let res = self.ext.call(&U256::from(*io_gas), 
 | 
								let opt = self.ext.call(&U256::from(*io_gas), 
 | 
				
			||||||
									&U256::from(call_gas), 
 | 
														&U256::from(call_gas), 
 | 
				
			||||||
									&Address::from_jit(&*receive_address),
 | 
														&Address::from_jit(&*receive_address),
 | 
				
			||||||
									&U256::from_jit(&*value),
 | 
														&U256::from_jit(&*value),
 | 
				
			||||||
									slice::from_raw_parts(in_beg, in_size as usize),
 | 
														slice::from_raw_parts(in_beg, in_size as usize),
 | 
				
			||||||
									&Address::from_jit(&*code_address),
 | 
														&Address::from_jit(&*code_address),
 | 
				
			||||||
									slice::from_raw_parts_mut(out_beg, out_size as usize));
 | 
														slice::from_raw_parts_mut(out_beg, out_size as usize));
 | 
				
			||||||
 | 
								match opt {
 | 
				
			||||||
			match res {
 | 
									None => {
 | 
				
			||||||
				Ok(gas_left) => {
 | 
					 | 
				
			||||||
					*io_gas = gas_left.low_u64();
 | 
					 | 
				
			||||||
					true
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
				Err(err @ evm::Error::OutOfGas) => {
 | 
					 | 
				
			||||||
					*self.err = Some(err);
 | 
					 | 
				
			||||||
					// hack to propagate `OutOfGas` to evmjit and stop
 | 
					 | 
				
			||||||
					// the execution immediately.
 | 
					 | 
				
			||||||
					// Works, cause evmjit uses i64, not u64
 | 
					 | 
				
			||||||
					*io_gas = -1i64 as u64;
 | 
										*io_gas = -1i64 as u64;
 | 
				
			||||||
					false
 | 
										false
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
				Err(err) => {
 | 
									Some(res) => {
 | 
				
			||||||
					*self.err = Some(err);
 | 
										*io_gas = res.gas_left.low_u64();
 | 
				
			||||||
					false
 | 
										res.success
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
				
			|||||||
@ -11,6 +11,6 @@ mod jit;
 | 
				
			|||||||
mod tests;
 | 
					mod tests;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub use self::evm::{Evm, Error, Result};
 | 
					pub use self::evm::{Evm, Error, Result};
 | 
				
			||||||
pub use self::ext::Ext;
 | 
					pub use self::ext::{Ext, CallResult};
 | 
				
			||||||
pub use self::factory::Factory;
 | 
					pub use self::factory::Factory;
 | 
				
			||||||
pub use self::schedule::Schedule;
 | 
					pub use self::schedule::Schedule;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
use common::*;
 | 
					use common::*;
 | 
				
			||||||
use evm;
 | 
					use evm;
 | 
				
			||||||
use evm::{Ext, Schedule, Factory};
 | 
					use evm::{Ext, Schedule, Factory, CallResult};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct FakeLogEntry {
 | 
					struct FakeLogEntry {
 | 
				
			||||||
	topics: Vec<H256>,
 | 
						topics: Vec<H256>,
 | 
				
			||||||
@ -53,7 +53,7 @@ impl Ext for FakeExt {
 | 
				
			|||||||
			_value: &U256, 
 | 
								_value: &U256, 
 | 
				
			||||||
			_data: &[u8], 
 | 
								_data: &[u8], 
 | 
				
			||||||
			_code_address: &Address, 
 | 
								_code_address: &Address, 
 | 
				
			||||||
			_output: &mut [u8]) -> result::Result<U256, evm::Error> {
 | 
								_output: &mut [u8]) -> Option<CallResult> {
 | 
				
			||||||
		unimplemented!();
 | 
							unimplemented!();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,7 @@
 | 
				
			|||||||
use common::*;
 | 
					use common::*;
 | 
				
			||||||
use state::*;
 | 
					use state::*;
 | 
				
			||||||
use engine::*;
 | 
					use engine::*;
 | 
				
			||||||
use evm::{self, Schedule, Factory, Ext};
 | 
					use evm::{self, Schedule, Factory, Ext, CallResult};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Returns new address created from address and given nonce.
 | 
					/// Returns new address created from address and given nonce.
 | 
				
			||||||
pub fn contract_address(address: &Address, nonce: &U256) -> Address {
 | 
					pub fn contract_address(address: &Address, nonce: &U256) -> Address {
 | 
				
			||||||
@ -38,6 +38,8 @@ impl Substate {
 | 
				
			|||||||
			contracts_created: vec![]
 | 
								contracts_created: vec![]
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pub fn out_of_gas(&self) -> bool { self.out_of_gas }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Transaction execution receipt.
 | 
					/// Transaction execution receipt.
 | 
				
			||||||
@ -207,7 +209,8 @@ impl<'a> Executive<'a> {
 | 
				
			|||||||
				let evm = Factory::create();
 | 
									let evm = Factory::create();
 | 
				
			||||||
				evm.exec(¶ms, &mut ext)
 | 
									evm.exec(¶ms, &mut ext)
 | 
				
			||||||
			};
 | 
								};
 | 
				
			||||||
			self.handle_out_of_gas(res, substate, backup)
 | 
								self.revert_if_needed(&res, substate, backup);
 | 
				
			||||||
 | 
								res
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			// otherwise, nothing
 | 
								// otherwise, nothing
 | 
				
			||||||
			Ok(params.gas)
 | 
								Ok(params.gas)
 | 
				
			||||||
@ -232,7 +235,8 @@ impl<'a> Executive<'a> {
 | 
				
			|||||||
			let evm = Factory::create();
 | 
								let evm = Factory::create();
 | 
				
			||||||
			evm.exec(¶ms, &mut ext)
 | 
								evm.exec(¶ms, &mut ext)
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
		self.handle_out_of_gas(res, substate, backup)
 | 
							self.revert_if_needed(&res, substate, backup);
 | 
				
			||||||
 | 
							res
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// Finalizes the transaction (does refunds and suicides).
 | 
						/// Finalizes the transaction (does refunds and suicides).
 | 
				
			||||||
@ -278,12 +282,11 @@ impl<'a> Executive<'a> {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pub fn handle_out_of_gas(&mut self, result: evm::Result, substate: &mut Substate, backup: State) -> evm::Result {
 | 
						pub fn revert_if_needed(&mut self, result: &evm::Result, substate: &mut Substate, backup: State) {
 | 
				
			||||||
		if let &Err(evm::Error::OutOfGas) = &result {
 | 
							if let &Err(evm::Error::OutOfGas) = result {
 | 
				
			||||||
			substate.out_of_gas = true;
 | 
								substate.out_of_gas = true;
 | 
				
			||||||
			self.state.revert(backup);
 | 
								self.state.revert(backup);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		result
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -398,7 +401,14 @@ impl<'a> Ext for Externalities<'a> {
 | 
				
			|||||||
		//ex.create(¶ms, self.substate).map(|gas_left| (gas_left, Some(address)))
 | 
							//ex.create(¶ms, self.substate).map(|gas_left| (gas_left, Some(address)))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn call(&mut self, gas: &U256, call_gas: &U256, receive_address: &Address, value: &U256, data: &[u8], code_address: &Address, output: &mut [u8]) -> Result<U256, evm::Error> {
 | 
						fn call(&mut self, 
 | 
				
			||||||
 | 
								gas: &U256, 
 | 
				
			||||||
 | 
								call_gas: &U256, 
 | 
				
			||||||
 | 
								receive_address: &Address, 
 | 
				
			||||||
 | 
								value: &U256, 
 | 
				
			||||||
 | 
								data: &[u8], 
 | 
				
			||||||
 | 
								code_address: &Address, 
 | 
				
			||||||
 | 
								output: &mut [u8]) -> Option<CallResult> {
 | 
				
			||||||
		let mut gas_cost = *call_gas;
 | 
							let mut gas_cost = *call_gas;
 | 
				
			||||||
		let mut call_gas = *call_gas;
 | 
							let mut call_gas = *call_gas;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -414,14 +424,17 @@ impl<'a> Ext for Externalities<'a> {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if gas_cost > *gas {
 | 
							if gas_cost > *gas {
 | 
				
			||||||
			return Err(evm::Error::OutOfGas)
 | 
								self.substate.out_of_gas = true;
 | 
				
			||||||
 | 
								return None;
 | 
				
			||||||
 | 
								//return (U256::from(-1i64 as u64), false);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let gas = *gas - gas_cost;
 | 
							let gas = *gas - gas_cost;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// if balance is insufficient or we are to deep, return
 | 
							// if balance is insufficient or we are to deep, return
 | 
				
			||||||
		if self.state.balance(&self.params.address) < *value || self.depth >= self.schedule.max_depth {
 | 
							if self.state.balance(&self.params.address) < *value || self.depth >= self.schedule.max_depth {
 | 
				
			||||||
			return Ok(gas + call_gas)
 | 
								return Some(CallResult::new(gas + call_gas, true));
 | 
				
			||||||
 | 
								//return (gas + call_gas, true);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let params = ActionParams {
 | 
							let params = ActionParams {
 | 
				
			||||||
@ -436,7 +449,14 @@ impl<'a> Ext for Externalities<'a> {
 | 
				
			|||||||
		};
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let mut ex = Executive::from_parent(self.state, self.info, self.engine, self.depth);
 | 
							let mut ex = Executive::from_parent(self.state, self.info, self.engine, self.depth);
 | 
				
			||||||
		ex.call(¶ms, self.substate, BytesRef::Fixed(output)).map(|gas_left| gas + gas_left)
 | 
							match ex.call(¶ms, self.substate, BytesRef::Fixed(output)) {
 | 
				
			||||||
 | 
								Ok(gas_left) => Some(CallResult::new(gas + gas_left, true)),
 | 
				
			||||||
 | 
								_ => {
 | 
				
			||||||
 | 
									self.substate.out_of_gas = true;
 | 
				
			||||||
 | 
									Some(CallResult::new(gas, false))
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							//ex.call(¶ms, self.substate, BytesRef::Fixed(output)).map(|gas_left| gas + gas_left)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn extcode(&self, address: &Address) -> Vec<u8> {
 | 
						fn extcode(&self, address: &Address) -> Vec<u8> {
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,7 @@ use executive::*;
 | 
				
			|||||||
use spec::*;
 | 
					use spec::*;
 | 
				
			||||||
use engine::*;
 | 
					use engine::*;
 | 
				
			||||||
use evm;
 | 
					use evm;
 | 
				
			||||||
use evm::{Schedule, Ext, Factory};
 | 
					use evm::{Schedule, Ext, Factory, CallResult};
 | 
				
			||||||
use ethereum;
 | 
					use ethereum;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct TestEngine {
 | 
					struct TestEngine {
 | 
				
			||||||
@ -110,22 +110,21 @@ impl<'a> Ext for TestExt<'a> {
 | 
				
			|||||||
			value: &U256, 
 | 
								value: &U256, 
 | 
				
			||||||
			data: &[u8], 
 | 
								data: &[u8], 
 | 
				
			||||||
			code_address: &Address, 
 | 
								code_address: &Address, 
 | 
				
			||||||
			output: &mut [u8]) -> Result<U256, evm::Error> {
 | 
								output: &mut [u8]) -> Option<CallResult> {
 | 
				
			||||||
		let res = self.ext.call(gas, call_gas, receive_address, value, data, code_address, output);
 | 
							let opt = self.ext.call(gas, call_gas, receive_address, value, data, code_address, output);
 | 
				
			||||||
		let ext = &self.ext;
 | 
							let ext = &self.ext;
 | 
				
			||||||
		match res {
 | 
							if let &Some(_) = &opt {
 | 
				
			||||||
			Ok(gas_left) if ext.state.balance(&ext.params.address) >= *value => {
 | 
								if ext.state.balance(&ext.params.address) >= *value {
 | 
				
			||||||
				self.callcreates.push(CallCreate {
 | 
									self.callcreates.push(CallCreate {
 | 
				
			||||||
					data: data.to_vec(),
 | 
										data: data.to_vec(),
 | 
				
			||||||
					destination: receive_address.clone(),
 | 
										destination: receive_address.clone(),
 | 
				
			||||||
					_gas_limit: *call_gas,
 | 
										_gas_limit: *call_gas,
 | 
				
			||||||
					value: *value
 | 
										value: *value
 | 
				
			||||||
				});
 | 
									});
 | 
				
			||||||
				Ok(gas_left)
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			other => other
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							opt
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn extcode(&self, address: &Address) -> Vec<u8> {
 | 
						fn extcode(&self, address: &Address) -> Vec<u8> {
 | 
				
			||||||
		self.ext.extcode(address)
 | 
							self.ext.extcode(address)
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user