EIP-86 fixes (#5506)
This commit is contained in:
		
							parent
							
								
									8b9adb4d74
								
							
						
					
					
						commit
						ed7c366b90
					
				@ -1354,8 +1354,7 @@ impl BlockChainClient for Client {
 | 
				
			|||||||
					.collect();
 | 
										.collect();
 | 
				
			||||||
				match (transaction, previous_receipts) {
 | 
									match (transaction, previous_receipts) {
 | 
				
			||||||
					(Some(transaction), Some(previous_receipts)) => {
 | 
										(Some(transaction), Some(previous_receipts)) => {
 | 
				
			||||||
						let schedule = self.engine().schedule(block_number);
 | 
											Some(transaction_receipt(self.engine(), transaction, previous_receipts))
 | 
				
			||||||
						Some(transaction_receipt(&schedule, transaction, previous_receipts))
 | 
					 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
					_ => None,
 | 
										_ => None,
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
@ -1748,7 +1747,7 @@ impl Drop for Client {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/// Returns `LocalizedReceipt` given `LocalizedTransaction`
 | 
					/// Returns `LocalizedReceipt` given `LocalizedTransaction`
 | 
				
			||||||
/// and a vector of receipts from given block up to transaction index.
 | 
					/// and a vector of receipts from given block up to transaction index.
 | 
				
			||||||
fn transaction_receipt(schedule: &Schedule, mut tx: LocalizedTransaction, mut receipts: Vec<Receipt>) -> LocalizedReceipt {
 | 
					fn transaction_receipt(engine: &Engine, mut tx: LocalizedTransaction, mut receipts: Vec<Receipt>) -> LocalizedReceipt {
 | 
				
			||||||
	assert_eq!(receipts.len(), tx.transaction_index + 1, "All previous receipts are provided.");
 | 
						assert_eq!(receipts.len(), tx.transaction_index + 1, "All previous receipts are provided.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let sender = tx.sender();
 | 
						let sender = tx.sender();
 | 
				
			||||||
@ -1772,7 +1771,7 @@ fn transaction_receipt(schedule: &Schedule, mut tx: LocalizedTransaction, mut re
 | 
				
			|||||||
		gas_used: receipt.gas_used - prior_gas_used,
 | 
							gas_used: receipt.gas_used - prior_gas_used,
 | 
				
			||||||
		contract_address: match tx.action {
 | 
							contract_address: match tx.action {
 | 
				
			||||||
			Action::Call(_) => None,
 | 
								Action::Call(_) => None,
 | 
				
			||||||
			Action::Create => Some(contract_address(schedule.create_address, &sender, &tx.nonce, &tx.data.sha3()))
 | 
								Action::Create => Some(contract_address(engine.create_address_scheme(block_number), &sender, &tx.nonce, &tx.data.sha3()))
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		logs: receipt.logs.into_iter().enumerate().map(|(i, log)| LocalizedLogEntry {
 | 
							logs: receipt.logs.into_iter().enumerate().map(|(i, log)| LocalizedLogEntry {
 | 
				
			||||||
			entry: log,
 | 
								entry: log,
 | 
				
			||||||
@ -1827,17 +1826,17 @@ mod tests {
 | 
				
			|||||||
	#[test]
 | 
						#[test]
 | 
				
			||||||
	fn should_return_correct_log_index() {
 | 
						fn should_return_correct_log_index() {
 | 
				
			||||||
		use super::transaction_receipt;
 | 
							use super::transaction_receipt;
 | 
				
			||||||
		use evm::schedule::Schedule;
 | 
					 | 
				
			||||||
		use ethkey::KeyPair;
 | 
							use ethkey::KeyPair;
 | 
				
			||||||
		use log_entry::{LogEntry, LocalizedLogEntry};
 | 
							use log_entry::{LogEntry, LocalizedLogEntry};
 | 
				
			||||||
		use receipt::{Receipt, LocalizedReceipt};
 | 
							use receipt::{Receipt, LocalizedReceipt};
 | 
				
			||||||
		use transaction::{Transaction, LocalizedTransaction, Action};
 | 
							use transaction::{Transaction, LocalizedTransaction, Action};
 | 
				
			||||||
		use util::Hashable;
 | 
							use util::Hashable;
 | 
				
			||||||
 | 
							use tests::helpers::TestEngine;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// given
 | 
							// given
 | 
				
			||||||
		let key = KeyPair::from_secret_slice(&"test".sha3()).unwrap();
 | 
							let key = KeyPair::from_secret_slice(&"test".sha3()).unwrap();
 | 
				
			||||||
		let secret = key.secret();
 | 
							let secret = key.secret();
 | 
				
			||||||
		let schedule = Schedule::new_homestead();
 | 
							let engine = TestEngine::new(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let block_number = 1;
 | 
							let block_number = 1;
 | 
				
			||||||
		let block_hash = 5.into();
 | 
							let block_hash = 5.into();
 | 
				
			||||||
@ -1881,7 +1880,7 @@ mod tests {
 | 
				
			|||||||
		}];
 | 
							}];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// when
 | 
							// when
 | 
				
			||||||
		let receipt = transaction_receipt(&schedule, transaction, receipts);
 | 
							let receipt = transaction_receipt(&engine, transaction, receipts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// then
 | 
							// then
 | 
				
			||||||
		assert_eq!(receipt, LocalizedReceipt {
 | 
							assert_eq!(receipt, LocalizedReceipt {
 | 
				
			||||||
 | 
				
			|||||||
@ -48,6 +48,7 @@ use receipt::Receipt;
 | 
				
			|||||||
use snapshot::SnapshotComponents;
 | 
					use snapshot::SnapshotComponents;
 | 
				
			||||||
use spec::CommonParams;
 | 
					use spec::CommonParams;
 | 
				
			||||||
use transaction::{UnverifiedTransaction, SignedTransaction};
 | 
					use transaction::{UnverifiedTransaction, SignedTransaction};
 | 
				
			||||||
 | 
					use evm::CreateContractAddress;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use ethkey::Signature;
 | 
					use ethkey::Signature;
 | 
				
			||||||
use util::*;
 | 
					use util::*;
 | 
				
			||||||
@ -294,4 +295,9 @@ pub trait Engine : Sync + Send {
 | 
				
			|||||||
	fn snapshot_components(&self) -> Option<Box<SnapshotComponents>> {
 | 
						fn snapshot_components(&self) -> Option<Box<SnapshotComponents>> {
 | 
				
			||||||
		None
 | 
							None
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// Returns new contract address generation scheme at given block number.
 | 
				
			||||||
 | 
						fn create_address_scheme(&self, number: BlockNumber) -> CreateContractAddress {
 | 
				
			||||||
 | 
							if number >= self.params().eip86_transition { CreateContractAddress::FromCodeHash } else { CreateContractAddress::FromSenderAndNonce }
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -278,7 +278,7 @@ lazy_static! {
 | 
				
			|||||||
		arr[RETURN as usize] =			InstructionInfo::new("RETURN",			0, 2, 0, true, GasPriceTier::Zero);
 | 
							arr[RETURN as usize] =			InstructionInfo::new("RETURN",			0, 2, 0, true, GasPriceTier::Zero);
 | 
				
			||||||
		arr[DELEGATECALL as usize] =	InstructionInfo::new("DELEGATECALL",	0, 6, 1, true, GasPriceTier::Special);
 | 
							arr[DELEGATECALL as usize] =	InstructionInfo::new("DELEGATECALL",	0, 6, 1, true, GasPriceTier::Special);
 | 
				
			||||||
		arr[SUICIDE as usize] = 		InstructionInfo::new("SUICIDE",			0, 1, 0, true, GasPriceTier::Special);
 | 
							arr[SUICIDE as usize] = 		InstructionInfo::new("SUICIDE",			0, 1, 0, true, GasPriceTier::Special);
 | 
				
			||||||
		arr[CREATE_P2SH as usize] = 	InstructionInfo::new("CREATE_P2SH",		0, 3, 1, true, GasPriceTier::Special);
 | 
							arr[CREATE2 as usize] = 		InstructionInfo::new("CREATE2",			0, 3, 1, true, GasPriceTier::Special);
 | 
				
			||||||
		arr
 | 
							arr
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -555,7 +555,7 @@ pub const RETURN: Instruction = 0xf3;
 | 
				
			|||||||
/// like CALLCODE but keeps caller's value and sender
 | 
					/// like CALLCODE but keeps caller's value and sender
 | 
				
			||||||
pub const DELEGATECALL: Instruction = 0xf4;
 | 
					pub const DELEGATECALL: Instruction = 0xf4;
 | 
				
			||||||
/// create a new account and set creation address to sha3(sender + sha3(init code)) % 2**160
 | 
					/// create a new account and set creation address to sha3(sender + sha3(init code)) % 2**160
 | 
				
			||||||
pub const CREATE_P2SH: Instruction = 0xfb;
 | 
					pub const CREATE2: Instruction = 0xfb;
 | 
				
			||||||
/// halt execution and register account for later deletion
 | 
					/// halt execution and register account for later deletion
 | 
				
			||||||
pub const SUICIDE: Instruction = 0xff;
 | 
					pub const SUICIDE: Instruction = 0xff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -223,7 +223,7 @@ impl<Gas: CostType> Gasometer<Gas> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
				Request::GasMemProvide(gas, mem, Some(requested))
 | 
									Request::GasMemProvide(gas, mem, Some(requested))
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			instructions::CREATE | instructions::CREATE_P2SH => {
 | 
								instructions::CREATE | instructions::CREATE2 => {
 | 
				
			||||||
				let gas = Gas::from(schedule.create_gas);
 | 
									let gas = Gas::from(schedule.create_gas);
 | 
				
			||||||
				let mem = mem_needed(stack.peek(1), stack.peek(2))?;
 | 
									let mem = mem_needed(stack.peek(1), stack.peek(2))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -183,7 +183,7 @@ impl<Cost: CostType> Interpreter<Cost> {
 | 
				
			|||||||
		let schedule = ext.schedule();
 | 
							let schedule = ext.schedule();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (instruction == instructions::DELEGATECALL && !schedule.have_delegate_call) ||
 | 
							if (instruction == instructions::DELEGATECALL && !schedule.have_delegate_call) ||
 | 
				
			||||||
			(instruction == instructions::CREATE_P2SH && !schedule.have_create_p2sh) {
 | 
								(instruction == instructions::CREATE2 && !schedule.have_create2) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return Err(evm::Error::BadInstruction {
 | 
								return Err(evm::Error::BadInstruction {
 | 
				
			||||||
				instruction: instruction
 | 
									instruction: instruction
 | 
				
			||||||
@ -268,12 +268,12 @@ impl<Cost: CostType> Interpreter<Cost> {
 | 
				
			|||||||
			instructions::JUMPDEST => {
 | 
								instructions::JUMPDEST => {
 | 
				
			||||||
				// ignore
 | 
									// ignore
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			instructions::CREATE | instructions::CREATE_P2SH => {
 | 
								instructions::CREATE | instructions::CREATE2 => {
 | 
				
			||||||
				let endowment = stack.pop_back();
 | 
									let endowment = stack.pop_back();
 | 
				
			||||||
				let init_off = stack.pop_back();
 | 
									let init_off = stack.pop_back();
 | 
				
			||||||
				let init_size = stack.pop_back();
 | 
									let init_size = stack.pop_back();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				let address_scheme = if instruction == instructions::CREATE { ext.schedule().create_address } else { CreateContractAddress::FromSenderAndCodeHash };
 | 
									let address_scheme = if instruction == instructions::CREATE { CreateContractAddress::FromSenderAndNonce } else { CreateContractAddress::FromSenderAndCodeHash };
 | 
				
			||||||
				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);
 | 
				
			||||||
 | 
				
			|||||||
@ -15,7 +15,6 @@
 | 
				
			|||||||
// along with Parity.  If not, see <http://www.gnu.org/licenses/>.
 | 
					// along with Parity.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//! Cost schedule and other parameterisations for the EVM.
 | 
					//! Cost schedule and other parameterisations for the EVM.
 | 
				
			||||||
use evm::CreateContractAddress;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Definition of the cost schedule and other parameterisations for the EVM.
 | 
					/// Definition of the cost schedule and other parameterisations for the EVM.
 | 
				
			||||||
pub struct Schedule {
 | 
					pub struct Schedule {
 | 
				
			||||||
@ -24,7 +23,7 @@ pub struct Schedule {
 | 
				
			|||||||
	/// Does it have a delegate cal
 | 
						/// Does it have a delegate cal
 | 
				
			||||||
	pub have_delegate_call: bool,
 | 
						pub have_delegate_call: bool,
 | 
				
			||||||
	/// Does it have a CREATE_P2SH instruction
 | 
						/// Does it have a CREATE_P2SH instruction
 | 
				
			||||||
	pub have_create_p2sh: bool,
 | 
						pub have_create2: bool,
 | 
				
			||||||
	/// VM stack limit
 | 
						/// VM stack limit
 | 
				
			||||||
	pub stack_limit: usize,
 | 
						pub stack_limit: usize,
 | 
				
			||||||
	/// Max number of nested calls/creates
 | 
						/// Max number of nested calls/creates
 | 
				
			||||||
@ -102,8 +101,6 @@ pub struct Schedule {
 | 
				
			|||||||
	pub no_empty: bool,
 | 
						pub no_empty: bool,
 | 
				
			||||||
	/// Kill empty accounts if touched.
 | 
						/// Kill empty accounts if touched.
 | 
				
			||||||
	pub kill_empty: bool,
 | 
						pub kill_empty: bool,
 | 
				
			||||||
	/// Contract address generation scheme
 | 
					 | 
				
			||||||
	pub create_address: CreateContractAddress,
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Schedule {
 | 
					impl Schedule {
 | 
				
			||||||
@ -118,11 +115,11 @@ impl Schedule {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// Schedule for the post-EIP-150-era of the Ethereum main net.
 | 
						/// Schedule for the post-EIP-150-era of the Ethereum main net.
 | 
				
			||||||
	pub fn new_post_eip150(max_code_size: usize, fix_exp: bool, no_empty: bool, kill_empty: bool, have_create_p2sh: bool) -> Schedule {
 | 
						pub fn new_post_eip150(max_code_size: usize, fix_exp: bool, no_empty: bool, kill_empty: bool, have_metropolis_instructions: bool) -> Schedule {
 | 
				
			||||||
		Schedule {
 | 
							Schedule {
 | 
				
			||||||
			exceptional_failed_code_deposit: true,
 | 
								exceptional_failed_code_deposit: true,
 | 
				
			||||||
			have_delegate_call: true,
 | 
								have_delegate_call: true,
 | 
				
			||||||
			have_create_p2sh: have_create_p2sh,
 | 
								have_create2: have_metropolis_instructions,
 | 
				
			||||||
			stack_limit: 1024,
 | 
								stack_limit: 1024,
 | 
				
			||||||
			max_depth: 1024,
 | 
								max_depth: 1024,
 | 
				
			||||||
			tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0],
 | 
								tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0],
 | 
				
			||||||
@ -161,7 +158,6 @@ impl Schedule {
 | 
				
			|||||||
			sub_gas_cap_divisor: Some(64),
 | 
								sub_gas_cap_divisor: Some(64),
 | 
				
			||||||
			no_empty: no_empty,
 | 
								no_empty: no_empty,
 | 
				
			||||||
			kill_empty: kill_empty,
 | 
								kill_empty: kill_empty,
 | 
				
			||||||
			create_address: if have_create_p2sh { CreateContractAddress::FromCodeHash } else { CreateContractAddress::FromSenderAndNonce },
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -174,7 +170,7 @@ impl Schedule {
 | 
				
			|||||||
		Schedule {
 | 
							Schedule {
 | 
				
			||||||
			exceptional_failed_code_deposit: efcd,
 | 
								exceptional_failed_code_deposit: efcd,
 | 
				
			||||||
			have_delegate_call: hdc,
 | 
								have_delegate_call: hdc,
 | 
				
			||||||
			have_create_p2sh: false,
 | 
								have_create2: false,
 | 
				
			||||||
			stack_limit: 1024,
 | 
								stack_limit: 1024,
 | 
				
			||||||
			max_depth: 1024,
 | 
								max_depth: 1024,
 | 
				
			||||||
			tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0],
 | 
								tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0],
 | 
				
			||||||
@ -213,7 +209,6 @@ impl Schedule {
 | 
				
			|||||||
			sub_gas_cap_divisor: None,
 | 
								sub_gas_cap_divisor: None,
 | 
				
			||||||
			no_empty: false,
 | 
								no_empty: false,
 | 
				
			||||||
			kill_empty: false,
 | 
								kill_empty: false,
 | 
				
			||||||
			create_address: CreateContractAddress::FromSenderAndNonce,
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -185,7 +185,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
 | 
				
			|||||||
		let (gas_left, output) = match t.action {
 | 
							let (gas_left, output) = match t.action {
 | 
				
			||||||
			Action::Create => {
 | 
								Action::Create => {
 | 
				
			||||||
				let code_hash = t.data.sha3();
 | 
									let code_hash = t.data.sha3();
 | 
				
			||||||
				let new_address = contract_address(schedule.create_address, &sender, &nonce, &code_hash);
 | 
									let new_address = contract_address(self.engine.create_address_scheme(self.info.number), &sender, &nonce, &code_hash);
 | 
				
			||||||
				let params = ActionParams {
 | 
									let params = ActionParams {
 | 
				
			||||||
					code_address: new_address.clone(),
 | 
										code_address: new_address.clone(),
 | 
				
			||||||
					code_hash: code_hash,
 | 
										code_hash: code_hash,
 | 
				
			||||||
@ -386,8 +386,8 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
 | 
				
			|||||||
		vm_tracer: &mut V,
 | 
							vm_tracer: &mut V,
 | 
				
			||||||
	) -> evm::Result<U256> where T: Tracer, V: VMTracer {
 | 
						) -> evm::Result<U256> where T: Tracer, V: VMTracer {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let schedule = self.engine.schedule(self.info.number);
 | 
							let scheme = self.engine.create_address_scheme(self.info.number);
 | 
				
			||||||
		if schedule.create_address != CreateContractAddress::FromSenderAndNonce && self.state.exists(¶ms.address)? {
 | 
							if scheme != CreateContractAddress::FromSenderAndNonce && self.state.exists_and_has_code(¶ms.address)? {
 | 
				
			||||||
			return Err(evm::Error::OutOfGas);
 | 
								return Err(evm::Error::OutOfGas);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -398,6 +398,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
 | 
				
			|||||||
		let mut unconfirmed_substate = Substate::new();
 | 
							let mut unconfirmed_substate = Substate::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// 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.number);
 | 
				
			||||||
		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 {
 | 
				
			||||||
 | 
				
			|||||||
@ -1048,7 +1048,7 @@ impl MinerService for Miner {
 | 
				
			|||||||
								Action::Call(_) => None,
 | 
													Action::Call(_) => None,
 | 
				
			||||||
								Action::Create => {
 | 
													Action::Create => {
 | 
				
			||||||
									let sender = tx.sender();
 | 
														let sender = tx.sender();
 | 
				
			||||||
									Some(contract_address(self.engine.schedule(pending.header().number()).create_address, &sender, &tx.nonce, &tx.data.sha3()))
 | 
														Some(contract_address(self.engine.create_address_scheme(pending.header().number()), &sender, &tx.nonce, &tx.data.sha3()))
 | 
				
			||||||
								}
 | 
													}
 | 
				
			||||||
							},
 | 
												},
 | 
				
			||||||
							logs: receipt.logs.clone(),
 | 
												logs: receipt.logs.clone(),
 | 
				
			||||||
 | 
				
			|||||||
@ -433,6 +433,11 @@ impl<B: Backend> State<B> {
 | 
				
			|||||||
		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()))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// Determine whether an account exists and has code.
 | 
				
			||||||
 | 
						pub fn exists_and_has_code(&self, a: &Address) -> trie::Result<bool> {
 | 
				
			||||||
 | 
							self.ensure_cached(a, RequireCache::CodeSize, false, |a| a.map_or(false, |a| a.code_size().map_or(false, |size| size != 0)))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// Get the balance of account `a`.
 | 
						/// Get the balance of account `a`.
 | 
				
			||||||
	pub fn balance(&self, a: &Address) -> trie::Result<U256> {
 | 
						pub fn balance(&self, a: &Address) -> trie::Result<U256> {
 | 
				
			||||||
		self.ensure_cached(a, RequireCache::None, true,
 | 
							self.ensure_cached(a, RequireCache::None, true,
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user