return errors on database corruption
This commit is contained in:
		
							parent
							
								
									636b2deb2e
								
							
						
					
					
						commit
						3655601693
					
				| @ -540,7 +540,8 @@ pub fn enact( | |||||||
| 	{ | 	{ | ||||||
| 		if ::log::max_log_level() >= ::log::LogLevel::Trace { | 		if ::log::max_log_level() >= ::log::LogLevel::Trace { | ||||||
| 			let s = State::from_existing(db.boxed_clone(), parent.state_root().clone(), engine.account_start_nonce(), factories.clone())?; | 			let s = State::from_existing(db.boxed_clone(), parent.state_root().clone(), engine.account_start_nonce(), factories.clone())?; | ||||||
| 			trace!(target: "enact", "num={}, root={}, author={}, author_balance={}\n", header.number(), s.root(), header.author(), s.balance(&header.author())); | 			trace!(target: "enact", "num={}, root={}, author={}, author_balance={}\n", | ||||||
|  | 				header.number(), s.root(), header.author(), s.balance(&header.author())?); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -890,17 +890,20 @@ impl BlockChainClient for Client { | |||||||
| 		let original_state = if analytics.state_diffing { Some(state.clone()) } else { None }; | 		let original_state = if analytics.state_diffing { Some(state.clone()) } else { None }; | ||||||
| 
 | 
 | ||||||
| 		let sender = t.sender(); | 		let sender = t.sender(); | ||||||
| 		let balance = state.balance(&sender); | 		let balance = state.balance(&sender).map_err(|_| CallError::StateCorrupt)?; | ||||||
| 		let needed_balance = t.value + t.gas * t.gas_price; | 		let needed_balance = t.value + t.gas * t.gas_price; | ||||||
| 		if balance < needed_balance { | 		if balance < needed_balance { | ||||||
| 			// give the sender a sufficient balance
 | 			// give the sender a sufficient balance
 | ||||||
| 			state.add_balance(&sender, &(needed_balance - balance), CleanupMode::NoEmpty); | 			state.add_balance(&sender, &(needed_balance - balance), CleanupMode::NoEmpty) | ||||||
|  | 				.map_err(|_| CallError::StateCorrupt)?; | ||||||
| 		} | 		} | ||||||
| 		let options = TransactOptions { tracing: analytics.transaction_tracing, vm_tracing: analytics.vm_tracing, check_nonce: false }; | 		let options = TransactOptions { tracing: analytics.transaction_tracing, vm_tracing: analytics.vm_tracing, check_nonce: false }; | ||||||
| 		let mut ret = Executive::new(&mut state, &env_info, &*self.engine, &self.factories.vm).transact(t, options)?; | 		let mut ret = Executive::new(&mut state, &env_info, &*self.engine, &self.factories.vm).transact(t, options)?; | ||||||
| 
 | 
 | ||||||
| 		// TODO gav move this into Executive.
 | 		// TODO gav move this into Executive.
 | ||||||
| 		ret.state_diff = original_state.map(|original| state.diff_from(original)); | 		if let Some(original) = original_state { | ||||||
|  | 			ret.state_diff = Some(state.diff_from(original).map_err(ExecutionError::from)?); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		Ok(ret) | 		Ok(ret) | ||||||
| 	} | 	} | ||||||
| @ -921,7 +924,7 @@ impl BlockChainClient for Client { | |||||||
| 		// that's just a copy of the state.
 | 		// that's just a copy of the state.
 | ||||||
| 		let original_state = self.state_at(block).ok_or(CallError::StatePruned)?; | 		let original_state = self.state_at(block).ok_or(CallError::StatePruned)?; | ||||||
| 		let sender = t.sender(); | 		let sender = t.sender(); | ||||||
| 		let balance = original_state.balance(&sender); | 		let balance = original_state.balance(&sender).map_err(ExecutionError::from)?; | ||||||
| 		let options = TransactOptions { tracing: true, vm_tracing: false, check_nonce: false }; | 		let options = TransactOptions { tracing: true, vm_tracing: false, check_nonce: false }; | ||||||
| 
 | 
 | ||||||
| 		let cond = |gas| { | 		let cond = |gas| { | ||||||
| @ -933,27 +936,29 @@ impl BlockChainClient for Client { | |||||||
| 			let needed_balance = tx.value + tx.gas * tx.gas_price; | 			let needed_balance = tx.value + tx.gas * tx.gas_price; | ||||||
| 			if balance < needed_balance { | 			if balance < needed_balance { | ||||||
| 				// give the sender a sufficient balance
 | 				// give the sender a sufficient balance
 | ||||||
| 				state.add_balance(&sender, &(needed_balance - balance), CleanupMode::NoEmpty); | 				state.add_balance(&sender, &(needed_balance - balance), CleanupMode::NoEmpty) | ||||||
|  | 					.map_err(ExecutionError::from)?; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			Executive::new(&mut state, &env_info, &*self.engine, &self.factories.vm) | 			Ok(Executive::new(&mut state, &env_info, &*self.engine, &self.factories.vm) | ||||||
| 				.transact(&tx, options.clone()) | 				.transact(&tx, options.clone()) | ||||||
| 				.map(|r| r.exception.is_none()) | 				.map(|r| r.exception.is_none()) | ||||||
| 				.unwrap_or(false) | 				.unwrap_or(false)) | ||||||
| 		}; | 		}; | ||||||
| 
 | 
 | ||||||
| 		let mut upper = header.gas_limit(); | 		let mut upper = header.gas_limit(); | ||||||
| 		if !cond(upper) { | 		if !cond(upper)? { | ||||||
| 			// impossible at block gas limit - try `UPPER_CEILING` instead.
 | 			// impossible at block gas limit - try `UPPER_CEILING` instead.
 | ||||||
| 			// TODO: consider raising limit by powers of two.
 | 			// TODO: consider raising limit by powers of two.
 | ||||||
| 			upper = UPPER_CEILING.into(); | 			upper = UPPER_CEILING.into(); | ||||||
| 			if !cond(upper) { | 			if !cond(upper)? { | ||||||
| 				trace!(target: "estimate_gas", "estimate_gas failed with {}", upper); | 				trace!(target: "estimate_gas", "estimate_gas failed with {}", upper); | ||||||
| 				return Err(CallError::Execution(ExecutionError::Internal)) | 				let err = ExecutionError::Internal(format!("Requires higher than upper limit of {}", upper)); | ||||||
|  | 				return Err(err.into()) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		let lower = t.gas_required(&self.engine.schedule(&env_info)).into(); | 		let lower = t.gas_required(&self.engine.schedule(&env_info)).into(); | ||||||
| 		if cond(lower) { | 		if cond(lower)? { | ||||||
| 			trace!(target: "estimate_gas", "estimate_gas succeeded with {}", lower); | 			trace!(target: "estimate_gas", "estimate_gas succeeded with {}", lower); | ||||||
| 			return Ok(lower) | 			return Ok(lower) | ||||||
| 		} | 		} | ||||||
| @ -961,23 +966,25 @@ impl BlockChainClient for Client { | |||||||
| 		/// Find transition point between `lower` and `upper` where `cond` changes from `false` to `true`.
 | 		/// Find transition point between `lower` and `upper` where `cond` changes from `false` to `true`.
 | ||||||
| 		/// Returns the lowest value between `lower` and `upper` for which `cond` returns true.
 | 		/// Returns the lowest value between `lower` and `upper` for which `cond` returns true.
 | ||||||
| 		/// We assert: `cond(lower) = false`, `cond(upper) = true`
 | 		/// We assert: `cond(lower) = false`, `cond(upper) = true`
 | ||||||
| 		fn binary_chop<F>(mut lower: U256, mut upper: U256, mut cond: F) -> U256 where F: FnMut(U256) -> bool { | 		fn binary_chop<F, E>(mut lower: U256, mut upper: U256, mut cond: F) -> Result<U256, E> | ||||||
|  | 			where F: FnMut(U256) -> Result<bool, E> | ||||||
|  | 		{ | ||||||
| 			while upper - lower > 1.into() { | 			while upper - lower > 1.into() { | ||||||
| 				let mid = (lower + upper) / 2.into(); | 				let mid = (lower + upper) / 2.into(); | ||||||
| 				trace!(target: "estimate_gas", "{} .. {} .. {}", lower, mid, upper); | 				trace!(target: "estimate_gas", "{} .. {} .. {}", lower, mid, upper); | ||||||
| 				let c = cond(mid); | 				let c = cond(mid)?; | ||||||
| 				match c { | 				match c { | ||||||
| 					true => upper = mid, | 					true => upper = mid, | ||||||
| 					false => lower = mid, | 					false => lower = mid, | ||||||
| 				}; | 				}; | ||||||
| 				trace!(target: "estimate_gas", "{} => {} .. {}", c, lower, upper); | 				trace!(target: "estimate_gas", "{} => {} .. {}", c, lower, upper); | ||||||
| 			} | 			} | ||||||
| 			upper | 			Ok(upper) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// binary chop to non-excepting call with gas somewhere between 21000 and block gas limit
 | 		// binary chop to non-excepting call with gas somewhere between 21000 and block gas limit
 | ||||||
| 		trace!(target: "estimate_gas", "estimate_gas chopping {} .. {}", lower, upper); | 		trace!(target: "estimate_gas", "estimate_gas chopping {} .. {}", lower, upper); | ||||||
| 		Ok(binary_chop(lower, upper, cond)) | 		binary_chop(lower, upper, cond) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	fn replay(&self, id: TransactionId, analytics: CallAnalytics) -> Result<Executed, CallError> { | 	fn replay(&self, id: TransactionId, analytics: CallAnalytics) -> Result<Executed, CallError> { | ||||||
| @ -1006,17 +1013,16 @@ impl BlockChainClient for Client { | |||||||
| 		let rest = txs.split_off(address.index); | 		let rest = txs.split_off(address.index); | ||||||
| 		for t in txs { | 		for t in txs { | ||||||
| 			let t = SignedTransaction::new(t).expect(PROOF); | 			let t = SignedTransaction::new(t).expect(PROOF); | ||||||
| 			match Executive::new(&mut state, &env_info, &*self.engine, &self.factories.vm).transact(&t, Default::default()) { | 			let x = Executive::new(&mut state, &env_info, &*self.engine, &self.factories.vm).transact(&t, Default::default())?; | ||||||
| 				Ok(x) => { env_info.gas_used = env_info.gas_used + x.gas_used; } | 			env_info.gas_used = env_info.gas_used + x.gas_used; | ||||||
| 				Err(ee) => { return Err(CallError::Execution(ee)) } |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 		let first = rest.into_iter().next().expect("We split off < `address.index`; Length is checked earlier; qed"); | 		let first = rest.into_iter().next().expect("We split off < `address.index`; Length is checked earlier; qed"); | ||||||
| 		let t = SignedTransaction::new(first).expect(PROOF); | 		let t = SignedTransaction::new(first).expect(PROOF); | ||||||
| 		let original_state = if analytics.state_diffing { Some(state.clone()) } else { None }; | 		let original_state = if analytics.state_diffing { Some(state.clone()) } else { None }; | ||||||
| 		let mut ret = Executive::new(&mut state, &env_info, &*self.engine, &self.factories.vm).transact(&t, options)?; | 		let mut ret = Executive::new(&mut state, &env_info, &*self.engine, &self.factories.vm).transact(&t, options)?; | ||||||
| 		ret.state_diff = original_state.map(|original| state.diff_from(original)); | 		if let Some(original) = original_state { | ||||||
| 
 | 			ret.state_diff = Some(state.diff_from(original).map_err(ExecutionError::from)?) | ||||||
|  | 		} | ||||||
| 		Ok(ret) | 		Ok(ret) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -1108,11 +1114,11 @@ impl BlockChainClient for Client { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	fn nonce(&self, address: &Address, id: BlockId) -> Option<U256> { | 	fn nonce(&self, address: &Address, id: BlockId) -> Option<U256> { | ||||||
| 		self.state_at(id).map(|s| s.nonce(address)) | 		self.state_at(id).and_then(|s| s.nonce(address).ok()) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	fn storage_root(&self, address: &Address, id: BlockId) -> Option<H256> { | 	fn storage_root(&self, address: &Address, id: BlockId) -> Option<H256> { | ||||||
| 		self.state_at(id).and_then(|s| s.storage_root(address)) | 		self.state_at(id).and_then(|s| s.storage_root(address).ok()).and_then(|x| x) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	fn block_hash(&self, id: BlockId) -> Option<H256> { | 	fn block_hash(&self, id: BlockId) -> Option<H256> { | ||||||
| @ -1121,15 +1127,15 @@ impl BlockChainClient for Client { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	fn code(&self, address: &Address, id: BlockId) -> Option<Option<Bytes>> { | 	fn code(&self, address: &Address, id: BlockId) -> Option<Option<Bytes>> { | ||||||
| 		self.state_at(id).map(|s| s.code(address).map(|c| (*c).clone())) | 		self.state_at(id).and_then(|s| s.code(address).ok()).map(|c| c.map(|c| (&*c).clone())) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	fn balance(&self, address: &Address, id: BlockId) -> Option<U256> { | 	fn balance(&self, address: &Address, id: BlockId) -> Option<U256> { | ||||||
| 		self.state_at(id).map(|s| s.balance(address)) | 		self.state_at(id).and_then(|s| s.balance(address).ok()) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	fn storage_at(&self, address: &Address, position: &H256, id: BlockId) -> Option<H256> { | 	fn storage_at(&self, address: &Address, position: &H256, id: BlockId) -> Option<H256> { | ||||||
| 		self.state_at(id).map(|s| s.storage_at(address, position)) | 		self.state_at(id).and_then(|s| s.storage_at(address, position).ok()) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	fn list_accounts(&self, id: BlockId, after: Option<&Address>, count: u64) -> Option<Vec<Address>> { | 	fn list_accounts(&self, id: BlockId, after: Option<&Address>, count: u64) -> Option<Vec<Address>> { | ||||||
| @ -1182,7 +1188,7 @@ impl BlockChainClient for Client { | |||||||
| 		}; | 		}; | ||||||
| 
 | 
 | ||||||
| 		let root = match state.storage_root(account) { | 		let root = match state.storage_root(account) { | ||||||
| 			Some(root) => root, | 			Ok(Some(root)) => root, | ||||||
| 			_ => return None, | 			_ => return None, | ||||||
| 		}; | 		}; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -215,8 +215,14 @@ impl Engine for Ethash { | |||||||
| //			if block.fields().header.gas_limit() <= 4_000_000.into() {
 | //			if block.fields().header.gas_limit() <= 4_000_000.into() {
 | ||||||
| 				let mut state = block.fields_mut().state; | 				let mut state = block.fields_mut().state; | ||||||
| 				for child in &self.ethash_params.dao_hardfork_accounts { | 				for child in &self.ethash_params.dao_hardfork_accounts { | ||||||
| 					let b = state.balance(child); | 					let beneficiary = &self.ethash_params.dao_hardfork_beneficiary; | ||||||
| 					state.transfer_balance(child, &self.ethash_params.dao_hardfork_beneficiary, &b, CleanupMode::NoEmpty); | 					let res = state.balance(child) | ||||||
|  | 						.and_then(|b| state.transfer_balance(child, beneficiary, &b, CleanupMode::NoEmpty)); | ||||||
|  | 
 | ||||||
|  | 					if let Err(e) = res { | ||||||
|  | 						warn!("Unable to apply DAO hardfork due to database corruption."); | ||||||
|  | 						warn!("Your node is now likely out of consensus."); | ||||||
|  | 					} | ||||||
| 				} | 				} | ||||||
| //			}
 | //			}
 | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -17,12 +17,12 @@ | |||||||
| //! Evm interface.
 | //! Evm interface.
 | ||||||
| 
 | 
 | ||||||
| use std::{ops, cmp, fmt}; | use std::{ops, cmp, fmt}; | ||||||
| use util::{U128, U256, U512, Uint}; | use util::{U128, U256, U512, Uint, trie}; | ||||||
| use action_params::ActionParams; | use action_params::ActionParams; | ||||||
| use evm::Ext; | use evm::Ext; | ||||||
| 
 | 
 | ||||||
| /// Evm errors.
 | /// Evm errors.
 | ||||||
| #[derive(Debug, Clone, Copy, PartialEq)] | #[derive(Debug, Clone, PartialEq)] | ||||||
| pub enum Error { | pub enum Error { | ||||||
| 	/// `OutOfGas` is returned when transaction execution runs out of gas.
 | 	/// `OutOfGas` is returned when transaction execution runs out of gas.
 | ||||||
| 	/// The state should be reverted to the state from before the
 | 	/// The state should be reverted to the state from before the
 | ||||||
| @ -61,8 +61,13 @@ pub enum Error { | |||||||
| 	}, | 	}, | ||||||
| 	/// Returned on evm internal error. Should never be ignored during development.
 | 	/// Returned on evm internal error. Should never be ignored during development.
 | ||||||
| 	/// Likely to cause consensus issues.
 | 	/// Likely to cause consensus issues.
 | ||||||
| 	#[allow(dead_code)] // created only by jit
 | 	Internal(String), | ||||||
| 	Internal, | } | ||||||
|  | 
 | ||||||
|  | impl From<Box<trie::TrieError>> for Error { | ||||||
|  | 	fn from(err: Box<trie::TrieError>) -> Self { | ||||||
|  | 		Error::Internal(format!("Internal error: {}", err)) | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl fmt::Display for Error { | impl fmt::Display for Error { | ||||||
| @ -74,7 +79,7 @@ impl fmt::Display for Error { | |||||||
| 			BadInstruction { .. } => "Bad instruction", | 			BadInstruction { .. } => "Bad instruction", | ||||||
| 			StackUnderflow { .. } => "Stack underflow", | 			StackUnderflow { .. } => "Stack underflow", | ||||||
| 			OutOfStack { .. } => "Out of stack", | 			OutOfStack { .. } => "Out of stack", | ||||||
| 			Internal => "Internal error", | 			Internal(ref msg) => msg, | ||||||
| 		}; | 		}; | ||||||
| 		message.fmt(f) | 		message.fmt(f) | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -42,24 +42,25 @@ pub enum MessageCallResult { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Externalities interface for EVMs
 | /// Externalities interface for EVMs
 | ||||||
|  | // TODO: [rob] associated error type instead of `trie::Result`. Not all EVMs are trie powered.
 | ||||||
| pub trait Ext { | pub trait Ext { | ||||||
| 	/// Returns a value for given key.
 | 	/// Returns a value for given key.
 | ||||||
| 	fn storage_at(&self, key: &H256) -> H256; | 	fn storage_at(&self, key: &H256) -> trie::Result<H256>; | ||||||
| 
 | 
 | ||||||
| 	/// Stores a value for given key.
 | 	/// Stores a value for given key.
 | ||||||
| 	fn set_storage(&mut self, key: H256, value: H256); | 	fn set_storage(&mut self, key: H256, value: H256) -> trie::Result<()>; | ||||||
| 
 | 
 | ||||||
| 	/// Determine whether an account exists.
 | 	/// Determine whether an account exists.
 | ||||||
| 	fn exists(&self, address: &Address) -> bool; | 	fn exists(&self, address: &Address) -> trie::Result<bool>; | ||||||
| 
 | 
 | ||||||
| 	/// Determine whether an account exists and is not null (zero balance/nonce, no code).
 | 	/// Determine whether an account exists and is not null (zero balance/nonce, no code).
 | ||||||
| 	fn exists_and_not_null(&self, address: &Address) -> bool; | 	fn exists_and_not_null(&self, address: &Address) -> trie::Result<bool>; | ||||||
| 
 | 
 | ||||||
| 	/// Balance of the origin account.
 | 	/// Balance of the origin account.
 | ||||||
| 	fn origin_balance(&self) -> U256; | 	fn origin_balance(&self) -> trie::Result<U256>; | ||||||
| 
 | 
 | ||||||
| 	/// Returns address balance.
 | 	/// Returns address balance.
 | ||||||
| 	fn balance(&self, address: &Address) -> U256; | 	fn balance(&self, address: &Address) -> trie::Result<U256>; | ||||||
| 
 | 
 | ||||||
| 	/// Returns the hash of one of the 256 most recent complete blocks.
 | 	/// Returns the hash of one of the 256 most recent complete blocks.
 | ||||||
| 	fn blockhash(&self, number: &U256) -> H256; | 	fn blockhash(&self, number: &U256) -> H256; | ||||||
| @ -87,10 +88,10 @@ pub trait Ext { | |||||||
| 	) -> MessageCallResult; | 	) -> MessageCallResult; | ||||||
| 
 | 
 | ||||||
| 	/// Returns code at given address
 | 	/// Returns code at given address
 | ||||||
| 	fn extcode(&self, address: &Address) -> Arc<Bytes>; | 	fn extcode(&self, address: &Address) -> trie::Result<Arc<Bytes>>; | ||||||
| 
 | 
 | ||||||
| 	/// Returns code size at given address
 | 	/// Returns code size at given address
 | ||||||
| 	fn extcodesize(&self, address: &Address) -> usize; | 	fn extcodesize(&self, address: &Address) -> trie::Result<usize>; | ||||||
| 
 | 
 | ||||||
| 	/// Creates log entry with given topics and data
 | 	/// Creates log entry with given topics and data
 | ||||||
| 	fn log(&mut self, topics: Vec<H256>, data: &[u8]); | 	fn log(&mut self, topics: Vec<H256>, data: &[u8]); | ||||||
| @ -101,7 +102,7 @@ pub trait Ext { | |||||||
| 
 | 
 | ||||||
| 	/// Should be called when contract commits suicide.
 | 	/// Should be called when contract commits suicide.
 | ||||||
| 	/// Address to which funds should be refunded.
 | 	/// Address to which funds should be refunded.
 | ||||||
| 	fn suicide(&mut self, refund_address: &Address); | 	fn suicide(&mut self, refund_address: &Address) -> trie::Result<()> ; | ||||||
| 
 | 
 | ||||||
| 	/// Returns schedule.
 | 	/// Returns schedule.
 | ||||||
| 	fn schedule(&self) -> &Schedule; | 	fn schedule(&self) -> &Schedule; | ||||||
|  | |||||||
| @ -123,7 +123,7 @@ impl<Gas: CostType> Gasometer<Gas> { | |||||||
| 			instructions::SSTORE => { | 			instructions::SSTORE => { | ||||||
| 				let address = H256::from(stack.peek(0)); | 				let address = H256::from(stack.peek(0)); | ||||||
| 				let newval = stack.peek(1); | 				let newval = stack.peek(1); | ||||||
| 				let val = U256::from(&*ext.storage_at(&address)); | 				let val = U256::from(&*ext.storage_at(&address)?); | ||||||
| 
 | 
 | ||||||
| 				let gas = if val.is_zero() && !newval.is_zero() { | 				let gas = if val.is_zero() && !newval.is_zero() { | ||||||
| 					schedule.sstore_set_gas | 					schedule.sstore_set_gas | ||||||
| @ -146,12 +146,12 @@ impl<Gas: CostType> Gasometer<Gas> { | |||||||
| 			instructions::SUICIDE => { | 			instructions::SUICIDE => { | ||||||
| 				let mut gas = Gas::from(schedule.suicide_gas); | 				let mut gas = Gas::from(schedule.suicide_gas); | ||||||
| 
 | 
 | ||||||
| 				let is_value_transfer = !ext.origin_balance().is_zero(); | 				let is_value_transfer = !ext.origin_balance()?.is_zero(); | ||||||
| 				let address = u256_to_address(stack.peek(0)); | 				let address = u256_to_address(stack.peek(0)); | ||||||
| 				if ( | 				if ( | ||||||
| 					!schedule.no_empty && !ext.exists(&address) | 					!schedule.no_empty && !ext.exists(&address)? | ||||||
| 				) || ( | 				) || ( | ||||||
| 					schedule.no_empty && is_value_transfer && !ext.exists_and_not_null(&address) | 					schedule.no_empty && is_value_transfer && !ext.exists_and_not_null(&address)? | ||||||
| 				) { | 				) { | ||||||
| 					gas = overflowing!(gas.overflow_add(schedule.suicide_to_new_account_cost.into())); | 					gas = overflowing!(gas.overflow_add(schedule.suicide_to_new_account_cost.into())); | ||||||
| 				} | 				} | ||||||
| @ -198,9 +198,9 @@ impl<Gas: CostType> Gasometer<Gas> { | |||||||
| 				let is_value_transfer = !stack.peek(2).is_zero(); | 				let is_value_transfer = !stack.peek(2).is_zero(); | ||||||
| 
 | 
 | ||||||
| 				if instruction == instructions::CALL && ( | 				if instruction == instructions::CALL && ( | ||||||
| 					(!schedule.no_empty && !ext.exists(&address)) | 					(!schedule.no_empty && !ext.exists(&address)?) | ||||||
| 					|| | 					|| | ||||||
| 					(schedule.no_empty && is_value_transfer && !ext.exists_and_not_null(&address)) | 					(schedule.no_empty && is_value_transfer && !ext.exists_and_not_null(&address)?) | ||||||
| 				) { | 				) { | ||||||
| 					gas = overflowing!(gas.overflow_add(schedule.call_new_account_gas.into())); | 					gas = overflowing!(gas.overflow_add(schedule.call_new_account_gas.into())); | ||||||
| 				} | 				} | ||||||
|  | |||||||
| @ -273,7 +273,7 @@ impl<Cost: CostType> Interpreter<Cost> { | |||||||
| 				let create_gas = provided.expect("`provided` comes through Self::exec from `Gasometer::get_gas_cost_mem`; `gas_gas_mem_cost` guarantees `Some` when instruction is `CALL`/`CALLCODE`/`DELEGATECALL`/`CREATE`; this is `CREATE`; qed"); | 				let create_gas = provided.expect("`provided` comes through Self::exec from `Gasometer::get_gas_cost_mem`; `gas_gas_mem_cost` guarantees `Some` when instruction is `CALL`/`CALLCODE`/`DELEGATECALL`/`CREATE`; this is `CREATE`; qed"); | ||||||
| 
 | 
 | ||||||
| 				let contract_code = self.mem.read_slice(init_off, init_size); | 				let contract_code = self.mem.read_slice(init_off, init_size); | ||||||
| 				let can_create = ext.balance(¶ms.address) >= endowment && ext.depth() < ext.schedule().max_depth; | 				let can_create = ext.balance(¶ms.address)? >= endowment && ext.depth() < ext.schedule().max_depth; | ||||||
| 
 | 
 | ||||||
| 				if !can_create { | 				if !can_create { | ||||||
| 					stack.push(U256::zero()); | 					stack.push(U256::zero()); | ||||||
| @ -319,11 +319,11 @@ impl<Cost: CostType> Interpreter<Cost> { | |||||||
| 				// Get sender & receive addresses, check if we have balance
 | 				// Get sender & receive addresses, check if we have balance
 | ||||||
| 				let (sender_address, receive_address, has_balance, call_type) = match instruction { | 				let (sender_address, receive_address, has_balance, call_type) = match instruction { | ||||||
| 					instructions::CALL => { | 					instructions::CALL => { | ||||||
| 						let has_balance = ext.balance(¶ms.address) >= value.expect("value set for all but delegate call; qed"); | 						let has_balance = ext.balance(¶ms.address)? >= value.expect("value set for all but delegate call; qed"); | ||||||
| 						(¶ms.address, &code_address, has_balance, CallType::Call) | 						(¶ms.address, &code_address, has_balance, CallType::Call) | ||||||
| 					}, | 					}, | ||||||
| 					instructions::CALLCODE => { | 					instructions::CALLCODE => { | ||||||
| 						let has_balance = ext.balance(¶ms.address) >= value.expect("value set for all but delegate call; qed"); | 						let has_balance = ext.balance(¶ms.address)? >= value.expect("value set for all but delegate call; qed"); | ||||||
| 						(¶ms.address, ¶ms.address, has_balance, CallType::CallCode) | 						(¶ms.address, ¶ms.address, has_balance, CallType::CallCode) | ||||||
| 					}, | 					}, | ||||||
| 					instructions::DELEGATECALL => (¶ms.sender, ¶ms.address, true, CallType::DelegateCall), | 					instructions::DELEGATECALL => (¶ms.sender, ¶ms.address, true, CallType::DelegateCall), | ||||||
| @ -366,7 +366,7 @@ impl<Cost: CostType> Interpreter<Cost> { | |||||||
| 			}, | 			}, | ||||||
| 			instructions::SUICIDE => { | 			instructions::SUICIDE => { | ||||||
| 				let address = stack.pop_back(); | 				let address = stack.pop_back(); | ||||||
| 				ext.suicide(&u256_to_address(&address)); | 				ext.suicide(&u256_to_address(&address))?; | ||||||
| 				return Ok(InstructionResult::StopExecution); | 				return Ok(InstructionResult::StopExecution); | ||||||
| 			}, | 			}, | ||||||
| 			instructions::LOG0...instructions::LOG4 => { | 			instructions::LOG0...instructions::LOG4 => { | ||||||
| @ -410,19 +410,19 @@ impl<Cost: CostType> Interpreter<Cost> { | |||||||
| 			}, | 			}, | ||||||
| 			instructions::SLOAD => { | 			instructions::SLOAD => { | ||||||
| 				let key = H256::from(&stack.pop_back()); | 				let key = H256::from(&stack.pop_back()); | ||||||
| 				let word = U256::from(&*ext.storage_at(&key)); | 				let word = U256::from(&*ext.storage_at(&key)?); | ||||||
| 				stack.push(word); | 				stack.push(word); | ||||||
| 			}, | 			}, | ||||||
| 			instructions::SSTORE => { | 			instructions::SSTORE => { | ||||||
| 				let address = H256::from(&stack.pop_back()); | 				let address = H256::from(&stack.pop_back()); | ||||||
| 				let val = stack.pop_back(); | 				let val = stack.pop_back(); | ||||||
| 
 | 
 | ||||||
| 				let current_val = U256::from(&*ext.storage_at(&address)); | 				let current_val = U256::from(&*ext.storage_at(&address)?); | ||||||
| 				// Increase refund for clear
 | 				// Increase refund for clear
 | ||||||
| 				if !self.is_zero(¤t_val) && self.is_zero(&val) { | 				if !self.is_zero(¤t_val) && self.is_zero(&val) { | ||||||
| 					ext.inc_sstore_clears(); | 					ext.inc_sstore_clears(); | ||||||
| 				} | 				} | ||||||
| 				ext.set_storage(address, H256::from(&val)); | 				ext.set_storage(address, H256::from(&val))?; | ||||||
| 			}, | 			}, | ||||||
| 			instructions::PC => { | 			instructions::PC => { | ||||||
| 				stack.push(U256::from(code.position - 1)); | 				stack.push(U256::from(code.position - 1)); | ||||||
| @ -438,7 +438,7 @@ impl<Cost: CostType> Interpreter<Cost> { | |||||||
| 			}, | 			}, | ||||||
| 			instructions::BALANCE => { | 			instructions::BALANCE => { | ||||||
| 				let address = u256_to_address(&stack.pop_back()); | 				let address = u256_to_address(&stack.pop_back()); | ||||||
| 				let balance = ext.balance(&address); | 				let balance = ext.balance(&address)?; | ||||||
| 				stack.push(balance); | 				stack.push(balance); | ||||||
| 			}, | 			}, | ||||||
| 			instructions::CALLER => { | 			instructions::CALLER => { | ||||||
| @ -474,7 +474,7 @@ impl<Cost: CostType> Interpreter<Cost> { | |||||||
| 			}, | 			}, | ||||||
| 			instructions::EXTCODESIZE => { | 			instructions::EXTCODESIZE => { | ||||||
| 				let address = u256_to_address(&stack.pop_back()); | 				let address = u256_to_address(&stack.pop_back()); | ||||||
| 				let len = ext.extcodesize(&address); | 				let len = ext.extcodesize(&address)?; | ||||||
| 				stack.push(U256::from(len)); | 				stack.push(U256::from(len)); | ||||||
| 			}, | 			}, | ||||||
| 			instructions::CALLDATACOPY => { | 			instructions::CALLDATACOPY => { | ||||||
| @ -485,7 +485,7 @@ impl<Cost: CostType> Interpreter<Cost> { | |||||||
| 			}, | 			}, | ||||||
| 			instructions::EXTCODECOPY => { | 			instructions::EXTCODECOPY => { | ||||||
| 				let address = u256_to_address(&stack.pop_back()); | 				let address = u256_to_address(&stack.pop_back()); | ||||||
| 				let code = ext.extcode(&address); | 				let code = ext.extcode(&address)?; | ||||||
| 				self.copy_data_to_memory(stack, &code); | 				self.copy_data_to_memory(stack, &code); | ||||||
| 			}, | 			}, | ||||||
| 			instructions::GASPRICE => { | 			instructions::GASPRICE => { | ||||||
|  | |||||||
| @ -123,7 +123,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { | |||||||
| 		mut vm_tracer: V | 		mut vm_tracer: V | ||||||
| 	) -> Result<Executed, ExecutionError> where T: Tracer, V: VMTracer { | 	) -> Result<Executed, ExecutionError> where T: Tracer, V: VMTracer { | ||||||
| 		let sender = t.sender(); | 		let sender = t.sender(); | ||||||
| 		let nonce = self.state.nonce(&sender); | 		let nonce = self.state.nonce(&sender)?; | ||||||
| 
 | 
 | ||||||
| 		let schedule = self.engine.schedule(self.info); | 		let schedule = self.engine.schedule(self.info); | ||||||
| 		let base_gas_required = U256::from(t.gas_required(&schedule)); | 		let base_gas_required = U256::from(t.gas_required(&schedule)); | ||||||
| @ -149,7 +149,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { | |||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// TODO: we might need bigints here, or at least check overflows.
 | 		// TODO: we might need bigints here, or at least check overflows.
 | ||||||
| 		let balance = self.state.balance(&sender); | 		let balance = self.state.balance(&sender)?; | ||||||
| 		let gas_cost = t.gas.full_mul(t.gas_price); | 		let gas_cost = t.gas.full_mul(t.gas_price); | ||||||
| 		let total_cost = U512::from(t.value) + gas_cost; | 		let total_cost = U512::from(t.value) + gas_cost; | ||||||
| 
 | 
 | ||||||
| @ -160,8 +160,8 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { | |||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// NOTE: there can be no invalid transactions from this point.
 | 		// NOTE: there can be no invalid transactions from this point.
 | ||||||
| 		self.state.inc_nonce(&sender); | 		self.state.inc_nonce(&sender)?; | ||||||
| 		self.state.sub_balance(&sender, &U256::from(gas_cost)); | 		self.state.sub_balance(&sender, &U256::from(gas_cost))?; | ||||||
| 
 | 
 | ||||||
| 		let mut substate = Substate::new(); | 		let mut substate = Substate::new(); | ||||||
| 
 | 
 | ||||||
| @ -192,8 +192,8 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { | |||||||
| 					gas: init_gas, | 					gas: init_gas, | ||||||
| 					gas_price: t.gas_price, | 					gas_price: t.gas_price, | ||||||
| 					value: ActionValue::Transfer(t.value), | 					value: ActionValue::Transfer(t.value), | ||||||
| 					code: self.state.code(address), | 					code: self.state.code(address)?, | ||||||
| 					code_hash: self.state.code_hash(address), | 					code_hash: self.state.code_hash(address)?, | ||||||
| 					data: Some(t.data.clone()), | 					data: Some(t.data.clone()), | ||||||
| 					call_type: CallType::Call, | 					call_type: CallType::Call, | ||||||
| 				}; | 				}; | ||||||
| @ -257,7 +257,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { | |||||||
| 
 | 
 | ||||||
| 		// at first, transfer value to destination
 | 		// at first, transfer value to destination
 | ||||||
| 		if let ActionValue::Transfer(val) = params.value { | 		if let ActionValue::Transfer(val) = params.value { | ||||||
| 			self.state.transfer_balance(¶ms.sender, ¶ms.address, &val, substate.to_cleanup_mode(&schedule)); | 			self.state.transfer_balance(¶ms.sender, ¶ms.address, &val, substate.to_cleanup_mode(&schedule))?; | ||||||
| 		} | 		} | ||||||
| 		trace!("Executive::call(params={:?}) self.env_info={:?}", params, self.info); | 		trace!("Executive::call(params={:?}) self.env_info={:?}", params, self.info); | ||||||
| 
 | 
 | ||||||
| @ -322,13 +322,13 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { | |||||||
| 
 | 
 | ||||||
| 				let traces = subtracer.traces(); | 				let traces = subtracer.traces(); | ||||||
| 				match res { | 				match res { | ||||||
| 					Ok(gas_left) => tracer.trace_call( | 					Ok(ref gas_left) => tracer.trace_call( | ||||||
| 						trace_info, | 						trace_info, | ||||||
| 						gas - gas_left, | 						gas - *gas_left, | ||||||
| 						trace_output, | 						trace_output, | ||||||
| 						traces | 						traces | ||||||
| 					), | 					), | ||||||
| 					Err(e) => tracer.trace_failed_call(trace_info, traces, e.into()), | 					Err(ref e) => tracer.trace_failed_call(trace_info, traces, e.into()), | ||||||
| 				}; | 				}; | ||||||
| 
 | 
 | ||||||
| 				trace!(target: "executive", "substate={:?}; unconfirmed_substate={:?}\n", substate, unconfirmed_substate); | 				trace!(target: "executive", "substate={:?}; unconfirmed_substate={:?}\n", substate, unconfirmed_substate); | ||||||
| @ -365,9 +365,9 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { | |||||||
| 		// create contract and transfer value to it if necessary
 | 		// create contract and transfer value to it if necessary
 | ||||||
| 		let schedule = self.engine.schedule(self.info); | 		let schedule = self.engine.schedule(self.info); | ||||||
| 		let nonce_offset = if schedule.no_empty {1} else {0}.into(); | 		let nonce_offset = if schedule.no_empty {1} else {0}.into(); | ||||||
| 		let prev_bal = self.state.balance(¶ms.address); | 		let prev_bal = self.state.balance(¶ms.address)?; | ||||||
| 		if let ActionValue::Transfer(val) = params.value { | 		if let ActionValue::Transfer(val) = params.value { | ||||||
| 			self.state.sub_balance(¶ms.sender, &val); | 			self.state.sub_balance(¶ms.sender, &val)?; | ||||||
| 			self.state.new_contract(¶ms.address, val + prev_bal, nonce_offset); | 			self.state.new_contract(¶ms.address, val + prev_bal, nonce_offset); | ||||||
| 		} else { | 		} else { | ||||||
| 			self.state.new_contract(¶ms.address, prev_bal, nonce_offset); | 			self.state.new_contract(¶ms.address, prev_bal, nonce_offset); | ||||||
| @ -388,14 +388,14 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { | |||||||
| 		vm_tracer.done_subtrace(subvmtracer); | 		vm_tracer.done_subtrace(subvmtracer); | ||||||
| 
 | 
 | ||||||
| 		match res { | 		match res { | ||||||
| 			Ok(gas_left) => tracer.trace_create( | 			Ok(ref gas_left) => tracer.trace_create( | ||||||
| 				trace_info, | 				trace_info, | ||||||
| 				gas - gas_left, | 				gas - *gas_left, | ||||||
| 				trace_output, | 				trace_output, | ||||||
| 				created, | 				created, | ||||||
| 				subtracer.traces() | 				subtracer.traces() | ||||||
| 			), | 			), | ||||||
| 			Err(e) => tracer.trace_failed_create(trace_info, subtracer.traces(), e.into()) | 			Err(ref e) => tracer.trace_failed_create(trace_info, subtracer.traces(), e.into()) | ||||||
| 		}; | 		}; | ||||||
| 
 | 
 | ||||||
| 		self.enact_result(&res, substate, unconfirmed_substate); | 		self.enact_result(&res, substate, unconfirmed_substate); | ||||||
| @ -435,9 +435,9 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { | |||||||
| 		let sender = t.sender(); | 		let sender = t.sender(); | ||||||
| 		trace!("exec::finalize: Refunding refund_value={}, sender={}\n", refund_value, sender); | 		trace!("exec::finalize: Refunding refund_value={}, sender={}\n", refund_value, sender); | ||||||
| 		// Below: NoEmpty is safe since the sender must already be non-null to have sent this transaction
 | 		// Below: NoEmpty is safe since the sender must already be non-null to have sent this transaction
 | ||||||
| 		self.state.add_balance(&sender, &refund_value, CleanupMode::NoEmpty); | 		self.state.add_balance(&sender, &refund_value, CleanupMode::NoEmpty)?; | ||||||
| 		trace!("exec::finalize: Compensating author: fees_value={}, author={}\n", fees_value, &self.info.author); | 		trace!("exec::finalize: Compensating author: fees_value={}, author={}\n", fees_value, &self.info.author); | ||||||
| 		self.state.add_balance(&self.info.author, &fees_value, substate.to_cleanup_mode(&schedule)); | 		self.state.add_balance(&self.info.author, &fees_value, substate.to_cleanup_mode(&schedule))?; | ||||||
| 
 | 
 | ||||||
| 		// perform suicides
 | 		// perform suicides
 | ||||||
| 		for address in &substate.suicides { | 		for address in &substate.suicides { | ||||||
| @ -446,13 +446,13 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { | |||||||
| 
 | 
 | ||||||
| 		// perform garbage-collection
 | 		// perform garbage-collection
 | ||||||
| 		for address in &substate.garbage { | 		for address in &substate.garbage { | ||||||
| 			if self.state.exists(address) && !self.state.exists_and_not_null(address) { | 			if self.state.exists(address)? && !self.state.exists_and_not_null(address)? { | ||||||
| 				self.state.kill_account(address); | 				self.state.kill_account(address); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		match result { | 		match result { | ||||||
| 			Err(evm::Error::Internal) => Err(ExecutionError::Internal), | 			Err(evm::Error::Internal(msg)) => Err(ExecutionError::Internal(msg)), | ||||||
| 			Err(exception) => { | 			Err(exception) => { | ||||||
| 				Ok(Executed { | 				Ok(Executed { | ||||||
| 					exception: Some(exception), | 					exception: Some(exception), | ||||||
| @ -495,7 +495,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { | |||||||
| 				| Err(evm::Error::OutOfStack {..}) => { | 				| Err(evm::Error::OutOfStack {..}) => { | ||||||
| 					self.state.revert_to_checkpoint(); | 					self.state.revert_to_checkpoint(); | ||||||
| 			}, | 			}, | ||||||
| 			Ok(_) | Err(evm::Error::Internal) => { | 			Ok(_) | Err(evm::Error::Internal(_)) => { | ||||||
| 				self.state.discard_checkpoint(); | 				self.state.discard_checkpoint(); | ||||||
| 				substate.accrue(un_substate); | 				substate.accrue(un_substate); | ||||||
| 			} | 			} | ||||||
|  | |||||||
| @ -108,25 +108,25 @@ impl<'a, T: 'a, V: 'a, B: 'a> Externalities<'a, T, V, B> | |||||||
| impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> | impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> | ||||||
| 	where T: Tracer, V: VMTracer, B: StateBackend | 	where T: Tracer, V: VMTracer, B: StateBackend | ||||||
| { | { | ||||||
| 	fn storage_at(&self, key: &H256) -> H256 { | 	fn storage_at(&self, key: &H256) -> trie::Result<H256> { | ||||||
| 		self.state.storage_at(&self.origin_info.address, key) | 		self.state.storage_at(&self.origin_info.address, key) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	fn set_storage(&mut self, key: H256, value: H256) { | 	fn set_storage(&mut self, key: H256, value: H256) -> trie::Result<()> { | ||||||
| 		self.state.set_storage(&self.origin_info.address, key, value) | 		self.state.set_storage(&self.origin_info.address, key, value) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	fn exists(&self, address: &Address) -> bool { | 	fn exists(&self, address: &Address) -> trie::Result<bool> { | ||||||
| 		self.state.exists(address) | 		self.state.exists(address) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	fn exists_and_not_null(&self, address: &Address) -> bool { | 	fn exists_and_not_null(&self, address: &Address) -> trie::Result<bool> { | ||||||
| 		self.state.exists_and_not_null(address) | 		self.state.exists_and_not_null(address) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	fn origin_balance(&self) -> U256 { self.balance(&self.origin_info.address) } | 	fn origin_balance(&self) -> trie::Result<U256> { self.balance(&self.origin_info.address) } | ||||||
| 
 | 
 | ||||||
| 	fn balance(&self, address: &Address) -> U256 { | 	fn balance(&self, address: &Address) -> trie::Result<U256> { | ||||||
| 		self.state.balance(address) | 		self.state.balance(address) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -149,7 +149,13 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> | |||||||
| 
 | 
 | ||||||
| 	fn create(&mut self, gas: &U256, value: &U256, code: &[u8]) -> ContractCreateResult { | 	fn create(&mut self, gas: &U256, value: &U256, code: &[u8]) -> ContractCreateResult { | ||||||
| 		// create new contract address
 | 		// create new contract address
 | ||||||
| 		let address = contract_address(&self.origin_info.address, &self.state.nonce(&self.origin_info.address)); | 		let address = match self.state.nonce(&self.origin_info.address) { | ||||||
|  | 			Ok(nonce) => contract_address(&self.origin_info.address, &nonce), | ||||||
|  | 			Err(e) => { | ||||||
|  | 				debug!(target: "ext", "Database corruption encountered: {:?}", e); | ||||||
|  | 				return ContractCreateResult::Failed | ||||||
|  | 			} | ||||||
|  | 		}; | ||||||
| 
 | 
 | ||||||
| 		// prepare the params
 | 		// prepare the params
 | ||||||
| 		let params = ActionParams { | 		let params = ActionParams { | ||||||
| @ -166,7 +172,10 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> | |||||||
| 			call_type: CallType::None, | 			call_type: CallType::None, | ||||||
| 		}; | 		}; | ||||||
| 
 | 
 | ||||||
| 		self.state.inc_nonce(&self.origin_info.address); | 		if let Err(e) = self.state.inc_nonce(&self.origin_info.address) { | ||||||
|  | 			debug!(target: "ext", "Database corruption encountered: {:?}", e); | ||||||
|  | 			return ContractCreateResult::Failed | ||||||
|  | 		} | ||||||
| 		let mut ex = Executive::from_parent(self.state, self.env_info, self.engine, self.vm_factory, self.depth); | 		let mut ex = Executive::from_parent(self.state, self.env_info, self.engine, self.vm_factory, self.depth); | ||||||
| 
 | 
 | ||||||
| 		// TODO: handle internal error separately
 | 		// TODO: handle internal error separately
 | ||||||
| @ -191,6 +200,14 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> | |||||||
| 	) -> MessageCallResult { | 	) -> MessageCallResult { | ||||||
| 		trace!(target: "externalities", "call"); | 		trace!(target: "externalities", "call"); | ||||||
| 
 | 
 | ||||||
|  | 		let code_res = self.state.code(code_address) | ||||||
|  | 			.and_then(|code| self.state.code_hash(code_address).map(|hash| (code, hash))); | ||||||
|  | 
 | ||||||
|  | 		let (code, code_hash) = match code_res { | ||||||
|  | 			Ok((code, hash)) => (code, hash), | ||||||
|  | 			Err(_) => return MessageCallResult::Failed, | ||||||
|  | 		}; | ||||||
|  | 
 | ||||||
| 		let mut params = ActionParams { | 		let mut params = ActionParams { | ||||||
| 			sender: sender_address.clone(), | 			sender: sender_address.clone(), | ||||||
| 			address: receive_address.clone(), | 			address: receive_address.clone(), | ||||||
| @ -199,8 +216,8 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> | |||||||
| 			origin: self.origin_info.origin.clone(), | 			origin: self.origin_info.origin.clone(), | ||||||
| 			gas: *gas, | 			gas: *gas, | ||||||
| 			gas_price: self.origin_info.gas_price, | 			gas_price: self.origin_info.gas_price, | ||||||
| 			code: self.state.code(code_address), | 			code: code, | ||||||
| 			code_hash: self.state.code_hash(code_address), | 			code_hash: code_hash, | ||||||
| 			data: Some(data.to_vec()), | 			data: Some(data.to_vec()), | ||||||
| 			call_type: call_type, | 			call_type: call_type, | ||||||
| 		}; | 		}; | ||||||
| @ -217,12 +234,12 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	fn extcode(&self, address: &Address) -> Arc<Bytes> { | 	fn extcode(&self, address: &Address) -> trie::Result<Arc<Bytes>> { | ||||||
| 		self.state.code(address).unwrap_or_else(|| Arc::new(vec![])) | 		Ok(self.state.code(address)?.unwrap_or_else(|| Arc::new(vec![]))) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	fn extcodesize(&self, address: &Address) -> usize { | 	fn extcodesize(&self, address: &Address) -> trie::Result<usize> { | ||||||
| 		self.state.code_size(address).unwrap_or(0) | 		Ok(self.state.code_size(address)?.unwrap_or(0)) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	#[cfg_attr(feature="dev", allow(match_ref_pats))] | 	#[cfg_attr(feature="dev", allow(match_ref_pats))] | ||||||
| @ -257,10 +274,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> | |||||||
| 
 | 
 | ||||||
| 				handle_copy(copy); | 				handle_copy(copy); | ||||||
| 
 | 
 | ||||||
| 				let mut code = vec![]; | 				self.state.init_code(&self.origin_info.address, data.to_vec())?; | ||||||
| 				code.extend_from_slice(data); |  | ||||||
| 
 |  | ||||||
| 				self.state.init_code(&self.origin_info.address, code); |  | ||||||
| 				Ok(*gas - return_cost) | 				Ok(*gas - return_cost) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @ -277,19 +291,26 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> | |||||||
| 		}); | 		}); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	fn suicide(&mut self, refund_address: &Address) { | 	fn suicide(&mut self, refund_address: &Address) -> trie::Result<()> { | ||||||
| 		let address = self.origin_info.address.clone(); | 		let address = self.origin_info.address.clone(); | ||||||
| 		let balance = self.balance(&address); | 		let balance = self.balance(&address)?; | ||||||
| 		if &address == refund_address { | 		if &address == refund_address { | ||||||
| 			// TODO [todr] To be consistent with CPP client we set balance to 0 in that case.
 | 			// TODO [todr] To be consistent with CPP client we set balance to 0 in that case.
 | ||||||
| 			self.state.sub_balance(&address, &balance); | 			self.state.sub_balance(&address, &balance)?; | ||||||
| 		} else { | 		} else { | ||||||
| 			trace!(target: "ext", "Suiciding {} -> {} (xfer: {})", address, refund_address, balance); | 			trace!(target: "ext", "Suiciding {} -> {} (xfer: {})", address, refund_address, balance); | ||||||
| 			self.state.transfer_balance(&address, refund_address, &balance, self.substate.to_cleanup_mode(&self.schedule)); | 			self.state.transfer_balance( | ||||||
|  | 				&address, | ||||||
|  | 				refund_address, | ||||||
|  | 				&balance, | ||||||
|  | 				self.substate.to_cleanup_mode(&self.schedule) | ||||||
|  | 			)?; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		self.tracer.trace_suicide(address, balance, refund_address.clone()); | 		self.tracer.trace_suicide(address, balance, refund_address.clone()); | ||||||
| 		self.substate.suicides.insert(address); | 		self.substate.suicides.insert(address); | ||||||
|  | 
 | ||||||
|  | 		Ok(()) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	fn schedule(&self) -> &Schedule { | 	fn schedule(&self) -> &Schedule { | ||||||
|  | |||||||
| @ -711,7 +711,7 @@ impl MinerService for Miner { | |||||||
| 				let original_state = if analytics.state_diffing { Some(state.clone()) } else { None }; | 				let original_state = if analytics.state_diffing { Some(state.clone()) } else { None }; | ||||||
| 
 | 
 | ||||||
| 				let sender = t.sender(); | 				let sender = t.sender(); | ||||||
| 				let balance = state.balance(&sender); | 				let balance = state.balance(&sender).map_err(ExecutionError::from)?; | ||||||
| 				let needed_balance = t.value + t.gas * t.gas_price; | 				let needed_balance = t.value + t.gas * t.gas_price; | ||||||
| 				if balance < needed_balance { | 				if balance < needed_balance { | ||||||
| 					// give the sender a sufficient balance
 | 					// give the sender a sufficient balance
 | ||||||
| @ -721,7 +721,9 @@ impl MinerService for Miner { | |||||||
| 				let mut ret = Executive::new(&mut state, &env_info, &*self.engine, client.vm_factory()).transact(t, options)?; | 				let mut ret = Executive::new(&mut state, &env_info, &*self.engine, client.vm_factory()).transact(t, options)?; | ||||||
| 
 | 
 | ||||||
| 				// TODO gav move this into Executive.
 | 				// TODO gav move this into Executive.
 | ||||||
| 				ret.state_diff = original_state.map(|original| state.diff_from(original)); | 				if let Some(original) = original_state { | ||||||
|  | 					ret.state_diff = Some(state.diff_from(original).map_err(ExecutionError::from)?); | ||||||
|  | 				} | ||||||
| 
 | 
 | ||||||
| 				Ok(ret) | 				Ok(ret) | ||||||
| 			}, | 			}, | ||||||
| @ -729,35 +731,37 @@ impl MinerService for Miner { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	fn balance(&self, chain: &MiningBlockChainClient, address: &Address) -> U256 { | 	// TODO: The `chain.latest_x` actually aren't infallible, they just panic on corruption.
 | ||||||
|  | 	// TODO: return trie::Result<T> here, or other.
 | ||||||
|  | 	fn balance(&self, chain: &MiningBlockChainClient, address: &Address) -> Option<U256> { | ||||||
| 		self.from_pending_block( | 		self.from_pending_block( | ||||||
| 			chain.chain_info().best_block_number, | 			chain.chain_info().best_block_number, | ||||||
| 			|| chain.latest_balance(address), | 			|| Some(chain.latest_balance(address)), | ||||||
| 			|b| b.block().fields().state.balance(address) | 			|b| b.block().fields().state.balance(address).ok(), | ||||||
| 		) | 		) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	fn storage_at(&self, chain: &MiningBlockChainClient, address: &Address, position: &H256) -> H256 { | 	fn storage_at(&self, chain: &MiningBlockChainClient, address: &Address, position: &H256) -> Option<H256> { | ||||||
| 		self.from_pending_block( | 		self.from_pending_block( | ||||||
| 			chain.chain_info().best_block_number, | 			chain.chain_info().best_block_number, | ||||||
| 			|| chain.latest_storage_at(address, position), | 			|| Some(chain.latest_storage_at(address, position)), | ||||||
| 			|b| b.block().fields().state.storage_at(address, position) | 			|b| b.block().fields().state.storage_at(address, position).ok(), | ||||||
| 		) | 		) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	fn nonce(&self, chain: &MiningBlockChainClient, address: &Address) -> U256 { | 	fn nonce(&self, chain: &MiningBlockChainClient, address: &Address) -> Option<U256> { | ||||||
| 		self.from_pending_block( | 		self.from_pending_block( | ||||||
| 			chain.chain_info().best_block_number, | 			chain.chain_info().best_block_number, | ||||||
| 			|| chain.latest_nonce(address), | 			|| Some(chain.latest_nonce(address)), | ||||||
| 			|b| b.block().fields().state.nonce(address) | 			|b| b.block().fields().state.nonce(address).ok(), | ||||||
| 		) | 		) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	fn code(&self, chain: &MiningBlockChainClient, address: &Address) -> Option<Bytes> { | 	fn code(&self, chain: &MiningBlockChainClient, address: &Address) -> Option<Option<Bytes>> { | ||||||
| 		self.from_pending_block( | 		self.from_pending_block( | ||||||
| 			chain.chain_info().best_block_number, | 			chain.chain_info().best_block_number, | ||||||
| 			|| chain.latest_code(address), | 			|| Some(chain.latest_code(address)), | ||||||
| 			|b| b.block().fields().state.code(address).map(|c| (*c).clone()) | 			|b| b.block().fields().state.code(address).ok().map(|c| c.map(|c| (&*c).clone())) | ||||||
| 		) | 		) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -62,7 +62,7 @@ pub use self::work_notify::NotifyWork; | |||||||
| pub use self::stratum::{Stratum, Error as StratumError, Options as StratumOptions}; | pub use self::stratum::{Stratum, Error as StratumError, Options as StratumOptions}; | ||||||
| 
 | 
 | ||||||
| use std::collections::BTreeMap; | use std::collections::BTreeMap; | ||||||
| use util::{H256, U256, Address, Bytes}; | use util::{H256, U256, Address, Bytes, trie}; | ||||||
| use client::{MiningBlockChainClient, Executed, CallAnalytics}; | use client::{MiningBlockChainClient, Executed, CallAnalytics}; | ||||||
| use block::ClosedBlock; | use block::ClosedBlock; | ||||||
| use header::BlockNumber; | use header::BlockNumber; | ||||||
| @ -181,19 +181,19 @@ pub trait MinerService : Send + Sync { | |||||||
| 	fn sensible_gas_limit(&self) -> U256 { 21000.into() } | 	fn sensible_gas_limit(&self) -> U256 { 21000.into() } | ||||||
| 
 | 
 | ||||||
| 	/// Latest account balance in pending state.
 | 	/// Latest account balance in pending state.
 | ||||||
| 	fn balance(&self, chain: &MiningBlockChainClient, address: &Address) -> U256; | 	fn balance(&self, chain: &MiningBlockChainClient, address: &Address) -> Option<U256>; | ||||||
| 
 | 
 | ||||||
| 	/// Call into contract code using pending state.
 | 	/// Call into contract code using pending state.
 | ||||||
| 	fn call(&self, chain: &MiningBlockChainClient, t: &SignedTransaction, analytics: CallAnalytics) -> Result<Executed, CallError>; | 	fn call(&self, chain: &MiningBlockChainClient, t: &SignedTransaction, analytics: CallAnalytics) -> Result<Executed, CallError>; | ||||||
| 
 | 
 | ||||||
| 	/// Get storage value in pending state.
 | 	/// Get storage value in pending state.
 | ||||||
| 	fn storage_at(&self, chain: &MiningBlockChainClient, address: &Address, position: &H256) -> H256; | 	fn storage_at(&self, chain: &MiningBlockChainClient, address: &Address, position: &H256) -> Option<H256>; | ||||||
| 
 | 
 | ||||||
| 	/// Get account nonce in pending state.
 | 	/// Get account nonce in pending state.
 | ||||||
| 	fn nonce(&self, chain: &MiningBlockChainClient, address: &Address) -> U256; | 	fn nonce(&self, chain: &MiningBlockChainClient, address: &Address) -> Option<U256>; | ||||||
| 
 | 
 | ||||||
| 	/// Get contract code in pending state.
 | 	/// Get contract code in pending state.
 | ||||||
| 	fn code(&self, chain: &MiningBlockChainClient, address: &Address) -> Option<Bytes>; | 	fn code(&self, chain: &MiningBlockChainClient, address: &Address) -> Option<Option<Bytes>>; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Mining status
 | /// Mining status
 | ||||||
|  | |||||||
| @ -169,22 +169,16 @@ impl Account { | |||||||
| 
 | 
 | ||||||
| 	/// Get (and cache) the contents of the trie's storage at `key`.
 | 	/// Get (and cache) the contents of the trie's storage at `key`.
 | ||||||
| 	/// Takes modifed storage into account.
 | 	/// Takes modifed storage into account.
 | ||||||
| 	pub fn storage_at(&self, db: &HashDB, key: &H256) -> H256 { | 	pub fn storage_at(&self, db: &HashDB, key: &H256) -> trie::Result<H256> { | ||||||
| 		if let Some(value) = self.cached_storage_at(key) { | 		if let Some(value) = self.cached_storage_at(key) { | ||||||
| 			return value; | 			return Ok(value); | ||||||
| 		} | 		} | ||||||
| 		let db = SecTrieDB::new(db, &self.storage_root) | 		let db = SecTrieDB::new(db, &self.storage_root)?; | ||||||
| 			.expect("Account storage_root initially set to zero (valid) and only altered by SecTrieDBMut. \ |  | ||||||
| 			SecTrieDBMut would not set it to an invalid state root. Therefore the root is valid and DB creation \ |  | ||||||
| 			using it will not fail.");
 |  | ||||||
| 
 | 
 | ||||||
| 		let item: U256 = match db.get_with(key, ::rlp::decode) { | 		let item: U256 = db.get_with(key, ::rlp::decode)?.unwrap_or_else(U256::zero); | ||||||
| 			Ok(x) => x.unwrap_or_else(U256::zero), |  | ||||||
| 			Err(e) => panic!("Encountered potential DB corruption: {}", e), |  | ||||||
| 		}; |  | ||||||
| 		let value: H256 = item.into(); | 		let value: H256 = item.into(); | ||||||
| 		self.storage_cache.borrow_mut().insert(key.clone(), value.clone()); | 		self.storage_cache.borrow_mut().insert(key.clone(), value.clone()); | ||||||
| 		value | 		Ok(value) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/// Get cached storage value if any. Returns `None` if the
 | 	/// Get cached storage value if any. Returns `None` if the
 | ||||||
| @ -345,24 +339,19 @@ impl Account { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/// Commit the `storage_changes` to the backing DB and update `storage_root`.
 | 	/// Commit the `storage_changes` to the backing DB and update `storage_root`.
 | ||||||
| 	pub fn commit_storage(&mut self, trie_factory: &TrieFactory, db: &mut HashDB) { | 	pub fn commit_storage(&mut self, trie_factory: &TrieFactory, db: &mut HashDB) -> trie::Result<()> { | ||||||
| 		let mut t = trie_factory.from_existing(db, &mut self.storage_root) | 		let mut t = trie_factory.from_existing(db, &mut self.storage_root)?; | ||||||
| 			.expect("Account storage_root initially set to zero (valid) and only altered by SecTrieDBMut. \ |  | ||||||
| 				SecTrieDBMut would not set it to an invalid state root. Therefore the root is valid and DB creation \ |  | ||||||
| 				using it will not fail.");
 |  | ||||||
| 		for (k, v) in self.storage_changes.drain() { | 		for (k, v) in self.storage_changes.drain() { | ||||||
| 			// cast key and value to trait type,
 | 			// cast key and value to trait type,
 | ||||||
| 			// so we can call overloaded `to_bytes` method
 | 			// so we can call overloaded `to_bytes` method
 | ||||||
| 			let res = match v.is_zero() { | 			match v.is_zero() { | ||||||
| 				true => t.remove(&k), | 				true => t.remove(&k)?, | ||||||
| 				false => t.insert(&k, &encode(&U256::from(&*v))), | 				false => t.insert(&k, &encode(&U256::from(&*v)))?, | ||||||
| 			}; | 			}; | ||||||
| 
 | 
 | ||||||
| 			if let Err(e) = res { |  | ||||||
| 				warn!("Encountered potential DB corruption: {}", e); |  | ||||||
| 			} |  | ||||||
| 			self.storage_cache.borrow_mut().insert(k, v); | 			self.storage_cache.borrow_mut().insert(k, v); | ||||||
| 		} | 		} | ||||||
|  | 		Ok(()) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/// Commit any unsaved code. `code_hash` will always return the hash of the `code_cache` after this.
 | 	/// Commit any unsaved code. `code_hash` will always return the hash of the `code_cache` after this.
 | ||||||
|  | |||||||
| @ -37,6 +37,7 @@ use state_db::StateDB; | |||||||
| 
 | 
 | ||||||
| use util::*; | use util::*; | ||||||
| 
 | 
 | ||||||
|  | use util::trie; | ||||||
| use util::trie::recorder::Recorder; | use util::trie::recorder::Recorder; | ||||||
| 
 | 
 | ||||||
| mod account; | mod account; | ||||||
| @ -362,37 +363,37 @@ impl<B: Backend> State<B> { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/// Determine whether an account exists.
 | 	/// Determine whether an account exists.
 | ||||||
| 	pub fn exists(&self, a: &Address) -> bool { | 	pub fn exists(&self, a: &Address) -> trie::Result<bool> { | ||||||
| 		// Bloom filter does not contain empty accounts, so it is important here to
 | 		// Bloom filter does not contain empty accounts, so it is important here to
 | ||||||
| 		// check if account exists in the database directly before EIP-161 is in effect.
 | 		// check if account exists in the database directly before EIP-161 is in effect.
 | ||||||
| 		self.ensure_cached(a, RequireCache::None, false, |a| a.is_some()) | 		self.ensure_cached(a, RequireCache::None, false, |a| a.is_some()) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/// Determine whether an account exists and if not empty.
 | 	/// Determine whether an account exists and if not empty.
 | ||||||
| 	pub fn exists_and_not_null(&self, a: &Address) -> bool { | 	pub fn exists_and_not_null(&self, a: &Address) -> trie::Result<bool> { | ||||||
| 		self.ensure_cached(a, RequireCache::None, false, |a| a.map_or(false, |a| !a.is_null())) | 		self.ensure_cached(a, RequireCache::None, false, |a| a.map_or(false, |a| !a.is_null())) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/// Get the balance of account `a`.
 | 	/// Get the balance of account `a`.
 | ||||||
| 	pub fn balance(&self, a: &Address) -> U256 { | 	pub fn balance(&self, a: &Address) -> trie::Result<U256> { | ||||||
| 		self.ensure_cached(a, RequireCache::None, true, | 		self.ensure_cached(a, RequireCache::None, true, | ||||||
| 			|a| a.as_ref().map_or(U256::zero(), |account| *account.balance())) | 			|a| a.as_ref().map_or(U256::zero(), |account| *account.balance())) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/// Get the nonce of account `a`.
 | 	/// Get the nonce of account `a`.
 | ||||||
| 	pub fn nonce(&self, a: &Address) -> U256 { | 	pub fn nonce(&self, a: &Address) -> trie::Result<U256> { | ||||||
| 		self.ensure_cached(a, RequireCache::None, true, | 		self.ensure_cached(a, RequireCache::None, true, | ||||||
| 			|a| a.as_ref().map_or(self.account_start_nonce, |account| *account.nonce())) | 			|a| a.as_ref().map_or(self.account_start_nonce, |account| *account.nonce())) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/// Get the storage root of account `a`.
 | 	/// Get the storage root of account `a`.
 | ||||||
| 	pub fn storage_root(&self, a: &Address) -> Option<H256> { | 	pub fn storage_root(&self, a: &Address) -> trie::Result<Option<H256>> { | ||||||
| 		self.ensure_cached(a, RequireCache::None, true, | 		self.ensure_cached(a, RequireCache::None, true, | ||||||
| 			|a| a.as_ref().and_then(|account| account.storage_root().cloned())) | 			|a| a.as_ref().and_then(|account| account.storage_root().cloned())) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/// Mutate storage of account `address` so that it is `value` for `key`.
 | 	/// Mutate storage of account `address` so that it is `value` for `key`.
 | ||||||
| 	pub fn storage_at(&self, address: &Address, key: &H256) -> H256 { | 	pub fn storage_at(&self, address: &Address, key: &H256) -> trie::Result<H256> { | ||||||
| 		// Storage key search and update works like this:
 | 		// Storage key search and update works like this:
 | ||||||
| 		// 1. If there's an entry for the account in the local cache check for the key and return it if found.
 | 		// 1. If there's an entry for the account in the local cache check for the key and return it if found.
 | ||||||
| 		// 2. If there's an entry for the account in the global cache check for the key or load it into that account.
 | 		// 2. If there's an entry for the account in the global cache check for the key or load it into that account.
 | ||||||
| @ -406,42 +407,46 @@ impl<B: Backend> State<B> { | |||||||
| 				match maybe_acc.account { | 				match maybe_acc.account { | ||||||
| 					Some(ref account) => { | 					Some(ref account) => { | ||||||
| 						if let Some(value) = account.cached_storage_at(key) { | 						if let Some(value) = account.cached_storage_at(key) { | ||||||
| 							return value; | 							return Ok(value); | ||||||
| 						} else { | 						} else { | ||||||
| 							local_account = Some(maybe_acc); | 							local_account = Some(maybe_acc); | ||||||
| 						} | 						} | ||||||
| 					}, | 					}, | ||||||
| 					_ => return H256::new(), | 					_ => return Ok(H256::new()), | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			// check the global cache and and cache storage key there if found,
 | 			// check the global cache and and cache storage key there if found,
 | ||||||
| 			// otherwise cache the account localy and cache storage key there.
 | 			let trie_res = self.db.get_cached(address, |acc| match acc { | ||||||
| 			if let Some(result) = self.db.get_cached(address, |acc| acc.map_or(H256::new(), |a| { | 				None => Ok(H256::new()), | ||||||
|  | 				Some(a) => { | ||||||
| 					let account_db = self.factories.accountdb.readonly(self.db.as_hashdb(), a.address_hash(address)); | 					let account_db = self.factories.accountdb.readonly(self.db.as_hashdb(), a.address_hash(address)); | ||||||
| 					a.storage_at(account_db.as_hashdb(), key) | 					a.storage_at(account_db.as_hashdb(), key) | ||||||
| 				})) { | 				} | ||||||
| 				return result; | 			}); | ||||||
|  | 
 | ||||||
|  | 			match trie_res { | ||||||
|  | 				None => {} | ||||||
|  | 				Some(res) => return res, | ||||||
| 			} | 			} | ||||||
|  | 
 | ||||||
|  | 			// otherwise cache the account localy and cache storage key there.
 | ||||||
| 			if let Some(ref mut acc) = local_account { | 			if let Some(ref mut acc) = local_account { | ||||||
| 				if let Some(ref account) = acc.account { | 				if let Some(ref account) = acc.account { | ||||||
| 					let account_db = self.factories.accountdb.readonly(self.db.as_hashdb(), account.address_hash(address)); | 					let account_db = self.factories.accountdb.readonly(self.db.as_hashdb(), account.address_hash(address)); | ||||||
| 					return account.storage_at(account_db.as_hashdb(), key) | 					return account.storage_at(account_db.as_hashdb(), key) | ||||||
| 				} else { | 				} else { | ||||||
| 					return H256::new() | 					return Ok(H256::new()) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// check if the account could exist before any requests to trie
 | 		// check if the account could exist before any requests to trie
 | ||||||
| 		if self.db.is_known_null(address) { return H256::zero() } | 		if self.db.is_known_null(address) { return Ok(H256::zero()) } | ||||||
| 
 | 
 | ||||||
| 		// account is not found in the global cache, get from the DB and insert into local
 | 		// account is not found in the global cache, get from the DB and insert into local
 | ||||||
| 		let db = self.factories.trie.readonly(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR); | 		let db = self.factories.trie.readonly(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR); | ||||||
| 		let maybe_acc = match db.get_with(address, Account::from_rlp) { | 		let maybe_acc = db.get_with(address, Account::from_rlp)?; | ||||||
| 			Ok(acc) => acc, | 		let r = maybe_acc.as_ref().map_or(Ok(H256::new()), |a| { | ||||||
| 			Err(e) => panic!("Potential DB corruption encountered: {}", e), |  | ||||||
| 		}; |  | ||||||
| 		let r = maybe_acc.as_ref().map_or(H256::new(), |a| { |  | ||||||
| 			let account_db = self.factories.accountdb.readonly(self.db.as_hashdb(), a.address_hash(address)); | 			let account_db = self.factories.accountdb.readonly(self.db.as_hashdb(), a.address_hash(address)); | ||||||
| 			a.storage_at(account_db.as_hashdb(), key) | 			a.storage_at(account_db.as_hashdb(), key) | ||||||
| 		}); | 		}); | ||||||
| @ -450,75 +455,84 @@ impl<B: Backend> State<B> { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/// Get accounts' code.
 | 	/// Get accounts' code.
 | ||||||
| 	pub fn code(&self, a: &Address) -> Option<Arc<Bytes>> { | 	pub fn code(&self, a: &Address) -> trie::Result<Option<Arc<Bytes>>> { | ||||||
| 		self.ensure_cached(a, RequireCache::Code, true, | 		self.ensure_cached(a, RequireCache::Code, true, | ||||||
| 			|a| a.as_ref().map_or(None, |a| a.code().clone())) | 			|a| a.as_ref().map_or(None, |a| a.code().clone())) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/// Get an account's code hash.
 | 	/// Get an account's code hash.
 | ||||||
| 	pub fn code_hash(&self, a: &Address) -> H256 { | 	pub fn code_hash(&self, a: &Address) -> trie::Result<H256> { | ||||||
| 		self.ensure_cached(a, RequireCache::None, true, | 		self.ensure_cached(a, RequireCache::None, true, | ||||||
| 			|a| a.as_ref().map_or(SHA3_EMPTY, |a| a.code_hash())) | 			|a| a.as_ref().map_or(SHA3_EMPTY, |a| a.code_hash())) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/// Get accounts' code size.
 | 	/// Get accounts' code size.
 | ||||||
| 	pub fn code_size(&self, a: &Address) -> Option<usize> { | 	pub fn code_size(&self, a: &Address) -> trie::Result<Option<usize>> { | ||||||
| 		self.ensure_cached(a, RequireCache::CodeSize, true, | 		self.ensure_cached(a, RequireCache::CodeSize, true, | ||||||
| 			|a| a.as_ref().and_then(|a| a.code_size())) | 			|a| a.as_ref().and_then(|a| a.code_size())) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/// Add `incr` to the balance of account `a`.
 | 	/// Add `incr` to the balance of account `a`.
 | ||||||
| 	#[cfg_attr(feature="dev", allow(single_match))] | 	#[cfg_attr(feature="dev", allow(single_match))] | ||||||
| 	pub fn add_balance(&mut self, a: &Address, incr: &U256, cleanup_mode: CleanupMode) { | 	pub fn add_balance(&mut self, a: &Address, incr: &U256, cleanup_mode: CleanupMode) -> trie::Result<()> { | ||||||
| 		trace!(target: "state", "add_balance({}, {}): {}", a, incr, self.balance(a)); | 		trace!(target: "state", "add_balance({}, {}): {}", a, incr, self.balance(a)?); | ||||||
| 		let is_value_transfer = !incr.is_zero(); | 		let is_value_transfer = !incr.is_zero(); | ||||||
| 		if is_value_transfer || (cleanup_mode == CleanupMode::ForceCreate && !self.exists(a)) { | 		if is_value_transfer || (cleanup_mode == CleanupMode::ForceCreate && !self.exists(a)?) { | ||||||
| 			self.require(a, false).add_balance(incr); | 			self.require(a, false)?.add_balance(incr); | ||||||
| 		} else { | 		} else { | ||||||
| 			match cleanup_mode { | 			match cleanup_mode { | ||||||
| 				CleanupMode::KillEmpty(set) => if !is_value_transfer && self.exists(a) && !self.exists_and_not_null(a) { | 				CleanupMode::KillEmpty(set) => if !is_value_transfer && self.exists(a)? && !self.exists_and_not_null(a)? { | ||||||
| 					set.insert(a.clone()); | 					set.insert(a.clone()); | ||||||
| 				}, | 				}, | ||||||
| 				_ => {} | 				_ => {} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
|  | 		Ok(()) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/// Subtract `decr` from the balance of account `a`.
 | 	/// Subtract `decr` from the balance of account `a`.
 | ||||||
| 	pub fn sub_balance(&mut self, a: &Address, decr: &U256) { | 	pub fn sub_balance(&mut self, a: &Address, decr: &U256) -> trie::Result<()> { | ||||||
| 		trace!(target: "state", "sub_balance({}, {}): {}", a, decr, self.balance(a)); | 		trace!(target: "state", "sub_balance({}, {}): {}", a, decr, self.balance(a)?); | ||||||
| 		if !decr.is_zero() || !self.exists(a) { | 		if !decr.is_zero() || !self.exists(a)? { | ||||||
| 			self.require(a, false).sub_balance(decr); | 			self.require(a, false)?.sub_balance(decr); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
|  | 		Ok(()) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/// Subtracts `by` from the balance of `from` and adds it to that of `to`.
 | 	/// Subtracts `by` from the balance of `from` and adds it to that of `to`.
 | ||||||
| 	pub fn transfer_balance(&mut self, from: &Address, to: &Address, by: &U256, cleanup_mode: CleanupMode) { | 	pub fn transfer_balance(&mut self, from: &Address, to: &Address, by: &U256, cleanup_mode: CleanupMode) -> trie::Result<()> { | ||||||
| 		self.sub_balance(from, by); | 		self.sub_balance(from, by)?; | ||||||
| 		self.add_balance(to, by, cleanup_mode); | 		self.add_balance(to, by, cleanup_mode)?; | ||||||
|  | 		Ok(()) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/// Increment the nonce of account `a` by 1.
 | 	/// Increment the nonce of account `a` by 1.
 | ||||||
| 	pub fn inc_nonce(&mut self, a: &Address) { | 	pub fn inc_nonce(&mut self, a: &Address) -> trie::Result<()> { | ||||||
| 		self.require(a, false).inc_nonce() | 		self.require(a, false).map(|mut x| x.inc_nonce()) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/// Mutate storage of account `a` so that it is `value` for `key`.
 | 	/// Mutate storage of account `a` so that it is `value` for `key`.
 | ||||||
| 	pub fn set_storage(&mut self, a: &Address, key: H256, value: H256) { | 	pub fn set_storage(&mut self, a: &Address, key: H256, value: H256) -> trie::Result<()> { | ||||||
| 		if self.storage_at(a, &key) != value { | 		if self.storage_at(a, &key)? != value { | ||||||
| 			self.require(a, false).set_storage(key, value) | 			self.require(a, false)?.set_storage(key, value) | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
|  | 		Ok(()) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/// Initialise the code of account `a` so that it is `code`.
 | 	/// Initialise the code of account `a` so that it is `code`.
 | ||||||
| 	/// NOTE: Account should have been created with `new_contract`.
 | 	/// NOTE: Account should have been created with `new_contract`.
 | ||||||
| 	pub fn init_code(&mut self, a: &Address, code: Bytes) { | 	pub fn init_code(&mut self, a: &Address, code: Bytes) -> trie::Result<()> { | ||||||
| 		self.require_or_from(a, true, || Account::new_contract(0.into(), self.account_start_nonce), |_|{}).init_code(code); | 		self.require_or_from(a, true, || Account::new_contract(0.into(), self.account_start_nonce), |_|{})?.init_code(code); | ||||||
|  | 		Ok(()) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/// Reset the code of account `a` so that it is `code`.
 | 	/// Reset the code of account `a` so that it is `code`.
 | ||||||
| 	pub fn reset_code(&mut self, a: &Address, code: Bytes) { | 	pub fn reset_code(&mut self, a: &Address, code: Bytes) -> trie::Result<()> { | ||||||
| 		self.require_or_from(a, true, || Account::new_contract(0.into(), self.account_start_nonce), |_|{}).reset_code(code); | 		self.require_or_from(a, true, || Account::new_contract(0.into(), self.account_start_nonce), |_|{})?.reset_code(code); | ||||||
|  | 		Ok(()) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/// Execute a given transaction.
 | 	/// Execute a given transaction.
 | ||||||
| @ -629,25 +643,29 @@ impl<B: Backend> State<B> { | |||||||
| 		})) | 		})) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	fn query_pod(&mut self, query: &PodState) { | 	fn query_pod(&mut self, query: &PodState) -> trie::Result<()> { | ||||||
| 		for (address, pod_account) in query.get().into_iter() | 		for (address, pod_account) in query.get() { | ||||||
| 			.filter(|&(a, _)| self.ensure_cached(a, RequireCache::Code, true, |a| a.is_some())) | 			if !self.ensure_cached(address, RequireCache::Code, true, |a| a.is_some())? { | ||||||
| 		{ | 				continue
 | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 			// needs to be split into two parts for the refcell code here
 | 			// needs to be split into two parts for the refcell code here
 | ||||||
| 			// to work.
 | 			// to work.
 | ||||||
| 			for key in pod_account.storage.keys() { | 			for key in pod_account.storage.keys() { | ||||||
| 				self.storage_at(address, key); | 				self.storage_at(address, key)?; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
|  | 		Ok(()) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/// Returns a `StateDiff` describing the difference from `orig` to `self`.
 | 	/// Returns a `StateDiff` describing the difference from `orig` to `self`.
 | ||||||
| 	/// Consumes self.
 | 	/// Consumes self.
 | ||||||
| 	pub fn diff_from<X: Backend>(&self, orig: State<X>) -> StateDiff { | 	pub fn diff_from<X: Backend>(&self, orig: State<X>) -> trie::Result<StateDiff> { | ||||||
| 		let pod_state_post = self.to_pod(); | 		let pod_state_post = self.to_pod(); | ||||||
| 		let mut state_pre = orig; | 		let mut state_pre = orig; | ||||||
| 		state_pre.query_pod(&pod_state_post); | 		state_pre.query_pod(&pod_state_post)?; | ||||||
| 		pod_state::diff_pod(&state_pre.to_pod(), &pod_state_post) | 		Ok(pod_state::diff_pod(&state_pre.to_pod(), &pod_state_post)) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// load required account data from the databases.
 | 	// load required account data from the databases.
 | ||||||
| @ -681,16 +699,16 @@ impl<B: Backend> State<B> { | |||||||
| 	/// Check caches for required data
 | 	/// Check caches for required data
 | ||||||
| 	/// First searches for account in the local, then the shared cache.
 | 	/// First searches for account in the local, then the shared cache.
 | ||||||
| 	/// Populates local cache if nothing found.
 | 	/// Populates local cache if nothing found.
 | ||||||
| 	fn ensure_cached<F, U>(&self, a: &Address, require: RequireCache, check_null: bool, f: F) -> U | 	fn ensure_cached<F, U>(&self, a: &Address, require: RequireCache, check_null: bool, f: F) -> trie::Result<U> | ||||||
| 		where F: Fn(Option<&Account>) -> U { | 		where F: Fn(Option<&Account>) -> U { | ||||||
| 		// check local cache first
 | 		// check local cache first
 | ||||||
| 		if let Some(ref mut maybe_acc) = self.cache.borrow_mut().get_mut(a) { | 		if let Some(ref mut maybe_acc) = self.cache.borrow_mut().get_mut(a) { | ||||||
| 			if let Some(ref mut account) = maybe_acc.account { | 			if let Some(ref mut account) = maybe_acc.account { | ||||||
| 				let accountdb = self.factories.accountdb.readonly(self.db.as_hashdb(), account.address_hash(a)); | 				let accountdb = self.factories.accountdb.readonly(self.db.as_hashdb(), account.address_hash(a)); | ||||||
| 				Self::update_account_cache(require, account, &self.db, accountdb.as_hashdb()); | 				Self::update_account_cache(require, account, &self.db, accountdb.as_hashdb()); | ||||||
| 				return f(Some(account)); | 				return Ok(f(Some(account))); | ||||||
| 			} | 			} | ||||||
| 			return f(None); | 			return Ok(f(None)); | ||||||
| 		} | 		} | ||||||
| 		// check global cache
 | 		// check global cache
 | ||||||
| 		let result = self.db.get_cached(a, |mut acc| { | 		let result = self.db.get_cached(a, |mut acc| { | ||||||
| @ -701,37 +719,34 @@ impl<B: Backend> State<B> { | |||||||
| 			f(acc.map(|a| &*a)) | 			f(acc.map(|a| &*a)) | ||||||
| 		}); | 		}); | ||||||
| 		match result { | 		match result { | ||||||
| 			Some(r) => r, | 			Some(r) => Ok(r), | ||||||
| 			None => { | 			None => { | ||||||
| 				// first check if it is not in database for sure
 | 				// first check if it is not in database for sure
 | ||||||
| 				if check_null && self.db.is_known_null(a) { return f(None); } | 				if check_null && self.db.is_known_null(a) { return Ok(f(None)); } | ||||||
| 
 | 
 | ||||||
| 				// not found in the global cache, get from the DB and insert into local
 | 				// not found in the global cache, get from the DB and insert into local
 | ||||||
| 				let db = self.factories.trie.readonly(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR); | 				let db = self.factories.trie.readonly(self.db.as_hashdb(), &self.root)?; | ||||||
| 				let mut maybe_acc = match db.get_with(a, Account::from_rlp) { | 				let mut maybe_acc = db.get_with(a, Account::from_rlp)?; | ||||||
| 					Ok(acc) => acc, |  | ||||||
| 					Err(e) => panic!("Potential DB corruption encountered: {}", e), |  | ||||||
| 				}; |  | ||||||
| 				if let Some(ref mut account) = maybe_acc.as_mut() { | 				if let Some(ref mut account) = maybe_acc.as_mut() { | ||||||
| 					let accountdb = self.factories.accountdb.readonly(self.db.as_hashdb(), account.address_hash(a)); | 					let accountdb = self.factories.accountdb.readonly(self.db.as_hashdb(), account.address_hash(a)); | ||||||
| 					Self::update_account_cache(require, account, &self.db, accountdb.as_hashdb()); | 					Self::update_account_cache(require, account, &self.db, accountdb.as_hashdb()); | ||||||
| 				} | 				} | ||||||
| 				let r = f(maybe_acc.as_ref()); | 				let r = f(maybe_acc.as_ref()); | ||||||
| 				self.insert_cache(a, AccountEntry::new_clean(maybe_acc)); | 				self.insert_cache(a, AccountEntry::new_clean(maybe_acc)); | ||||||
| 				r | 				Ok(r) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/// Pull account `a` in our cache from the trie DB. `require_code` requires that the code be cached, too.
 | 	/// Pull account `a` in our cache from the trie DB. `require_code` requires that the code be cached, too.
 | ||||||
| 	fn require<'a>(&'a self, a: &Address, require_code: bool) -> RefMut<'a, Account> { | 	fn require<'a>(&'a self, a: &Address, require_code: bool) -> trie::Result<RefMut<'a, Account>> { | ||||||
| 		self.require_or_from(a, require_code, || Account::new_basic(U256::from(0u8), self.account_start_nonce), |_|{}) | 		self.require_or_from(a, require_code, || Account::new_basic(U256::from(0u8), self.account_start_nonce), |_|{}) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/// Pull account `a` in our cache from the trie DB. `require_code` requires that the code be cached, too.
 | 	/// Pull account `a` in our cache from the trie DB. `require_code` requires that the code be cached, too.
 | ||||||
| 	/// If it doesn't exist, make account equal the evaluation of `default`.
 | 	/// If it doesn't exist, make account equal the evaluation of `default`.
 | ||||||
| 	fn require_or_from<'a, F: FnOnce() -> Account, G: FnOnce(&mut Account)>(&'a self, a: &Address, require_code: bool, default: F, not_default: G) | 	fn require_or_from<'a, F, G>(&'a self, a: &Address, require_code: bool, default: F, not_default: G) -> trie::Result<RefMut<'a, Account>> | ||||||
| 		-> RefMut<'a, Account> | 		where F: FnOnce() -> Account, G: FnOnce(&mut Account), | ||||||
| 	{ | 	{ | ||||||
| 		let contains_key = self.cache.borrow().contains_key(a); | 		let contains_key = self.cache.borrow().contains_key(a); | ||||||
| 		if !contains_key { | 		if !contains_key { | ||||||
| @ -739,11 +754,8 @@ impl<B: Backend> State<B> { | |||||||
| 				Some(acc) => self.insert_cache(a, AccountEntry::new_clean_cached(acc)), | 				Some(acc) => self.insert_cache(a, AccountEntry::new_clean_cached(acc)), | ||||||
| 				None => { | 				None => { | ||||||
| 					let maybe_acc = if !self.db.is_known_null(a) { | 					let maybe_acc = if !self.db.is_known_null(a) { | ||||||
| 						let db = self.factories.trie.readonly(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR); | 						let db = self.factories.trie.readonly(self.db.as_hashdb(), &self.root)?; | ||||||
| 						match db.get_with(a, Account::from_rlp) { | 						AccountEntry::new_clean(db.get_with(a, Account::from_rlp)?) | ||||||
| 							Ok(acc) => AccountEntry::new_clean(acc), |  | ||||||
| 							Err(e) => panic!("Potential DB corruption encountered: {}", e), |  | ||||||
| 						} |  | ||||||
| 					} else { | 					} else { | ||||||
| 						AccountEntry::new_clean(None) | 						AccountEntry::new_clean(None) | ||||||
| 					}; | 					}; | ||||||
| @ -754,7 +766,7 @@ impl<B: Backend> State<B> { | |||||||
| 		self.note_cache(a); | 		self.note_cache(a); | ||||||
| 
 | 
 | ||||||
| 		// at this point the entry is guaranteed to be in the cache.
 | 		// at this point the entry is guaranteed to be in the cache.
 | ||||||
| 		RefMut::map(self.cache.borrow_mut(), |c| { | 		Ok(RefMut::map(self.cache.borrow_mut(), |c| { | ||||||
| 			let mut entry = c.get_mut(a).expect("entry known to exist in the cache; qed"); | 			let mut entry = c.get_mut(a).expect("entry known to exist in the cache; qed"); | ||||||
| 
 | 
 | ||||||
| 			match &mut entry.account { | 			match &mut entry.account { | ||||||
| @ -775,18 +787,18 @@ impl<B: Backend> State<B> { | |||||||
| 				}, | 				}, | ||||||
| 				_ => panic!("Required account must always exist; qed"), | 				_ => panic!("Required account must always exist; qed"), | ||||||
| 			} | 			} | ||||||
| 		}) | 		})) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // LES state proof implementations.
 | // State proof implementations; useful for light client protocols.
 | ||||||
| impl<B: Backend> State<B> { | impl<B: Backend> State<B> { | ||||||
| 	/// Prove an account's existence or nonexistence in the state trie.
 | 	/// Prove an account's existence or nonexistence in the state trie.
 | ||||||
| 	/// Returns a merkle proof of the account's trie node with all nodes before `from_level`
 | 	/// Returns a merkle proof of the account's trie node with all nodes before `from_level`
 | ||||||
| 	/// omitted or an encountered trie error.
 | 	/// omitted or an encountered trie error.
 | ||||||
| 	/// Requires a secure trie to be used for accurate results.
 | 	/// Requires a secure trie to be used for accurate results.
 | ||||||
| 	/// `account_key` == sha3(address)
 | 	/// `account_key` == sha3(address)
 | ||||||
| 	pub fn prove_account(&self, account_key: H256, from_level: u32) -> Result<Vec<Bytes>, Box<TrieError>> { | 	pub fn prove_account(&self, account_key: H256, from_level: u32) -> trie::Result<Vec<Bytes>> { | ||||||
| 		let mut recorder = Recorder::with_depth(from_level); | 		let mut recorder = Recorder::with_depth(from_level); | ||||||
| 		let trie = TrieDB::new(self.db.as_hashdb(), &self.root)?; | 		let trie = TrieDB::new(self.db.as_hashdb(), &self.root)?; | ||||||
| 		trie.get_with(&account_key, &mut recorder)?; | 		trie.get_with(&account_key, &mut recorder)?; | ||||||
| @ -799,7 +811,7 @@ impl<B: Backend> State<B> { | |||||||
| 	/// `from_level` omitted. Requires a secure trie to be used for correctness.
 | 	/// `from_level` omitted. Requires a secure trie to be used for correctness.
 | ||||||
| 	/// `account_key` == sha3(address)
 | 	/// `account_key` == sha3(address)
 | ||||||
| 	/// `storage_key` == sha3(key)
 | 	/// `storage_key` == sha3(key)
 | ||||||
| 	pub fn prove_storage(&self, account_key: H256, storage_key: H256, from_level: u32) -> Result<Vec<Bytes>, Box<TrieError>> { | 	pub fn prove_storage(&self, account_key: H256, storage_key: H256, from_level: u32) -> trie::Result<Vec<Bytes>> { | ||||||
| 		// TODO: probably could look into cache somehow but it's keyed by
 | 		// TODO: probably could look into cache somehow but it's keyed by
 | ||||||
| 		// address, not sha3(address).
 | 		// address, not sha3(address).
 | ||||||
| 		let trie = TrieDB::new(self.db.as_hashdb(), &self.root)?; | 		let trie = TrieDB::new(self.db.as_hashdb(), &self.root)?; | ||||||
| @ -814,7 +826,7 @@ impl<B: Backend> State<B> { | |||||||
| 
 | 
 | ||||||
| 	/// Get code by address hash.
 | 	/// Get code by address hash.
 | ||||||
| 	/// Only works when backed by a secure trie.
 | 	/// Only works when backed by a secure trie.
 | ||||||
| 	pub fn code_by_address_hash(&self, account_key: H256) -> Result<Option<Bytes>, Box<TrieError>> { | 	pub fn code_by_address_hash(&self, account_key: H256) -> trie::Result<Option<Bytes>> { | ||||||
| 		let trie = TrieDB::new(self.db.as_hashdb(), &self.root)?; | 		let trie = TrieDB::new(self.db.as_hashdb(), &self.root)?; | ||||||
| 		let mut acc = match trie.get_with(&account_key, Account::from_rlp)? { | 		let mut acc = match trie.get_with(&account_key, Account::from_rlp)? { | ||||||
| 			Some(acc) => acc, | 			Some(acc) => acc, | ||||||
|  | |||||||
| @ -16,7 +16,7 @@ | |||||||
| 
 | 
 | ||||||
| //! Transaction execution format module.
 | //! Transaction execution format module.
 | ||||||
| 
 | 
 | ||||||
| use util::{Bytes, U256, Address, U512}; | use util::{Bytes, U256, Address, U512, trie}; | ||||||
| use rlp::*; | use rlp::*; | ||||||
| use evm; | use evm; | ||||||
| use trace::{VMTrace, FlatTrace}; | use trace::{VMTrace, FlatTrace}; | ||||||
| @ -146,27 +146,33 @@ pub enum ExecutionError { | |||||||
| 		got: U512 | 		got: U512 | ||||||
| 	}, | 	}, | ||||||
| 	/// Returned when internal evm error occurs.
 | 	/// Returned when internal evm error occurs.
 | ||||||
| 	Internal, | 	Internal(String), | ||||||
| 	/// Returned when generic transaction occurs
 | 	/// Returned when generic transaction occurs
 | ||||||
| 	TransactionMalformed(String), | 	TransactionMalformed(String), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | impl From<Box<trie::TrieError>> for ExecutionError { | ||||||
|  | 	fn from(err: Box<trie::TrieError>) -> Self { | ||||||
|  | 		ExecutionError::Internal(format!("{}", err)) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| impl fmt::Display for ExecutionError { | impl fmt::Display for ExecutionError { | ||||||
| 	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | 	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||||
| 		use self::ExecutionError::*; | 		use self::ExecutionError::*; | ||||||
| 
 | 
 | ||||||
| 		let msg = match *self { | 		let msg = match *self { | ||||||
| 			NotEnoughBaseGas { required, got } => | 			NotEnoughBaseGas { ref required, ref got } => | ||||||
| 				format!("Not enough base gas. {} is required, but only {} paid", required, got), | 				format!("Not enough base gas. {} is required, but only {} paid", required, got), | ||||||
| 			BlockGasLimitReached { gas_limit, gas_used, gas } => | 			BlockGasLimitReached { ref gas_limit, ref gas_used, ref gas } => | ||||||
| 				format!("Block gas limit reached. The limit is {}, {} has \ | 				format!("Block gas limit reached. The limit is {}, {} has \ | ||||||
| 					already been used, and {} more is required", gas_limit, gas_used, gas),
 | 					already been used, and {} more is required", gas_limit, gas_used, gas),
 | ||||||
| 			InvalidNonce { expected, got } => | 			InvalidNonce { ref expected, ref got } => | ||||||
| 				format!("Invalid transaction nonce: expected {}, found {}", expected, got), | 				format!("Invalid transaction nonce: expected {}, found {}", expected, got), | ||||||
| 			NotEnoughCash { required, got } => | 			NotEnoughCash { ref required, ref got } => | ||||||
| 				format!("Cost of transaction exceeds sender balance. {} is required \ | 				format!("Cost of transaction exceeds sender balance. {} is required \ | ||||||
| 					but the sender only has {}", required, got),
 | 					but the sender only has {}", required, got),
 | ||||||
| 			Internal => "Internal evm error".into(), | 			Internal(ref msg) => msg.clone(), | ||||||
| 			TransactionMalformed(ref err) => format!("Malformed transaction: {}", err), | 			TransactionMalformed(ref err) => format!("Malformed transaction: {}", err), | ||||||
| 		}; | 		}; | ||||||
| 
 | 
 | ||||||
| @ -184,6 +190,8 @@ pub enum CallError { | |||||||
| 	StatePruned, | 	StatePruned, | ||||||
| 	/// Couldn't find an amount of gas that didn't result in an exception.
 | 	/// Couldn't find an amount of gas that didn't result in an exception.
 | ||||||
| 	Exceptional, | 	Exceptional, | ||||||
|  | 	/// Corrupt state.
 | ||||||
|  | 	StateCorrupt, | ||||||
| 	/// Error executing.
 | 	/// Error executing.
 | ||||||
| 	Execution(ExecutionError), | 	Execution(ExecutionError), | ||||||
| } | } | ||||||
| @ -202,6 +210,7 @@ impl fmt::Display for CallError { | |||||||
| 			TransactionNotFound => "Transaction couldn't be found in the chain".into(), | 			TransactionNotFound => "Transaction couldn't be found in the chain".into(), | ||||||
| 			StatePruned => "Couldn't find the transaction block's state in the chain".into(), | 			StatePruned => "Couldn't find the transaction block's state in the chain".into(), | ||||||
| 			Exceptional => "An exception happened in the execution".into(), | 			Exceptional => "An exception happened in the execution".into(), | ||||||
|  | 			StateCorrupt => "Stored state found to be corrupted.".into(), | ||||||
| 			Execution(ref e) => format!("{}", e), | 			Execution(ref e) => format!("{}", e), | ||||||
| 		}; | 		}; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -40,19 +40,25 @@ pub enum Error { | |||||||
| 	Internal, | 	Internal, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl From<EvmError> for Error { | impl<'a> From<&'a EvmError> for Error { | ||||||
| 	fn from(e: EvmError) -> Self { | 	fn from(e: &'a EvmError) -> Self { | ||||||
| 		match e { | 		match *e { | ||||||
| 			EvmError::OutOfGas => Error::OutOfGas, | 			EvmError::OutOfGas => Error::OutOfGas, | ||||||
| 			EvmError::BadJumpDestination { .. } => Error::BadJumpDestination, | 			EvmError::BadJumpDestination { .. } => Error::BadJumpDestination, | ||||||
| 			EvmError::BadInstruction { .. } => Error::BadInstruction, | 			EvmError::BadInstruction { .. } => Error::BadInstruction, | ||||||
| 			EvmError::StackUnderflow { .. } => Error::StackUnderflow, | 			EvmError::StackUnderflow { .. } => Error::StackUnderflow, | ||||||
| 			EvmError::OutOfStack { .. } => Error::OutOfStack, | 			EvmError::OutOfStack { .. } => Error::OutOfStack, | ||||||
| 			EvmError::Internal => Error::Internal, | 			EvmError::Internal(_) => Error::Internal, | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | impl From<EvmError> for Error { | ||||||
|  | 	fn from(e: EvmError) -> Self { | ||||||
|  | 		Error::from(&e) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| impl fmt::Display for Error { | impl fmt::Display for Error { | ||||||
| 	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | 	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||||
| 		use self::Error::*; | 		use self::Error::*; | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user