From 5d9f5e3509e298d8d55b815d7f4410b1c5ebdf3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 30 Jun 2017 11:30:32 +0200 Subject: [PATCH] Defer code hash calculation. --- ethcore/src/action_params.rs | 6 ++--- ethcore/src/client/client.rs | 2 +- ethcore/src/engines/mod.rs | 2 +- ethcore/src/evm/interpreter/mod.rs | 3 ++- ethcore/src/evm/tests.rs | 4 ++-- ethcore/src/executive.rs | 37 +++++++++++++++-------------- ethcore/src/externalities.rs | 9 ++++--- ethcore/src/json_tests/executive.rs | 2 +- ethcore/src/miner/miner.rs | 2 +- ethcore/src/spec/spec.rs | 2 +- evmbin/src/display/json.rs | 2 +- rpc/src/v1/types/transaction.rs | 5 ++-- 12 files changed, 38 insertions(+), 38 deletions(-) diff --git a/ethcore/src/action_params.rs b/ethcore/src/action_params.rs index 9ff86418e..96f7b1136 100644 --- a/ethcore/src/action_params.rs +++ b/ethcore/src/action_params.rs @@ -48,7 +48,7 @@ pub struct ActionParams { /// Address of currently executed code. pub code_address: Address, /// Hash of currently executed code. - pub code_hash: H256, + pub code_hash: Option, /// Receive address. Usually equal to code_address, /// except when called using CALLCODE. pub address: Address, @@ -76,7 +76,7 @@ impl Default for ActionParams { fn default() -> ActionParams { ActionParams { code_address: Address::new(), - code_hash: SHA3_EMPTY, + code_hash: Some(SHA3_EMPTY), address: Address::new(), sender: Address::new(), origin: Address::new(), @@ -95,7 +95,7 @@ impl From for ActionParams { let address: Address = t.address.into(); ActionParams { code_address: Address::new(), - code_hash: (&*t.code).sha3(), + code_hash: Some((&*t.code).sha3()), address: address, sender: t.sender.into(), origin: t.origin.into(), diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 98cefdabd..dcb9ab9f8 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -1841,7 +1841,7 @@ fn transaction_receipt(engine: &Engine, mut tx: LocalizedTransaction, mut receip gas_used: receipt.gas_used - prior_gas_used, contract_address: match tx.action { Action::Call(_) => None, - Action::Create => Some(contract_address(engine.create_address_scheme(block_number), &sender, &tx.nonce, &tx.data.sha3())) + Action::Create => Some(contract_address(engine.create_address_scheme(block_number), &sender, &tx.nonce, &tx.data).0) }, logs: receipt.logs.into_iter().enumerate().map(|(i, log)| LocalizedLogEntry { entry: log, diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index d24325803..632ba08c3 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -434,7 +434,7 @@ pub mod common { gas_price: 0.into(), value: ActionValue::Transfer(0.into()), code: state.code(&contract_address)?, - code_hash: state.code_hash(&contract_address)?, + code_hash: Some(state.code_hash(&contract_address)?), data: data, call_type: CallType::Call, }; diff --git a/ethcore/src/evm/interpreter/mod.rs b/ethcore/src/evm/interpreter/mod.rs index 72112faed..7b0becdb7 100644 --- a/ethcore/src/evm/interpreter/mod.rs +++ b/ethcore/src/evm/interpreter/mod.rs @@ -163,7 +163,8 @@ impl evm::Evm for Interpreter { match result { InstructionResult::JumpToPosition(position) => { if valid_jump_destinations.is_none() { - valid_jump_destinations = Some(self.cache.jump_destinations(¶ms.code_hash, code)); + let code_hash = params.code_hash.clone().unwrap_or_else(|| code.sha3()); + valid_jump_destinations = Some(self.cache.jump_destinations(&code_hash, code)); } let jump_destinations = valid_jump_destinations.as_ref().expect("jump_destinations are initialized on first jump; qed"); let pos = self.verify_jump(position, jump_destinations)?; diff --git a/ethcore/src/evm/tests.rs b/ethcore/src/evm/tests.rs index 7f3cf0e1c..832e003bf 100644 --- a/ethcore/src/evm/tests.rs +++ b/ethcore/src/evm/tests.rs @@ -462,7 +462,7 @@ fn test_blockhash_eip210(factory: super::Factory) { gas_price: 0.into(), value: ActionValue::Transfer(0.into()), code: Some(blockhash_contract_code.clone()), - code_hash: blockhash_contract_code_hash, + code_hash: Some(blockhash_contract_code_hash), data: Some(H256::from(i - 1).to_vec()), call_type: CallType::Call, }; @@ -484,7 +484,7 @@ fn test_blockhash_eip210(factory: super::Factory) { gas_price: 0.into(), value: ActionValue::Transfer(0.into()), code: Some(get_prev_hash_code), - code_hash: get_prev_hash_code_hash, + code_hash: Some(get_prev_hash_code_hash), data: None, call_type: CallType::Call, }; diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index b486aa8d4..bf4e7dd26 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -35,7 +35,7 @@ pub use types::executed::{Executed, ExecutionResult}; const STACK_SIZE_PER_DEPTH: usize = 24*1024; /// Returns new address created from address, nonce, and code hash -pub fn contract_address(address_scheme: CreateContractAddress, sender: &Address, nonce: &U256, code_hash: &H256) -> Address { +pub fn contract_address(address_scheme: CreateContractAddress, sender: &Address, nonce: &U256, code: &[u8]) -> (Address, Option) { use rlp::RlpStream; match address_scheme { @@ -43,18 +43,20 @@ pub fn contract_address(address_scheme: CreateContractAddress, sender: &Address, let mut stream = RlpStream::new_list(2); stream.append(sender); stream.append(nonce); - From::from(stream.as_raw().sha3()) + (From::from(stream.as_raw().sha3()), None) }, CreateContractAddress::FromCodeHash => { + let code_hash = code.sha3(); let mut buffer = [0xffu8; 20 + 32]; &mut buffer[20..].copy_from_slice(&code_hash[..]); - From::from((&buffer[..]).sha3()) + (From::from((&buffer[..]).sha3()), Some(code_hash)) }, CreateContractAddress::FromSenderAndCodeHash => { + let code_hash = code.sha3(); let mut buffer = [0u8; 20 + 32]; &mut buffer[..20].copy_from_slice(&sender[..]); &mut buffer[20..].copy_from_slice(&code_hash[..]); - From::from((&buffer[..]).sha3()) + (From::from((&buffer[..]).sha3()), Some(code_hash)) }, } } @@ -205,8 +207,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { let (result, output) = match t.action { Action::Create => { - let code_hash = t.data.sha3(); - let new_address = contract_address(self.engine.create_address_scheme(self.info.number), &sender, &nonce, &code_hash); + let (new_address, code_hash) = contract_address(self.engine.create_address_scheme(self.info.number), &sender, &nonce, &t.data); let params = ActionParams { code_address: new_address.clone(), code_hash: code_hash, @@ -232,7 +233,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { gas_price: t.gas_price, value: ActionValue::Transfer(t.value), code: self.state.code(address)?, - code_hash: self.state.code_hash(address)?, + code_hash: Some(self.state.code_hash(address)?), data: Some(t.data.clone()), call_type: CallType::Call, }; @@ -599,14 +600,14 @@ mod tests { fn test_contract_address() { let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); let expected_address = Address::from_str("3f09c73a5ed19289fb9bdc72f1742566df146f56").unwrap(); - assert_eq!(expected_address, contract_address(CreateContractAddress::FromSenderAndNonce, &address, &U256::from(88), &H256::default())); + assert_eq!(expected_address, contract_address(CreateContractAddress::FromSenderAndNonce, &address, &U256::from(88), &[]).0); } // TODO: replace params with transactions! evm_test!{test_sender_balance: test_sender_balance_jit, test_sender_balance_int} fn test_sender_balance(factory: Factory) { let sender = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); - let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &H256::default()); + let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &[]).0; let mut params = ActionParams::default(); params.address = address.clone(); params.sender = sender.clone(); @@ -661,7 +662,7 @@ mod tests { let code = "7c601080600c6000396000f3006000355415600957005b60203560003555600052601d60036017f0600055".from_hex().unwrap(); let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap(); - let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &H256::default()); + let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &[]).0; // TODO: add tests for 'callcreate' //let next_address = contract_address(&address, &U256::zero()); let mut params = ActionParams::default(); @@ -715,7 +716,7 @@ mod tests { let code = "7c601080600c6000396000f3006000355415600957005b60203560003555600052601d60036017f0600055".from_hex().unwrap(); let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap(); - let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &H256::default()); + let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &[]).0; // TODO: add tests for 'callcreate' //let next_address = contract_address(&address, &U256::zero()); let mut params = ActionParams::default(); @@ -826,7 +827,7 @@ mod tests { let code = "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(); let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap(); - let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &H256::default()); + let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &[]).0; // TODO: add tests for 'callcreate' //let next_address = contract_address(&address, &U256::zero()); let mut params = ActionParams::default(); @@ -913,7 +914,7 @@ mod tests { let code = "7c601080600c6000396000f3006000355415600957005b60203560003555600052601d600360e6f0600055".from_hex().unwrap(); let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap(); - let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &H256::default()); + let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &[]).0; // TODO: add tests for 'callcreate' //let next_address = contract_address(&address, &U256::zero()); let mut params = ActionParams::default(); @@ -965,8 +966,8 @@ mod tests { let code = "7c601080600c6000396000f3006000355415600957005b60203560003555600052601d60036017f0".from_hex().unwrap(); let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap(); - let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &H256::default()); - let next_address = contract_address(CreateContractAddress::FromSenderAndNonce, &address, &U256::zero(), &H256::default()); + let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &[]).0; + let next_address = contract_address(CreateContractAddress::FromSenderAndNonce, &address, &U256::zero(), &[]).0; let mut params = ActionParams::default(); params.address = address.clone(); params.sender = sender.clone(); @@ -1073,7 +1074,7 @@ mod tests { // 55 - sstore let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap(); let code = "600160005401600055600060006000600060003060e05a03f1600155".from_hex().unwrap(); - let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &H256::default()); + let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &[]).0; let mut params = ActionParams::default(); params.address = address.clone(); params.gas = U256::from(100_000); @@ -1108,7 +1109,7 @@ mod tests { nonce: U256::zero() }.sign(keypair.secret(), None); let sender = t.sender(); - let contract = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &H256::default()); + let contract = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &[]).0; let mut state = get_temp_state_with_factory(factory); state.add_balance(&sender, &U256::from(18), CleanupMode::NoEmpty).unwrap(); @@ -1237,7 +1238,7 @@ mod tests { let code = "6064640fffffffff20600055".from_hex().unwrap(); let sender = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); - let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &H256::default()); + let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &[]).0; // TODO: add tests for 'callcreate' //let next_address = contract_address(&address, &U256::zero()); let mut params = ActionParams::default(); diff --git a/ethcore/src/externalities.rs b/ethcore/src/externalities.rs index 6abb6e3fa..3d30abf2a 100644 --- a/ethcore/src/externalities.rs +++ b/ethcore/src/externalities.rs @@ -157,7 +157,7 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E> gas: self.engine.params().eip210_contract_gas, gas_price: 0.into(), code: code, - code_hash: code_hash, + code_hash: Some(code_hash), data: Some(H256::from(number).to_vec()), call_type: CallType::Call, }; @@ -187,9 +187,8 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E> fn create(&mut self, gas: &U256, value: &U256, code: &[u8], address_scheme: CreateContractAddress) -> ContractCreateResult { // create new contract address - let code_hash = code.sha3(); - let address = match self.state.nonce(&self.origin_info.address) { - Ok(nonce) => contract_address(address_scheme, &self.origin_info.address, &nonce, &code_hash), + let (address, code_hash) = match self.state.nonce(&self.origin_info.address) { + Ok(nonce) => contract_address(address_scheme, &self.origin_info.address, &nonce, &code), Err(e) => { debug!(target: "ext", "Database corruption encountered: {:?}", e); return ContractCreateResult::Failed @@ -258,7 +257,7 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E> gas: *gas, gas_price: self.origin_info.gas_price, code: code, - code_hash: code_hash, + code_hash: Some(code_hash), data: Some(data.to_vec()), call_type: call_type, }; diff --git a/ethcore/src/json_tests/executive.rs b/ethcore/src/json_tests/executive.rs index 7e37818f2..b7fad2787 100644 --- a/ethcore/src/json_tests/executive.rs +++ b/ethcore/src/json_tests/executive.rs @@ -123,7 +123,7 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for TestExt<'a, T, V, B, E> gas_limit: *gas, value: *value }); - let contract_address = contract_address(address, &self.sender, &self.nonce, &code.sha3()); + let contract_address = contract_address(address, &self.sender, &self.nonce, &code).0; ContractCreateResult::Created(contract_address, *gas) } diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index c772490ba..dc2c97431 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -1051,7 +1051,7 @@ impl MinerService for Miner { Action::Call(_) => None, Action::Create => { let sender = tx.sender(); - Some(contract_address(self.engine.create_address_scheme(pending.header().number()), &sender, &tx.nonce, &tx.data.sha3())) + Some(contract_address(self.engine.create_address_scheme(pending.header().number()), &sender, &tx.nonce, &tx.data).0) } }, logs: receipt.logs.clone(), diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index 1d0d2bc6f..c2c4e172d 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -260,7 +260,7 @@ impl Spec { trace!(target: "spec", " .. root before = {}", state.root()); let params = ActionParams { code_address: address.clone(), - code_hash: constructor.sha3(), + code_hash: Some(constructor.sha3()), address: address.clone(), sender: from.clone(), origin: from.clone(), diff --git a/evmbin/src/display/json.rs b/evmbin/src/display/json.rs index 38265c14c..1791640d6 100644 --- a/evmbin/src/display/json.rs +++ b/evmbin/src/display/json.rs @@ -122,7 +122,7 @@ impl trace::VMTracer for Informant { fn prepare_subtrace(&self, code: &[u8]) -> Self where Self: Sized { let mut vm = Informant::default(); vm.depth = self.depth + 1; - vm.code = code.into_vec(); + vm.code = code.to_vec(); vm.gas_used = self.gas_used; vm } diff --git a/rpc/src/v1/types/transaction.rs b/rpc/src/v1/types/transaction.rs index 7cc109ec2..ee0203d65 100644 --- a/rpc/src/v1/types/transaction.rs +++ b/rpc/src/v1/types/transaction.rs @@ -16,7 +16,6 @@ use serde::{Serialize, Serializer}; use serde::ser::SerializeStruct; -use util::Hashable; use ethcore::miner; use ethcore::{contract_address, CreateContractAddress}; use ethcore::transaction::{LocalizedTransaction, Action, PendingTransaction, SignedTransaction}; @@ -192,7 +191,7 @@ impl Transaction { gas: t.gas.into(), input: Bytes::new(t.data.clone()), creates: match t.action { - Action::Create => Some(contract_address(scheme, &t.sender(), &t.nonce, &t.data.sha3()).into()), + Action::Create => Some(contract_address(scheme, &t.sender(), &t.nonce, &t.data).0.into()), Action::Call(_) => None, }, raw: ::rlp::encode(&t.signed).into_vec().into(), @@ -226,7 +225,7 @@ impl Transaction { gas: t.gas.into(), input: Bytes::new(t.data.clone()), creates: match t.action { - Action::Create => Some(contract_address(scheme, &t.sender(), &t.nonce, &t.data.sha3()).into()), + Action::Create => Some(contract_address(scheme, &t.sender(), &t.nonce, &t.data).0.into()), Action::Call(_) => None, }, raw: ::rlp::encode(&t).into_vec().into(),