From eefc94eaf65288cf3a949b2f59114aeb3ace8973 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Tue, 31 Jul 2018 13:27:57 +0800 Subject: [PATCH 01/19] Implement EIP-1052 (EXTCODEHASH) and fix several issues in state account cache (#9234) * Implement EIP-1052 and fix several issues related to account cache * Fix jsontests * Merge two matches together * Avoid making unnecessary Arc * Address grumbles --- ethcore/evm/src/instructions.rs | 3 ++ ethcore/evm/src/interpreter/gasometer.rs | 3 ++ ethcore/evm/src/interpreter/mod.rs | 18 +++++++--- ethcore/src/client/client.rs | 2 +- ethcore/src/executive.rs | 2 +- ethcore/src/externalities.rs | 16 +++++---- ethcore/src/json_tests/executive.rs | 8 +++-- ethcore/src/machine.rs | 2 +- ethcore/src/spec/spec.rs | 7 ++++ ethcore/src/state/account.rs | 16 +++++---- ethcore/src/state/mod.rs | 46 +++++++++++++++--------- ethcore/vm/src/ext.rs | 7 ++-- ethcore/vm/src/schedule.rs | 8 +++++ ethcore/vm/src/tests.rs | 13 ++++--- json/src/spec/params.rs | 3 ++ 15 files changed, 111 insertions(+), 43 deletions(-) diff --git a/ethcore/evm/src/instructions.rs b/ethcore/evm/src/instructions.rs index 7a41ed33c75..3be4556942c 100644 --- a/ethcore/evm/src/instructions.rs +++ b/ethcore/evm/src/instructions.rs @@ -134,6 +134,8 @@ enum_with_from_u8! { RETURNDATASIZE = 0x3d, #[doc = "copy return data buffer to memory"] RETURNDATACOPY = 0x3e, + #[doc = "return the keccak256 hash of contract code"] + EXTCODEHASH = 0x3f, #[doc = "get hash of most recent complete block"] BLOCKHASH = 0x40, @@ -492,6 +494,7 @@ lazy_static! { arr[CALLDATALOAD as usize] = Some(InstructionInfo::new("CALLDATALOAD", 1, 1, GasPriceTier::VeryLow)); arr[CALLDATASIZE as usize] = Some(InstructionInfo::new("CALLDATASIZE", 0, 1, GasPriceTier::Base)); arr[CALLDATACOPY as usize] = Some(InstructionInfo::new("CALLDATACOPY", 3, 0, GasPriceTier::VeryLow)); + arr[EXTCODEHASH as usize] = Some(InstructionInfo::new("EXTCODEHASH", 1, 1, GasPriceTier::Special)); arr[CODESIZE as usize] = Some(InstructionInfo::new("CODESIZE", 0, 1, GasPriceTier::Base)); arr[CODECOPY as usize] = Some(InstructionInfo::new("CODECOPY", 3, 0, GasPriceTier::VeryLow)); arr[GASPRICE as usize] = Some(InstructionInfo::new("GASPRICE", 0, 1, GasPriceTier::Base)); diff --git a/ethcore/evm/src/interpreter/gasometer.rs b/ethcore/evm/src/interpreter/gasometer.rs index dbb33383793..943a8320bb4 100644 --- a/ethcore/evm/src/interpreter/gasometer.rs +++ b/ethcore/evm/src/interpreter/gasometer.rs @@ -143,6 +143,9 @@ impl Gasometer { instructions::EXTCODESIZE => { Request::Gas(Gas::from(schedule.extcodesize_gas)) }, + instructions::EXTCODEHASH => { + Request::Gas(Gas::from(schedule.extcodehash_gas)) + }, instructions::SUICIDE => { let mut gas = Gas::from(schedule.suicide_gas); diff --git a/ethcore/evm/src/interpreter/mod.rs b/ethcore/evm/src/interpreter/mod.rs index 1119869138c..6b8abcc17f7 100644 --- a/ethcore/evm/src/interpreter/mod.rs +++ b/ethcore/evm/src/interpreter/mod.rs @@ -230,8 +230,9 @@ impl Interpreter { (instruction == instructions::STATICCALL && !schedule.have_static_call) || ((instruction == instructions::RETURNDATACOPY || instruction == instructions::RETURNDATASIZE) && !schedule.have_return_data) || (instruction == instructions::REVERT && !schedule.have_revert) || - ((instruction == instructions::SHL || instruction == instructions::SHR || instruction == instructions::SAR) && !schedule.have_bitwise_shifting) { - + ((instruction == instructions::SHL || instruction == instructions::SHR || instruction == instructions::SAR) && !schedule.have_bitwise_shifting) || + (instruction == instructions::EXTCODEHASH && !schedule.have_extcodehash) + { return Err(vm::Error::BadInstruction { instruction: instruction as u8 }); @@ -568,9 +569,14 @@ impl Interpreter { }, instructions::EXTCODESIZE => { let address = u256_to_address(&stack.pop_back()); - let len = ext.extcodesize(&address)?; + let len = ext.extcodesize(&address)?.unwrap_or(0); stack.push(U256::from(len)); }, + instructions::EXTCODEHASH => { + let address = u256_to_address(&stack.pop_back()); + let hash = ext.extcodehash(&address)?.unwrap_or_else(H256::zero); + stack.push(U256::from(hash)); + }, instructions::CALLDATACOPY => { Self::copy_data_to_memory(&mut self.mem, stack, params.data.as_ref().map_or_else(|| &[] as &[u8], |d| &*d as &[u8])); }, @@ -591,7 +597,11 @@ impl Interpreter { instructions::EXTCODECOPY => { let address = u256_to_address(&stack.pop_back()); let code = ext.extcode(&address)?; - Self::copy_data_to_memory(&mut self.mem, stack, &code); + Self::copy_data_to_memory( + &mut self.mem, + stack, + code.as_ref().map(|c| &(*c)[..]).unwrap_or(&[]) + ); }, instructions::GASPRICE => { stack.push(params.gas_price.clone()); diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index aa5a3019cbe..01ae9291f72 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -1349,7 +1349,7 @@ impl BlockInfo for Client { } fn code_hash(&self, address: &Address, id: BlockId) -> Option { - self.state_at(id).and_then(|s| s.code_hash(address).ok()) + self.state_at(id).and_then(|s| s.code_hash(address).unwrap_or(None)) } } diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index 37dc03dee28..a5084da8a71 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -320,7 +320,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { gas_price: t.gas_price, value: ActionValue::Transfer(t.value), code: self.state.code(address)?, - code_hash: Some(self.state.code_hash(address)?), + code_hash: self.state.code_hash(address)?, data: Some(t.data.clone()), call_type: CallType::Call, params_type: vm::ParamsType::Separate, diff --git a/ethcore/src/externalities.rs b/ethcore/src/externalities.rs index d315122d56a..de8d5282471 100644 --- a/ethcore/src/externalities.rs +++ b/ethcore/src/externalities.rs @@ -163,7 +163,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> gas: self.machine.params().eip210_contract_gas, gas_price: 0.into(), code: code, - code_hash: Some(code_hash), + code_hash: code_hash, data: Some(H256::from(number).to_vec()), call_type: CallType::Call, params_type: vm::ParamsType::Separate, @@ -270,7 +270,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> gas: *gas, gas_price: self.origin_info.gas_price, code: code, - code_hash: Some(code_hash), + code_hash: code_hash, data: Some(data.to_vec()), call_type: call_type, params_type: vm::ParamsType::Separate, @@ -289,12 +289,16 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> } } - fn extcode(&self, address: &Address) -> vm::Result> { - Ok(self.state.code(address)?.unwrap_or_else(|| Arc::new(vec![]))) + fn extcode(&self, address: &Address) -> vm::Result>> { + Ok(self.state.code(address)?) + } + + fn extcodehash(&self, address: &Address) -> vm::Result> { + Ok(self.state.code_hash(address)?) } - fn extcodesize(&self, address: &Address) -> vm::Result { - Ok(self.state.code_size(address)?.unwrap_or(0)) + fn extcodesize(&self, address: &Address) -> vm::Result> { + Ok(self.state.code_size(address)?) } fn ret(mut self, gas: &U256, data: &ReturnData, apply_state: bool) -> vm::Result diff --git a/ethcore/src/json_tests/executive.rs b/ethcore/src/json_tests/executive.rs index daeed18ebfb..7c7ce4969e2 100644 --- a/ethcore/src/json_tests/executive.rs +++ b/ethcore/src/json_tests/executive.rs @@ -165,14 +165,18 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for TestExt<'a, T, V, B> MessageCallResult::Success(*gas, ReturnData::empty()) } - fn extcode(&self, address: &Address) -> vm::Result> { + fn extcode(&self, address: &Address) -> vm::Result>> { self.ext.extcode(address) } - fn extcodesize(&self, address: &Address) -> vm::Result { + fn extcodesize(&self, address: &Address) -> vm::Result> { self.ext.extcodesize(address) } + fn extcodehash(&self, address: &Address) -> vm::Result> { + self.ext.extcodehash(address) + } + fn log(&mut self, topics: Vec, data: &[u8]) -> vm::Result<()> { self.ext.log(topics, data) } diff --git a/ethcore/src/machine.rs b/ethcore/src/machine.rs index dbf66aa1217..d149062c3aa 100644 --- a/ethcore/src/machine.rs +++ b/ethcore/src/machine.rs @@ -140,7 +140,7 @@ impl EthereumMachine { gas_price: 0.into(), value: ActionValue::Transfer(0.into()), code: state.code(&contract_address)?, - code_hash: Some(state.code_hash(&contract_address)?), + code_hash: state.code_hash(&contract_address)?, data: data, call_type: CallType::Call, params_type: ParamsType::Separate, diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index f0243be73c1..bbcc28452e8 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -115,6 +115,8 @@ pub struct CommonParams { pub eip214_transition: BlockNumber, /// Number of first block where EIP-145 rules begin. pub eip145_transition: BlockNumber, + /// Number of first block where EIP-1052 rules begin. + pub eip1052_transition: BlockNumber, /// Number of first block where dust cleanup rules (EIP-168 and EIP169) begin. pub dust_protection_transition: BlockNumber, /// Nonce cap increase per block. Nonce cap is only checked if dust protection is enabled. @@ -174,6 +176,7 @@ impl CommonParams { schedule.have_static_call = block_number >= self.eip214_transition; schedule.have_return_data = block_number >= self.eip211_transition; schedule.have_bitwise_shifting = block_number >= self.eip145_transition; + schedule.have_extcodehash = block_number >= self.eip1052_transition; if block_number >= self.eip210_transition { schedule.blockhash_gas = 800; } @@ -270,6 +273,10 @@ impl From for CommonParams { BlockNumber::max_value, Into::into, ), + eip1052_transition: p.eip1052_transition.map_or_else( + BlockNumber::max_value, + Into::into, + ), dust_protection_transition: p.dust_protection_transition.map_or_else( BlockNumber::max_value, Into::into, diff --git a/ethcore/src/state/account.rs b/ethcore/src/state/account.rs index 359b84b1eca..eec713a4e36 100644 --- a/ethcore/src/state/account.rs +++ b/ethcore/src/state/account.rs @@ -278,12 +278,13 @@ impl Account { !self.code_cache.is_empty() || (self.code_cache.is_empty() && self.code_hash == KECCAK_EMPTY) } - /// Provide a database to get `code_hash`. Should not be called if it is a contract without code. + /// Provide a database to get `code_hash`. Should not be called if it is a contract without code. Returns the cached code, if successful. + #[must_use] pub fn cache_code(&mut self, db: &HashDB) -> Option> { // TODO: fill out self.code_cache; trace!("Account::cache_code: ic={}; self.code_hash={:?}, self.code_cache={}", self.is_cached(), self.code_hash, self.code_cache.pretty()); - if self.is_cached() { return Some(self.code_cache.clone()) } + if self.is_cached() { return Some(self.code_cache.clone()); } match db.get(&self.code_hash) { Some(x) => { @@ -298,8 +299,7 @@ impl Account { } } - /// Provide code to cache. For correctness, should be the correct code for the - /// account. + /// Provide code to cache. For correctness, should be the correct code for the account. pub fn cache_given_code(&mut self, code: Arc) { trace!("Account::cache_given_code: ic={}; self.code_hash={:?}, self.code_cache={}", self.is_cached(), self.code_hash, self.code_cache.pretty()); @@ -307,7 +307,9 @@ impl Account { self.code_cache = code; } - /// Provide a database to get `code_size`. Should not be called if it is a contract without code. + /// Provide a database to get `code_size`. Should not be called if it is a contract without code. Returns whether + /// the cache succeeds. + #[must_use] pub fn cache_code_size(&mut self, db: &HashDB) -> bool { // TODO: fill out self.code_cache; trace!("Account::cache_code_size: ic={}; self.code_hash={:?}, self.code_cache={}", self.is_cached(), self.code_hash, self.code_cache.pretty()); @@ -324,7 +326,9 @@ impl Account { }, } } else { - false + // If the code hash is empty hash, then the code size is zero. + self.code_size = Some(0); + true } } diff --git a/ethcore/src/state/mod.rs b/ethcore/src/state/mod.rs index 0118f4d850c..354f6f60eb9 100644 --- a/ethcore/src/state/mod.rs +++ b/ethcore/src/state/mod.rs @@ -607,9 +607,9 @@ impl State { } /// Get an account's code hash. - pub fn code_hash(&self, a: &Address) -> TrieResult { + pub fn code_hash(&self, a: &Address) -> TrieResult> { self.ensure_cached(a, RequireCache::None, true, - |a| a.as_ref().map_or(KECCAK_EMPTY, |a| a.code_hash())) + |a| a.as_ref().map(|a| a.code_hash())) } /// Get accounts' code size. @@ -909,31 +909,38 @@ impl State { Ok(pod_state::diff_pod(&pod_state_pre, &pod_state_post)) } - // load required account data from the databases. - fn update_account_cache(require: RequireCache, account: &mut Account, state_db: &B, db: &HashDB) { + /// Load required account data from the databases. Returns whether the cache succeeds. + #[must_use] + fn update_account_cache(require: RequireCache, account: &mut Account, state_db: &B, db: &HashDB) -> bool { if let RequireCache::None = require { - return; + return true; } if account.is_cached() { - return; + return true; } // if there's already code in the global cache, always cache it localy let hash = account.code_hash(); match state_db.get_cached_code(&hash) { - Some(code) => account.cache_given_code(code), + Some(code) => { + account.cache_given_code(code); + true + }, None => match require { - RequireCache::None => {}, + RequireCache::None => true, RequireCache::Code => { if let Some(code) = account.cache_code(db) { // propagate code loaded from the database to // the global code cache. - state_db.cache_code(hash, code) + state_db.cache_code(hash, code); + true + } else { + false } }, RequireCache::CodeSize => { - account.cache_code_size(db); + account.cache_code_size(db) } } } @@ -948,8 +955,11 @@ impl State { if let Some(ref mut maybe_acc) = self.cache.borrow_mut().get_mut(a) { if let Some(ref mut account) = maybe_acc.account { 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()); - return Ok(f(Some(account))); + if Self::update_account_cache(require, account, &self.db, accountdb.as_hashdb()) { + return Ok(f(Some(account))); + } else { + return Err(Box::new(TrieError::IncompleteDatabase(H256::from(a)))); + } } return Ok(f(None)); } @@ -957,12 +967,14 @@ impl State { let result = self.db.get_cached(a, |mut acc| { if let Some(ref mut account) = acc { 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()); + if !Self::update_account_cache(require, account, &self.db, accountdb.as_hashdb()) { + return Err(Box::new(TrieError::IncompleteDatabase(H256::from(a)))); + } } - f(acc.map(|a| &*a)) + Ok(f(acc.map(|a| &*a))) }); match result { - Some(r) => Ok(r), + Some(r) => Ok(r?), None => { // first check if it is not in database for sure if check_null && self.db.is_known_null(a) { return Ok(f(None)); } @@ -973,7 +985,9 @@ impl State { let mut maybe_acc = db.get_with(a, from_rlp)?; if let Some(ref mut account) = maybe_acc.as_mut() { 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()); + if !Self::update_account_cache(require, account, &self.db, accountdb.as_hashdb()) { + return Err(Box::new(TrieError::IncompleteDatabase(H256::from(a)))); + } } let r = f(maybe_acc.as_ref()); self.insert_cache(a, AccountEntry::new_clean(maybe_acc)); diff --git a/ethcore/vm/src/ext.rs b/ethcore/vm/src/ext.rs index 166e8712aae..b6d41a39521 100644 --- a/ethcore/vm/src/ext.rs +++ b/ethcore/vm/src/ext.rs @@ -106,10 +106,13 @@ pub trait Ext { ) -> MessageCallResult; /// Returns code at given address - fn extcode(&self, address: &Address) -> Result>; + fn extcode(&self, address: &Address) -> Result>>; + + /// Returns code hash at given address + fn extcodehash(&self, address: &Address) -> Result>; /// Returns code size at given address - fn extcodesize(&self, address: &Address) -> Result; + fn extcodesize(&self, address: &Address) -> Result>; /// Creates log entry with given topics and data fn log(&mut self, topics: Vec, data: &[u8]) -> Result<()>; diff --git a/ethcore/vm/src/schedule.rs b/ethcore/vm/src/schedule.rs index 960821e72c7..6215aed78d9 100644 --- a/ethcore/vm/src/schedule.rs +++ b/ethcore/vm/src/schedule.rs @@ -26,6 +26,8 @@ pub struct Schedule { pub have_create2: bool, /// Does it have a REVERT instruction pub have_revert: bool, + /// Does it have a EXTCODEHASH instruction + pub have_extcodehash: bool, /// VM stack limit pub stack_limit: usize, /// Max number of nested calls/creates @@ -92,6 +94,8 @@ pub struct Schedule { pub extcodecopy_base_gas: usize, /// Price of BALANCE pub balance_gas: usize, + /// Price of EXTCODEHASH + pub extcodehash_gas: usize, /// Price of SUICIDE pub suicide_gas: usize, /// Amount of additional gas to pay when SUICIDE credits a non-existant account @@ -197,6 +201,7 @@ impl Schedule { have_revert: false, have_return_data: false, have_bitwise_shifting: false, + have_extcodehash: false, stack_limit: 1024, max_depth: 1024, tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0], @@ -229,6 +234,7 @@ impl Schedule { copy_gas: 3, extcodesize_gas: 700, extcodecopy_base_gas: 700, + extcodehash_gas: 400, balance_gas: 400, suicide_gas: 5000, suicide_to_new_account_cost: 25000, @@ -268,6 +274,7 @@ impl Schedule { have_revert: false, have_return_data: false, have_bitwise_shifting: false, + have_extcodehash: false, stack_limit: 1024, max_depth: 1024, tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0], @@ -300,6 +307,7 @@ impl Schedule { copy_gas: 3, extcodesize_gas: 20, extcodecopy_base_gas: 20, + extcodehash_gas: 400, balance_gas: 20, suicide_gas: 0, suicide_to_new_account_cost: 0, diff --git a/ethcore/vm/src/tests.rs b/ethcore/vm/src/tests.rs index 9a17e0d3dc4..d83e6881a12 100644 --- a/ethcore/vm/src/tests.rs +++ b/ethcore/vm/src/tests.rs @@ -24,6 +24,7 @@ use { ReturnData, Ext, ContractCreateResult, MessageCallResult, CreateContractAddress, Result, GasLeft, }; +use hash::keccak; pub struct FakeLogEntry { pub topics: Vec, @@ -168,12 +169,16 @@ impl Ext for FakeExt { MessageCallResult::Success(*gas, ReturnData::empty()) } - fn extcode(&self, address: &Address) -> Result> { - Ok(self.codes.get(address).unwrap_or(&Arc::new(Bytes::new())).clone()) + fn extcode(&self, address: &Address) -> Result>> { + Ok(self.codes.get(address).cloned()) } - fn extcodesize(&self, address: &Address) -> Result { - Ok(self.codes.get(address).map_or(0, |c| c.len())) + fn extcodesize(&self, address: &Address) -> Result> { + Ok(self.codes.get(address).map(|c| c.len())) + } + + fn extcodehash(&self, address: &Address) -> Result> { + Ok(self.codes.get(address).map(|c| keccak(c.as_ref()))) } fn log(&mut self, topics: Vec, data: &[u8]) -> Result<()> { diff --git a/json/src/spec/params.rs b/json/src/spec/params.rs index e03fe7081b9..a37e4f23ba8 100644 --- a/json/src/spec/params.rs +++ b/json/src/spec/params.rs @@ -109,6 +109,9 @@ pub struct Params { #[serde(rename="eip658Transition")] pub eip658_transition: Option, /// See `CommonParams` docs. + #[serde(rename="eip1052Transition")] + pub eip1052_transition: Option, + /// See `CommonParams` docs. #[serde(rename="dustProtectionTransition")] pub dust_protection_transition: Option, /// See `CommonParams` docs. From 72594dba03364082b197292d3dc8a557a62326a2 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Wed, 1 Aug 2018 19:17:04 +0800 Subject: [PATCH 02/19] Comply EIP-86 with the new definition (#9140) * Comply EIP-86 with the new CREATE2 opcode * Fix rpc compile * Fix interpreter CREATE/CREATE2 stack pop difference * Add unreachable! to fix compile * Fix instruction_info * Fix gas check due to new stack item * Add new tests in executive * Fix have_create2 comment * Remove all unused references of eip86_transition and block_number --- ethcore/evm/src/instructions.rs | 2 +- ethcore/evm/src/interpreter/gasometer.rs | 6 +++- ethcore/evm/src/interpreter/mod.rs | 6 +++- ethcore/src/executive.rs | 8 +++-- ethcore/src/externalities.rs | 40 ++++++++++++++++++++++++ ethcore/src/machine.rs | 8 ++--- ethcore/vm/src/ext.rs | 8 ++--- ethcore/vm/src/schedule.rs | 2 +- rpc/src/v1/helpers/dispatch.rs | 6 ++-- rpc/src/v1/helpers/light_fetch.rs | 8 ++--- rpc/src/v1/impls/eth.rs | 11 +++---- rpc/src/v1/impls/light/eth.rs | 17 +++------- rpc/src/v1/impls/light/parity.rs | 8 ++--- rpc/src/v1/impls/parity.rs | 12 ++----- rpc/src/v1/impls/parity_set.rs | 5 +-- rpc/src/v1/tests/mocked/signing.rs | 2 +- rpc/src/v1/types/transaction.rs | 20 ++++++------ 17 files changed, 96 insertions(+), 73 deletions(-) diff --git a/ethcore/evm/src/instructions.rs b/ethcore/evm/src/instructions.rs index 3be4556942c..67d390d4dff 100644 --- a/ethcore/evm/src/instructions.rs +++ b/ethcore/evm/src/instructions.rs @@ -594,7 +594,7 @@ lazy_static! { arr[DELEGATECALL as usize] = Some(InstructionInfo::new("DELEGATECALL", 6, 1, GasPriceTier::Special)); arr[STATICCALL as usize] = Some(InstructionInfo::new("STATICCALL", 6, 1, GasPriceTier::Special)); arr[SUICIDE as usize] = Some(InstructionInfo::new("SUICIDE", 1, 0, GasPriceTier::Special)); - arr[CREATE2 as usize] = Some(InstructionInfo::new("CREATE2", 3, 1, GasPriceTier::Special)); + arr[CREATE2 as usize] = Some(InstructionInfo::new("CREATE2", 4, 1, GasPriceTier::Special)); arr[REVERT as usize] = Some(InstructionInfo::new("REVERT", 2, 0, GasPriceTier::Zero)); arr }; diff --git a/ethcore/evm/src/interpreter/gasometer.rs b/ethcore/evm/src/interpreter/gasometer.rs index 943a8320bb4..78a33ef3ead 100644 --- a/ethcore/evm/src/interpreter/gasometer.rs +++ b/ethcore/evm/src/interpreter/gasometer.rs @@ -228,7 +228,11 @@ impl Gasometer { }, instructions::CREATE | instructions::CREATE2 => { let gas = Gas::from(schedule.create_gas); - let mem = mem_needed(stack.peek(1), stack.peek(2))?; + let mem = match instruction { + instructions::CREATE => mem_needed(stack.peek(1), stack.peek(2))?, + instructions::CREATE2 => mem_needed(stack.peek(2), stack.peek(3))?, + _ => unreachable!("instruction can only be CREATE/CREATE2 checked above; qed"), + }; Request::GasMemProvide(gas, mem, None) }, diff --git a/ethcore/evm/src/interpreter/mod.rs b/ethcore/evm/src/interpreter/mod.rs index 6b8abcc17f7..3af1e34dd36 100644 --- a/ethcore/evm/src/interpreter/mod.rs +++ b/ethcore/evm/src/interpreter/mod.rs @@ -317,6 +317,11 @@ impl Interpreter { }, instructions::CREATE | instructions::CREATE2 => { let endowment = stack.pop_back(); + let address_scheme = match instruction { + instructions::CREATE => CreateContractAddress::FromSenderAndNonce, + instructions::CREATE2 => CreateContractAddress::FromSenderSaltAndCodeHash(stack.pop_back().into()), + _ => unreachable!("instruction can only be CREATE/CREATE2 checked above; qed"), + }; let init_off = stack.pop_back(); let init_size = stack.pop_back(); @@ -336,7 +341,6 @@ impl Interpreter { } let contract_code = self.mem.read_slice(init_off, init_size); - let address_scheme = if instruction == instructions::CREATE { CreateContractAddress::FromSenderAndNonce } else { CreateContractAddress::FromSenderAndCodeHash }; let create_result = ext.create(&create_gas.as_u256(), &endowment, contract_code, address_scheme); return match create_result { diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index a5084da8a71..28ce8b2120d 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -61,10 +61,12 @@ pub fn contract_address(address_scheme: CreateContractAddress, sender: &Address, stream.append(nonce); (From::from(keccak(stream.as_raw())), None) }, - CreateContractAddress::FromCodeHash => { + CreateContractAddress::FromSenderSaltAndCodeHash(salt) => { let code_hash = keccak(code); - let mut buffer = [0xffu8; 20 + 32]; - &mut buffer[20..].copy_from_slice(&code_hash[..]); + let mut buffer = [0u8; 20 + 32 + 32]; + &mut buffer[0..20].copy_from_slice(&sender[..]); + &mut buffer[20..(20+32)].copy_from_slice(&salt[..]); + &mut buffer[(20+32)..].copy_from_slice(&code_hash[..]); (From::from(keccak(&buffer[..])), Some(code_hash)) }, CreateContractAddress::FromSenderAndCodeHash => { diff --git a/ethcore/src/externalities.rs b/ethcore/src/externalities.rs index de8d5282471..6966b23c94e 100644 --- a/ethcore/src/externalities.rs +++ b/ethcore/src/externalities.rs @@ -574,4 +574,44 @@ mod tests { assert_eq!(setup.sub_state.suicides.len(), 1); } + + #[test] + fn can_create() { + use std::str::FromStr; + + let mut setup = TestSetup::new(); + let state = &mut setup.state; + let mut tracer = NoopTracer; + let mut vm_tracer = NoopVMTracer; + + let address = { + let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false); + match ext.create(&U256::max_value(), &U256::zero(), &[], CreateContractAddress::FromSenderAndNonce) { + ContractCreateResult::Created(address, _) => address, + _ => panic!("Test create failed; expected Created, got Failed/Reverted."), + } + }; + + assert_eq!(address, Address::from_str("bd770416a3345f91e4b34576cb804a576fa48eb1").unwrap()); + } + + #[test] + fn can_create2() { + use std::str::FromStr; + + let mut setup = TestSetup::new(); + let state = &mut setup.state; + let mut tracer = NoopTracer; + let mut vm_tracer = NoopVMTracer; + + let address = { + let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false); + match ext.create(&U256::max_value(), &U256::zero(), &[], CreateContractAddress::FromSenderSaltAndCodeHash(H256::default())) { + ContractCreateResult::Created(address, _) => address, + _ => panic!("Test create failed; expected Created, got Failed/Reverted."), + } + }; + + assert_eq!(address, Address::from_str("b7c227636666831278bacdb8d7f52933b8698ab9").unwrap()); + } } diff --git a/ethcore/src/machine.rs b/ethcore/src/machine.rs index d149062c3aa..949df9af43a 100644 --- a/ethcore/src/machine.rs +++ b/ethcore/src/machine.rs @@ -309,12 +309,8 @@ impl EthereumMachine { } /// Returns new contract address generation scheme at given block number. - pub fn create_address_scheme(&self, number: BlockNumber) -> CreateContractAddress { - if number >= self.params().eip86_transition { - CreateContractAddress::FromCodeHash - } else { - CreateContractAddress::FromSenderAndNonce - } + pub fn create_address_scheme(&self, _number: BlockNumber) -> CreateContractAddress { + CreateContractAddress::FromSenderAndNonce } /// Verify a particular transaction is valid, regardless of order. diff --git a/ethcore/vm/src/ext.rs b/ethcore/vm/src/ext.rs index b6d41a39521..3e6ee1e0265 100644 --- a/ethcore/vm/src/ext.rs +++ b/ethcore/vm/src/ext.rs @@ -53,11 +53,11 @@ pub enum MessageCallResult { /// Specifies how an address is calculated for a new contract. #[derive(Copy, Clone, PartialEq, Eq)] pub enum CreateContractAddress { - /// Address is calculated from nonce and sender. Pre EIP-86 (Metropolis) + /// Address is calculated from sender and nonce. Pre EIP-86 (Metropolis) FromSenderAndNonce, - /// Address is calculated from code hash. Default since EIP-86 - FromCodeHash, - /// Address is calculated from code hash and sender. Used by CREATE_P2SH instruction. + /// Address is calculated from sender, salt and code hash. EIP-86 CREATE2 scheme. + FromSenderSaltAndCodeHash(H256), + /// Address is calculated from code hash and sender. Used by pwasm create ext. FromSenderAndCodeHash, } diff --git a/ethcore/vm/src/schedule.rs b/ethcore/vm/src/schedule.rs index 6215aed78d9..757d8a16d5d 100644 --- a/ethcore/vm/src/schedule.rs +++ b/ethcore/vm/src/schedule.rs @@ -22,7 +22,7 @@ pub struct Schedule { pub exceptional_failed_code_deposit: bool, /// Does it have a delegate cal pub have_delegate_call: bool, - /// Does it have a CREATE_P2SH instruction + /// Does it have a CREATE2 instruction pub have_create2: bool, /// Does it have a REVERT instruction pub have_revert: bool, diff --git a/rpc/src/v1/helpers/dispatch.rs b/rpc/src/v1/helpers/dispatch.rs index c6f10400a58..9b789a56bb2 100644 --- a/rpc/src/v1/helpers/dispatch.rs +++ b/rpc/src/v1/helpers/dispatch.rs @@ -178,8 +178,7 @@ impl Dispatcher } fn enrich(&self, signed_transaction: SignedTransaction) -> RpcRichRawTransaction { - let block_number = self.client.best_block_header().number(); - RpcRichRawTransaction::from_signed(signed_transaction, block_number, self.client.eip86_transition()) + RpcRichRawTransaction::from_signed(signed_transaction) } fn dispatch_transaction(&self, signed_transaction: PendingTransaction) -> Result { @@ -405,8 +404,7 @@ impl Dispatcher for LightDispatcher { } fn enrich(&self, signed_transaction: SignedTransaction) -> RpcRichRawTransaction { - let block_number = self.client.best_block_header().number(); - RpcRichRawTransaction::from_signed(signed_transaction, block_number, self.client.eip86_transition()) + RpcRichRawTransaction::from_signed(signed_transaction) } fn dispatch_transaction(&self, signed_transaction: PendingTransaction) -> Result { diff --git a/rpc/src/v1/helpers/light_fetch.rs b/rpc/src/v1/helpers/light_fetch.rs index 2ec3af631aa..b6afde3dfca 100644 --- a/rpc/src/v1/helpers/light_fetch.rs +++ b/rpc/src/v1/helpers/light_fetch.rs @@ -68,7 +68,7 @@ pub struct LightFetch { } /// Extract a transaction at given index. -pub fn extract_transaction_at_index(block: encoded::Block, index: usize, eip86_transition: u64) -> Option { +pub fn extract_transaction_at_index(block: encoded::Block, index: usize) -> Option { block.transactions().into_iter().nth(index) // Verify if transaction signature is correct. .and_then(|tx| SignedTransaction::new(tx).ok()) @@ -87,7 +87,7 @@ pub fn extract_transaction_at_index(block: encoded::Block, index: usize, eip86_t cached_sender, } }) - .map(|tx| Transaction::from_localized(tx, eip86_transition)) + .map(|tx| Transaction::from_localized(tx)) } // extract the header indicated by the given `HeaderRef` from the given responses. @@ -367,7 +367,7 @@ impl LightFetch { // Get a transaction by hash. also returns the index in the block. // Only returns transactions in the canonical chain. - pub fn transaction_by_hash(&self, tx_hash: H256, eip86_transition: u64) + pub fn transaction_by_hash(&self, tx_hash: H256) -> impl Future, Error = Error> + Send { let params = (self.sync.clone(), self.on_demand.clone()); @@ -399,7 +399,7 @@ impl LightFetch { } let index = index.index as usize; - let transaction = extract_transaction_at_index(blk, index, eip86_transition); + let transaction = extract_transaction_at_index(blk, index); if transaction.as_ref().map_or(true, |tx| tx.hash != tx_hash.into()) { // index is actively wrong: indicated block has diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 5717dd70d7e..e47f0c925dd 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -106,7 +106,6 @@ pub struct EthClient where external_miner: Arc, seed_compute: Mutex, options: EthClientOptions, - eip86_transition: u64, } #[derive(Debug)] @@ -168,7 +167,6 @@ impl EthClient EthClient BlockTransactions::Full(block.view().localized_transactions().into_iter().map(|t| Transaction::from_localized(t, self.eip86_transition)).collect()), + true => BlockTransactions::Full(block.view().localized_transactions().into_iter().map(|t| Transaction::from_localized(t)).collect()), false => BlockTransactions::Hashes(block.transaction_hashes().into_iter().map(Into::into).collect()), }, extra_data: Bytes::new(view.extra_data()), @@ -267,7 +265,7 @@ impl EthClient Result> { let client_transaction = |id| match self.client.transaction(id) { - Some(t) => Ok(Some(Transaction::from_localized(t, self.eip86_transition))), + Some(t) => Ok(Some(Transaction::from_localized(t))), None => Ok(None), }; @@ -304,7 +302,7 @@ impl EthClient Eth for EthClient< fn transaction_by_hash(&self, hash: RpcH256) -> BoxFuture> { let hash: H256 = hash.into(); - let block_number = self.client.chain_info().best_block_number; let tx = try_bf!(self.transaction(PendingTransactionId::Hash(hash))).or_else(|| { self.miner.transaction(&hash) - .map(|t| Transaction::from_pending(t.pending().clone(), block_number + 1, self.eip86_transition)) + .map(|t| Transaction::from_pending(t.pending().clone())) }); Box::new(future::ok(tx)) diff --git a/rpc/src/v1/impls/light/eth.rs b/rpc/src/v1/impls/light/eth.rs index d90deb64815..b0ec0abadb1 100644 --- a/rpc/src/v1/impls/light/eth.rs +++ b/rpc/src/v1/impls/light/eth.rs @@ -142,7 +142,6 @@ impl EthClient { fn rich_block(&self, id: BlockId, include_txs: bool) -> BoxFuture { let (on_demand, sync) = (self.on_demand.clone(), self.sync.clone()); let (client, engine) = (self.client.clone(), self.client.engine().clone()); - let eip86_transition = self.client.eip86_transition(); // helper for filling out a rich block once we've got a block and a score. let fill_rich = move |block: encoded::Block, score: Option| { @@ -169,7 +168,7 @@ impl EthClient { seal_fields: header.seal().into_iter().cloned().map(Into::into).collect(), uncles: block.uncle_hashes().into_iter().map(Into::into).collect(), transactions: match include_txs { - true => BlockTransactions::Full(block.view().localized_transactions().into_iter().map(|t| Transaction::from_localized(t, eip86_transition)).collect()), + true => BlockTransactions::Full(block.view().localized_transactions().into_iter().map(|t| Transaction::from_localized(t)).collect()), _ => BlockTransactions::Hashes(block.transaction_hashes().into_iter().map(Into::into).collect()), }, extra_data: Bytes::new(header.extra_data().clone()), @@ -419,40 +418,34 @@ impl Eth for EthClient { fn transaction_by_hash(&self, hash: RpcH256) -> BoxFuture> { let hash = hash.into(); - let eip86 = self.client.eip86_transition(); { let tx_queue = self.transaction_queue.read(); if let Some(tx) = tx_queue.get(&hash) { return Box::new(future::ok(Some(Transaction::from_pending( tx.clone(), - self.client.chain_info().best_block_number, - eip86, )))); } } - Box::new(self.fetcher().transaction_by_hash(hash, eip86).map(|x| x.map(|(tx, _)| tx))) + Box::new(self.fetcher().transaction_by_hash(hash).map(|x| x.map(|(tx, _)| tx))) } fn transaction_by_block_hash_and_index(&self, hash: RpcH256, idx: Index) -> BoxFuture> { - let eip86 = self.client.eip86_transition(); Box::new(self.fetcher().block(BlockId::Hash(hash.into())).map(move |block| { - light_fetch::extract_transaction_at_index(block, idx.value(), eip86) + light_fetch::extract_transaction_at_index(block, idx.value()) })) } fn transaction_by_block_number_and_index(&self, num: BlockNumber, idx: Index) -> BoxFuture> { - let eip86 = self.client.eip86_transition(); Box::new(self.fetcher().block(Self::num_to_id(num)).map(move |block| { - light_fetch::extract_transaction_at_index(block, idx.value(), eip86) + light_fetch::extract_transaction_at_index(block, idx.value()) })) } fn transaction_receipt(&self, hash: RpcH256) -> BoxFuture> { - let eip86 = self.client.eip86_transition(); let fetcher = self.fetcher(); - Box::new(fetcher.transaction_by_hash(hash.clone().into(), eip86).and_then(move |tx| { + Box::new(fetcher.transaction_by_hash(hash.clone().into()).and_then(move |tx| { // the block hash included in the transaction object here has // already been checked for canonicality and whether it contains // the transaction. diff --git a/rpc/src/v1/impls/light/parity.rs b/rpc/src/v1/impls/light/parity.rs index 3fd528d0391..f74886e619f 100644 --- a/rpc/src/v1/impls/light/parity.rs +++ b/rpc/src/v1/impls/light/parity.rs @@ -57,7 +57,6 @@ pub struct ParityClient { settings: Arc, signer: Option>, ws_address: Option, - eip86_transition: u64, gas_price_percentile: usize, } @@ -80,7 +79,6 @@ impl ParityClient { settings, signer, ws_address, - eip86_transition: client.eip86_transition(), client, gas_price_percentile, } @@ -260,7 +258,7 @@ impl Parity for ParityClient { txq.ready_transactions(chain_info.best_block_number, chain_info.best_block_timestamp) .into_iter() .take(limit.unwrap_or_else(usize::max_value)) - .map(|tx| Transaction::from_pending(tx, chain_info.best_block_number, self.eip86_transition)) + .map(|tx| Transaction::from_pending(tx)) .collect::>() ) } @@ -275,7 +273,7 @@ impl Parity for ParityClient { current .into_iter() .chain(future.into_iter()) - .map(|tx| Transaction::from_pending(tx, chain_info.best_block_number, self.eip86_transition)) + .map(|tx| Transaction::from_pending(tx)) .collect::>() ) } @@ -286,7 +284,7 @@ impl Parity for ParityClient { Ok( txq.future_transactions(chain_info.best_block_number, chain_info.best_block_timestamp) .into_iter() - .map(|tx| Transaction::from_pending(tx, chain_info.best_block_number, self.eip86_transition)) + .map(|tx| Transaction::from_pending(tx)) .collect::>() ) } diff --git a/rpc/src/v1/impls/parity.rs b/rpc/src/v1/impls/parity.rs index 9f825ba896a..3e20d582141 100644 --- a/rpc/src/v1/impls/parity.rs +++ b/rpc/src/v1/impls/parity.rs @@ -62,7 +62,6 @@ pub struct ParityClient { settings: Arc, signer: Option>, ws_address: Option, - eip86_transition: u64, } impl ParityClient where @@ -81,7 +80,6 @@ impl ParityClient where signer: Option>, ws_address: Option, ) -> Self { - let eip86_transition = client.eip86_transition(); ParityClient { client, miner, @@ -93,7 +91,6 @@ impl ParityClient where settings, signer, ws_address, - eip86_transition, } } } @@ -289,7 +286,6 @@ impl Parity for ParityClient where } fn pending_transactions(&self, limit: Trailing) -> Result> { - let block_number = self.client.chain_info().best_block_number; let ready_transactions = self.miner.ready_transactions( &*self.client, limit.unwrap_or_else(usize::max_value), @@ -298,18 +294,17 @@ impl Parity for ParityClient where Ok(ready_transactions .into_iter() - .map(|t| Transaction::from_pending(t.pending().clone(), block_number, self.eip86_transition)) + .map(|t| Transaction::from_pending(t.pending().clone())) .collect() ) } fn all_transactions(&self) -> Result> { - let block_number = self.client.chain_info().best_block_number; let all_transactions = self.miner.queued_transactions(); Ok(all_transactions .into_iter() - .map(|t| Transaction::from_pending(t.pending().clone(), block_number, self.eip86_transition)) + .map(|t| Transaction::from_pending(t.pending().clone())) .collect() ) } @@ -328,10 +323,9 @@ impl Parity for ParityClient where fn local_transactions(&self) -> Result> { let transactions = self.miner.local_transactions(); - let block_number = self.client.chain_info().best_block_number; Ok(transactions .into_iter() - .map(|(hash, status)| (hash.into(), LocalTransactionStatus::from(status, block_number, self.eip86_transition))) + .map(|(hash, status)| (hash.into(), LocalTransactionStatus::from(status))) .collect() ) } diff --git a/rpc/src/v1/impls/parity_set.rs b/rpc/src/v1/impls/parity_set.rs index c811b3e5daf..9bbb7ceab14 100644 --- a/rpc/src/v1/impls/parity_set.rs +++ b/rpc/src/v1/impls/parity_set.rs @@ -41,7 +41,6 @@ pub struct ParitySetClient { net: Arc, fetch: F, pool: CpuPool, - eip86_transition: u64, } impl ParitySetClient @@ -63,7 +62,6 @@ impl ParitySetClient net: net.clone(), fetch: fetch, pool: pool, - eip86_transition: client.eip86_transition(), } } } @@ -191,11 +189,10 @@ impl ParitySet for ParitySetClient where } fn remove_transaction(&self, hash: H256) -> Result> { - let block_number = self.client.chain_info().best_block_number; let hash = hash.into(); Ok(self.miner.remove_transaction(&hash) - .map(|t| Transaction::from_pending(t.pending().clone(), block_number + 1, self.eip86_transition)) + .map(|t| Transaction::from_pending(t.pending().clone())) ) } } diff --git a/rpc/src/v1/tests/mocked/signing.rs b/rpc/src/v1/tests/mocked/signing.rs index 632d8fb76b7..c063ee09601 100644 --- a/rpc/src/v1/tests/mocked/signing.rs +++ b/rpc/src/v1/tests/mocked/signing.rs @@ -339,7 +339,7 @@ fn should_add_sign_transaction_to_the_queue() { // respond let sender = signer.take(&1.into()).unwrap(); signer.request_confirmed(sender, Ok(ConfirmationResponse::SignTransaction( - RichRawTransaction::from_signed(t.into(), 0x0, u64::max_value()) + RichRawTransaction::from_signed(t.into()) ))); break } diff --git a/rpc/src/v1/types/transaction.rs b/rpc/src/v1/types/transaction.rs index d41fc84e001..4266f60b623 100644 --- a/rpc/src/v1/types/transaction.rs +++ b/rpc/src/v1/types/transaction.rs @@ -161,8 +161,8 @@ pub struct RichRawTransaction { impl RichRawTransaction { /// Creates new `RichRawTransaction` from `SignedTransaction`. - pub fn from_signed(tx: SignedTransaction, block_number: u64, eip86_transition: u64) -> Self { - let tx = Transaction::from_signed(tx, block_number, eip86_transition); + pub fn from_signed(tx: SignedTransaction) -> Self { + let tx = Transaction::from_signed(tx); RichRawTransaction { raw: tx.raw.clone(), transaction: tx, @@ -172,9 +172,9 @@ impl RichRawTransaction { impl Transaction { /// Convert `LocalizedTransaction` into RPC Transaction. - pub fn from_localized(mut t: LocalizedTransaction, eip86_transition: u64) -> Transaction { + pub fn from_localized(mut t: LocalizedTransaction) -> Transaction { let signature = t.signature(); - let scheme = if t.block_number >= eip86_transition { CreateContractAddress::FromCodeHash } else { CreateContractAddress::FromSenderAndNonce }; + let scheme = CreateContractAddress::FromSenderAndNonce; Transaction { hash: t.hash().into(), nonce: t.nonce.into(), @@ -206,9 +206,9 @@ impl Transaction { } /// Convert `SignedTransaction` into RPC Transaction. - pub fn from_signed(t: SignedTransaction, block_number: u64, eip86_transition: u64) -> Transaction { + pub fn from_signed(t: SignedTransaction) -> Transaction { let signature = t.signature(); - let scheme = if block_number >= eip86_transition { CreateContractAddress::FromCodeHash } else { CreateContractAddress::FromSenderAndNonce }; + let scheme = CreateContractAddress::FromSenderAndNonce; Transaction { hash: t.hash().into(), nonce: t.nonce.into(), @@ -240,8 +240,8 @@ impl Transaction { } /// Convert `PendingTransaction` into RPC Transaction. - pub fn from_pending(t: PendingTransaction, block_number: u64, eip86_transition: u64) -> Transaction { - let mut r = Transaction::from_signed(t.transaction, block_number, eip86_transition); + pub fn from_pending(t: PendingTransaction) -> Transaction { + let mut r = Transaction::from_signed(t.transaction); r.condition = t.condition.map(|b| b.into()); r } @@ -249,9 +249,9 @@ impl Transaction { impl LocalTransactionStatus { /// Convert `LocalTransactionStatus` into RPC `LocalTransactionStatus`. - pub fn from(s: miner::pool::local_transactions::Status, block_number: u64, eip86_transition: u64) -> Self { + pub fn from(s: miner::pool::local_transactions::Status) -> Self { let convert = |tx: Arc| { - Transaction::from_signed(tx.signed().clone(), block_number, eip86_transition) + Transaction::from_signed(tx.signed().clone()) }; use miner::pool::local_transactions::Status::*; match s { From a86e973bc8fbd79624734dc51efd8536abb532c6 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Mon, 6 Aug 2018 23:15:52 +0800 Subject: [PATCH 03/19] Implement KIP4: create2 for wasm (#9277) * Basic implementation for kip4 * Add KIP-4 config flags * typo: docs fix * Fix args offset * Add tests for create2 * tests: evm * Update wasm-tests and fix all gas costs * Update wasm-tests * Update wasm-tests and fix gas costs --- ethcore/evm/src/tests.rs | 2 + ethcore/res/wasm-tests | 2 +- ethcore/src/spec/spec.rs | 12 +++++- ethcore/vm/src/ext.rs | 2 +- ethcore/vm/src/schedule.rs | 3 ++ ethcore/vm/src/tests.rs | 5 ++- ethcore/wasm/src/env.rs | 15 ++++++- ethcore/wasm/src/lib.rs | 2 +- ethcore/wasm/src/runtime.rs | 82 ++++++++++++++++++++++++++----------- ethcore/wasm/src/tests.rs | 73 +++++++++++++++++++++------------ json/src/spec/params.rs | 3 ++ 11 files changed, 143 insertions(+), 58 deletions(-) diff --git a/ethcore/evm/src/tests.rs b/ethcore/evm/src/tests.rs index b62faf87d77..b8f0df3639d 100644 --- a/ethcore/evm/src/tests.rs +++ b/ethcore/evm/src/tests.rs @@ -746,6 +746,7 @@ fn test_calls(factory: super::Factory) { assert_set_contains(&ext.calls, &FakeCall { call_type: FakeCallType::Call, + create_scheme: None, gas: U256::from(2556), sender_address: Some(address.clone()), receive_address: Some(code_address.clone()), @@ -755,6 +756,7 @@ fn test_calls(factory: super::Factory) { }); assert_set_contains(&ext.calls, &FakeCall { call_type: FakeCallType::Call, + create_scheme: None, gas: U256::from(2556), sender_address: Some(address.clone()), receive_address: Some(address.clone()), diff --git a/ethcore/res/wasm-tests b/ethcore/res/wasm-tests index 474110de59a..986a6fb9467 160000 --- a/ethcore/res/wasm-tests +++ b/ethcore/res/wasm-tests @@ -1 +1 @@ -Subproject commit 474110de59a0f632b20615256c913b144c49354c +Subproject commit 986a6fb94673ba270f8f7ef1fff521ba33d427c2 diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index bbcc28452e8..3b46b27d1d7 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -125,6 +125,8 @@ pub struct CommonParams { pub remove_dust_contracts: bool, /// Wasm activation blocknumber, if any disabled initially. pub wasm_activation_transition: BlockNumber, + /// Number of first block where KIP-4 rules begin. Only has effect if Wasm is activated. + pub kip4_transition: BlockNumber, /// Gas limit bound divisor (how much gas limit can change per block) pub gas_limit_bound_divisor: U256, /// Registrar contract address. @@ -187,7 +189,11 @@ impl CommonParams { }; } if block_number >= self.wasm_activation_transition { - schedule.wasm = Some(Default::default()); + let mut wasm = ::vm::WasmCosts::default(); + if block_number >= self.kip4_transition { + wasm.have_create2 = true; + } + schedule.wasm = Some(wasm); } } @@ -294,6 +300,10 @@ impl From for CommonParams { BlockNumber::max_value, Into::into ), + kip4_transition: p.kip4_transition.map_or_else( + BlockNumber::max_value, + Into::into + ), } } } diff --git a/ethcore/vm/src/ext.rs b/ethcore/vm/src/ext.rs index 3e6ee1e0265..c1ce1b79f0b 100644 --- a/ethcore/vm/src/ext.rs +++ b/ethcore/vm/src/ext.rs @@ -51,7 +51,7 @@ pub enum MessageCallResult { } /// Specifies how an address is calculated for a new contract. -#[derive(Copy, Clone, PartialEq, Eq)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] pub enum CreateContractAddress { /// Address is calculated from sender and nonce. Pre EIP-86 (Metropolis) FromSenderAndNonce, diff --git a/ethcore/vm/src/schedule.rs b/ethcore/vm/src/schedule.rs index 757d8a16d5d..ec72c4683fd 100644 --- a/ethcore/vm/src/schedule.rs +++ b/ethcore/vm/src/schedule.rs @@ -149,6 +149,8 @@ pub struct WasmCosts { pub opcodes_mul: u32, /// Cost of wasm opcode is calculated as TABLE_ENTRY_COST * `opcodes_mul` / `opcodes_div` pub opcodes_div: u32, + /// Whether create2 extern function is activated. + pub have_create2: bool, } impl Default for WasmCosts { @@ -166,6 +168,7 @@ impl Default for WasmCosts { max_stack_height: 64*1024, opcodes_mul: 3, opcodes_div: 8, + have_create2: false, } } } diff --git a/ethcore/vm/src/tests.rs b/ethcore/vm/src/tests.rs index d83e6881a12..4930e4219ba 100644 --- a/ethcore/vm/src/tests.rs +++ b/ethcore/vm/src/tests.rs @@ -39,6 +39,7 @@ pub enum FakeCallType { #[derive(PartialEq, Eq, Hash, Debug)] pub struct FakeCall { pub call_type: FakeCallType, + pub create_scheme: Option, pub gas: U256, pub sender_address: Option
, pub receive_address: Option
, @@ -133,9 +134,10 @@ impl Ext for FakeExt { self.blockhashes.get(number).unwrap_or(&H256::new()).clone() } - fn create(&mut self, gas: &U256, value: &U256, code: &[u8], _address: CreateContractAddress) -> ContractCreateResult { + fn create(&mut self, gas: &U256, value: &U256, code: &[u8], address: CreateContractAddress) -> ContractCreateResult { self.calls.insert(FakeCall { call_type: FakeCallType::Create, + create_scheme: Some(address), gas: *gas, sender_address: None, receive_address: None, @@ -159,6 +161,7 @@ impl Ext for FakeExt { self.calls.insert(FakeCall { call_type: FakeCallType::Call, + create_scheme: None, gas: *gas, sender_address: Some(sender_address.clone()), receive_address: Some(receive_address.clone()), diff --git a/ethcore/wasm/src/env.rs b/ethcore/wasm/src/env.rs index 9bcbee63fb0..a9e536f5f1f 100644 --- a/ethcore/wasm/src/env.rs +++ b/ethcore/wasm/src/env.rs @@ -17,6 +17,7 @@ //! Env module glue for wasmi interpreter use std::cell::RefCell; +use vm::WasmCosts; use wasmi::{ self, Signature, Error, FuncRef, FuncInstance, MemoryDescriptor, MemoryRef, MemoryInstance, memory_units, @@ -47,6 +48,7 @@ pub mod ids { pub const SENDER_FUNC: usize = 190; pub const ORIGIN_FUNC: usize = 200; pub const ELOG_FUNC: usize = 210; + pub const CREATE2_FUNC: usize = 220; pub const PANIC_FUNC: usize = 1000; pub const DEBUG_FUNC: usize = 1010; @@ -125,6 +127,11 @@ pub mod signatures { Some(I32), ); + pub const CREATE2: StaticSignature = StaticSignature( + &[I32, I32, I32, I32, I32], + Some(I32), + ); + pub const SUICIDE: StaticSignature = StaticSignature( &[I32], None, @@ -195,18 +202,21 @@ fn host(signature: signatures::StaticSignature, idx: usize) -> FuncRef { /// Maps all functions that runtime support to the corresponding contract import /// entries. /// Also manages initial memory request from the runtime. -#[derive(Default)] pub struct ImportResolver { max_memory: u32, memory: RefCell>, + + have_create2: bool, } impl ImportResolver { /// New import resolver with specifed maximum amount of inital memory (in wasm pages = 64kb) - pub fn with_limit(max_memory: u32) -> ImportResolver { + pub fn with_limit(max_memory: u32, schedule: &WasmCosts) -> ImportResolver { ImportResolver { max_memory: max_memory, memory: RefCell::new(None), + + have_create2: schedule.have_create2, } } @@ -263,6 +273,7 @@ impl wasmi::ModuleImportResolver for ImportResolver { "sender" => host(signatures::SENDER, ids::SENDER_FUNC), "origin" => host(signatures::ORIGIN, ids::ORIGIN_FUNC), "elog" => host(signatures::ELOG, ids::ELOG_FUNC), + "create2" if self.have_create2 => host(signatures::CREATE2, ids::CREATE2_FUNC), _ => { return Err(wasmi::Error::Instantiation( format!("Export {} not found", field_name), diff --git a/ethcore/wasm/src/lib.rs b/ethcore/wasm/src/lib.rs index f1290318e0f..1fcfe9371ee 100644 --- a/ethcore/wasm/src/lib.rs +++ b/ethcore/wasm/src/lib.rs @@ -90,7 +90,7 @@ impl vm::Vm for WasmInterpreter { let loaded_module = wasmi::Module::from_parity_wasm_module(module).map_err(Error::Interpreter)?; - let instantiation_resolver = env::ImportResolver::with_limit(16); + let instantiation_resolver = env::ImportResolver::with_limit(16, ext.schedule().wasm()); let module_instance = wasmi::ModuleInstance::new( &loaded_module, diff --git a/ethcore/wasm/src/runtime.rs b/ethcore/wasm/src/runtime.rs index d99ab8645a1..347023dd97c 100644 --- a/ethcore/wasm/src/runtime.rs +++ b/ethcore/wasm/src/runtime.rs @@ -321,7 +321,7 @@ impl<'a> Runtime<'a> { if self.gas_counter > self.gas_limit { return Err(Error::InvalidGasState); } Ok(self.gas_limit - self.gas_counter) } - + /// General gas charging extern. fn gas(&mut self, args: RuntimeArgs) -> Result<()> { let amount: u32 = args.nth_checked(0)?; @@ -511,29 +511,7 @@ impl<'a> Runtime<'a> { self.return_u256_ptr(args.nth_checked(0)?, val) } - /// Creates a new contract - /// - /// Arguments: - /// * endowment - how much value (in Wei) transfer to the newly created contract - /// * code_ptr - pointer to the code data - /// * code_len - lenght of the code data - /// * result_ptr - pointer to write an address of the newly created contract - pub fn create(&mut self, args: RuntimeArgs) -> Result - { - // - // method signature: - // fn create(endowment: *const u8, code_ptr: *const u8, code_len: u32, result_ptr: *mut u8) -> i32; - // - trace!(target: "wasm", "runtime: CREATE"); - let endowment = self.u256_at(args.nth_checked(0)?)?; - trace!(target: "wasm", " val: {:?}", endowment); - let code_ptr: u32 = args.nth_checked(1)?; - trace!(target: "wasm", " code_ptr: {:?}", code_ptr); - let code_len: u32 = args.nth_checked(2)?; - trace!(target: "wasm", " code_len: {:?}", code_len); - let result_ptr: u32 = args.nth_checked(3)?; - trace!(target: "wasm", "result_ptr: {:?}", result_ptr); - + fn do_create(&mut self, endowment: U256, code_ptr: u32, code_len: u32, result_ptr: u32, scheme: vm::CreateContractAddress) -> Result { let code = self.memory.get(code_ptr, code_len as usize)?; self.adjusted_charge(|schedule| schedule.create_gas as u64)?; @@ -543,7 +521,7 @@ impl<'a> Runtime<'a> { * U256::from(self.ext.schedule().wasm().opcodes_mul) / U256::from(self.ext.schedule().wasm().opcodes_div); - match self.ext.create(&gas_left, &endowment, &code, vm::CreateContractAddress::FromSenderAndCodeHash) { + match self.ext.create(&gas_left, &endowment, &code, scheme) { vm::ContractCreateResult::Created(address, gas_left) => { self.memory.set(result_ptr, &*address)?; self.gas_counter = self.gas_limit - @@ -571,6 +549,59 @@ impl<'a> Runtime<'a> { } } + /// Creates a new contract + /// + /// Arguments: + /// * endowment - how much value (in Wei) transfer to the newly created contract + /// * code_ptr - pointer to the code data + /// * code_len - lenght of the code data + /// * result_ptr - pointer to write an address of the newly created contract + pub fn create(&mut self, args: RuntimeArgs) -> Result { + // + // method signature: + // fn create(endowment: *const u8, code_ptr: *const u8, code_len: u32, result_ptr: *mut u8) -> i32; + // + trace!(target: "wasm", "runtime: CREATE"); + let endowment = self.u256_at(args.nth_checked(0)?)?; + trace!(target: "wasm", " val: {:?}", endowment); + let code_ptr: u32 = args.nth_checked(1)?; + trace!(target: "wasm", " code_ptr: {:?}", code_ptr); + let code_len: u32 = args.nth_checked(2)?; + trace!(target: "wasm", " code_len: {:?}", code_len); + let result_ptr: u32 = args.nth_checked(3)?; + trace!(target: "wasm", "result_ptr: {:?}", result_ptr); + + self.do_create(endowment, code_ptr, code_len, result_ptr, vm::CreateContractAddress::FromSenderAndCodeHash) + } + + /// Creates a new contract using FromSenderSaltAndCodeHash scheme + /// + /// Arguments: + /// * endowment - how much value (in Wei) transfer to the newly created contract + /// * salt - salt to be used in contract creation address + /// * code_ptr - pointer to the code data + /// * code_len - lenght of the code data + /// * result_ptr - pointer to write an address of the newly created contract + pub fn create2(&mut self, args: RuntimeArgs) -> Result { + // + // method signature: + // fn create2(endowment: *const u8, salt: *const u8, code_ptr: *const u8, code_len: u32, result_ptr: *mut u8) -> i32; + // + trace!(target: "wasm", "runtime: CREATE2"); + let endowment = self.u256_at(args.nth_checked(0)?)?; + trace!(target: "wasm", " val: {:?}", endowment); + let salt: H256 = self.u256_at(args.nth_checked(1)?)?.into(); + trace!(target: "wasm", " salt: {:?}", salt); + let code_ptr: u32 = args.nth_checked(2)?; + trace!(target: "wasm", " code_ptr: {:?}", code_ptr); + let code_len: u32 = args.nth_checked(3)?; + trace!(target: "wasm", " code_len: {:?}", code_len); + let result_ptr: u32 = args.nth_checked(4)?; + trace!(target: "wasm", "result_ptr: {:?}", result_ptr); + + self.do_create(endowment, code_ptr, code_len, result_ptr, vm::CreateContractAddress::FromSenderSaltAndCodeHash(salt)) + } + fn debug(&mut self, args: RuntimeArgs) -> Result<()> { trace!(target: "wasm", "Contract debug message: {}", { @@ -744,6 +775,7 @@ mod ext_impl { SENDER_FUNC => void!(self.sender(args)), ORIGIN_FUNC => void!(self.origin(args)), ELOG_FUNC => void!(self.elog(args)), + CREATE2_FUNC => some!(self.create2(args)), _ => panic!("env module doesn't provide function at index {}", index), } } diff --git a/ethcore/wasm/src/tests.rs b/ethcore/wasm/src/tests.rs index 726b9ebabbb..e72cc15c81d 100644 --- a/ethcore/wasm/src/tests.rs +++ b/ethcore/wasm/src/tests.rs @@ -20,7 +20,7 @@ use byteorder::{LittleEndian, ByteOrder}; use ethereum_types::{H256, U256, Address}; use super::WasmInterpreter; -use vm::{self, Vm, GasLeft, ActionParams, ActionValue}; +use vm::{self, Vm, GasLeft, ActionParams, ActionValue, CreateContractAddress}; use vm::tests::{FakeCall, FakeExt, FakeCallType}; macro_rules! load_sample { @@ -138,7 +138,7 @@ fn logger() { U256::from(1_000_000_000), "Logger sets 0x04 key to the trasferred value" ); - assert_eq!(gas_left, U256::from(16_181)); + assert_eq!(gas_left, U256::from(17_716)); } // This test checks if the contract can allocate memory and pass pointer to the result stream properly. @@ -173,7 +173,7 @@ fn identity() { sender, "Idenity test contract does not return the sender passed" ); - assert_eq!(gas_left, U256::from(96_883)); + assert_eq!(gas_left, U256::from(98_419)); } // Dispersion test sends byte array and expect the contract to 'disperse' the original elements with @@ -207,7 +207,7 @@ fn dispersion() { result, vec![0u8, 0, 125, 11, 197, 7, 255, 8, 19, 0] ); - assert_eq!(gas_left, U256::from(92_371)); + assert_eq!(gas_left, U256::from(92_377)); } #[test] @@ -267,7 +267,7 @@ fn suicide() { }; assert!(ext.suicides.contains(&refund)); - assert_eq!(gas_left, U256::from(93_348)); + assert_eq!(gas_left, U256::from(93_346)); } #[test] @@ -281,14 +281,19 @@ fn create() { params.value = ActionValue::transfer(1_000_000_000); let mut ext = FakeExt::new().with_wasm(); + ext.schedule.wasm.as_mut().unwrap().have_create2 = true; let gas_left = { let mut interpreter = wasm_interpreter(); let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors"); match result { - GasLeft::Known(gas) => gas, - GasLeft::NeedsReturn { .. } => { - panic!("Create contract should not return anthing because ext always fails on creation"); + GasLeft::Known(_) => { + panic!("Create contract always return 40 bytes of the creation address, or in the case where it fails, return 40 bytes of zero."); + }, + GasLeft::NeedsReturn { gas_left, data, apply_state } => { + assert!(apply_state); + assert_eq!(data.as_ref(), [0u8; 40].as_ref()); // FakeExt never succeeds in create. + gas_left }, } }; @@ -297,15 +302,28 @@ fn create() { assert!(ext.calls.contains( &FakeCall { call_type: FakeCallType::Create, - gas: U256::from(59_269), + create_scheme: Some(CreateContractAddress::FromSenderAndCodeHash), + gas: U256::from(52_017), + sender_address: None, + receive_address: None, + value: Some((1_000_000_000 / 2).into()), + data: vec![0u8, 2, 4, 8, 16, 32, 64, 128], + code_address: None, + } + )); + assert!(ext.calls.contains( + &FakeCall { + call_type: FakeCallType::Create, + create_scheme: Some(CreateContractAddress::FromSenderSaltAndCodeHash(H256::from([5u8].as_ref()))), + gas: U256::from(10_740), sender_address: None, receive_address: None, - value: Some(1_000_000_000.into()), + value: Some((1_000_000_000 / 2).into()), data: vec![0u8, 2, 4, 8, 16, 32, 64, 128], code_address: None, } )); - assert_eq!(gas_left, U256::from(59_212)); + assert_eq!(gas_left, U256::from(10_675)); } #[test] @@ -340,6 +358,7 @@ fn call_msg() { assert!(ext.calls.contains( &FakeCall { call_type: FakeCallType::Call, + create_scheme: None, gas: U256::from(33_000), sender_address: Some(receiver), receive_address: Some(Address::from([99, 88, 77, 66, 55, 44, 33, 22, 11, 0, 11, 22, 33, 44, 55, 66, 77, 88, 99, 0])), @@ -382,6 +401,7 @@ fn call_code() { assert!(ext.calls.contains( &FakeCall { call_type: FakeCallType::Call, + create_scheme: None, gas: U256::from(20_000), sender_address: Some(sender), receive_address: Some(receiver), @@ -394,7 +414,7 @@ fn call_code() { // siphash result let res = LittleEndian::read_u32(&result[..]); assert_eq!(res, 4198595614); - assert_eq!(gas_left, U256::from(90_038)); + assert_eq!(gas_left, U256::from(90_037)); } #[test] @@ -429,6 +449,7 @@ fn call_static() { assert!(ext.calls.contains( &FakeCall { call_type: FakeCallType::Call, + create_scheme: None, gas: U256::from(20_000), sender_address: Some(receiver), receive_address: Some("13077bfb00000000000000000000000000000000".parse().unwrap()), @@ -442,7 +463,7 @@ fn call_static() { let res = LittleEndian::read_u32(&result[..]); assert_eq!(res, 317632590); - assert_eq!(gas_left, U256::from(90_043)); + assert_eq!(gas_left, U256::from(90_042)); } // Realloc test @@ -465,7 +486,7 @@ fn realloc() { } }; assert_eq!(result, vec![0u8; 2]); - assert_eq!(gas_left, U256::from(92_842)); + assert_eq!(gas_left, U256::from(92_848)); } #[test] @@ -487,7 +508,7 @@ fn alloc() { } }; assert_eq!(result, vec![5u8; 1024*400]); - assert_eq!(gas_left, U256::from(6_893_883)); + assert_eq!(gas_left, U256::from(6_893_881)); } // Tests that contract's ability to read from a storage @@ -515,7 +536,7 @@ fn storage_read() { }; assert_eq!(Address::from(&result[12..32]), address); - assert_eq!(gas_left, U256::from(96_833)); + assert_eq!(gas_left, U256::from(98_369)); } // Tests keccak calculation @@ -541,7 +562,7 @@ fn keccak() { }; assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87")); - assert_eq!(gas_left, U256::from(84_134)); + assert_eq!(gas_left, U256::from(85_949)); } // math_* tests check the ability of wasm contract to perform big integer operations @@ -570,7 +591,7 @@ fn math_add() { U256::from_dec_str("1888888888888888888888888888887").unwrap(), (&result[..]).into() ); - assert_eq!(gas_left, U256::from(92_086)); + assert_eq!(gas_left, U256::from(92_095)); } // multiplication @@ -592,7 +613,7 @@ fn math_mul() { U256::from_dec_str("888888888888888888888888888887111111111111111111111111111112").unwrap(), (&result[..]).into() ); - assert_eq!(gas_left, U256::from(91_414)); + assert_eq!(gas_left, U256::from(91_423)); } // subtraction @@ -614,7 +635,7 @@ fn math_sub() { U256::from_dec_str("111111111111111111111111111111").unwrap(), (&result[..]).into() ); - assert_eq!(gas_left, U256::from(92_086)); + assert_eq!(gas_left, U256::from(92_095)); } // subtraction with overflow @@ -656,7 +677,7 @@ fn math_div() { U256::from_dec_str("1125000").unwrap(), (&result[..]).into() ); - assert_eq!(gas_left, U256::from(87_376)); + assert_eq!(gas_left, U256::from(87_379)); } #[test] @@ -684,7 +705,7 @@ fn storage_metering() { }; // 0 -> not 0 - assert_eq!(gas_left, U256::from(72_399)); + assert_eq!(gas_left, U256::from(72_395)); // #2 @@ -703,7 +724,7 @@ fn storage_metering() { }; // not 0 -> not 0 - assert_eq!(gas_left, U256::from(87_399)); + assert_eq!(gas_left, U256::from(87_395)); } // This test checks the ability of wasm contract to invoke @@ -791,7 +812,7 @@ fn externs() { "Gas limit requested and returned does not match" ); - assert_eq!(gas_left, U256::from(90_435)); + assert_eq!(gas_left, U256::from(90_428)); } #[test] @@ -817,7 +838,7 @@ fn embedded_keccak() { }; assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87")); - assert_eq!(gas_left, U256::from(84_134)); + assert_eq!(gas_left, U256::from(85_949)); } /// This test checks the correctness of log extern @@ -852,7 +873,7 @@ fn events() { assert_eq!(&log_entry.data, b"gnihtemos"); assert_eq!(&result, b"gnihtemos"); - assert_eq!(gas_left, U256::from(81_351)); + assert_eq!(gas_left, U256::from(83_158)); } #[test] diff --git a/json/src/spec/params.rs b/json/src/spec/params.rs index a37e4f23ba8..0fab68198ac 100644 --- a/json/src/spec/params.rs +++ b/json/src/spec/params.rs @@ -146,6 +146,9 @@ pub struct Params { /// Wasm activation block height, if not activated from start #[serde(rename="wasmActivationTransition")] pub wasm_activation_transition: Option, + /// KIP4 activiation block height. + #[serde(rename="kip4Transition")] + pub kip4_transition: Option, } #[cfg(test)] From a1e2d94ed59d5113d7387ccd297397b4ba506734 Mon Sep 17 00:00:00 2001 From: Alexey Date: Fri, 24 Aug 2018 20:03:46 +0400 Subject: [PATCH 04/19] `gasleft` extern implemented for WASM runtime (kip-6) (#9357) * Wasm gasleft extern added * wasm_gasleft_activation_transition -> kip4_transition * use kip-6 switch * gasleft_panic -> gasleft_fail rename * call_msg_gasleft test added and gas_left agustments because this https://github.com/paritytech/wasm-tests/pull/52 * change .. to _ * fix comment for the have_gasleft param * update tests (https://github.com/paritytech/wasm-tests/pull/54/commits/0edbf860ff7ed4b6b6336097ba44836e8c6482dd) --- ethcore/res/wasm-tests | 2 +- ethcore/src/spec/spec.rs | 9 +++ ethcore/vm/src/schedule.rs | 3 + ethcore/wasm/src/env.rs | 9 +++ ethcore/wasm/src/runtime.rs | 10 ++++ ethcore/wasm/src/tests.rs | 109 ++++++++++++++++++++++++++++++++---- json/src/spec/params.rs | 3 + 7 files changed, 134 insertions(+), 11 deletions(-) diff --git a/ethcore/res/wasm-tests b/ethcore/res/wasm-tests index 986a6fb9467..0edbf860ff7 160000 --- a/ethcore/res/wasm-tests +++ b/ethcore/res/wasm-tests @@ -1 +1 @@ -Subproject commit 986a6fb94673ba270f8f7ef1fff521ba33d427c2 +Subproject commit 0edbf860ff7ed4b6b6336097ba44836e8c6482dd diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index 3b46b27d1d7..0852f09fb5b 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -127,6 +127,8 @@ pub struct CommonParams { pub wasm_activation_transition: BlockNumber, /// Number of first block where KIP-4 rules begin. Only has effect if Wasm is activated. pub kip4_transition: BlockNumber, + /// Number of first block where KIP-6 rules begin. Only has effect if Wasm is activated. + pub kip6_transition: BlockNumber, /// Gas limit bound divisor (how much gas limit can change per block) pub gas_limit_bound_divisor: U256, /// Registrar contract address. @@ -193,6 +195,9 @@ impl CommonParams { if block_number >= self.kip4_transition { wasm.have_create2 = true; } + if block_number >= self.kip6_transition { + wasm.have_gasleft = true; + } schedule.wasm = Some(wasm); } } @@ -304,6 +309,10 @@ impl From for CommonParams { BlockNumber::max_value, Into::into ), + kip6_transition: p.kip6_transition.map_or_else( + BlockNumber::max_value, + Into::into + ), } } } diff --git a/ethcore/vm/src/schedule.rs b/ethcore/vm/src/schedule.rs index ec72c4683fd..2d263b63efd 100644 --- a/ethcore/vm/src/schedule.rs +++ b/ethcore/vm/src/schedule.rs @@ -151,6 +151,8 @@ pub struct WasmCosts { pub opcodes_div: u32, /// Whether create2 extern function is activated. pub have_create2: bool, + /// Whether gasleft extern function is activated. + pub have_gasleft: bool, } impl Default for WasmCosts { @@ -169,6 +171,7 @@ impl Default for WasmCosts { opcodes_mul: 3, opcodes_div: 8, have_create2: false, + have_gasleft: false, } } } diff --git a/ethcore/wasm/src/env.rs b/ethcore/wasm/src/env.rs index a9e536f5f1f..fb9e93e0fd0 100644 --- a/ethcore/wasm/src/env.rs +++ b/ethcore/wasm/src/env.rs @@ -49,6 +49,7 @@ pub mod ids { pub const ORIGIN_FUNC: usize = 200; pub const ELOG_FUNC: usize = 210; pub const CREATE2_FUNC: usize = 220; + pub const GASLEFT_FUNC: usize = 230; pub const PANIC_FUNC: usize = 1000; pub const DEBUG_FUNC: usize = 1010; @@ -157,6 +158,11 @@ pub mod signatures { None, ); + pub const GASLEFT: StaticSignature = StaticSignature( + &[], + Some(I64), + ); + pub const GASLIMIT: StaticSignature = StaticSignature( &[I32], None, @@ -207,6 +213,7 @@ pub struct ImportResolver { memory: RefCell>, have_create2: bool, + have_gasleft: bool, } impl ImportResolver { @@ -217,6 +224,7 @@ impl ImportResolver { memory: RefCell::new(None), have_create2: schedule.have_create2, + have_gasleft: schedule.have_gasleft, } } @@ -274,6 +282,7 @@ impl wasmi::ModuleImportResolver for ImportResolver { "origin" => host(signatures::ORIGIN, ids::ORIGIN_FUNC), "elog" => host(signatures::ELOG, ids::ELOG_FUNC), "create2" if self.have_create2 => host(signatures::CREATE2, ids::CREATE2_FUNC), + "gasleft" if self.have_gasleft => host(signatures::GASLEFT, ids::GASLEFT_FUNC), _ => { return Err(wasmi::Error::Instantiation( format!("Export {} not found", field_name), diff --git a/ethcore/wasm/src/runtime.rs b/ethcore/wasm/src/runtime.rs index 347023dd97c..20bb384b05c 100644 --- a/ethcore/wasm/src/runtime.rs +++ b/ethcore/wasm/src/runtime.rs @@ -660,6 +660,15 @@ impl<'a> Runtime<'a> { self.return_u256_ptr(args.nth_checked(0)?, difficulty) } + /// Signature: `fn gasleft() -> i64` + pub fn gasleft(&mut self) -> Result { + Ok(RuntimeValue::from( + self.gas_left()? * self.ext.schedule().wasm().opcodes_mul as u64 + / self.ext.schedule().wasm().opcodes_div as u64 + ) + ) + } + /// Signature: `fn gaslimit(dest: *mut u8)` pub fn gaslimit(&mut self, args: RuntimeArgs) -> Result<()> { let gas_limit = self.ext.env_info().gas_limit; @@ -776,6 +785,7 @@ mod ext_impl { ORIGIN_FUNC => void!(self.origin(args)), ELOG_FUNC => void!(self.elog(args)), CREATE2_FUNC => some!(self.create2(args)), + GASLEFT_FUNC => some!(self.gasleft()), _ => panic!("env module doesn't provide function at index {}", index), } } diff --git a/ethcore/wasm/src/tests.rs b/ethcore/wasm/src/tests.rs index e72cc15c81d..35898241d1e 100644 --- a/ethcore/wasm/src/tests.rs +++ b/ethcore/wasm/src/tests.rs @@ -303,7 +303,7 @@ fn create() { &FakeCall { call_type: FakeCallType::Create, create_scheme: Some(CreateContractAddress::FromSenderAndCodeHash), - gas: U256::from(52_017), + gas: U256::from(49_674), sender_address: None, receive_address: None, value: Some((1_000_000_000 / 2).into()), @@ -315,7 +315,7 @@ fn create() { &FakeCall { call_type: FakeCallType::Create, create_scheme: Some(CreateContractAddress::FromSenderSaltAndCodeHash(H256::from([5u8].as_ref()))), - gas: U256::from(10_740), + gas: U256::from(6039), sender_address: None, receive_address: None, value: Some((1_000_000_000 / 2).into()), @@ -323,7 +323,7 @@ fn create() { code_address: None, } )); - assert_eq!(gas_left, U256::from(10_675)); + assert_eq!(gas_left, U256::from(5974)); } #[test] @@ -371,6 +371,54 @@ fn call_msg() { assert_eq!(gas_left, U256::from(91_672)); } +// The same as `call_msg`, but send a `pwasm_ethereum::gasleft` +// value as `gas` argument to the inner pwasm_ethereum::call +#[test] +fn call_msg_gasleft() { + ::ethcore_logger::init_log(); + + let sender: Address = "01030507090b0d0f11131517191b1d1f21232527".parse().unwrap(); + let receiver: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap(); + let contract_address: Address = "0d461d4174b4ae35775c4a342f1e5e1e4e6c4db5".parse().unwrap(); + + let mut params = ActionParams::default(); + params.sender = sender.clone(); + params.address = receiver.clone(); + params.code_address = contract_address.clone(); + params.gas = U256::from(100_000); + params.code = Some(Arc::new(load_sample!("call_gasleft.wasm"))); + params.data = Some(Vec::new()); + + let mut ext = FakeExt::new().with_wasm(); + ext.schedule.wasm.as_mut().unwrap().have_gasleft = true; + ext.balances.insert(receiver.clone(), U256::from(10000000000u64)); + + let gas_left = { + let mut interpreter = wasm_interpreter(); + let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors"); + match result { + GasLeft::Known(gas_left) => gas_left, + GasLeft::NeedsReturn { .. } => { panic!("Call test should not return payload"); }, + } + }; + + trace!(target: "wasm", "fake_calls: {:?}", &ext.calls); + assert!(ext.calls.contains( + &FakeCall { + call_type: FakeCallType::Call, + create_scheme: None, + gas: U256::from(91_165), + sender_address: Some(receiver), + receive_address: Some(Address::from([99, 88, 77, 66, 55, 44, 33, 22, 11, 0, 11, 22, 33, 44, 55, 66, 77, 88, 99, 0])), + value: Some(1000000000.into()), + data: vec![129u8, 123, 113, 107, 101, 97], + code_address: Some(Address::from([99, 88, 77, 66, 55, 44, 33, 22, 11, 0, 11, 22, 33, 44, 55, 66, 77, 88, 99, 0])), + } + )); + + assert_eq!(gas_left, U256::from(91_671)); +} + #[test] fn call_code() { ::ethcore_logger::init_log(); @@ -591,7 +639,7 @@ fn math_add() { U256::from_dec_str("1888888888888888888888888888887").unwrap(), (&result[..]).into() ); - assert_eq!(gas_left, U256::from(92_095)); + assert_eq!(gas_left, U256::from(92_072)); } // multiplication @@ -613,7 +661,7 @@ fn math_mul() { U256::from_dec_str("888888888888888888888888888887111111111111111111111111111112").unwrap(), (&result[..]).into() ); - assert_eq!(gas_left, U256::from(91_423)); + assert_eq!(gas_left, U256::from(91_400)); } // subtraction @@ -635,7 +683,7 @@ fn math_sub() { U256::from_dec_str("111111111111111111111111111111").unwrap(), (&result[..]).into() ); - assert_eq!(gas_left, U256::from(92_095)); + assert_eq!(gas_left, U256::from(92_072)); } // subtraction with overflow @@ -677,7 +725,7 @@ fn math_div() { U256::from_dec_str("1125000").unwrap(), (&result[..]).into() ); - assert_eq!(gas_left, U256::from(87_379)); + assert_eq!(gas_left, U256::from(85_700)); } #[test] @@ -705,7 +753,7 @@ fn storage_metering() { }; // 0 -> not 0 - assert_eq!(gas_left, U256::from(72_395)); + assert_eq!(gas_left, U256::from(72_164)); // #2 @@ -724,7 +772,7 @@ fn storage_metering() { }; // not 0 -> not 0 - assert_eq!(gas_left, U256::from(87_395)); + assert_eq!(gas_left, U256::from(87_164)); } // This test checks the ability of wasm contract to invoke @@ -815,6 +863,47 @@ fn externs() { assert_eq!(gas_left, U256::from(90_428)); } +// This test checks the ability of wasm contract to invoke gasleft +#[test] +fn gasleft() { + ::ethcore_logger::init_log(); + + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(Arc::new(load_sample!("gasleft.wasm"))); + + let mut ext = FakeExt::new().with_wasm(); + ext.schedule.wasm.as_mut().unwrap().have_gasleft = true; + + let mut interpreter = wasm_interpreter(); + let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors"); + match result { + GasLeft::Known(_) => {}, + GasLeft::NeedsReturn { gas_left, data, .. } => { + let gas = LittleEndian::read_u64(data.as_ref()); + assert_eq!(gas, 93_423); + assert_eq!(gas_left, U256::from(93_349)); + }, + } +} + +// This test should fail because +// ext.schedule.wasm.as_mut().unwrap().have_gasleft = false; +#[test] +fn gasleft_fail() { + ::ethcore_logger::init_log(); + + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(Arc::new(load_sample!("gasleft.wasm"))); + let mut ext = FakeExt::new().with_wasm(); + let mut interpreter = wasm_interpreter(); + match interpreter.exec(params, &mut ext) { + Err(_) => {}, + Ok(_) => panic!("interpreter.exec should return Err if ext.schedule.wasm.have_gasleft = false") + } +} + #[test] fn embedded_keccak() { ::ethcore_logger::init_log(); @@ -873,7 +962,7 @@ fn events() { assert_eq!(&log_entry.data, b"gnihtemos"); assert_eq!(&result, b"gnihtemos"); - assert_eq!(gas_left, U256::from(83_158)); + assert_eq!(gas_left, U256::from(83_161)); } #[test] diff --git a/json/src/spec/params.rs b/json/src/spec/params.rs index 0fab68198ac..d57a5b28a74 100644 --- a/json/src/spec/params.rs +++ b/json/src/spec/params.rs @@ -149,6 +149,9 @@ pub struct Params { /// KIP4 activiation block height. #[serde(rename="kip4Transition")] pub kip4_transition: Option, + /// KIP6 activiation block height. + #[serde(rename="kip6Transition")] + pub kip6_transition: Option, } #[cfg(test)] From b7d9ec6195c24f9f95b82019c55b06e34476866f Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Fri, 31 Aug 2018 23:43:51 +0800 Subject: [PATCH 05/19] Add EIP-1014 transition config flag (#9268) * Add EIP-1014 transition config flag * Remove EIP-86 configs * Change CREATE2 opcode index to 0xf5 * Move salt to the last item in the stack * Change sendersaltandaddress scheme to comply with current EIP-1014 * Fix json configs * Fix create2 test * Fix deprecated comments --- ethcore/evm/src/instructions.rs | 2 +- ethcore/evm/src/interpreter/mod.rs | 4 ++-- ethcore/light/src/client/mod.rs | 7 ------- ethcore/res/ethereum/classic.json | 3 +-- ethcore/res/ethereum/easthub.json | 3 +-- ethcore/res/ethereum/eip150_test.json | 1 - ethcore/res/ethereum/eip161_test.json | 1 - ethcore/res/ethereum/ellaism.json | 1 - ethcore/res/ethereum/expanse.json | 1 - ethcore/res/ethereum/foundation.json | 1 - ethcore/res/ethereum/frontier_like_test.json | 1 - ethcore/res/ethereum/frontier_test.json | 1 - ethcore/res/ethereum/homestead_test.json | 1 - ethcore/res/ethereum/mcip3_test.json | 1 - ethcore/res/ethereum/mcip6_byz.json | 1 - ethcore/res/ethereum/morden.json | 3 +-- ethcore/res/ethereum/musicoin.json | 1 - ethcore/res/ethereum/olympic.json | 1 - ethcore/res/ethereum/ropsten.json | 1 - ethcore/res/ethereum/social.json | 3 +-- ethcore/res/instant_seal.json | 1 - ethcore/res/null.json | 1 - ethcore/src/client/client.rs | 4 ---- ethcore/src/client/evm_test_client.rs | 2 +- ethcore/src/client/test_client.rs | 2 -- ethcore/src/client/traits.rs | 3 --- ethcore/src/executive.rs | 11 ++++++----- ethcore/src/externalities.rs | 4 ++-- ethcore/src/spec/spec.rs | 14 +++++++------- ethcore/vm/src/ext.rs | 4 ++-- ethcore/vm/src/schedule.rs | 8 ++++---- json/src/spec/params.rs | 6 +++--- 32 files changed, 32 insertions(+), 66 deletions(-) diff --git a/ethcore/evm/src/instructions.rs b/ethcore/evm/src/instructions.rs index 67d390d4dff..e1d31b13a79 100644 --- a/ethcore/evm/src/instructions.rs +++ b/ethcore/evm/src/instructions.rs @@ -328,7 +328,7 @@ enum_with_from_u8! { #[doc = "like CALLCODE but keeps caller's value and sender"] DELEGATECALL = 0xf4, #[doc = "create a new account and set creation address to sha3(sender + sha3(init code)) % 2**160"] - CREATE2 = 0xfb, + CREATE2 = 0xf5, #[doc = "stop execution and revert state changes. Return output data."] REVERT = 0xfd, #[doc = "like CALL but it does not take value, nor modify the state"] diff --git a/ethcore/evm/src/interpreter/mod.rs b/ethcore/evm/src/interpreter/mod.rs index 3af1e34dd36..f533c97e261 100644 --- a/ethcore/evm/src/interpreter/mod.rs +++ b/ethcore/evm/src/interpreter/mod.rs @@ -317,13 +317,13 @@ impl Interpreter { }, instructions::CREATE | instructions::CREATE2 => { let endowment = stack.pop_back(); + let init_off = stack.pop_back(); + let init_size = stack.pop_back(); let address_scheme = match instruction { instructions::CREATE => CreateContractAddress::FromSenderAndNonce, instructions::CREATE2 => CreateContractAddress::FromSenderSaltAndCodeHash(stack.pop_back().into()), _ => unreachable!("instruction can only be CREATE/CREATE2 checked above; qed"), }; - let init_off = stack.pop_back(); - let init_size = stack.pop_back(); 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"); diff --git a/ethcore/light/src/client/mod.rs b/ethcore/light/src/client/mod.rs index a1625b0e8f3..af557c02411 100644 --- a/ethcore/light/src/client/mod.rs +++ b/ethcore/light/src/client/mod.rs @@ -127,9 +127,6 @@ pub trait LightChainClient: Send + Sync { /// Get the `i`th CHT root. fn cht_root(&self, i: usize) -> Option; - /// Get the EIP-86 transition block number. - fn eip86_transition(&self) -> BlockNumber; - /// Get a report of import activity since the last call. fn report(&self) -> ClientReport; } @@ -585,10 +582,6 @@ impl LightChainClient for Client { Client::cht_root(self, i) } - fn eip86_transition(&self) -> BlockNumber { - self.engine().params().eip86_transition - } - fn report(&self) -> ClientReport { Client::report(self) } diff --git a/ethcore/res/ethereum/classic.json b/ethcore/res/ethereum/classic.json index 602c05cd3bd..a2bcb717a2b 100644 --- a/ethcore/res/ethereum/classic.json +++ b/ethcore/res/ethereum/classic.json @@ -31,8 +31,7 @@ "eip161abcTransition": "0x7fffffffffffffff", "eip161dTransition": "0x7fffffffffffffff", "eip155Transition": 3000000, - "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff" + "eip98Transition": "0x7fffffffffffff" }, "genesis": { "seal": { diff --git a/ethcore/res/ethereum/easthub.json b/ethcore/res/ethereum/easthub.json index e7e1a6e708e..bcc34a78273 100644 --- a/ethcore/res/ethereum/easthub.json +++ b/ethcore/res/ethereum/easthub.json @@ -27,8 +27,7 @@ "eip155Transition": "0x0", "eip161abcTransition": "0x7fffffffffffffff", "eip161dTransition": "0x7fffffffffffffff", - "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff" + "eip98Transition": "0x7fffffffffffff" }, "genesis": { "seal": { diff --git a/ethcore/res/ethereum/eip150_test.json b/ethcore/res/ethereum/eip150_test.json index baf9c1b7bfc..32f6401ff87 100644 --- a/ethcore/res/ethereum/eip150_test.json +++ b/ethcore/res/ethereum/eip150_test.json @@ -23,7 +23,6 @@ "eip161abcTransition": "0x7fffffffffffffff", "eip161dTransition": "0x7fffffffffffffff", "eip98Transition": "0x7fffffffffffffff", - "eip86Transition": "0x7fffffffffffffff", "eip155Transition": "0x7fffffffffffffff", "maxCodeSize": 24576, "maxCodeSizeTransition": "0x7fffffffffffffff" diff --git a/ethcore/res/ethereum/eip161_test.json b/ethcore/res/ethereum/eip161_test.json index 079ce7d55a2..72288115883 100644 --- a/ethcore/res/ethereum/eip161_test.json +++ b/ethcore/res/ethereum/eip161_test.json @@ -23,7 +23,6 @@ "eip161abcTransition": "0x0", "eip161dTransition": "0x0", "eip98Transition": "0x7fffffffffffffff", - "eip86Transition": "0x7fffffffffffffff", "eip155Transition": "0x7fffffffffffffff", "maxCodeSize": 24576, "maxCodeSizeTransition": "0x0" diff --git a/ethcore/res/ethereum/ellaism.json b/ethcore/res/ethereum/ellaism.json index c3107bbe469..de56ae9472d 100644 --- a/ethcore/res/ethereum/ellaism.json +++ b/ethcore/res/ethereum/ellaism.json @@ -29,7 +29,6 @@ "eip161dTransition": "0x7fffffffffffffff", "eip155Transition": "0x0", "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff", "wasmActivationTransition": 2000000, "eip140Transition": 2000000, "eip211Transition": 2000000, diff --git a/ethcore/res/ethereum/expanse.json b/ethcore/res/ethereum/expanse.json index 2061231c60d..5e54f683346 100644 --- a/ethcore/res/ethereum/expanse.json +++ b/ethcore/res/ethereum/expanse.json @@ -38,7 +38,6 @@ "eip161abcTransition": "0x927C0", "eip161dTransition": "0x927C0", "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff", "eip155Transition": "0x927C0", "eip140Transition": "0xC3500", "eip211Transition": "0xC3500", diff --git a/ethcore/res/ethereum/foundation.json b/ethcore/res/ethereum/foundation.json index 3332ad6f971..59e8daa8cbd 100644 --- a/ethcore/res/ethereum/foundation.json +++ b/ethcore/res/ethereum/foundation.json @@ -150,7 +150,6 @@ "eip161dTransition": 2675000, "eip155Transition": 2675000, "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff", "maxCodeSize": 24576, "maxCodeSizeTransition": 2675000, "eip140Transition": 4370000, diff --git a/ethcore/res/ethereum/frontier_like_test.json b/ethcore/res/ethereum/frontier_like_test.json index 7eac5acbd0a..3596217cb99 100644 --- a/ethcore/res/ethereum/frontier_like_test.json +++ b/ethcore/res/ethereum/frontier_like_test.json @@ -143,7 +143,6 @@ "eip161abcTransition": "0x7fffffffffffffff", "eip161dTransition": "0x7fffffffffffffff", "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff", "eip155Transition": "0x7fffffffffffffff" }, "genesis": { diff --git a/ethcore/res/ethereum/frontier_test.json b/ethcore/res/ethereum/frontier_test.json index 7e52f6ecf97..b01ae9ef010 100644 --- a/ethcore/res/ethereum/frontier_test.json +++ b/ethcore/res/ethereum/frontier_test.json @@ -23,7 +23,6 @@ "eip161abcTransition": "0x7fffffffffffffff", "eip161dTransition": "0x7fffffffffffffff", "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff", "eip155Transition": "0x7fffffffffffffff" }, "genesis": { diff --git a/ethcore/res/ethereum/homestead_test.json b/ethcore/res/ethereum/homestead_test.json index 817bf5ff57f..2dc521b9af6 100644 --- a/ethcore/res/ethereum/homestead_test.json +++ b/ethcore/res/ethereum/homestead_test.json @@ -19,7 +19,6 @@ "minGasLimit": "0x1388", "networkID" : "0x1", "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff", "eip155Transition": "0x7fffffffffffffff", "eip150Transition": "0x7fffffffffffffff", "eip160Transition": "0x7fffffffffffffff", diff --git a/ethcore/res/ethereum/mcip3_test.json b/ethcore/res/ethereum/mcip3_test.json index 391a625730a..d24164dcf0e 100644 --- a/ethcore/res/ethereum/mcip3_test.json +++ b/ethcore/res/ethereum/mcip3_test.json @@ -33,7 +33,6 @@ "eip160Transition":"0x7fffffffffffff", "eip161abcTransition":"0x7fffffffffffff", "eip161dTransition":"0x7fffffffffffff", - "eip86Transition":"0x7fffffffffffff", "eip98Transition":"0x7fffffffffffff", "eip140Transition":"0x7fffffffffffff", "eip155Transition":"0x7fffffffffffff", diff --git a/ethcore/res/ethereum/mcip6_byz.json b/ethcore/res/ethereum/mcip6_byz.json index a12df7c7115..45aef8b4b7c 100644 --- a/ethcore/res/ethereum/mcip6_byz.json +++ b/ethcore/res/ethereum/mcip6_byz.json @@ -33,7 +33,6 @@ "eip160Transition":"0x7fffffffffffff", "eip161abcTransition":"0x7fffffffffffff", "eip161dTransition":"0x7fffffffffffff", - "eip86Transition":"0x7fffffffffffff", "eip98Transition":"0x7fffffffffffff", "eip140Transition":"0x2a", "eip155Transition":"0x2a", diff --git a/ethcore/res/ethereum/morden.json b/ethcore/res/ethereum/morden.json index b61799c0c9d..5cff465f83a 100644 --- a/ethcore/res/ethereum/morden.json +++ b/ethcore/res/ethereum/morden.json @@ -31,8 +31,7 @@ "eip161abcTransition": "0x7fffffffffffffff", "eip161dTransition": "0x7fffffffffffffff", "eip155Transition": 1915000, - "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff" + "eip98Transition": "0x7fffffffffffff" }, "genesis": { "seal": { diff --git a/ethcore/res/ethereum/musicoin.json b/ethcore/res/ethereum/musicoin.json index 724f11478bf..91c176cf4a3 100644 --- a/ethcore/res/ethereum/musicoin.json +++ b/ethcore/res/ethereum/musicoin.json @@ -33,7 +33,6 @@ "eip160Transition":"0x21e88e", "eip161abcTransition":"0x21e88e", "eip161dTransition":"0x21e88e", - "eip86Transition":"0x7fffffffffffff", "eip98Transition":"0x7fffffffffffff", "eip140Transition":"0x21e88e", "eip155Transition":"0x21e88e", diff --git a/ethcore/res/ethereum/olympic.json b/ethcore/res/ethereum/olympic.json index 3ae9baddf2b..274e8c23a3a 100644 --- a/ethcore/res/ethereum/olympic.json +++ b/ethcore/res/ethereum/olympic.json @@ -23,7 +23,6 @@ "eip161abcTransition": "0x7fffffffffffffff", "eip161dTransition": "0x7fffffffffffffff", "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff", "eip155Transition": "0x7fffffffffffffff" }, "genesis": { diff --git a/ethcore/res/ethereum/ropsten.json b/ethcore/res/ethereum/ropsten.json index bdf44fe83bc..fd24bbe6d54 100644 --- a/ethcore/res/ethereum/ropsten.json +++ b/ethcore/res/ethereum/ropsten.json @@ -32,7 +32,6 @@ "eip161dTransition": 10, "eip155Transition": 10, "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff", "eip140Transition": 1700000, "eip211Transition": 1700000, "eip214Transition": 1700000, diff --git a/ethcore/res/ethereum/social.json b/ethcore/res/ethereum/social.json index 2ad8fec8b06..bbc77359bd6 100644 --- a/ethcore/res/ethereum/social.json +++ b/ethcore/res/ethereum/social.json @@ -27,8 +27,7 @@ "eip161abcTransition": "0x7fffffffffffffff", "eip161dTransition": "0x7fffffffffffffff", "eip155Transition": "0x0", - "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff" + "eip98Transition": "0x7fffffffffffff" }, "genesis": { "seal": { diff --git a/ethcore/res/instant_seal.json b/ethcore/res/instant_seal.json index 36832e698e6..00534243774 100644 --- a/ethcore/res/instant_seal.json +++ b/ethcore/res/instant_seal.json @@ -16,7 +16,6 @@ "eip161dTransition": "0x0", "eip155Transition": "0x0", "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff", "maxCodeSize": 24576, "maxCodeSizeTransition": "0x0", "eip140Transition": "0x0", diff --git a/ethcore/res/null.json b/ethcore/res/null.json index 345bb02b276..7fa41a8def5 100644 --- a/ethcore/res/null.json +++ b/ethcore/res/null.json @@ -11,7 +11,6 @@ "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", "networkID" : "0x2", - "eip86Transition": "0x7fffffffffffff", "eip140Transition": "0x0", "eip211Transition": "0x0", "eip214Transition": "0x0", diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 01ae9291f72..2fb6d3f2abf 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -2020,10 +2020,6 @@ impl BlockChainClient for Client { fn registrar_address(&self) -> Option
{ self.registrar_address.clone() } - - fn eip86_transition(&self) -> u64 { - self.engine().params().eip86_transition - } } impl IoClient for Client { diff --git a/ethcore/src/client/evm_test_client.rs b/ethcore/src/client/evm_test_client.rs index f11cae3b0d4..9c91b4d46f3 100644 --- a/ethcore/src/client/evm_test_client.rs +++ b/ethcore/src/client/evm_test_client.rs @@ -205,7 +205,7 @@ impl<'a> EvmTestClient<'a> { ) -> TransactResult { let initial_gas = transaction.gas; // Verify transaction - let is_ok = transaction.verify_basic(true, None, env_info.number >= self.spec.engine.params().eip86_transition); + let is_ok = transaction.verify_basic(true, None, false); if let Err(error) = is_ok { return TransactResult::Err { state_root: *self.state.root(), diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 71bf70b6039..4051d004c86 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -845,8 +845,6 @@ impl BlockChainClient for TestBlockChainClient { } fn registrar_address(&self) -> Option
{ None } - - fn eip86_transition(&self) -> u64 { u64::max_value() } } impl IoClient for TestBlockChainClient { diff --git a/ethcore/src/client/traits.rs b/ethcore/src/client/traits.rs index 2e6d8d35e18..0dc16c9097e 100644 --- a/ethcore/src/client/traits.rs +++ b/ethcore/src/client/traits.rs @@ -377,9 +377,6 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra /// Get the address of the registry itself. fn registrar_address(&self) -> Option
; - - /// Get the EIP-86 transition block number. - fn eip86_transition(&self) -> u64; } /// Provides `reopen_block` method diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index 28ce8b2120d..4c494a42fc4 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -63,10 +63,11 @@ pub fn contract_address(address_scheme: CreateContractAddress, sender: &Address, }, CreateContractAddress::FromSenderSaltAndCodeHash(salt) => { let code_hash = keccak(code); - let mut buffer = [0u8; 20 + 32 + 32]; - &mut buffer[0..20].copy_from_slice(&sender[..]); - &mut buffer[20..(20+32)].copy_from_slice(&salt[..]); - &mut buffer[(20+32)..].copy_from_slice(&code_hash[..]); + let mut buffer = [0u8; 1 + 20 + 32 + 32]; + buffer[0] = 0xff; + &mut buffer[1..(1+20)].copy_from_slice(&sender[..]); + &mut buffer[(1+20)..(1+20+32)].copy_from_slice(&salt[..]); + &mut buffer[(1+20+32)..].copy_from_slice(&code_hash[..]); (From::from(keccak(&buffer[..])), Some(code_hash)) }, CreateContractAddress::FromSenderAndCodeHash => { @@ -287,7 +288,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { let mut substate = Substate::new(); // NOTE: there can be no invalid transactions from this point. - if !schedule.eip86 || !t.is_unsigned() { + if !schedule.keep_unsigned_nonce || !t.is_unsigned() { self.state.inc_nonce(&sender)?; } self.state.sub_balance(&sender, &U256::from(gas_cost), &mut substate.to_cleanup_mode(&schedule))?; diff --git a/ethcore/src/externalities.rs b/ethcore/src/externalities.rs index 6966b23c94e..edea64256a9 100644 --- a/ethcore/src/externalities.rs +++ b/ethcore/src/externalities.rs @@ -219,7 +219,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> }; if !self.static_flag { - if !self.schedule.eip86 || params.sender != UNSIGNED_SENDER { + if !self.schedule.keep_unsigned_nonce || params.sender != UNSIGNED_SENDER { if let Err(e) = self.state.inc_nonce(&self.origin_info.address) { debug!(target: "ext", "Database corruption encountered: {:?}", e); return ContractCreateResult::Failed @@ -612,6 +612,6 @@ mod tests { } }; - assert_eq!(address, Address::from_str("b7c227636666831278bacdb8d7f52933b8698ab9").unwrap()); + assert_eq!(address, Address::from_str("e33c0c7f7df4809055c3eba6c09cfe4baf1bd9e0").unwrap()); } } diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index 0852f09fb5b..b9b36e6a177 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -96,8 +96,6 @@ pub struct CommonParams { pub validate_receipts_transition: BlockNumber, /// Validate transaction chain id. pub validate_chain_id_transition: BlockNumber, - /// Number of first block where EIP-86 (Metropolis) rules begin. - pub eip86_transition: BlockNumber, /// Number of first block where EIP-140 (Metropolis: REVERT opcode) rules begin. pub eip140_transition: BlockNumber, /// Number of first block where EIP-210 (Metropolis: BLOCKHASH changes) rules begin. @@ -117,6 +115,8 @@ pub struct CommonParams { pub eip145_transition: BlockNumber, /// Number of first block where EIP-1052 rules begin. pub eip1052_transition: BlockNumber, + /// Number of first block where EIP-1014 rules begin. + pub eip1014_transition: BlockNumber, /// Number of first block where dust cleanup rules (EIP-168 and EIP169) begin. pub dust_protection_transition: BlockNumber, /// Nonce cap increase per block. Nonce cap is only checked if dust protection is enabled. @@ -175,7 +175,7 @@ impl CommonParams { /// Apply common spec config parameters to the schedule. pub fn update_schedule(&self, block_number: u64, schedule: &mut ::vm::Schedule) { - schedule.have_create2 = block_number >= self.eip86_transition; + schedule.have_create2 = block_number >= self.eip1014_transition; schedule.have_revert = block_number >= self.eip140_transition; schedule.have_static_call = block_number >= self.eip214_transition; schedule.have_return_data = block_number >= self.eip211_transition; @@ -246,10 +246,6 @@ impl From for CommonParams { eip155_transition: p.eip155_transition.map_or(0, Into::into), validate_receipts_transition: p.validate_receipts_transition.map_or(0, Into::into), validate_chain_id_transition: p.validate_chain_id_transition.map_or(0, Into::into), - eip86_transition: p.eip86_transition.map_or_else( - BlockNumber::max_value, - Into::into, - ), eip140_transition: p.eip140_transition.map_or_else( BlockNumber::max_value, Into::into, @@ -288,6 +284,10 @@ impl From for CommonParams { BlockNumber::max_value, Into::into, ), + eip1014_transition: p.eip1014_transition.map_or_else( + BlockNumber::max_value, + Into::into, + ), dust_protection_transition: p.dust_protection_transition.map_or_else( BlockNumber::max_value, Into::into, diff --git a/ethcore/vm/src/ext.rs b/ethcore/vm/src/ext.rs index c1ce1b79f0b..d1a856e5c1e 100644 --- a/ethcore/vm/src/ext.rs +++ b/ethcore/vm/src/ext.rs @@ -53,9 +53,9 @@ pub enum MessageCallResult { /// Specifies how an address is calculated for a new contract. #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] pub enum CreateContractAddress { - /// Address is calculated from sender and nonce. Pre EIP-86 (Metropolis) + /// Address is calculated from sender and nonce. pWASM `create` scheme. FromSenderAndNonce, - /// Address is calculated from sender, salt and code hash. EIP-86 CREATE2 scheme. + /// Address is calculated from sender, salt and code hash. pWASM `create2` scheme and EIP-1014 CREATE2 scheme. FromSenderSaltAndCodeHash(H256), /// Address is calculated from code hash and sender. Used by pwasm create ext. FromSenderAndCodeHash, diff --git a/ethcore/vm/src/schedule.rs b/ethcore/vm/src/schedule.rs index 2d263b63efd..b3d71457ebe 100644 --- a/ethcore/vm/src/schedule.rs +++ b/ethcore/vm/src/schedule.rs @@ -117,8 +117,8 @@ pub struct Schedule { pub have_bitwise_shifting: bool, /// Kill basic accounts below this balance if touched. pub kill_dust: CleanDustMode, - /// Enable EIP-86 rules - pub eip86: bool, + /// VM execution does not increase null signed address nonce if this field is true. + pub keep_unsigned_nonce: bool, /// Wasm extra schedule settings, if wasm activated pub wasm: Option, } @@ -250,7 +250,7 @@ impl Schedule { blockhash_gas: 20, have_static_call: false, kill_dust: CleanDustMode::Off, - eip86: false, + keep_unsigned_nonce: false, wasm: None, } } @@ -323,7 +323,7 @@ impl Schedule { blockhash_gas: 20, have_static_call: false, kill_dust: CleanDustMode::Off, - eip86: false, + keep_unsigned_nonce: false, wasm: None, } } diff --git a/json/src/spec/params.rs b/json/src/spec/params.rs index d57a5b28a74..341c0543b69 100644 --- a/json/src/spec/params.rs +++ b/json/src/spec/params.rs @@ -79,9 +79,6 @@ pub struct Params { #[serde(rename="validateReceiptsTransition")] pub validate_receipts_transition: Option, /// See `CommonParams` docs. - #[serde(rename="eip86Transition")] - pub eip86_transition: Option, - /// See `CommonParams` docs. #[serde(rename="eip140Transition")] pub eip140_transition: Option, /// See `CommonParams` docs. @@ -112,6 +109,9 @@ pub struct Params { #[serde(rename="eip1052Transition")] pub eip1052_transition: Option, /// See `CommonParams` docs. + #[serde(rename="eip1014Transition")] + pub eip1014_transition: Option, + /// See `CommonParams` docs. #[serde(rename="dustProtectionTransition")] pub dust_protection_transition: Option, /// See `CommonParams` docs. From bec26cbad38a3b4f3414d5cabb9c32bd71e5324f Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Fri, 7 Sep 2018 18:51:08 +0800 Subject: [PATCH 06/19] EIP 1283: Net gas metering for SSTORE without dirty maps (#9319) * Implement last_checkpoint_storage_at * Add reverted_storage_at for externalities * sstore_clears_count -> sstore_clears_refund * Implement eip1283 for evm * Add eip1283Transition params * evm: fix tests * jsontests: fix test * Return checkpoint index when creating * Comply with spec Version II * Fix docs * Fix jsontests feature compile * Address grumbles * Fix no-checkpoint-entry case * Remove unnecessary expect * Add test for State::checkpoint_storage_at * Add executive level test for eip1283 * Hard-code transaction_checkpoint_index to 0 * Fix jsontests * Add tests for checkpoint discard/revert * Require checkpoint to be empty for kill_account and commit * Get code coverage * Use saturating_add/saturating_sub * Fix issues in insert_cache * Clear the state again * Fix original_storage_at * Early return for empty RLP trie storage * Update comments * Fix borrow_mut issue * Simplify checkpoint_storage_at if branches * Better commenting for gas handling code * Address naming grumbles * More tests * Fix an issue in overwrite_with * Add another test * Fix comment * Remove unnecessary bracket * Move orig to inner if * Remove test coverage for this PR * Add tests for executive original value * Add warn! for an unreachable cause --- ethcore/evm/src/interpreter/gasometer.rs | 98 +++++- ethcore/evm/src/interpreter/mod.rs | 10 +- ethcore/evm/src/tests.rs | 2 +- ethcore/res/ethereum/constantinople_test.json | 3 +- ethcore/src/executive.rs | 65 +++- ethcore/src/externalities.rs | 12 +- ethcore/src/json_tests/executive.rs | 12 +- ethcore/src/spec/spec.rs | 7 + ethcore/src/state/account.rs | 141 ++++++-- ethcore/src/state/mod.rs | 304 ++++++++++++++++-- ethcore/src/state/substate.rs | 12 +- ethcore/vm/src/ext.rs | 10 +- ethcore/vm/src/schedule.rs | 4 + ethcore/vm/src/tests.rs | 14 +- ethcore/wasm/src/runtime.rs | 3 +- json/src/spec/params.rs | 2 + 16 files changed, 632 insertions(+), 67 deletions(-) diff --git a/ethcore/evm/src/interpreter/gasometer.rs b/ethcore/evm/src/interpreter/gasometer.rs index 78a33ef3ead..406df19fd35 100644 --- a/ethcore/evm/src/interpreter/gasometer.rs +++ b/ethcore/evm/src/interpreter/gasometer.rs @@ -125,12 +125,17 @@ impl Gasometer { let newval = stack.peek(1); let val = U256::from(&*ext.storage_at(&address)?); - let gas = if val.is_zero() && !newval.is_zero() { - schedule.sstore_set_gas + let gas = if schedule.eip1283 { + let orig = U256::from(&*ext.initial_storage_at(&address)?); + calculate_eip1283_sstore_gas(schedule, &orig, &val, &newval) } else { - // Refund for below case is added when actually executing sstore - // !is_zero(&val) && is_zero(newval) - schedule.sstore_reset_gas + if val.is_zero() && !newval.is_zero() { + schedule.sstore_set_gas + } else { + // Refund for below case is added when actually executing sstore + // !is_zero(&val) && is_zero(newval) + schedule.sstore_reset_gas + } }; Request::Gas(Gas::from(gas)) }, @@ -342,6 +347,89 @@ fn add_gas_usize(value: Gas, num: usize) -> (Gas, bool) { value.overflow_add(Gas::from(num)) } +#[inline] +fn calculate_eip1283_sstore_gas(schedule: &Schedule, original: &U256, current: &U256, new: &U256) -> Gas { + Gas::from( + if current == new { + // 1. If current value equals new value (this is a no-op), 200 gas is deducted. + schedule.sload_gas + } else { + // 2. If current value does not equal new value + if original == current { + // 2.1. If original value equals current value (this storage slot has not been changed by the current execution context) + if original.is_zero() { + // 2.1.1. If original value is 0, 20000 gas is deducted. + schedule.sstore_set_gas + } else { + // 2.1.2. Otherwise, 5000 gas is deducted. + schedule.sstore_reset_gas + + // 2.1.2.1. If new value is 0, add 15000 gas to refund counter. + } + } else { + // 2.2. If original value does not equal current value (this storage slot is dirty), 200 gas is deducted. Apply both of the following clauses. + schedule.sload_gas + + // 2.2.1. If original value is not 0 + // 2.2.1.1. If current value is 0 (also means that new value is not 0), remove 15000 gas from refund counter. We can prove that refund counter will never go below 0. + // 2.2.1.2. If new value is 0 (also means that current value is not 0), add 15000 gas to refund counter. + + // 2.2.2. If original value equals new value (this storage slot is reset) + // 2.2.2.1. If original value is 0, add 19800 gas to refund counter. + // 2.2.2.2. Otherwise, add 4800 gas to refund counter. + } + } + ) +} + +pub fn handle_eip1283_sstore_clears_refund(ext: &mut vm::Ext, original: &U256, current: &U256, new: &U256) { + let sstore_clears_schedule = U256::from(ext.schedule().sstore_refund_gas); + + if current == new { + // 1. If current value equals new value (this is a no-op), 200 gas is deducted. + } else { + // 2. If current value does not equal new value + if original == current { + // 2.1. If original value equals current value (this storage slot has not been changed by the current execution context) + if original.is_zero() { + // 2.1.1. If original value is 0, 20000 gas is deducted. + } else { + // 2.1.2. Otherwise, 5000 gas is deducted. + if new.is_zero() { + // 2.1.2.1. If new value is 0, add 15000 gas to refund counter. + ext.add_sstore_refund(sstore_clears_schedule); + } + } + } else { + // 2.2. If original value does not equal current value (this storage slot is dirty), 200 gas is deducted. Apply both of the following clauses. + + if !original.is_zero() { + // 2.2.1. If original value is not 0 + if current.is_zero() { + // 2.2.1.1. If current value is 0 (also means that new value is not 0), remove 15000 gas from refund counter. We can prove that refund counter will never go below 0. + ext.sub_sstore_refund(sstore_clears_schedule); + } else if new.is_zero() { + // 2.2.1.2. If new value is 0 (also means that current value is not 0), add 15000 gas to refund counter. + ext.add_sstore_refund(sstore_clears_schedule); + } + } + + if original == new { + // 2.2.2. If original value equals new value (this storage slot is reset) + if original.is_zero() { + // 2.2.2.1. If original value is 0, add 19800 gas to refund counter. + let refund = U256::from(ext.schedule().sstore_set_gas - ext.schedule().sload_gas); + ext.add_sstore_refund(refund); + } else { + // 2.2.2.2. Otherwise, add 4800 gas to refund counter. + let refund = U256::from(ext.schedule().sstore_reset_gas - ext.schedule().sload_gas); + ext.add_sstore_refund(refund); + } + } + } + } +} + #[test] fn test_mem_gas_cost() { // given diff --git a/ethcore/evm/src/interpreter/mod.rs b/ethcore/evm/src/interpreter/mod.rs index f533c97e261..4d6c3cb6c3c 100644 --- a/ethcore/evm/src/interpreter/mod.rs +++ b/ethcore/evm/src/interpreter/mod.rs @@ -515,8 +515,14 @@ impl Interpreter { let current_val = U256::from(&*ext.storage_at(&address)?); // Increase refund for clear - if !self.is_zero(¤t_val) && self.is_zero(&val) { - ext.inc_sstore_clears(); + if ext.schedule().eip1283 { + let original_val = U256::from(&*ext.initial_storage_at(&address)?); + gasometer::handle_eip1283_sstore_clears_refund(ext, &original_val, ¤t_val, &val); + } else { + if !current_val.is_zero() && val.is_zero() { + let sstore_clears_schedule = U256::from(ext.schedule().sstore_refund_gas); + ext.add_sstore_refund(sstore_clears_schedule); + } } ext.set_storage(address, H256::from(&val))?; }, diff --git a/ethcore/evm/src/tests.rs b/ethcore/evm/src/tests.rs index b8f0df3639d..6b4d5cc6f7a 100644 --- a/ethcore/evm/src/tests.rs +++ b/ethcore/evm/src/tests.rs @@ -716,7 +716,7 @@ fn test_jumps(factory: super::Factory) { test_finalize(vm.exec(params, &mut ext)).unwrap() }; - assert_eq!(ext.sstore_clears, 1); + assert_eq!(ext.sstore_clears, U256::from(ext.schedule.sstore_refund_gas)); assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000000"); // 5! assert_store(&ext, 1, "0000000000000000000000000000000000000000000000000000000000000078"); // 5! assert_eq!(gas_left, U256::from(54_117)); diff --git a/ethcore/res/ethereum/constantinople_test.json b/ethcore/res/ethereum/constantinople_test.json index 155b06507d0..9e7df1f7fba 100644 --- a/ethcore/res/ethereum/constantinople_test.json +++ b/ethcore/res/ethereum/constantinople_test.json @@ -33,7 +33,8 @@ "eip211Transition": "0x0", "eip214Transition": "0x0", "eip155Transition": "0x0", - "eip658Transition": "0x0" + "eip658Transition": "0x0", + "eip1283Transition": "0x0" }, "genesis": { "seal": { diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index 4c494a42fc4..bf5df2f9a19 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -560,9 +560,9 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { let prev_bal = self.state.balance(¶ms.address)?; if let ActionValue::Transfer(val) = params.value { self.state.sub_balance(¶ms.sender, &val, &mut substate.to_cleanup_mode(&schedule))?; - self.state.new_contract(¶ms.address, val + prev_bal, nonce_offset); + self.state.new_contract(¶ms.address, val + prev_bal, nonce_offset)?; } else { - self.state.new_contract(¶ms.address, prev_bal, nonce_offset); + self.state.new_contract(¶ms.address, prev_bal, nonce_offset)?; } let trace_info = tracer.prepare_trace_create(¶ms); @@ -613,7 +613,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { let schedule = self.machine.schedule(self.info.number); // refunds from SSTORE nonzero -> zero - let sstore_refunds = U256::from(schedule.sstore_refund_gas) * substate.sstore_clears_count; + let sstore_refunds = substate.sstore_clears_refund; // refunds from contract suicides let suicide_refunds = U256::from(schedule.suicide_refund_gas) * U256::from(substate.suicides.len()); let refunds_bound = sstore_refunds + suicide_refunds; @@ -1587,6 +1587,65 @@ mod tests { assert_eq!(state.storage_at(&contract_address, &H256::from(&U256::zero())).unwrap(), H256::from(&U256::from(0))); } + evm_test!{test_eip1283: test_eip1283_int} + fn test_eip1283(factory: Factory) { + let x1 = Address::from(0x1000); + let x2 = Address::from(0x1001); + let y1 = Address::from(0x2001); + let y2 = Address::from(0x2002); + let operating_address = Address::from(0); + let k = H256::new(); + + let mut state = get_temp_state_with_factory(factory.clone()); + state.new_contract(&x1, U256::zero(), U256::from(1)).unwrap(); + state.init_code(&x1, "600160005560006000556001600055".from_hex().unwrap()).unwrap(); + state.new_contract(&x2, U256::zero(), U256::from(1)).unwrap(); + state.init_code(&x2, "600060005560016000556000600055".from_hex().unwrap()).unwrap(); + state.new_contract(&y1, U256::zero(), U256::from(1)).unwrap(); + state.init_code(&y1, "600060006000600061100062fffffff4".from_hex().unwrap()).unwrap(); + state.new_contract(&y2, U256::zero(), U256::from(1)).unwrap(); + state.init_code(&y2, "600060006000600061100162fffffff4".from_hex().unwrap()).unwrap(); + + let info = EnvInfo::default(); + let machine = ::ethereum::new_constantinople_test_machine(); + + assert_eq!(state.storage_at(&operating_address, &k).unwrap(), H256::from(U256::from(0))); + // Test a call via top-level -> y1 -> x1 + let (FinalizationResult { gas_left, .. }, refund, gas) = { + let gas = U256::from(0xffffffffffu64); + let mut params = ActionParams::default(); + params.code = Some(Arc::new("6001600055600060006000600061200163fffffffff4".from_hex().unwrap())); + params.gas = gas; + let mut substate = Substate::new(); + let mut ex = Executive::new(&mut state, &info, &machine); + let res = ex.call(params, &mut substate, BytesRef::Fixed(&mut []), &mut NoopTracer, &mut NoopVMTracer).unwrap(); + + (res, substate.sstore_clears_refund, gas) + }; + let gas_used = gas - gas_left; + // sstore: 0 -> (1) -> () -> (1 -> 0 -> 1) + assert_eq!(gas_used, U256::from(41860)); + assert_eq!(refund, U256::from(19800)); + + assert_eq!(state.storage_at(&operating_address, &k).unwrap(), H256::from(U256::from(1))); + // Test a call via top-level -> y2 -> x2 + let (FinalizationResult { gas_left, .. }, refund, gas) = { + let gas = U256::from(0xffffffffffu64); + let mut params = ActionParams::default(); + params.code = Some(Arc::new("6001600055600060006000600061200263fffffffff4".from_hex().unwrap())); + params.gas = gas; + let mut substate = Substate::new(); + let mut ex = Executive::new(&mut state, &info, &machine); + let res = ex.call(params, &mut substate, BytesRef::Fixed(&mut []), &mut NoopTracer, &mut NoopVMTracer).unwrap(); + + (res, substate.sstore_clears_refund, gas) + }; + let gas_used = gas - gas_left; + // sstore: 1 -> (1) -> () -> (0 -> 1 -> 0) + assert_eq!(gas_used, U256::from(11860)); + assert_eq!(refund, U256::from(19800)); + } + fn wasm_sample_code() -> Arc> { Arc::new( "0061736d01000000010d0360027f7f0060017f0060000002270303656e7603726574000003656e760673656e646572000103656e76066d656d6f727902010110030201020404017000000501000708010463616c6c00020901000ac10101be0102057f017e4100410028020441c0006b22043602042004412c6a41106a220041003602002004412c6a41086a22014200370200200441186a41106a22024100360200200441186a41086a220342003703002004420037022c2004410036021c20044100360218200441186a1001200020022802002202360200200120032903002205370200200441106a2002360200200441086a200537030020042004290318220537022c200420053703002004411410004100200441c0006a3602040b0b0a010041040b0410c00000" diff --git a/ethcore/src/externalities.rs b/ethcore/src/externalities.rs index edea64256a9..2390268021a 100644 --- a/ethcore/src/externalities.rs +++ b/ethcore/src/externalities.rs @@ -111,6 +111,10 @@ 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> where T: Tracer, V: VMTracer, B: StateBackend { + fn initial_storage_at(&self, key: &H256) -> vm::Result { + self.state.checkpoint_storage_at(0, &self.origin_info.address, key).map(|v| v.unwrap_or(H256::zero())).map_err(Into::into) + } + fn storage_at(&self, key: &H256) -> vm::Result { self.state.storage_at(&self.origin_info.address, key).map_err(Into::into) } @@ -394,8 +398,12 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> self.depth } - fn inc_sstore_clears(&mut self) { - self.substate.sstore_clears_count = self.substate.sstore_clears_count + U256::one(); + fn add_sstore_refund(&mut self, value: U256) { + self.substate.sstore_clears_refund = self.substate.sstore_clears_refund.saturating_add(value); + } + + fn sub_sstore_refund(&mut self, value: U256) { + self.substate.sstore_clears_refund = self.substate.sstore_clears_refund.saturating_sub(value); } fn trace_next_instruction(&mut self, pc: usize, instruction: u8, current_gas: U256) -> bool { diff --git a/ethcore/src/json_tests/executive.rs b/ethcore/src/json_tests/executive.rs index 7c7ce4969e2..f01de2fb52e 100644 --- a/ethcore/src/json_tests/executive.rs +++ b/ethcore/src/json_tests/executive.rs @@ -111,6 +111,10 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for TestExt<'a, T, V, B> self.ext.storage_at(key) } + fn initial_storage_at(&self, key: &H256) -> vm::Result { + self.ext.initial_storage_at(key) + } + fn set_storage(&mut self, key: H256, value: H256) -> vm::Result<()> { self.ext.set_storage(key, value) } @@ -205,8 +209,12 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for TestExt<'a, T, V, B> false } - fn inc_sstore_clears(&mut self) { - self.ext.inc_sstore_clears() + fn add_sstore_refund(&mut self, value: U256) { + self.ext.add_sstore_refund(value) + } + + fn sub_sstore_refund(&mut self, value: U256) { + self.ext.sub_sstore_refund(value) } } diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index b9b36e6a177..0df5d0a378d 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -115,6 +115,8 @@ pub struct CommonParams { pub eip145_transition: BlockNumber, /// Number of first block where EIP-1052 rules begin. pub eip1052_transition: BlockNumber, + /// Number of first block where EIP-1283 rules begin. + pub eip1283_transition: BlockNumber, /// Number of first block where EIP-1014 rules begin. pub eip1014_transition: BlockNumber, /// Number of first block where dust cleanup rules (EIP-168 and EIP169) begin. @@ -181,6 +183,7 @@ impl CommonParams { schedule.have_return_data = block_number >= self.eip211_transition; schedule.have_bitwise_shifting = block_number >= self.eip145_transition; schedule.have_extcodehash = block_number >= self.eip1052_transition; + schedule.eip1283 = block_number >= self.eip1283_transition; if block_number >= self.eip210_transition { schedule.blockhash_gas = 800; } @@ -284,6 +287,10 @@ impl From for CommonParams { BlockNumber::max_value, Into::into, ), + eip1283_transition: p.eip1283_transition.map_or_else( + BlockNumber::max_value, + Into::into, + ), eip1014_transition: p.eip1014_transition.map_or_else( BlockNumber::max_value, Into::into, diff --git a/ethcore/src/state/account.rs b/ethcore/src/state/account.rs index eec713a4e36..9741a850539 100644 --- a/ethcore/src/state/account.rs +++ b/ethcore/src/state/account.rs @@ -59,6 +59,10 @@ pub struct Account { // LRU Cache of the trie-backed storage. // This is limited to `STORAGE_CACHE_ITEMS` recent queries storage_cache: RefCell>, + // LRU Cache of the trie-backed storage for original value. + // This is only used when the initial storage root is different compared to + // what is in the database. That is, it is only used for new contracts. + original_storage_cache: Option<(H256, RefCell>)>, // Modified storage. Accumulates changes to storage made in `set_storage` // Takes precedence over `storage_cache`. storage_changes: HashMap, @@ -81,6 +85,7 @@ impl From for Account { nonce: basic.nonce, storage_root: basic.storage_root, storage_cache: Self::empty_storage_cache(), + original_storage_cache: None, storage_changes: HashMap::new(), code_hash: basic.code_hash, code_size: None, @@ -100,6 +105,7 @@ impl Account { nonce: nonce, storage_root: KECCAK_NULL_RLP, storage_cache: Self::empty_storage_cache(), + original_storage_cache: None, storage_changes: storage, code_hash: keccak(&code), code_size: Some(code.len()), @@ -120,6 +126,7 @@ impl Account { nonce: pod.nonce, storage_root: KECCAK_NULL_RLP, storage_cache: Self::empty_storage_cache(), + original_storage_cache: None, storage_changes: pod.storage.into_iter().collect(), code_hash: pod.code.as_ref().map_or(KECCAK_EMPTY, |c| keccak(c)), code_filth: Filth::Dirty, @@ -136,6 +143,7 @@ impl Account { nonce: nonce, storage_root: KECCAK_NULL_RLP, storage_cache: Self::empty_storage_cache(), + original_storage_cache: None, storage_changes: HashMap::new(), code_hash: KECCAK_EMPTY, code_cache: Arc::new(vec![]), @@ -154,12 +162,17 @@ impl Account { /// Create a new contract account. /// NOTE: make sure you use `init_code` on this before `commit`ing. - pub fn new_contract(balance: U256, nonce: U256) -> Account { + pub fn new_contract(balance: U256, nonce: U256, original_storage_root: H256) -> Account { Account { balance: balance, nonce: nonce, storage_root: KECCAK_NULL_RLP, storage_cache: Self::empty_storage_cache(), + original_storage_cache: if original_storage_root == KECCAK_NULL_RLP { + None + } else { + Some((original_storage_root, Self::empty_storage_cache())) + }, storage_changes: HashMap::new(), code_hash: KECCAK_EMPTY, code_cache: Arc::new(vec![]), @@ -204,11 +217,43 @@ impl Account { if let Some(value) = self.cached_storage_at(key) { return Ok(value); } - let db = SecTrieDB::new(db, &self.storage_root)?; + Self::get_and_cache_storage( + &self.storage_root, + &mut self.storage_cache.borrow_mut(), + db, + key) + } + + /// Get (and cache) the contents of the trie's storage at `key`. + /// Does not take modified storage into account. + pub fn original_storage_at(&self, db: &HashDB, key: &H256) -> TrieResult { + if let Some(value) = self.cached_original_storage_at(key) { + return Ok(value); + } + match &self.original_storage_cache { + Some((ref original_storage_root, ref original_storage_cache)) => + Self::get_and_cache_storage( + original_storage_root, + &mut original_storage_cache.borrow_mut(), + db, + key + ), + None => + Self::get_and_cache_storage( + &self.storage_root, + &mut self.storage_cache.borrow_mut(), + db, + key + ), + } + } + + fn get_and_cache_storage(storage_root: &H256, storage_cache: &mut LruCache, db: &HashDB, key: &H256) -> TrieResult { + let db = SecTrieDB::new(db, storage_root)?; let panicky_decoder = |bytes:&[u8]| ::rlp::decode(&bytes).expect("decoding db value failed"); let item: U256 = db.get_with(key, panicky_decoder)?.unwrap_or_else(U256::zero); let value: H256 = item.into(); - self.storage_cache.borrow_mut().insert(key.clone(), value.clone()); + storage_cache.insert(key.clone(), value.clone()); Ok(value) } @@ -218,10 +263,38 @@ impl Account { if let Some(value) = self.storage_changes.get(key) { return Some(value.clone()) } + self.cached_moved_original_storage_at(key) + } + + /// Get cached original storage value after last state commitment. Returns `None` if the key is not in the cache. + pub fn cached_original_storage_at(&self, key: &H256) -> Option { + match &self.original_storage_cache { + Some((_, ref original_storage_cache)) => { + if let Some(value) = original_storage_cache.borrow_mut().get_mut(key) { + Some(value.clone()) + } else { + None + } + }, + None => { + self.cached_moved_original_storage_at(key) + }, + } + } + + /// Get cached original storage value since last contract creation on this address. Returns `None` if the key is not in the cache. + fn cached_moved_original_storage_at(&self, key: &H256) -> Option { + // If storage root is empty RLP, then early return zero value. Practically, this makes it so that if + // `original_storage_cache` is used, then `storage_cache` will always remain empty. + if self.storage_root == KECCAK_NULL_RLP { + return Some(H256::new()); + } + if let Some(value) = self.storage_cache.borrow_mut().get_mut(key) { - return Some(value.clone()) + Some(value.clone()) + } else { + None } - None } /// return the balance associated with this account. @@ -356,7 +429,27 @@ impl Account { } /// Return the storage root associated with this account or None if it has been altered via the overlay. - pub fn storage_root(&self) -> Option<&H256> { if self.storage_is_clean() {Some(&self.storage_root)} else {None} } + pub fn storage_root(&self) -> Option { + if self.storage_is_clean() { + Some(self.storage_root) + } else { + None + } + } + + /// Return the original storage root of this account. + pub fn original_storage_root(&self) -> H256 { + if let Some((original_storage_root, _)) = self.original_storage_cache { + original_storage_root + } else { + self.storage_root + } + } + + /// Storage root where the account changes are based upon. + pub fn base_storage_root(&self) -> H256 { + self.storage_root + } /// Return the storage overlay. pub fn storage_changes(&self) -> &HashMap { &self.storage_changes } @@ -391,6 +484,7 @@ impl Account { self.storage_cache.borrow_mut().insert(k, v); } + self.original_storage_cache = None; Ok(()) } @@ -428,6 +522,7 @@ impl Account { nonce: self.nonce.clone(), storage_root: self.storage_root.clone(), storage_cache: Self::empty_storage_cache(), + original_storage_cache: self.original_storage_cache.as_ref().map(|(r, _)| (*r, Self::empty_storage_cache())), storage_changes: HashMap::new(), code_hash: self.code_hash.clone(), code_size: self.code_size.clone(), @@ -448,6 +543,7 @@ impl Account { pub fn clone_all(&self) -> Account { let mut account = self.clone_dirty(); account.storage_cache = self.storage_cache.clone(); + account.original_storage_cache = self.original_storage_cache.clone(); account } @@ -457,16 +553,21 @@ impl Account { pub fn overwrite_with(&mut self, other: Account) { self.balance = other.balance; self.nonce = other.nonce; - self.storage_root = other.storage_root; self.code_hash = other.code_hash; self.code_filth = other.code_filth; self.code_cache = other.code_cache; self.code_size = other.code_size; self.address_hash = other.address_hash; - let mut cache = self.storage_cache.borrow_mut(); - for (k, v) in other.storage_cache.into_inner() { - cache.insert(k, v); + if self.storage_root == other.storage_root { + let mut cache = self.storage_cache.borrow_mut(); + for (k, v) in other.storage_cache.into_inner() { + cache.insert(k, v); + } + } else { + self.storage_cache = other.storage_cache; } + self.original_storage_cache = other.original_storage_cache; + self.storage_root = other.storage_root; self.storage_changes = other.storage_changes; } } @@ -525,7 +626,7 @@ mod tests { let mut db = MemoryDB::new(); let mut db = AccountDBMut::new(&mut db, &Address::new()); let rlp = { - let mut a = Account::new_contract(69.into(), 0.into()); + let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP); a.set_storage(0x00u64.into(), 0x1234u64.into()); a.commit_storage(&Default::default(), &mut db).unwrap(); a.init_code(vec![]); @@ -534,7 +635,7 @@ mod tests { }; let a = Account::from_rlp(&rlp).expect("decoding db value failed"); - assert_eq!(*a.storage_root().unwrap(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2".into()); + assert_eq!(a.storage_root().unwrap(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2".into()); assert_eq!(a.storage_at(&db.immutable(), &0x00u64.into()).unwrap(), 0x1234u64.into()); assert_eq!(a.storage_at(&db.immutable(), &0x01u64.into()).unwrap(), H256::default()); } @@ -545,7 +646,7 @@ mod tests { let mut db = AccountDBMut::new(&mut db, &Address::new()); let rlp = { - let mut a = Account::new_contract(69.into(), 0.into()); + let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP); a.init_code(vec![0x55, 0x44, 0xffu8]); a.commit_code(&mut db); a.rlp() @@ -560,18 +661,18 @@ mod tests { #[test] fn commit_storage() { - let mut a = Account::new_contract(69.into(), 0.into()); + let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP); let mut db = MemoryDB::new(); let mut db = AccountDBMut::new(&mut db, &Address::new()); a.set_storage(0.into(), 0x1234.into()); assert_eq!(a.storage_root(), None); a.commit_storage(&Default::default(), &mut db).unwrap(); - assert_eq!(*a.storage_root().unwrap(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2".into()); + assert_eq!(a.storage_root().unwrap(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2".into()); } #[test] fn commit_remove_commit_storage() { - let mut a = Account::new_contract(69.into(), 0.into()); + let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP); let mut db = MemoryDB::new(); let mut db = AccountDBMut::new(&mut db, &Address::new()); a.set_storage(0.into(), 0x1234.into()); @@ -580,12 +681,12 @@ mod tests { a.commit_storage(&Default::default(), &mut db).unwrap(); a.set_storage(1.into(), 0.into()); a.commit_storage(&Default::default(), &mut db).unwrap(); - assert_eq!(*a.storage_root().unwrap(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2".into()); + assert_eq!(a.storage_root().unwrap(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2".into()); } #[test] fn commit_code() { - let mut a = Account::new_contract(69.into(), 0.into()); + let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP); let mut db = MemoryDB::new(); let mut db = AccountDBMut::new(&mut db, &Address::new()); a.init_code(vec![0x55, 0x44, 0xffu8]); @@ -597,7 +698,7 @@ mod tests { #[test] fn reset_code() { - let mut a = Account::new_contract(69.into(), 0.into()); + let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP); let mut db = MemoryDB::new(); let mut db = AccountDBMut::new(&mut db, &Address::new()); a.init_code(vec![0x55, 0x44, 0xffu8]); @@ -628,7 +729,7 @@ mod tests { assert_eq!(*a.balance(), 69u8.into()); assert_eq!(*a.nonce(), 0u8.into()); assert_eq!(a.code_hash(), KECCAK_EMPTY); - assert_eq!(a.storage_root().unwrap(), &KECCAK_NULL_RLP); + assert_eq!(a.storage_root().unwrap(), KECCAK_NULL_RLP); } #[test] diff --git a/ethcore/src/state/mod.rs b/ethcore/src/state/mod.rs index 354f6f60eb9..2cff77bb38f 100644 --- a/ethcore/src/state/mod.rs +++ b/ethcore/src/state/mod.rs @@ -181,6 +181,8 @@ impl AccountEntry { Some(acc) => { if let Some(ref mut ours) = self.account { ours.overwrite_with(acc); + } else { + self.account = Some(acc); } }, None => self.account = None, @@ -400,9 +402,12 @@ impl State { self.factories.vm.clone() } - /// Create a recoverable checkpoint of this state. - pub fn checkpoint(&mut self) { - self.checkpoints.get_mut().push(HashMap::new()); + /// Create a recoverable checkpoint of this state. Return the checkpoint index. + pub fn checkpoint(&mut self) -> usize { + let checkpoints = self.checkpoints.get_mut(); + let index = checkpoints.len(); + checkpoints.push(HashMap::new()); + index } /// Merge last checkpoint with previous. @@ -415,7 +420,16 @@ impl State { **prev = checkpoint; } else { for (k, v) in checkpoint.drain() { - prev.entry(k).or_insert(v); + match prev.entry(k) { + Entry::Occupied(mut e) => { + if e.get().is_none() { + e.insert(v); + } + }, + Entry::Vacant(e) => { + e.insert(v); + } + } } } } @@ -493,8 +507,10 @@ impl State { /// Create a new contract at address `contract`. If there is already an account at the address /// it will have its code reset, ready for `init_code()`. - pub fn new_contract(&mut self, contract: &Address, balance: U256, nonce_offset: U256) { - self.insert_cache(contract, AccountEntry::new_dirty(Some(Account::new_contract(balance, self.account_start_nonce + nonce_offset)))); + pub fn new_contract(&mut self, contract: &Address, balance: U256, nonce_offset: U256) -> TrieResult<()> { + let original_storage_root = self.original_storage_root(contract)?; + self.insert_cache(contract, AccountEntry::new_dirty(Some(Account::new_contract(balance, self.account_start_nonce + nonce_offset, original_storage_root)))); + Ok(()) } /// Remove an existing account. @@ -535,11 +551,84 @@ impl State { /// Get the storage root of account `a`. pub fn storage_root(&self, a: &Address) -> TrieResult> { 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())) } - /// Mutate storage of account `address` so that it is `value` for `key`. - pub fn storage_at(&self, address: &Address, key: &H256) -> TrieResult { + /// Get the original storage root since last commit of account `a`. + pub fn original_storage_root(&self, a: &Address) -> TrieResult { + Ok(self.ensure_cached(a, RequireCache::None, true, + |a| a.as_ref().map(|account| account.original_storage_root()))? + .unwrap_or(KECCAK_NULL_RLP)) + } + + /// Get the value of storage at a specific checkpoint. + pub fn checkpoint_storage_at(&self, checkpoint_index: usize, address: &Address, key: &H256) -> TrieResult> { + enum ReturnKind { + /// Use original storage at value at this address. + OriginalAt, + /// Use the downward checkpoint value. + Downward, + } + + let (checkpoints_len, kind) = { + let checkpoints = self.checkpoints.borrow(); + let checkpoints_len = checkpoints.len(); + let checkpoint = match checkpoints.get(checkpoint_index) { + Some(checkpoint) => checkpoint, + // The checkpoint was not found. Return None. + None => return Ok(None), + }; + + let kind = match checkpoint.get(address) { + // The account exists at this checkpoint. + Some(Some(AccountEntry { account: Some(ref account), .. })) => { + if let Some(value) = account.cached_storage_at(key) { + return Ok(Some(value)); + } else { + // This account has checkpoint entry, but the key is not in the entry's cache. We can use + // original_storage_at if current account's original storage root is the same as checkpoint + // account's original storage root. Otherwise, the account must be a newly created contract. + if account.base_storage_root() == self.original_storage_root(address)? { + ReturnKind::OriginalAt + } else { + // If account base storage root is different from the original storage root since last + // commit, then it can only be created from a new contract, where the base storage root + // would always be empty. Note that this branch is actually never called, because + // `cached_storage_at` handled this case. + warn!("Trying to get an account's cached storage value, but base storage root does not equal to original storage root! Assuming the value is empty."); + return Ok(Some(H256::new())); + } + } + }, + // The account didn't exist at that point. Return empty value. + Some(Some(AccountEntry { account: None, .. })) => return Ok(Some(H256::new())), + // The value was not cached at that checkpoint, meaning it was not modified at all. + Some(None) => ReturnKind::OriginalAt, + // This key does not have a checkpoint entry. + None => ReturnKind::Downward, + }; + + (checkpoints_len, kind) + }; + + match kind { + ReturnKind::Downward => { + if checkpoint_index >= checkpoints_len - 1 { + Ok(Some(self.storage_at(address, key)?)) + } else { + self.checkpoint_storage_at(checkpoint_index + 1, address, key) + } + }, + ReturnKind::OriginalAt => Ok(Some(self.original_storage_at(address, key)?)), + } + } + + fn storage_at_inner( + &self, address: &Address, key: &H256, f_cached_at: FCachedStorageAt, f_at: FStorageAt, + ) -> TrieResult where + FCachedStorageAt: Fn(&Account, &H256) -> Option, + FStorageAt: Fn(&Account, &HashDB, &H256) -> TrieResult + { // 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. // 2. If there's an entry for the account in the global cache check for the key or load it into that account. @@ -552,7 +641,7 @@ impl State { if let Some(maybe_acc) = local_cache.get(address) { match maybe_acc.account { Some(ref account) => { - if let Some(value) = account.cached_storage_at(key) { + if let Some(value) = f_cached_at(account, key) { return Ok(value); } else { local_account = Some(maybe_acc); @@ -566,7 +655,7 @@ impl State { None => Ok(H256::new()), Some(a) => { let account_db = self.factories.accountdb.readonly(self.db.as_hashdb(), a.address_hash(address)); - a.storage_at(account_db.as_hashdb(), key) + f_at(a, account_db.as_hashdb(), key) } }); @@ -578,7 +667,7 @@ impl State { if let Some(ref mut acc) = local_account { if let Some(ref account) = acc.account { 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 f_at(account, account_db.as_hashdb(), key) } else { return Ok(H256::new()) } @@ -594,12 +683,32 @@ impl State { let maybe_acc = db.get_with(address, from_rlp)?; let r = maybe_acc.as_ref().map_or(Ok(H256::new()), |a| { let account_db = self.factories.accountdb.readonly(self.db.as_hashdb(), a.address_hash(address)); - a.storage_at(account_db.as_hashdb(), key) + f_at(a, account_db.as_hashdb(), key) }); self.insert_cache(address, AccountEntry::new_clean(maybe_acc)); r } + /// Mutate storage of account `address` so that it is `value` for `key`. + pub fn storage_at(&self, address: &Address, key: &H256) -> TrieResult { + self.storage_at_inner( + address, + key, + |account, key| { account.cached_storage_at(key) }, + |account, db, key| { account.storage_at(db, key) }, + ) + } + + /// Get the value of storage after last state commitment. + pub fn original_storage_at(&self, address: &Address, key: &H256) -> TrieResult { + self.storage_at_inner( + address, + key, + |account, key| { account.cached_original_storage_at(key) }, + |account, db, key| { account.original_storage_at(db, key) }, + ) + } + /// Get accounts' code. pub fn code(&self, a: &Address) -> TrieResult>> { self.ensure_cached(a, RequireCache::Code, true, @@ -670,13 +779,13 @@ impl State { /// Initialise the code of account `a` so that it is `code`. /// NOTE: Account should have been created with `new_contract`. pub fn init_code(&mut self, a: &Address, code: Bytes) -> TrieResult<()> { - 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, KECCAK_NULL_RLP), |_| {})?.init_code(code); Ok(()) } /// Reset the code of account `a` so that it is `code`. pub fn reset_code(&mut self, a: &Address, code: Bytes) -> TrieResult<()> { - 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, KECCAK_NULL_RLP), |_| {})?.reset_code(code); Ok(()) } @@ -759,6 +868,7 @@ impl State { /// Commits our cached account changes into the trie. pub fn commit(&mut self) -> Result<(), Error> { + assert!(self.checkpoints.borrow().is_empty()); // first, commit the sub trees. let mut accounts = self.cache.borrow_mut(); for (address, ref mut a) in accounts.iter_mut().filter(|&(_, ref a)| a.is_dirty()) { @@ -804,6 +914,7 @@ impl State { /// Clear state cache pub fn clear(&mut self) { + assert!(self.checkpoints.borrow().is_empty()); self.cache.borrow_mut().clear(); } @@ -998,7 +1109,7 @@ impl State { /// 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) -> TrieResult> { - self.require_or_from(a, require_code, || Account::new_basic(0u8.into(), self.account_start_nonce), |_|{}) + self.require_or_from(a, require_code, || Account::new_basic(0u8.into(), self.account_start_nonce), |_| {}) } /// Pull account `a` in our cache from the trie DB. `require_code` requires that the code be cached, too. @@ -1138,7 +1249,7 @@ mod tests { use std::sync::Arc; use std::str::FromStr; use rustc_hex::FromHex; - use hash::keccak; + use hash::{keccak, KECCAK_NULL_RLP}; use super::*; use ethkey::Secret; use ethereum_types::{H256, U256, Address}; @@ -1990,7 +2101,7 @@ mod tests { let a = Address::zero(); let (root, db) = { let mut state = get_temp_state(); - state.require_or_from(&a, false, ||Account::new_contract(42.into(), 0.into()), |_|{}).unwrap(); + state.require_or_from(&a, false, || Account::new_contract(42.into(), 0.into(), KECCAK_NULL_RLP), |_|{}).unwrap(); state.init_code(&a, vec![1, 2, 3]).unwrap(); assert_eq!(state.code(&a).unwrap(), Some(Arc::new(vec![1u8, 2, 3]))); state.commit().unwrap(); @@ -2194,6 +2305,161 @@ mod tests { assert_eq!(state.balance(&a).unwrap(), U256::from(0)); } + #[test] + fn checkpoint_revert_to_get_storage_at() { + let mut state = get_temp_state(); + let a = Address::zero(); + let k = H256::from(U256::from(0)); + + let c0 = state.checkpoint(); + let c1 = state.checkpoint(); + state.set_storage(&a, k, H256::from(U256::from(1))).unwrap(); + + assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.storage_at(&a, &k).unwrap(), H256::from(U256::from(1))); + + state.revert_to_checkpoint(); // Revert to c1. + assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.storage_at(&a, &k).unwrap(), H256::from(U256::from(0))); + } + + #[test] + fn checkpoint_from_empty_get_storage_at() { + let mut state = get_temp_state(); + let a = Address::zero(); + let k = H256::from(U256::from(0)); + let k2 = H256::from(U256::from(1)); + + assert_eq!(state.storage_at(&a, &k).unwrap(), H256::from(U256::from(0))); + state.clear(); + + let c0 = state.checkpoint(); + state.new_contract(&a, U256::zero(), U256::zero()).unwrap(); + let c1 = state.checkpoint(); + state.set_storage(&a, k, H256::from(U256::from(1))).unwrap(); + let c2 = state.checkpoint(); + let c3 = state.checkpoint(); + state.set_storage(&a, k2, H256::from(U256::from(3))).unwrap(); + state.set_storage(&a, k, H256::from(U256::from(3))).unwrap(); + let c4 = state.checkpoint(); + state.set_storage(&a, k, H256::from(U256::from(4))).unwrap(); + let c5 = state.checkpoint(); + + assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.checkpoint_storage_at(c2, &a, &k).unwrap(), Some(H256::from(U256::from(1)))); + assert_eq!(state.checkpoint_storage_at(c3, &a, &k).unwrap(), Some(H256::from(U256::from(1)))); + assert_eq!(state.checkpoint_storage_at(c4, &a, &k).unwrap(), Some(H256::from(U256::from(3)))); + assert_eq!(state.checkpoint_storage_at(c5, &a, &k).unwrap(), Some(H256::from(U256::from(4)))); + + state.discard_checkpoint(); // Commit/discard c5. + assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.checkpoint_storage_at(c2, &a, &k).unwrap(), Some(H256::from(U256::from(1)))); + assert_eq!(state.checkpoint_storage_at(c3, &a, &k).unwrap(), Some(H256::from(U256::from(1)))); + assert_eq!(state.checkpoint_storage_at(c4, &a, &k).unwrap(), Some(H256::from(U256::from(3)))); + + state.revert_to_checkpoint(); // Revert to c4. + assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.checkpoint_storage_at(c2, &a, &k).unwrap(), Some(H256::from(U256::from(1)))); + assert_eq!(state.checkpoint_storage_at(c3, &a, &k).unwrap(), Some(H256::from(U256::from(1)))); + + state.discard_checkpoint(); // Commit/discard c3. + assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.checkpoint_storage_at(c2, &a, &k).unwrap(), Some(H256::from(U256::from(1)))); + + state.revert_to_checkpoint(); // Revert to c2. + assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + + state.discard_checkpoint(); // Commit/discard c1. + assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + } + + #[test] + fn checkpoint_get_storage_at() { + let mut state = get_temp_state(); + let a = Address::zero(); + let k = H256::from(U256::from(0)); + let k2 = H256::from(U256::from(1)); + + state.set_storage(&a, k, H256::from(U256::from(0xffff))).unwrap(); + state.commit().unwrap(); + state.clear(); + + assert_eq!(state.storage_at(&a, &k).unwrap(), H256::from(U256::from(0xffff))); + state.clear(); + + let cm1 = state.checkpoint(); + let c0 = state.checkpoint(); + state.new_contract(&a, U256::zero(), U256::zero()).unwrap(); + let c1 = state.checkpoint(); + state.set_storage(&a, k, H256::from(U256::from(1))).unwrap(); + let c2 = state.checkpoint(); + let c3 = state.checkpoint(); + state.set_storage(&a, k2, H256::from(U256::from(3))).unwrap(); + state.set_storage(&a, k, H256::from(U256::from(3))).unwrap(); + let c4 = state.checkpoint(); + state.set_storage(&a, k, H256::from(U256::from(4))).unwrap(); + let c5 = state.checkpoint(); + + assert_eq!(state.checkpoint_storage_at(cm1, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff)))); + assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff)))); + assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.checkpoint_storage_at(c2, &a, &k).unwrap(), Some(H256::from(U256::from(1)))); + assert_eq!(state.checkpoint_storage_at(c3, &a, &k).unwrap(), Some(H256::from(U256::from(1)))); + assert_eq!(state.checkpoint_storage_at(c4, &a, &k).unwrap(), Some(H256::from(U256::from(3)))); + assert_eq!(state.checkpoint_storage_at(c5, &a, &k).unwrap(), Some(H256::from(U256::from(4)))); + + state.discard_checkpoint(); // Commit/discard c5. + assert_eq!(state.checkpoint_storage_at(cm1, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff)))); + assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff)))); + assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.checkpoint_storage_at(c2, &a, &k).unwrap(), Some(H256::from(U256::from(1)))); + assert_eq!(state.checkpoint_storage_at(c3, &a, &k).unwrap(), Some(H256::from(U256::from(1)))); + assert_eq!(state.checkpoint_storage_at(c4, &a, &k).unwrap(), Some(H256::from(U256::from(3)))); + + state.revert_to_checkpoint(); // Revert to c4. + assert_eq!(state.checkpoint_storage_at(cm1, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff)))); + assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff)))); + assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.checkpoint_storage_at(c2, &a, &k).unwrap(), Some(H256::from(U256::from(1)))); + assert_eq!(state.checkpoint_storage_at(c3, &a, &k).unwrap(), Some(H256::from(U256::from(1)))); + + state.discard_checkpoint(); // Commit/discard c3. + assert_eq!(state.checkpoint_storage_at(cm1, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff)))); + assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff)))); + assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.checkpoint_storage_at(c2, &a, &k).unwrap(), Some(H256::from(U256::from(1)))); + + state.revert_to_checkpoint(); // Revert to c2. + assert_eq!(state.checkpoint_storage_at(cm1, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff)))); + assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff)))); + assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + + state.discard_checkpoint(); // Commit/discard c1. + assert_eq!(state.checkpoint_storage_at(cm1, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff)))); + assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff)))); + } + + #[test] + fn kill_account_with_checkpoints() { + let mut state = get_temp_state(); + let a = Address::zero(); + let k = H256::from(U256::from(0)); + state.checkpoint(); + state.set_storage(&a, k, H256::from(U256::from(1))).unwrap(); + state.checkpoint(); + state.kill_account(&a); + + assert_eq!(state.storage_at(&a, &k).unwrap(), H256::from(U256::from(0))); + state.revert_to_checkpoint(); + assert_eq!(state.storage_at(&a, &k).unwrap(), H256::from(U256::from(1))); + } + #[test] fn create_empty() { let mut state = get_temp_state(); @@ -2231,7 +2497,7 @@ mod tests { state.add_balance(&b, &100.into(), CleanupMode::ForceCreate).unwrap(); // create a dust account state.add_balance(&c, &101.into(), CleanupMode::ForceCreate).unwrap(); // create a normal account state.add_balance(&d, &99.into(), CleanupMode::ForceCreate).unwrap(); // create another dust account - state.new_contract(&e, 100.into(), 1.into()); // create a contract account + state.new_contract(&e, 100.into(), 1.into()).unwrap(); // create a contract account state.init_code(&e, vec![0x00]).unwrap(); state.commit().unwrap(); state.drop() diff --git a/ethcore/src/state/substate.rs b/ethcore/src/state/substate.rs index c2f3c62dcb5..054b8b384bb 100644 --- a/ethcore/src/state/substate.rs +++ b/ethcore/src/state/substate.rs @@ -34,8 +34,8 @@ pub struct Substate { /// Any logs. pub logs: Vec, - /// Refund counter of SSTORE nonzero -> zero. - pub sstore_clears_count: U256, + /// Refund counter of SSTORE. + pub sstore_clears_refund: U256, /// Created contracts. pub contracts_created: Vec
, @@ -52,7 +52,7 @@ impl Substate { self.suicides.extend(s.suicides); self.touched.extend(s.touched); self.logs.extend(s.logs); - self.sstore_clears_count = self.sstore_clears_count + s.sstore_clears_count; + self.sstore_clears_refund = self.sstore_clears_refund + s.sstore_clears_refund; self.contracts_created.extend(s.contracts_created); } @@ -86,7 +86,7 @@ mod tests { topics: vec![], data: vec![] }); - sub_state.sstore_clears_count = 5.into(); + sub_state.sstore_clears_refund = (15000 * 5).into(); sub_state.suicides.insert(10u64.into()); let mut sub_state_2 = Substate::new(); @@ -96,11 +96,11 @@ mod tests { topics: vec![], data: vec![] }); - sub_state_2.sstore_clears_count = 7.into(); + sub_state_2.sstore_clears_refund = (15000 * 7).into(); sub_state.accrue(sub_state_2); assert_eq!(sub_state.contracts_created.len(), 2); - assert_eq!(sub_state.sstore_clears_count, 12.into()); + assert_eq!(sub_state.sstore_clears_refund, (15000 * 12).into()); assert_eq!(sub_state.suicides.len(), 1); } } diff --git a/ethcore/vm/src/ext.rs b/ethcore/vm/src/ext.rs index d1a856e5c1e..f0d21b1a25e 100644 --- a/ethcore/vm/src/ext.rs +++ b/ethcore/vm/src/ext.rs @@ -63,6 +63,9 @@ pub enum CreateContractAddress { /// Externalities interface for EVMs pub trait Ext { + /// Returns the storage value for a given key if reversion happens on the current transaction. + fn initial_storage_at(&self, key: &H256) -> Result; + /// Returns a value for given key. fn storage_at(&self, key: &H256) -> Result; @@ -137,8 +140,11 @@ pub trait Ext { /// then A depth is 0, B is 1, C is 2 and so on. fn depth(&self) -> usize; - /// Increments sstore refunds count by 1. - fn inc_sstore_clears(&mut self); + /// Increments sstore refunds counter. + fn add_sstore_refund(&mut self, value: U256); + + /// Decrements sstore refunds counter. + fn sub_sstore_refund(&mut self, value: U256); /// Decide if any more operations should be traced. Passthrough for the VM trace. fn trace_next_instruction(&mut self, _pc: usize, _instruction: u8, _current_gas: U256) -> bool { false } diff --git a/ethcore/vm/src/schedule.rs b/ethcore/vm/src/schedule.rs index b3d71457ebe..462e96b3250 100644 --- a/ethcore/vm/src/schedule.rs +++ b/ethcore/vm/src/schedule.rs @@ -117,6 +117,8 @@ pub struct Schedule { pub have_bitwise_shifting: bool, /// Kill basic accounts below this balance if touched. pub kill_dust: CleanDustMode, + /// Enable EIP-1283 rules + pub eip1283: bool, /// VM execution does not increase null signed address nonce if this field is true. pub keep_unsigned_nonce: bool, /// Wasm extra schedule settings, if wasm activated @@ -250,6 +252,7 @@ impl Schedule { blockhash_gas: 20, have_static_call: false, kill_dust: CleanDustMode::Off, + eip1283: false, keep_unsigned_nonce: false, wasm: None, } @@ -323,6 +326,7 @@ impl Schedule { blockhash_gas: 20, have_static_call: false, kill_dust: CleanDustMode::Off, + eip1283: false, keep_unsigned_nonce: false, wasm: None, } diff --git a/ethcore/vm/src/tests.rs b/ethcore/vm/src/tests.rs index 4930e4219ba..ae7a96e2807 100644 --- a/ethcore/vm/src/tests.rs +++ b/ethcore/vm/src/tests.rs @@ -56,7 +56,7 @@ pub struct FakeExt { pub store: HashMap, pub suicides: HashSet
, pub calls: HashSet, - pub sstore_clears: usize, + pub sstore_clears: U256, pub depth: usize, pub blockhashes: HashMap, pub codes: HashMap>, @@ -105,6 +105,10 @@ impl FakeExt { } impl Ext for FakeExt { + fn initial_storage_at(&self, _key: &H256) -> Result { + Ok(H256::new()) + } + fn storage_at(&self, key: &H256) -> Result { Ok(self.store.get(key).unwrap_or(&H256::new()).clone()) } @@ -217,8 +221,12 @@ impl Ext for FakeExt { self.is_static } - fn inc_sstore_clears(&mut self) { - self.sstore_clears += 1; + fn add_sstore_refund(&mut self, value: U256) { + self.sstore_clears = self.sstore_clears + value; + } + + fn sub_sstore_refund(&mut self, value: U256) { + self.sstore_clears = self.sstore_clears - value; } fn trace_next_instruction(&mut self, _pc: usize, _instruction: u8, _gas: U256) -> bool { diff --git a/ethcore/wasm/src/runtime.rs b/ethcore/wasm/src/runtime.rs index 20bb384b05c..d7a4855f958 100644 --- a/ethcore/wasm/src/runtime.rs +++ b/ethcore/wasm/src/runtime.rs @@ -284,7 +284,8 @@ impl<'a> Runtime<'a> { self.ext.set_storage(key, val).map_err(|_| Error::StorageUpdateError)?; if former_val != H256::zero() && val == H256::zero() { - self.ext.inc_sstore_clears(); + let sstore_clears_schedule = U256::from(self.schedule().sstore_refund_gas); + self.ext.add_sstore_refund(sstore_clears_schedule); } Ok(()) diff --git a/json/src/spec/params.rs b/json/src/spec/params.rs index 341c0543b69..624be09cb91 100644 --- a/json/src/spec/params.rs +++ b/json/src/spec/params.rs @@ -109,6 +109,8 @@ pub struct Params { #[serde(rename="eip1052Transition")] pub eip1052_transition: Option, /// See `CommonParams` docs. + #[serde(rename="eip1283Transition")] + pub eip1283_transition: Option, #[serde(rename="eip1014Transition")] pub eip1014_transition: Option, /// See `CommonParams` docs. From b360481d42cbed4125772bafacfdf3e03936f248 Mon Sep 17 00:00:00 2001 From: 5chdn <5chdn@users.noreply.github.com> Date: Sun, 22 Jul 2018 18:31:13 +0200 Subject: [PATCH 07/19] ethash: implement EIP-1234 (#9187) --- ethcore/res/ethereum/byzantium_test.json | 4 ++-- ethcore/res/ethereum/constantinople_test.json | 6 ++--- ethcore/src/ethereum/ethash.rs | 24 ++++++++++++++++--- json/src/spec/ethash.rs | 18 ++++++++++++++ 4 files changed, 44 insertions(+), 8 deletions(-) diff --git a/ethcore/res/ethereum/byzantium_test.json b/ethcore/res/ethereum/byzantium_test.json index 90c92bbff55..e3d8645d60f 100644 --- a/ethcore/res/ethereum/byzantium_test.json +++ b/ethcore/res/ethereum/byzantium_test.json @@ -6,10 +6,10 @@ "minimumDifficulty": "0x020000", "difficultyBoundDivisor": "0x0800", "durationLimit": "0x0d", - "blockReward": "0x4563918244F40000", + "blockReward": "0x29A2241AF62C0000", "homesteadTransition": "0x0", - "eip649Reward": "0x29A2241AF62C0000", "eip100bTransition": "0x0", + "eip649Reward": "0x29A2241AF62C0000", "eip649Transition": "0x0" } } diff --git a/ethcore/res/ethereum/constantinople_test.json b/ethcore/res/ethereum/constantinople_test.json index 9e7df1f7fba..4e1c3ae4cf6 100644 --- a/ethcore/res/ethereum/constantinople_test.json +++ b/ethcore/res/ethereum/constantinople_test.json @@ -6,11 +6,11 @@ "minimumDifficulty": "0x020000", "difficultyBoundDivisor": "0x0800", "durationLimit": "0x0d", - "blockReward": "0x4563918244F40000", + "blockReward": "0x29A2241AF62C0000", "homesteadTransition": "0x0", - "eip649Reward": "0x29A2241AF62C0000", "eip100bTransition": "0x0", - "eip649Transition": "0x0" + "eip649Transition": "0x0", + "eip649Reward": "0x29A2241AF62C0000" } } }, diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 26151df4416..0c045d236e5 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -36,8 +36,9 @@ use machine::EthereumMachine; const SNAPSHOT_BLOCKS: u64 = 5000; /// Maximum number of blocks allowed in an ethash snapshot. const MAX_SNAPSHOT_BLOCKS: u64 = 30000; - +/// Default number of blocks the difficulty bomb is delayed in EIP-{649,1234} const DEFAULT_EIP649_DELAY: u64 = 3_000_000; +const DEFAULT_EIP1234_DELAY: u64 = 2_000_000; /// Ethash specific seal #[derive(Debug, PartialEq)] @@ -120,6 +121,12 @@ pub struct EthashParams { pub eip649_delay: u64, /// EIP-649 base reward. pub eip649_reward: Option, + /// EIP-1234 transition block. + pub eip1234_transition: u64, + /// EIP-1234 bomb delay. + pub eip1234_delay: u64, + /// EIP-1234 base reward. + pub eip1234_reward: Option, /// EXPIP-2 block height pub expip2_transition: u64, /// EXPIP-2 duration limit @@ -152,6 +159,9 @@ impl From for EthashParams { eip649_transition: p.eip649_transition.map_or(u64::max_value(), Into::into), eip649_delay: p.eip649_delay.map_or(DEFAULT_EIP649_DELAY, Into::into), eip649_reward: p.eip649_reward.map(Into::into), + eip1234_transition: p.eip1234_transition.map_or(u64::max_value(), Into::into), + eip1234_delay: p.eip1234_delay.map_or(DEFAULT_EIP1234_DELAY, Into::into), + eip1234_reward: p.eip1234_reward.map(Into::into), expip2_transition: p.expip2_transition.map_or(u64::max_value(), Into::into), expip2_duration_limit: p.expip2_duration_limit.map_or(30, Into::into), } @@ -233,8 +243,10 @@ impl Engine for Arc { let mut rewards = Vec::new(); - // Applies EIP-649 reward. - let reward = if number >= self.ethash_params.eip649_transition { + // Applies EIP-{649,1234} reward, defaults to block_reward. + let reward = if number >= self.ethash_params.eip1234_transition { + self.ethash_params.eip1234_reward.unwrap_or(self.ethash_params.block_reward) + } else if number >= self.ethash_params.eip649_transition { self.ethash_params.eip649_reward.unwrap_or(self.ethash_params.block_reward) } else { self.ethash_params.block_reward @@ -427,6 +439,9 @@ impl Ethash { if header.number() < self.ethash_params.bomb_defuse_transition { if header.number() < self.ethash_params.ecip1010_pause_transition { let mut number = header.number(); + if number >= self.ethash_params.eip1234_transition { + number = number.saturating_sub(self.ethash_params.eip1234_delay); + } if number >= self.ethash_params.eip649_transition { number = number.saturating_sub(self.ethash_params.eip649_delay); } @@ -510,6 +525,9 @@ mod tests { eip649_transition: u64::max_value(), eip649_delay: 3_000_000, eip649_reward: None, + eip1234_transition: u64::max_value(), + eip1234_delay: 2_000_000, + eip1234_reward: None, expip2_transition: u64::max_value(), expip2_duration_limit: 30, } diff --git a/json/src/spec/ethash.rs b/json/src/spec/ethash.rs index fd6b9fca59f..806a940a286 100644 --- a/json/src/spec/ethash.rs +++ b/json/src/spec/ethash.rs @@ -116,6 +116,18 @@ pub struct EthashParams { #[serde(rename="eip649Reward")] pub eip649_reward: Option, + /// EIP-1234 transition block. + #[serde(rename="eip1234Transition")] + pub eip1234_transition: Option, + + /// EIP-1234 bomb delay. + #[serde(rename="eip1234Delay")] + pub eip1234_delay: Option, + + /// EIP-1234 base reward. + #[serde(rename="eip1234Reward")] + pub eip1234_reward: Option, + /// EXPIP-2 block height #[serde(rename="expip2Transition")] pub expip2_transition: Option, @@ -231,6 +243,9 @@ mod tests { eip649_transition: None, eip649_delay: None, eip649_reward: None, + eip1234_transition: None, + eip1234_delay: None, + eip1234_reward: None, expip2_transition: None, expip2_duration_limit: None, } @@ -275,6 +290,9 @@ mod tests { eip649_transition: None, eip649_delay: None, eip649_reward: None, + eip1234_transition: None, + eip1234_delay: None, + eip1234_reward: None, expip2_transition: None, expip2_duration_limit: None, } From 8cb18749b69fb30a149e2c3e00bc43c0fddc90b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 10 Sep 2018 22:38:30 +0200 Subject: [PATCH 08/19] Update state tests execution model (#9440) * Update & fix JSON state tests. * Update tests to be able to run ethtest at 021fe3d410773024cd5f0387e62db6e6ec800f32. - Touch user in state - Adjust transaction tests to new json format * Switch to same commit for submodule ethereum/test as geth (next includes constantinople changes). Added test `json_tests::trie::generic::TrieTests_trieanyorder` and a few difficulty tests. * Remove trietestnextprev as it would require to parse differently and implement it. * Support new (shitty) format of transaction tests. * Ignore junk in ethereum/tests repo. * Ignore incorrect test. * Update to a later commit * Move block number to a constant. * Fix ZK2 test - touched account should also be cleared. * Fix conflict resolution --- ethcore/res/ethereum/eip161_test.json | 2 +- ethcore/res/ethereum/tests | 2 +- ethcore/src/client/evm_test_client.rs | 34 ++++++-- ethcore/src/json_tests/difficulty.rs | 49 +++++++++-- ethcore/src/json_tests/state.rs | 14 +++ ethcore/src/json_tests/test_common.rs | 8 +- ethcore/src/json_tests/transaction.rs | 116 +++++++++++++------------ ethcore/transaction/src/transaction.rs | 17 ---- evmbin/src/info.rs | 2 +- json/src/blockchain/blockchain.rs | 3 +- json/src/spec/mod.rs | 2 +- json/src/spec/spec.rs | 15 ++++ json/src/state/test.rs | 16 +--- json/src/transaction/test.rs | 2 +- json/src/transaction/txtest.rs | 65 +++++++++----- rpc/src/v1/tests/eth.rs | 2 +- 16 files changed, 216 insertions(+), 133 deletions(-) diff --git a/ethcore/res/ethereum/eip161_test.json b/ethcore/res/ethereum/eip161_test.json index 72288115883..b64b6b0470e 100644 --- a/ethcore/res/ethereum/eip161_test.json +++ b/ethcore/res/ethereum/eip161_test.json @@ -23,7 +23,7 @@ "eip161abcTransition": "0x0", "eip161dTransition": "0x0", "eip98Transition": "0x7fffffffffffffff", - "eip155Transition": "0x7fffffffffffffff", + "eip155Transition": "0x0", "maxCodeSize": 24576, "maxCodeSizeTransition": "0x0" }, diff --git a/ethcore/res/ethereum/tests b/ethcore/res/ethereum/tests index b6011c3fb56..b8a21c19369 160000 --- a/ethcore/res/ethereum/tests +++ b/ethcore/res/ethereum/tests @@ -1 +1 @@ -Subproject commit b6011c3fb567d7178915574de0a8d4b5331fe725 +Subproject commit b8a21c193696976ca3b33b6d82107601063a5d26 diff --git a/ethcore/src/client/evm_test_client.rs b/ethcore/src/client/evm_test_client.rs index 9c91b4d46f3..838add4f6a8 100644 --- a/ethcore/src/client/evm_test_client.rs +++ b/ethcore/src/client/evm_test_client.rs @@ -60,7 +60,7 @@ impl fmt::Display for EvmTestError { } use ethereum; -use ethjson::state::test::ForkSpec; +use ethjson::spec::ForkSpec; /// Simplified, single-block EVM test client. pub struct EvmTestClient<'a> { @@ -69,12 +69,12 @@ pub struct EvmTestClient<'a> { } impl<'a> fmt::Debug for EvmTestClient<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("EvmTestClient") - .field("state", &self.state) - .field("spec", &self.spec.name) - .finish() - } + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("EvmTestClient") + .field("state", &self.state) + .field("spec", &self.spec.name) + .finish() + } } impl<'a> EvmTestClient<'a> { @@ -217,9 +217,27 @@ impl<'a> EvmTestClient<'a> { let result = self.state.apply_with_tracing(&env_info, self.spec.engine.machine(), &transaction, tracer, vm_tracer); let scheme = self.spec.engine.machine().create_address_scheme(env_info.number); + // Touch the coinbase at the end of the test to simulate + // miner reward. + // Details: https://github.com/paritytech/parity-ethereum/issues/9431 + let schedule = self.spec.engine.machine().schedule(env_info.number); + self.state.add_balance(&env_info.author, &0.into(), if schedule.no_empty { + state::CleanupMode::NoEmpty + } else { + state::CleanupMode::ForceCreate + }).ok(); + // Touching also means that we should remove the account if it's within eip161 + // conditions. + self.state.kill_garbage( + &vec![env_info.author].into_iter().collect(), + schedule.kill_empty, + &None, + false + ).ok(); + self.state.commit().ok(); + match result { Ok(result) => { - self.state.commit().ok(); TransactResult::Ok { state_root: *self.state.root(), gas_left: initial_gas - result.receipt.gas_used, diff --git a/ethcore/src/json_tests/difficulty.rs b/ethcore/src/json_tests/difficulty.rs index 2647e16595f..0de1f1777b7 100644 --- a/ethcore/src/json_tests/difficulty.rs +++ b/ethcore/src/json_tests/difficulty.rs @@ -52,26 +52,61 @@ pub fn json_difficulty_test(json_data: &[u8], spec: Sp vec![] } -mod difficulty_test_byzantium { +macro_rules! difficulty_json_test { + ( $spec:ident ) => { + use super::json_difficulty_test; + use tempdir::TempDir; use json_tests::HookType; fn do_json_test(json_data: &[u8], h: &mut H) -> Vec { - json_difficulty_test(json_data, ::ethereum::new_byzantium_test(), h) + let tempdir = TempDir::new("").unwrap(); + json_difficulty_test(json_data, ::ethereum::$spec(&tempdir.path()), h) } - declare_test!{DifficultyTests_difficultyByzantium, "BasicTests/difficultyByzantium.json"} + } } -mod difficulty_test_foundation { +macro_rules! difficulty_json_test_nopath { + ( $spec:ident ) => { + use super::json_difficulty_test; - use tempdir::TempDir; use json_tests::HookType; fn do_json_test(json_data: &[u8], h: &mut H) -> Vec { - let tempdir = TempDir::new("").unwrap(); - json_difficulty_test(json_data, ::ethereum::new_foundation(&tempdir.path()), h) + json_difficulty_test(json_data, ::ethereum::$spec(), h) } + } +} + +mod difficulty_test { + difficulty_json_test!(new_foundation); + declare_test!{DifficultyTests_difficulty, "BasicTests/difficulty.json"} +} + +mod difficulty_test_byzantium { + difficulty_json_test_nopath!(new_byzantium_test); + declare_test!{DifficultyTests_difficultyByzantium, "BasicTests/difficultyByzantium.json"} +} + +mod difficulty_test_foundation { + difficulty_json_test!(new_foundation); declare_test!{DifficultyTests_difficultyMainNetwork, "BasicTests/difficultyMainNetwork.json"} } + +mod difficulty_test_ropsten { + difficulty_json_test_nopath!(new_ropsten_test); + declare_test!{DifficultyTests_difficultyRopsten, "BasicTests/difficultyRopsten.json"} +} + +mod difficulty_test_frontier { + difficulty_json_test_nopath!(new_frontier_test); + declare_test!{DifficultyTests_difficultyFrontier, "BasicTests/difficultyFrontier.json"} +} + +mod difficulty_test_homestead { + difficulty_json_test_nopath!(new_homestead_test); + declare_test!{DifficultyTests_difficultyHomestead, "BasicTests/difficultyHomestead.json"} +} + diff --git a/ethcore/src/json_tests/state.rs b/ethcore/src/json_tests/state.rs index da171697216..5837f191c7d 100644 --- a/ethcore/src/json_tests/state.rs +++ b/ethcore/src/json_tests/state.rs @@ -114,12 +114,16 @@ mod state_tests { json_chain_test(json_data, h) } + declare_test!{GeneralStateTest_stArgsZeroOneBalance, "GeneralStateTests/stArgsZeroOneBalance/"} declare_test!{GeneralStateTest_stAttackTest, "GeneralStateTests/stAttackTest/"} declare_test!{GeneralStateTest_stBadOpcodeTest, "GeneralStateTests/stBadOpcode/"} + declare_test!{GeneralStateTest_stBugs, "GeneralStateTests/stBugs/"} declare_test!{GeneralStateTest_stCallCodes, "GeneralStateTests/stCallCodes/"} + declare_test!{GeneralStateTest_stCallCreateCallCodeTest, "GeneralStateTests/stCallCreateCallCodeTest/"} declare_test!{GeneralStateTest_stCallDelegateCodesCallCodeHomestead, "GeneralStateTests/stCallDelegateCodesCallCodeHomestead/"} declare_test!{GeneralStateTest_stCallDelegateCodesHomestead, "GeneralStateTests/stCallDelegateCodesHomestead/"} declare_test!{GeneralStateTest_stChangedEIP150, "GeneralStateTests/stChangedEIP150/"} + declare_test!{GeneralStateTest_stCodeCopyTest, "GeneralStateTests/stCodeCopyTest/"} declare_test!{GeneralStateTest_stCodeSizeLimit, "GeneralStateTests/stCodeSizeLimit/"} declare_test!{GeneralStateTest_stCreateTest, "GeneralStateTests/stCreateTest/"} declare_test!{GeneralStateTest_stDelegatecallTestHomestead, "GeneralStateTests/stDelegatecallTestHomestead/"} @@ -135,12 +139,15 @@ mod state_tests { declare_test!{GeneralStateTest_stMemoryTest, "GeneralStateTests/stMemoryTest/"} declare_test!{GeneralStateTest_stNonZeroCallsTest, "GeneralStateTests/stNonZeroCallsTest/"} declare_test!{GeneralStateTest_stPreCompiledContracts, "GeneralStateTests/stPreCompiledContracts/"} + declare_test!{GeneralStateTest_stPreCompiledContracts2, "GeneralStateTests/stPreCompiledContracts2/"} declare_test!{heavy => GeneralStateTest_stQuadraticComplexityTest, "GeneralStateTests/stQuadraticComplexityTest/"} declare_test!{GeneralStateTest_stRandom, "GeneralStateTests/stRandom/"} + declare_test!{GeneralStateTest_stRandom2, "GeneralStateTests/stRandom2/"} declare_test!{GeneralStateTest_stRecursiveCreate, "GeneralStateTests/stRecursiveCreate/"} declare_test!{GeneralStateTest_stRefundTest, "GeneralStateTests/stRefundTest/"} declare_test!{GeneralStateTest_stReturnDataTest, "GeneralStateTests/stReturnDataTest/"} declare_test!{GeneralStateTest_stRevertTest, "GeneralStateTests/stRevertTest/"} + declare_test!{GeneralStateTest_stShift, "GeneralStateTests/stShift/"} declare_test!{GeneralStateTest_stSolidityTest, "GeneralStateTests/stSolidityTest/"} declare_test!{GeneralStateTest_stSpecialTest, "GeneralStateTests/stSpecialTest/"} declare_test!{GeneralStateTest_stStackTests, "GeneralStateTests/stStackTests/"} @@ -152,4 +159,11 @@ mod state_tests { declare_test!{GeneralStateTest_stZeroCallsRevert, "GeneralStateTests/stZeroCallsRevert/"} declare_test!{GeneralStateTest_stZeroCallsTest, "GeneralStateTests/stZeroCallsTest/"} declare_test!{GeneralStateTest_stZeroKnowledge, "GeneralStateTests/stZeroKnowledge/"} + + // Attempts to send a transaction that requires more than current balance: + // Tx: + // https://github.com/ethereum/tests/blob/726b161ba8a739691006cc1ba080672bb50a9d49/GeneralStateTests/stZeroKnowledge2/ecmul_0-3_5616_28000_96.json#L170 + // Balance: + // https://github.com/ethereum/tests/blob/726b161ba8a739691006cc1ba080672bb50a9d49/GeneralStateTests/stZeroKnowledge2/ecmul_0-3_5616_28000_96.json#L126 + declare_test!{GeneralStateTest_stZeroKnowledge2, "GeneralStateTests/stZeroKnowledge2/"} } diff --git a/ethcore/src/json_tests/test_common.rs b/ethcore/src/json_tests/test_common.rs index 39b7447c7e8..ce5c68a73a0 100644 --- a/ethcore/src/json_tests/test_common.rs +++ b/ethcore/src/json_tests/test_common.rs @@ -41,6 +41,7 @@ pub fn run_test_path( os.push(".json"); os }).collect(); + let extension = path.extension().and_then(|s| s.to_str()); if path.is_dir() { for p in read_dir(path).unwrap().filter_map(|e| { let e = e.unwrap(); @@ -51,6 +52,8 @@ pub fn run_test_path( }}) { run_test_path(&p, skip, runner, start_stop_hook) } + } else if extension == Some("swp") || extension == None { + // Ignore junk } else { let mut path = p.to_path_buf(); path.set_extension("json"); @@ -64,7 +67,10 @@ pub fn run_test_file( start_stop_hook: &mut H ) { let mut data = Vec::new(); - let mut file = File::open(&path).expect("Error opening test file"); + let mut file = match File::open(&path) { + Ok(file) => file, + Err(_) => panic!("Error opening test file at: {:?}", path), + }; file.read_to_end(&mut data).expect("Error reading test file"); let results = runner(&data, start_stop_hook); let empty: [String; 0] = []; diff --git a/ethcore/src/json_tests/transaction.rs b/ethcore/src/json_tests/transaction.rs index af16481f41f..70021c9e985 100644 --- a/ethcore/src/json_tests/transaction.rs +++ b/ethcore/src/json_tests/transaction.rs @@ -16,10 +16,11 @@ use std::path::Path; use super::test_common::*; -use evm; +use client::EvmTestClient; +use header::Header; use ethjson; use rlp::Rlp; -use transaction::{Action, UnverifiedTransaction, SignedTransaction}; +use transaction::UnverifiedTransaction; /// Run transaction jsontests on a given folder. pub fn run_test_path(p: &Path, skip: &[&'static str], h: &mut H) { @@ -31,55 +32,61 @@ pub fn run_test_file(p: &Path, h: &mut H) { ::json_tests::test_common::run_test_file(p, do_json_test, h) } +// Block number used to run the tests. +// Make sure that all the specified features are activated. +const BLOCK_NUMBER: u64 = 0x6ffffffffffffe; + fn do_json_test(json_data: &[u8], start_stop_hook: &mut H) -> Vec { let tests = ethjson::transaction::Test::load(json_data).unwrap(); let mut failed = Vec::new(); - let frontier_schedule = evm::Schedule::new_frontier(); - let homestead_schedule = evm::Schedule::new_homestead(); - let byzantium_schedule = evm::Schedule::new_byzantium(); for (name, test) in tests.into_iter() { start_stop_hook(&name, HookType::OnStart); - let mut fail_unless = |cond: bool, title: &str| if !cond { failed.push(name.clone()); println!("Transaction failed: {:?}: {:?}", name, title); }; - - let number: Option = test.block_number.map(Into::into); - let schedule = match number { - None => &frontier_schedule, - Some(x) if x < 1_150_000 => &frontier_schedule, - Some(x) if x < 3_000_000 => &homestead_schedule, - Some(_) => &byzantium_schedule - }; - let allow_chain_id_of_one = number.map_or(false, |n| n >= 2_675_000); - let allow_unsigned = number.map_or(false, |n| n >= 3_000_000); - - let rlp: Vec = test.rlp.into(); - let res = Rlp::new(&rlp) - .as_val() - .map_err(::error::Error::from) - .and_then(|t: UnverifiedTransaction| { - t.validate(schedule, schedule.have_delegate_call, allow_chain_id_of_one, allow_unsigned).map_err(Into::into) - }); - - fail_unless(test.transaction.is_none() == res.is_err(), "Validity different"); - if let (Some(tx), Some(sender)) = (test.transaction, test.sender) { - let t = res.unwrap(); - fail_unless(SignedTransaction::new(t.clone()).unwrap().sender() == sender.into(), "sender mismatch"); - let is_acceptable_chain_id = match t.chain_id() { - None => true, - Some(1) if allow_chain_id_of_one => true, - _ => false, + for (spec_name, result) in test.post_state { + let spec = match EvmTestClient::spec_from_json(&spec_name) { + Some(spec) => spec, + None => { + println!(" - {} | {:?} Ignoring tests because of missing spec", name, spec_name); + continue; + } + }; + + let mut fail_unless = |cond: bool, title: &str| if !cond { + failed.push(format!("{}-{:?}", name, spec_name)); + println!("Transaction failed: {:?}-{:?}: {:?}", name, spec_name, title); }; - fail_unless(is_acceptable_chain_id, "Network ID unacceptable"); - let data: Vec = tx.data.into(); - fail_unless(t.data == data, "data mismatch"); - fail_unless(t.gas_price == tx.gas_price.into(), "gas_price mismatch"); - fail_unless(t.nonce == tx.nonce.into(), "nonce mismatch"); - fail_unless(t.value == tx.value.into(), "value mismatch"); - let to: Option = tx.to.into(); - let to: Option
= to.map(Into::into); - match t.action { - Action::Call(dest) => fail_unless(Some(dest) == to, "call/destination mismatch"), - Action::Create => fail_unless(None == to, "create mismatch"), + + let rlp: Vec = test.rlp.clone().into(); + let res = Rlp::new(&rlp) + .as_val() + .map_err(::error::Error::from) + .and_then(|t: UnverifiedTransaction| { + let mut header: Header = Default::default(); + // Use high enough number to activate all required features. + header.set_number(BLOCK_NUMBER); + + let minimal = t.gas_required(&spec.engine.schedule(header.number())).into(); + if t.gas < minimal { + return Err(::transaction::Error::InsufficientGas { + minimal, got: t.gas, + }.into()); + } + spec.engine.verify_transaction_basic(&t, &header)?; + Ok(spec.engine.verify_transaction_unordered(t, &header)?) + }); + + match (res, result.hash, result.sender) { + (Ok(t), Some(hash), Some(sender)) => { + fail_unless(t.sender() == sender.into(), "sender mismatch"); + fail_unless(t.hash() == hash.into(), "hash mismatch"); + }, + (Err(_), None, None) => {}, + data => { + fail_unless( + false, + &format!("Validity different: {:?}", data) + ); + } } } @@ -92,13 +99,14 @@ fn do_json_test(json_data: &[u8], start_stop_hook: &mu failed } -declare_test!{TransactionTests_ttEip155VitaliksHomesead, "TransactionTests/ttEip155VitaliksHomesead"} -declare_test!{TransactionTests_ttEip155VitaliksEip158, "TransactionTests/ttEip155VitaliksEip158"} -declare_test!{TransactionTests_ttEip158, "TransactionTests/ttEip158"} -declare_test!{TransactionTests_ttFrontier, "TransactionTests/ttFrontier"} -declare_test!{TransactionTests_ttHomestead, "TransactionTests/ttHomestead"} -declare_test!{TransactionTests_ttVRuleEip158, "TransactionTests/ttVRuleEip158"} -declare_test!{TransactionTests_ttWrongRLPFrontier, "TransactionTests/ttWrongRLPFrontier"} -declare_test!{TransactionTests_ttWrongRLPHomestead, "TransactionTests/ttWrongRLPHomestead"} -declare_test!{TransactionTests_ttConstantinople, "TransactionTests/ttConstantinople"} -declare_test!{TransactionTests_ttSpecConstantinople, "TransactionTests/ttSpecConstantinople"} +declare_test!{TransactionTests_ttAddress, "TransactionTests/ttAddress"} +declare_test!{TransactionTests_ttData, "TransactionTests/ttData"} +declare_test!{TransactionTests_ttGasLimit, "TransactionTests/ttGasLimit"} +declare_test!{TransactionTests_ttGasPrice, "TransactionTests/ttGasPrice"} +declare_test!{TransactionTests_ttNonce, "TransactionTests/ttNonce"} +declare_test!{TransactionTests_ttRSValue, "TransactionTests/ttRSValue"} +declare_test!{TransactionTests_ttSignature, "TransactionTests/ttSignature"} +declare_test!{TransactionTests_ttValue, "TransactionTests/ttValue"} +declare_test!{TransactionTests_ttVValue, "TransactionTests/ttVValue"} +declare_test!{TransactionTests_ttWrongRLP, "TransactionTests/ttWrongRLP"} + diff --git a/ethcore/transaction/src/transaction.rs b/ethcore/transaction/src/transaction.rs index 27b8b346cf2..b6434384bb2 100644 --- a/ethcore/transaction/src/transaction.rs +++ b/ethcore/transaction/src/transaction.rs @@ -387,23 +387,6 @@ impl UnverifiedTransaction { Ok(recover(&self.signature(), &self.unsigned.hash(self.chain_id()))?) } - /// Do basic validation, checking for valid signature and minimum gas, - // TODO: consider use in block validation. - #[cfg(feature = "json-tests")] - pub fn validate(self, schedule: &Schedule, require_low: bool, allow_chain_id_of_one: bool, allow_empty_signature: bool) - -> Result - { - let chain_id = if allow_chain_id_of_one { Some(1) } else { None }; - self.verify_basic(require_low, chain_id, allow_empty_signature)?; - if !allow_empty_signature || !self.is_unsigned() { - self.recover_public()?; - } - if self.gas < U256::from(self.gas_required(&schedule)) { - return Err(error::Error::InvalidGasLimit(::unexpected::OutOfBounds{min: Some(U256::from(self.gas_required(&schedule))), max: None, found: self.gas}).into()) - } - Ok(self) - } - /// Verify basic signature params. Does not attempt sender recovery. pub fn verify_basic(&self, check_low_s: bool, chain_id: Option, allow_empty_signature: bool) -> Result<(), error::Error> { if check_low_s && !(allow_empty_signature && self.is_unsigned()) { diff --git a/evmbin/src/info.rs b/evmbin/src/info.rs index ce824fe17d3..67f76fe7816 100644 --- a/evmbin/src/info.rs +++ b/evmbin/src/info.rs @@ -84,7 +84,7 @@ pub fn run_action( pub fn run_transaction( name: &str, idx: usize, - spec: ðjson::state::test::ForkSpec, + spec: ðjson::spec::ForkSpec, pre_state: &pod_state::PodState, post_root: H256, env_info: &client::EnvInfo, diff --git a/json/src/blockchain/blockchain.rs b/json/src/blockchain/blockchain.rs index 9e4d650b85a..ff0bc556f9b 100644 --- a/json/src/blockchain/blockchain.rs +++ b/json/src/blockchain/blockchain.rs @@ -21,8 +21,7 @@ use hash::H256; use blockchain::state::State; use blockchain::header::Header; use blockchain::block::Block; -use state::test::ForkSpec; -use spec::{Genesis, Seal, Ethereum}; +use spec::{ForkSpec, Genesis, Seal, Ethereum}; /// Blockchain deserialization. #[derive(Debug, PartialEq, Deserialize)] diff --git a/json/src/spec/mod.rs b/json/src/spec/mod.rs index 26965c887d0..fdede4a47fc 100644 --- a/json/src/spec/mod.rs +++ b/json/src/spec/mod.rs @@ -36,7 +36,7 @@ pub use self::account::Account; pub use self::builtin::{Builtin, Pricing, Linear}; pub use self::genesis::Genesis; pub use self::params::Params; -pub use self::spec::Spec; +pub use self::spec::{Spec, ForkSpec}; pub use self::seal::{Seal, Ethereum, AuthorityRoundSeal, TendermintSeal}; pub use self::engine::Engine; pub use self::state::State; diff --git a/json/src/spec/spec.rs b/json/src/spec/spec.rs index 2be695689e4..a15d1faf6e6 100644 --- a/json/src/spec/spec.rs +++ b/json/src/spec/spec.rs @@ -21,6 +21,21 @@ use serde_json; use serde_json::Error; use spec::{Params, Genesis, Engine, State, HardcodedSync}; +/// Fork spec definition +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Deserialize)] +pub enum ForkSpec { + EIP150, + EIP158, + Frontier, + Homestead, + Byzantium, + Constantinople, + EIP158ToByzantiumAt5, + FrontierToHomesteadAt5, + HomesteadToDaoAt5, + HomesteadToEIP150At5, +} + /// Spec deserialization. #[derive(Debug, PartialEq, Deserialize)] pub struct Spec { diff --git a/json/src/state/test.rs b/json/src/state/test.rs index 528a49b5a66..85eac0c935f 100644 --- a/json/src/state/test.rs +++ b/json/src/state/test.rs @@ -21,6 +21,7 @@ use std::collections::BTreeMap; use uint::Uint; use bytes::Bytes; use hash::{Address, H256}; +use spec::ForkSpec; use state::{Env, AccountState, Transaction}; use maybe::MaybeEmpty; use serde_json::{self, Error}; @@ -97,21 +98,6 @@ impl MultiTransaction { } } -/// State test transaction deserialization. -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Deserialize)] -pub enum ForkSpec { - EIP150, - EIP158, - Frontier, - Homestead, - Byzantium, - Constantinople, - EIP158ToByzantiumAt5, - FrontierToHomesteadAt5, - HomesteadToDaoAt5, - HomesteadToEIP150At5, -} - /// State test indexes deserialization. #[derive(Debug, PartialEq, Deserialize)] pub struct PostStateIndexes { diff --git a/json/src/transaction/test.rs b/json/src/transaction/test.rs index e1bd588de35..2c5f39f13cf 100644 --- a/json/src/transaction/test.rs +++ b/json/src/transaction/test.rs @@ -23,7 +23,7 @@ use serde_json::Error; use transaction::TransactionTest; /// TransactionTest test deserializer. -#[derive(Debug, PartialEq, Deserialize)] +#[derive(Debug, Deserialize)] pub struct Test(BTreeMap); impl IntoIterator for Test { diff --git a/json/src/transaction/txtest.rs b/json/src/transaction/txtest.rs index 60d65e70d66..2be035b4fe9 100644 --- a/json/src/transaction/txtest.rs +++ b/json/src/transaction/txtest.rs @@ -16,23 +16,29 @@ //! Transaction test deserialization. -use uint::Uint; +use std::collections::BTreeMap; use bytes::Bytes; use hash::Address; -use transaction::Transaction; +use hash::H256; +use spec::ForkSpec; /// Transaction test deserialization. -#[derive(Debug, PartialEq, Deserialize)] +#[derive(Debug, Deserialize)] pub struct TransactionTest { - /// Block number. - #[serde(rename="blocknumber")] - pub block_number: Option, - /// Transaction rlp. pub rlp: Bytes, + pub _info: ::serde::de::IgnoredAny, + #[serde(flatten)] + pub post_state: BTreeMap, +} + +/// TransactionTest post state. +#[derive(Debug, PartialEq, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct PostState { /// Transaction sender. pub sender: Option
, - /// Transaction - pub transaction: Option, + /// Transaction hash. + pub hash: Option, } #[cfg(test)] @@ -43,21 +49,34 @@ mod tests { #[test] fn transaction_deserialization() { let s = r#"{ - "blocknumber" : "0", - "rlp" : "0xf83f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870b801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a3664935301", - "sender" : "e115cf6bb5656786569dd273705242ca72d84bc0", - "transaction" : { - "data" : "", - "gasLimit" : "0x5208", - "gasPrice" : "0x01", - "nonce" : "0x00", - "r" : "0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353", - "s" : "0x01", - "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", - "v" : "0x1b", - "value" : "0x0b" - } + "Byzantium" : { + "hash" : "4782cb5edcaeda1f0aef204b161214f124cefade9e146245183abbb9ca01bca5", + "sender" : "2ea991808ba979ba103147edfd72304ebd95c028" + }, + "Constantinople" : { + "hash" : "4782cb5edcaeda1f0aef204b161214f124cefade9e146245183abbb9ca01bca5", + "sender" : "2ea991808ba979ba103147edfd72304ebd95c028" + }, + "EIP150" : { + }, + "EIP158" : { + "hash" : "4782cb5edcaeda1f0aef204b161214f124cefade9e146245183abbb9ca01bca5", + "sender" : "2ea991808ba979ba103147edfd72304ebd95c028" + }, + "Frontier" : { + }, + "Homestead" : { + }, + "_info" : { + "comment" : "", + "filledwith" : "cpp-1.3.0+commit.1829957d.Linux.g++", + "lllcversion" : "Version: 0.4.18-develop.2017.10.11+commit.81f9f86c.Linux.g++", + "source" : "src/TransactionTestsFiller/ttVValue/V_equals37Filler.json", + "sourceHash" : "89ef69312d4c0b4e3742da501263d23d2a64f180258ac93940997ac6a17b9b19" + }, + "rlp" : "0xf865808698852840a46f82d6d894095e7baea6a6c7c4c2dfeb977efac326af552d87808025a098ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4aa01887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3" }"#; + let _deserialized: TransactionTest = serde_json::from_str(s).unwrap(); // TODO: validate all fields } diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 6e3b9855d65..ba9cfcc74df 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -29,7 +29,7 @@ use ethcore::spec::{Genesis, Spec}; use ethcore::test_helpers; use ethcore::views::BlockView; use ethjson::blockchain::BlockChain; -use ethjson::state::test::ForkSpec; +use ethjson::spec::ForkSpec; use io::IoChannel; use miner::external::ExternalMiner; use parking_lot::Mutex; From 6e30af2db710061085cf2b1a36a31bc4433b2dd7 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Tue, 11 Sep 2018 16:28:31 +0800 Subject: [PATCH 09/19] Fix checkpointing when creating contract failed (#9514) --- ethcore/src/state/mod.rs | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/ethcore/src/state/mod.rs b/ethcore/src/state/mod.rs index 2cff77bb38f..4c5fef09722 100644 --- a/ethcore/src/state/mod.rs +++ b/ethcore/src/state/mod.rs @@ -420,16 +420,7 @@ impl State { **prev = checkpoint; } else { for (k, v) in checkpoint.drain() { - match prev.entry(k) { - Entry::Occupied(mut e) => { - if e.get().is_none() { - e.insert(v); - } - }, - Entry::Vacant(e) => { - e.insert(v); - } - } + prev.entry(k).or_insert(v); } } } @@ -2460,6 +2451,25 @@ mod tests { assert_eq!(state.storage_at(&a, &k).unwrap(), H256::from(U256::from(1))); } + #[test] + fn create_contract_fail() { + let mut state = get_temp_state(); + let orig_root = state.root().clone(); + let a: Address = 1000.into(); + + state.checkpoint(); // c1 + state.new_contract(&a, U256::zero(), U256::zero()).unwrap(); + state.add_balance(&a, &U256::from(1), CleanupMode::ForceCreate).unwrap(); + state.checkpoint(); // c2 + state.add_balance(&a, &U256::from(1), CleanupMode::ForceCreate).unwrap(); + state.discard_checkpoint(); // discard c2 + state.revert_to_checkpoint(); // revert to c1 + assert_eq!(state.exists(&a).unwrap(), false); + + state.commit().unwrap(); + assert_eq!(orig_root, state.root().clone()); + } + #[test] fn create_empty() { let mut state = get_temp_state(); From 05f5e48b3f6d8c88b31fae2a14029233acc0da0b Mon Sep 17 00:00:00 2001 From: cheme Date: Tue, 11 Sep 2018 17:47:26 +0200 Subject: [PATCH 10/19] In create memory calculation is the same for create2 because the additional parameter was popped before. (#9522) --- ethcore/evm/src/interpreter/gasometer.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/ethcore/evm/src/interpreter/gasometer.rs b/ethcore/evm/src/interpreter/gasometer.rs index 406df19fd35..db67556e38c 100644 --- a/ethcore/evm/src/interpreter/gasometer.rs +++ b/ethcore/evm/src/interpreter/gasometer.rs @@ -233,11 +233,7 @@ impl Gasometer { }, instructions::CREATE | instructions::CREATE2 => { let gas = Gas::from(schedule.create_gas); - let mem = match instruction { - instructions::CREATE => mem_needed(stack.peek(1), stack.peek(2))?, - instructions::CREATE2 => mem_needed(stack.peek(2), stack.peek(3))?, - _ => unreachable!("instruction can only be CREATE/CREATE2 checked above; qed"), - }; + let mem = mem_needed(stack.peek(1), stack.peek(2))?; Request::GasMemProvide(gas, mem, None) }, From dd5a298a080d1668a1de9e3b602094c4ffb7879e Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Wed, 12 Sep 2018 02:08:23 +0800 Subject: [PATCH 11/19] Enable all Constantinople hard fork changes in constantinople_test.json (#9505) * Enable all Constantinople hard fork changes in constantinople_test.json * Address grumbles * Remove EIP-210 activation * 8m -> 5m * Temporarily add back eip210 transition so we can get test passed * Add eip210_test and remove eip210 transition from const_test --- ethcore/res/ethereum/constantinople_test.json | 12 +++-- ethcore/res/ethereum/eip210_test.json | 54 +++++++++++++++++++ ethcore/src/ethereum/mod.rs | 3 ++ ethcore/src/tests/evm.rs | 2 +- 4 files changed, 66 insertions(+), 5 deletions(-) create mode 100644 ethcore/res/ethereum/eip210_test.json diff --git a/ethcore/res/ethereum/constantinople_test.json b/ethcore/res/ethereum/constantinople_test.json index 4e1c3ae4cf6..56c556f4cec 100644 --- a/ethcore/res/ethereum/constantinople_test.json +++ b/ethcore/res/ethereum/constantinople_test.json @@ -1,16 +1,18 @@ { - "name": "Byzantium (Test)", + "name": "Constantinople (test)", "engine": { "Ethash": { "params": { "minimumDifficulty": "0x020000", "difficultyBoundDivisor": "0x0800", "durationLimit": "0x0d", - "blockReward": "0x29A2241AF62C0000", + "blockReward": "0x1BC16D674EC80000", "homesteadTransition": "0x0", "eip100bTransition": "0x0", "eip649Transition": "0x0", - "eip649Reward": "0x29A2241AF62C0000" + "eip649Reward": "0x1BC16D674EC80000", + "eip1234Transition": "0x0", + "eip1234Reward": "0x1BC16D674EC80000" } } }, @@ -29,11 +31,13 @@ "eip161abcTransition": "0x0", "eip161dTransition": "0x0", "eip140Transition": "0x0", - "eip210Transition": "0x0", "eip211Transition": "0x0", "eip214Transition": "0x0", "eip155Transition": "0x0", "eip658Transition": "0x0", + "eip145Transition": "0x0", + "eip1014Transition": "0x0", + "eip1052Transition": "0x0", "eip1283Transition": "0x0" }, "genesis": { diff --git a/ethcore/res/ethereum/eip210_test.json b/ethcore/res/ethereum/eip210_test.json new file mode 100644 index 00000000000..9733e5d87ef --- /dev/null +++ b/ethcore/res/ethereum/eip210_test.json @@ -0,0 +1,54 @@ +{ + "name": "EIP210 (test)", + "engine": { + "Ethash": { + "params": { + "minimumDifficulty": "0x020000", + "difficultyBoundDivisor": "0x0800", + "durationLimit": "0x0d", + "blockReward": "0x4563918244F40000", + "homesteadTransition": "0x0" + } + } + }, + "params": { + "gasLimitBoundDivisor": "0x0400", + "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", + "accountStartNonce": "0x00", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID" : "0x1", + "maxCodeSize": 24576, + "maxCodeSizeTransition": "0x0", + "eip98Transition": "0xffffffffffffffff", + "eip150Transition": "0x0", + "eip160Transition": "0x0", + "eip161abcTransition": "0x0", + "eip161dTransition": "0x0", + "eip210Transition": "0x0" + }, + "genesis": { + "seal": { + "ethereum": { + "nonce": "0x0000000000000042", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "difficulty": "0x400000000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa", + "gasLimit": "0x1388" + }, + "accounts": { + "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 100 } } } }, + "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0x00", "pricing": { "linear": { "base": 500, "word": 0 } } } }, + "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x00", "pricing": { "linear": { "base": 2000, "word": 0 } } } }, + "0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x00", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } } + } +} diff --git a/ethcore/src/ethereum/mod.rs b/ethcore/src/ethereum/mod.rs index 1069970443c..b7fa4f48691 100644 --- a/ethcore/src/ethereum/mod.rs +++ b/ethcore/src/ethereum/mod.rs @@ -151,6 +151,9 @@ pub fn new_frontier_test_machine() -> EthereumMachine { load_machine(include_byt /// Create a new Foundation Homestead-era chain spec as though it never changed from Frontier. pub fn new_homestead_test_machine() -> EthereumMachine { load_machine(include_bytes!("../../res/ethereum/homestead_test.json")) } +/// Create a new Foundation Homestead-EIP210-era chain spec as though it never changed from Homestead/Frontier. +pub fn new_eip210_test_machine() -> EthereumMachine { load_machine(include_bytes!("../../res/ethereum/eip210_test.json")) } + /// Create a new Foundation Byzantium era spec. pub fn new_byzantium_test_machine() -> EthereumMachine { load_machine(include_bytes!("../../res/ethereum/byzantium_test.json")) } diff --git a/ethcore/src/tests/evm.rs b/ethcore/src/tests/evm.rs index 4f4ad4241f2..76d3928e4aa 100644 --- a/ethcore/src/tests/evm.rs +++ b/ethcore/src/tests/evm.rs @@ -39,7 +39,7 @@ fn test_blockhash_eip210(factory: Factory) { let test_blockhash_contract = "73fffffffffffffffffffffffffffffffffffffffe33141561007a57600143036020526000356101006020510755600061010060205107141561005057600035610100610100602051050761010001555b6000620100006020510714156100755760003561010062010000602051050761020001555b61014a565b4360003512151561009057600060405260206040f35b610100600035430312156100b357610100600035075460605260206060f3610149565b62010000600035430312156100d157600061010060003507146100d4565b60005b156100f6576101006101006000350507610100015460805260206080f3610148565b630100000060003543031215610116576000620100006000350714610119565b60005b1561013c57610100620100006000350507610200015460a052602060a0f3610147565b600060c052602060c0f35b5b5b5b5b"; let blockhash_contract_code = Arc::new(test_blockhash_contract.from_hex().unwrap()); let blockhash_contract_code_hash = keccak(blockhash_contract_code.as_ref()); - let machine = ::ethereum::new_constantinople_test_machine(); + let machine = ::ethereum::new_eip210_test_machine(); let mut env_info = EnvInfo::default(); // populate state with 256 last hashes From 6ba8edacbd51d1f2a9c54a37009d35f081a904bb Mon Sep 17 00:00:00 2001 From: cheme Date: Tue, 25 Sep 2018 12:24:40 +0200 Subject: [PATCH 12/19] Add constantinople conf to EvmTestClient. (#9570) * Add constantinople conf to EvmTestClient. * Skip some test to update submodule etheureum/tests submodule to latest. * Put skipping 'under issue' test behind a feature. * Change blockReward for const-test to pass ethereum/tests * Update tests to new constantinple definition (change of reward at block 5). Switch 'reference' to string, that way we can include issues from others repo (more flexible)Update tests to new constantinple definition (change of reward at block 5). Switch 'reference' to string, that way we can include issues from others repo (more flexible). * Fix modexp and bn128_mul gas prices in chain config * Changes `run_test_path` method to append its directory results (without that it stop testing at the first file failure). Add some missing tests. Add skip for those (block create2 is one hundred percent false but on hive we can see that geth and aleth got similar issue for this item). * retab current.json * Update reference to parity issue for failing tests. --- Cargo.toml | 1 + ethcore/Cargo.toml | 2 + ethcore/res/ethereum/constantinople_test.json | 10 +- ethcore/res/ethereum/tests | 2 +- .../res/ethereum/tests-issues/currents.json | 370 ++++++++++++++++++ ethcore/src/client/evm_test_client.rs | 2 +- ethcore/src/json_tests/chain.rs | 18 + ethcore/src/json_tests/mod.rs | 3 + ethcore/src/json_tests/skip.rs | 37 ++ ethcore/src/json_tests/state.rs | 20 +- ethcore/src/json_tests/test_common.rs | 31 +- json/src/test/mod.rs | 57 +++ test.sh | 2 +- 13 files changed, 544 insertions(+), 11 deletions(-) create mode 100644 ethcore/res/ethereum/tests-issues/currents.json create mode 100644 ethcore/src/json_tests/skip.rs diff --git a/Cargo.toml b/Cargo.toml index 6f2559cd67f..3fdfd56d8ea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -89,6 +89,7 @@ daemonize = { git = "https://github.com/paritytech/daemonize" } [features] miner-debug = ["ethcore/miner-debug"] json-tests = ["ethcore/json-tests"] +ci-skip-issue = ["ethcore/ci-skip-issue"] test-heavy = ["ethcore/test-heavy"] evm-debug = ["ethcore/evm-debug"] evm-debug-tests = ["ethcore/evm-debug-tests"] diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index 82dd2230dd6..80f7e432600 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -102,6 +102,8 @@ evm-debug-tests = ["evm-debug", "evm/evm-debug-tests"] slow-blocks = [] # Run JSON consensus tests. json-tests = ["ethcore-transaction/json-tests", "test-helpers", "tempdir"] +# Skip JSON consensus tests with pending issues. +ci-skip-issue = [] # Run memory/cpu heavy tests. test-heavy = [] # Compile benches diff --git a/ethcore/res/ethereum/constantinople_test.json b/ethcore/res/ethereum/constantinople_test.json index 56c556f4cec..fd7474dc2d7 100644 --- a/ethcore/res/ethereum/constantinople_test.json +++ b/ethcore/res/ethereum/constantinople_test.json @@ -6,12 +6,12 @@ "minimumDifficulty": "0x020000", "difficultyBoundDivisor": "0x0800", "durationLimit": "0x0d", - "blockReward": "0x1BC16D674EC80000", + "blockReward": "0x29A2241AF62C0000", "homesteadTransition": "0x0", "eip100bTransition": "0x0", - "eip649Transition": "0x0", + "eip649Transition": "0x5", "eip649Reward": "0x1BC16D674EC80000", - "eip1234Transition": "0x0", + "eip1234Transition": "0x5", "eip1234Reward": "0x1BC16D674EC80000" } } @@ -59,9 +59,9 @@ "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, - "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 100 } } } }, + "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 20 } } } }, "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0x00", "pricing": { "linear": { "base": 500, "word": 0 } } } }, - "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x00", "pricing": { "linear": { "base": 2000, "word": 0 } } } }, + "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x00", "pricing": { "linear": { "base": 40000, "word": 0 } } } }, "0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x00", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } } } } diff --git a/ethcore/res/ethereum/tests b/ethcore/res/ethereum/tests index b8a21c19369..3f5febc9019 160000 --- a/ethcore/res/ethereum/tests +++ b/ethcore/res/ethereum/tests @@ -1 +1 @@ -Subproject commit b8a21c193696976ca3b33b6d82107601063a5d26 +Subproject commit 3f5febc901913ef698f1b09dda8705babd729e4a diff --git a/ethcore/res/ethereum/tests-issues/currents.json b/ethcore/res/ethereum/tests-issues/currents.json new file mode 100644 index 00000000000..371211cab82 --- /dev/null +++ b/ethcore/res/ethereum/tests-issues/currents.json @@ -0,0 +1,370 @@ +{ "block": + [ + { + "reference": "9590", + "failing": "stCreateTest", + "subtests": [ + "CreateOOGafterInitCodeReturndata2_d0g1v0_Constantinople" + ] + }, + { + "reference": "9590", + "failing": "stCreate2", + "subtests": [ + "RevertDepthCreateAddressCollision_d0g1v0_Constantinople", + "RevertDepthCreateAddressCollision_d1g1v1_Constantinople", + "CREATE2_Suicide_d5g0v0_Constantinople", + "CREATE2_Suicide_d7g0v0_Constantinople", + "create2collisionSelfdestructedOOG_d2g0v0_Byzantium", + "create2collisionSelfdestructedOOG_d2g0v0_Constantinople", + "create2collisionNonce_d1g0v0_Byzantium", + "create2collisionNonce_d1g0v0_Constantinople", + "CreateMessageRevertedOOGInInit_d0g1v0_Constantinople", + "create2callPrecompiles_d3g0v0_Constantinople", + "create2collisionCode_d1g0v0_Byzantium", + "create2collisionCode_d1g0v0_Constantinople", + "create2collisionStorage_d0g0v0_Byzantium", + "create2collisionStorage_d0g0v0_Constantinople", + "create2callPrecompiles_d4g0v0_Constantinople", + "create2collisionSelfdestructedRevert_d0g0v0_Byzantium", + "create2collisionSelfdestructedRevert_d0g0v0_Constantinople", + "CreateMessageReverted_d0g1v0_Constantinople", + "RevertOpcodeCreate_d0g1v0_Constantinople", + "CREATE2_Suicide_d11g0v0_Constantinople", + "create2checkFieldsInInitcode_d5g0v0_Constantinople", + "create2collisionSelfdestructedOOG_d1g0v0_Byzantium", + "create2collisionSelfdestructedOOG_d1g0v0_Constantinople", + "returndatacopy_following_create_d1g0v0_Constantinople", + "RevertDepthCreate2OOG_d1g1v1_Constantinople", + "create2collisionSelfdestructed_d2g0v0_Byzantium", + "create2collisionSelfdestructed_d2g0v0_Constantinople", + "create2callPrecompiles_d2g0v0_Constantinople", + "create2InitCodes_d2g0v0_Constantinople", + "create2collisionNonce_d2g0v0_Byzantium", + "create2collisionNonce_d2g0v0_Constantinople", + "create2collisionCode_d0g0v0_Byzantium", + "create2collisionCode_d0g0v0_Constantinople", + "CREATE2_Bounds_d0g0v0_Constantinople", + "RevertDepthCreate2OOG_d0g0v0_Constantinople", + "CREATE2_Suicide_d1g0v0_Constantinople", + "CREATE2_Bounds3_d0g1v0_Constantinople", + "create2collisionStorage_d2g0v0_Byzantium", + "create2collisionStorage_d2g0v0_Constantinople", + "RevertDepthCreateAddressCollision_d0g0v1_Constantinople", + "create2callPrecompiles_d5g0v0_Constantinople", + "create2collisionCode2_d0g0v0_Byzantium", + "create2collisionCode2_d0g0v0_Constantinople", + "create2noCash_d0g0v0_Byzantium", + "create2noCash_d0g0v0_Constantinople", + "create2checkFieldsInInitcode_d7g0v0_Constantinople", + "create2SmartInitCode_d1g0v0_Constantinople", + "create2InitCodes_d6g0v0_Constantinople", + "create2noCash_d1g0v0_Byzantium", + "create2noCash_d1g0v0_Constantinople", + "CREATE2_ContractSuicideDuringInit_ThenStoreThenReturn_d0g0v0_Constantinople", + "RevertOpcodeInCreateReturns_d0g0v0_Constantinople", + "create2collisionStorage_d1g0v0_Byzantium", + "create2collisionStorage_d1g0v0_Constantinople", + "create2checkFieldsInInitcode_d3g0v0_Constantinople", + "create2collisionBalance_d0g0v0_Byzantium", + "create2collisionBalance_d0g0v0_Constantinople", + "create2collisionSelfdestructed2_d0g0v0_Constantinople", + "create2InitCodes_d3g0v0_Constantinople", + "create2collisionCode2_d1g0v0_Byzantium", + "create2collisionCode2_d1g0v0_Constantinople", + "create2checkFieldsInInitcode_d1g0v0_Constantinople", + "create2collisionBalance_d1g0v0_Byzantium", + "create2collisionBalance_d1g0v0_Constantinople", + "CREATE2_Bounds3_d0g2v0_Constantinople", + "create2callPrecompiles_d6g0v0_Constantinople", + "Create2Recursive_d0g0v0_Constantinople", + "create2collisionSelfdestructedOOG_d0g0v0_Byzantium", + "create2collisionSelfdestructedOOG_d0g0v0_Constantinople", + "CREATE2_Suicide_d3g0v0_Constantinople", + "returndatacopy_following_create_d0g0v0_Constantinople", + "create2InitCodes_d8g0v0_Constantinople", + "RevertDepthCreate2OOG_d0g0v1_Constantinople", + "create2checkFieldsInInitcode_d2g0v0_Constantinople", + "RevertDepthCreate2OOG_d1g0v1_Constantinople", + "Create2OnDepth1024_d0g0v0_Constantinople", + "create2collisionSelfdestructed2_d1g0v0_Constantinople", + "create2collisionSelfdestructedRevert_d2g0v0_Byzantium", + "create2collisionSelfdestructedRevert_d2g0v0_Constantinople", + "create2callPrecompiles_d0g0v0_Constantinople", + "RevertDepthCreateAddressCollision_d0g1v1_Constantinople", + "create2collisionSelfdestructed_d1g0v0_Byzantium", + "create2collisionSelfdestructed_d1g0v0_Constantinople", + "call_outsize_then_create2_successful_then_returndatasize_d0g0v0_Byzantium", + "call_outsize_then_create2_successful_then_returndatasize_d0g0v0_Constantinople", + "Create2OOGafterInitCodeRevert_d0g0v0_Constantinople", + "Create2OOGafterInitCodeReturndata3_d0g0v0_Constantinople", + "Create2OOGafterInitCodeReturndataSize_d0g0v0_Constantinople", + "create2InitCodes_d7g0v0_Constantinople", + "CREATE2_Suicide_d10g0v0_Constantinople", + "RevertDepthCreate2OOG_d0g1v0_Constantinople", + "create2InitCodes_d5g0v0_Constantinople", + "create2collisionSelfdestructedRevert_d1g0v0_Byzantium", + "create2collisionSelfdestructedRevert_d1g0v0_Constantinople", + "RevertDepthCreate2OOG_d1g1v0_Constantinople", + "create2collisionSelfdestructed_d0g0v0_Byzantium", + "create2collisionSelfdestructed_d0g0v0_Constantinople", + "create2noCash_d2g0v0_Byzantium", + "create2noCash_d2g0v0_Constantinople", + "CREATE2_Bounds3_d0g0v0_Constantinople", + "create2collisionNonce_d0g0v0_Byzantium", + "create2collisionNonce_d0g0v0_Constantinople", + "CREATE2_Suicide_d2g0v0_Constantinople", + "Create2OOGafterInitCode_d0g0v0_Constantinople", + "call_then_create2_successful_then_returndatasize_d0g0v0_Byzantium", + "call_then_create2_successful_then_returndatasize_d0g0v0_Constantinople", + "create2collisionBalance_d2g0v0_Byzantium", + "create2collisionBalance_d2g0v0_Constantinople", + "create2checkFieldsInInitcode_d6g0v0_Constantinople", + "RevertDepthCreate2OOG_d0g1v1_Constantinople", + "returndatacopy_afterFailing_create_d0g0v0_Constantinople", + "returndatacopy_following_revert_in_create_d0g0v0_Constantinople", + "CREATE2_Suicide_d9g0v0_Constantinople", + "create2callPrecompiles_d7g0v0_Constantinople", + "RevertDepthCreateAddressCollision_d1g0v1_Constantinople", + "create2InitCodes_d1g0v0_Constantinople", + "CREATE2_Bounds_d0g1v0_Constantinople", + "Create2OOGafterInitCodeReturndata_d0g0v0_Constantinople", + "create2checkFieldsInInitcode_d4g0v0_Constantinople", + "CreateMessageRevertedOOGInInit_d0g0v0_Constantinople", + "RevertDepthCreateAddressCollision_d1g1v0_Constantinople", + "returndatacopy_following_successful_create_d0g0v0_Constantinople", + "create2checkFieldsInInitcode_d0g0v0_Constantinople", + "CreateMessageReverted_d0g0v0_Constantinople", + "create2SmartInitCode_d0g0v0_Constantinople", + "CREATE2_Bounds2_d0g0v0_Constantinople", + "returndatasize_following_successful_create_d0g0v0_Constantinople", + "CREATE2_Bounds2_d0g1v0_Constantinople", + "returndatacopy_0_0_following_successful_create_d0g0v0_Constantinople", + "RevertDepthCreateAddressCollision_d0g0v0_Constantinople", + "CREATE2_Suicide_d0g0v0_Constantinople", + "create2InitCodes_d0g0v0_Constantinople", + "Create2OnDepth1023_d0g0v0_Constantinople", + "create2InitCodes_d4g0v0_Constantinople", + "Create2OOGafterInitCodeReturndata2_d0g0v0_Constantinople", + "create2collisionBalance_d3g0v0_Byzantium", + "create2collisionBalance_d3g0v0_Constantinople", + "CREATE2_Suicide_d4g0v0_Constantinople", + "Create2OOGafterInitCode_d0g1v0_Constantinople", + "RevertDepthCreateAddressCollision_d1g0v0_Constantinople", + "Create2OOGafterInitCodeRevert2_d0g0v0_Constantinople", + "Create2OOGafterInitCodeReturndata_d0g1v0_Constantinople", + "Create2Recursive_d0g1v0_Constantinople", + "create2collisionCode_d2g0v0_Byzantium", + "create2collisionCode_d2g0v0_Constantinople", + "CREATE2_Suicide_d6g0v0_Constantinople", + "CREATE2_Suicide_d8g0v0_Constantinople", + "RevertOpcodeCreate_d0g0v0_Constantinople", + "Create2OOGafterInitCodeReturndata2_d0g1v0_Constantinople", + "create2callPrecompiles_d1g0v0_Constantinople", + "RevertInCreateInInit_d0g0v0_Constantinople", + "RevertDepthCreate2OOG_d1g0v0_Constantinople" + ] + }, + { + "reference": "9590", + "failing": "bcStateTest", + "subtests": [ + "suicideStorageCheck_Byzantium", + "suicideStorageCheck_Constantinople", + "suicideStorageCheckVCreate2_Byzantium", + "suicideStorageCheckVCreate2_Constantinople", + "create2collisionwithSelfdestructSameBlock_Constantinople", + "blockhashNonConstArg_Constantinople", + "suicideThenCheckBalance_Constantinople", + "suicideThenCheckBalance_Homestead", + "suicideStorageCheckVCreate_Byzantium", + "suicideStorageCheckVCreate_Constantinople" + ] + }, + { + "reference": "9590", + "failing": "stEIP158Specific", + "subtests": [ + "callToEmptyThenCallError_d0g0v0_Byzantium", + "callToEmptyThenCallError_d0g0v0_Constantinople", + "callToEmptyThenCallError_d0g0v0_EIP158" + ] + }, + { + "reference": "9590", + "failing": "stPreCompiledContracts", + "subtests": [ + "identity_to_smaller_d0g0v0_Constantinople", + "identity_to_bigger_d0g0v0_Constantinople" + ] + }, + { + "reference": "9590", + "failing": "stReturnDataTest", + "subtests": [ + "modexp_modsize0_returndatasize_d0g1v0_Constantinople", + "modexp_modsize0_returndatasize_d0g2v0_Constantinople", + "modexp_modsize0_returndatasize_d0g3v0_Constantinople" + ] + }, + { + "reference": "9590", + "failing": "stSpecialTest", + "subtests": [ + "push32withoutByte_d0g0v0_Constantinople" + ] + } + + ], + "state": + [ + { + "reference": "9590", + "failing": "stCreateTest", + "subtests": { + "CreateOOGafterInitCodeReturndata2": { + "subnumbers": ["2"], + "chain": "Constantinople (test)" + } + } + }, + { + "reference": "9590", + "failing": "stCreate2Test", + "subtests": { + "RevertInCreateInInit": { + "subnumbers": ["1"], + "chain": "Constantinople (test)" + } + } + }, + { + "reference": "9590", + "failing": "stEIP150Specific", + "subtests": { + "NewGasPriceForCodes": { + "subnumbers": ["1"], + "chain": "Constantinople (test)" + } + } + }, + { + "reference": "9590", + "failing": "stInitCodeTest", + "subtests": { + "OutOfGasContractCreation": { + "subnumbers": ["4"], + "chain": "Constantinople (test)" + } + } + }, + { + "reference": "9590", + "failing": "stPreCompiledContracts", + "subtests": { + "modexp": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + } + } + }, + { + "reference": "9590", + "failing": "stRevertTest", + "subtests": { + "LoopCallsDepthThenRevert3": { + "subnumbers": ["1"], + "chain": "Constantinople (test)" + }, + "RevertOpcodeCreate": { + "subnumbers": ["1"], + "chain": "Constantinople (test)" + }, + "RevertSubCallStorageOOG2": { + "subnumbers": ["1","3"], + "chain": "Constantinople (test)" + }, + "RevertDepthCreateOOG": { + "subnumbers": ["3","4"], + "chain": "Constantinople (test)" + }, + "RevertOpcodeMultipleSubCalls": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "RevertOpcodeDirectCall": { + "subnumbers": ["1","2"], + "chain": "Constantinople (test)" + }, + "LoopCallsDepthThenRevert2": { + "subnumbers": ["1"], + "chain": "Constantinople (test)" + }, + "RevertDepth2": { + "subnumbers": ["1"], + "chain": "Constantinople (test)" + }, + "RevertRemoteSubCallStorageOOG2": { + "subnumbers": ["1","2"], + "chain": "Constantinople (test)" + }, + "RevertDepthCreateAddressCollision": { + "subnumbers": ["3","4"], + "chain": "Constantinople (test)" + } + } + }, + { + "reference": "9590", + "failing": "stStaticCall", + "subtests": { + "static_RevertDepth2": { + "subnumbers": ["1","3"], + "chain": "Constantinople (test)" + }, + "static_CheckOpcodes4": { + "subnumbers": ["3"], + "chain": "Constantinople (test)" + }, + "static_CheckOpcodes3": { + "subnumbers": ["5","6","7","8"], + "chain": "Constantinople (test)" + }, + "static_callBasic": { + "subnumbers": ["1","2"], + "chain": "Constantinople (test)" + }, + "static_CheckOpcodes2": { + "subnumbers": ["5","6","7","8"], + "chain": "Constantinople (test)" + }, + "static_callCreate": { + "subnumbers": ["2"], + "chain": "Constantinople (test)" + } + } + }, + { + "reference": "https://github.com/ethereum/tests/issues/512", + "failing": "stZeroKnowledge", + "subtests": { + "pointAddTrunc": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "pointAdd": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "pointMulAdd": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "pointMulAdd2": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + } + } + } + ] +} diff --git a/ethcore/src/client/evm_test_client.rs b/ethcore/src/client/evm_test_client.rs index 838add4f6a8..f9699af46cd 100644 --- a/ethcore/src/client/evm_test_client.rs +++ b/ethcore/src/client/evm_test_client.rs @@ -86,9 +86,9 @@ impl<'a> EvmTestClient<'a> { ForkSpec::EIP150 => Some(ethereum::new_eip150_test()), ForkSpec::EIP158 => Some(ethereum::new_eip161_test()), ForkSpec::Byzantium => Some(ethereum::new_byzantium_test()), + ForkSpec::Constantinople => Some(ethereum::new_constantinople_test()), ForkSpec::EIP158ToByzantiumAt5 => Some(ethereum::new_transition_test()), ForkSpec::FrontierToHomesteadAt5 | ForkSpec::HomesteadToDaoAt5 | ForkSpec::HomesteadToEIP150At5 => None, - _ => None, } } diff --git a/ethcore/src/json_tests/chain.rs b/ethcore/src/json_tests/chain.rs index 2d643e75fe4..ae78d4d58c4 100644 --- a/ethcore/src/json_tests/chain.rs +++ b/ethcore/src/json_tests/chain.rs @@ -23,6 +23,7 @@ use ethjson; use miner::Miner; use io::IoChannel; use test_helpers; +use super::SKIP_TEST_STATE; use super::HookType; @@ -36,12 +37,20 @@ pub fn run_test_file(p: &Path, h: &mut H) { ::json_tests::test_common::run_test_file(p, json_chain_test, h) } +fn skip_test(name: &String) -> bool { + SKIP_TEST_STATE.block.iter().any(|block_test|block_test.subtests.contains(name)) +} + pub fn json_chain_test(json_data: &[u8], start_stop_hook: &mut H) -> Vec { ::ethcore_logger::init_log(); let tests = ethjson::blockchain::Test::load(json_data).unwrap(); let mut failed = Vec::new(); for (name, blockchain) in tests.into_iter() { + if skip_test(&name) { + println!(" - {} | {:?} Ignoring tests because in skip list", name, blockchain.network); + continue; + } start_stop_hook(&name, HookType::OnStart); let mut fail = false; @@ -122,19 +131,24 @@ mod block_tests { declare_test!{BlockchainTests_bcInvalidHeaderTest, "BlockchainTests/bcInvalidHeaderTest"} declare_test!{BlockchainTests_bcMultiChainTest, "BlockchainTests/bcMultiChainTest"} declare_test!{BlockchainTests_bcRandomBlockhashTest, "BlockchainTests/bcRandomBlockhashTest"} + declare_test!{BlockchainTests_bcStateTest, "BlockchainTests/bcStateTests"} declare_test!{BlockchainTests_bcTotalDifficultyTest, "BlockchainTests/bcTotalDifficultyTest"} declare_test!{BlockchainTests_bcUncleHeaderValidity, "BlockchainTests/bcUncleHeaderValidity"} declare_test!{BlockchainTests_bcUncleTest, "BlockchainTests/bcUncleTest"} declare_test!{BlockchainTests_bcValidBlockTest, "BlockchainTests/bcValidBlockTest"} declare_test!{BlockchainTests_bcWalletTest, "BlockchainTests/bcWalletTest"} + declare_test!{BlockchainTests_GeneralStateTest_stArgsZeroOneBalance, "BlockchainTests/GeneralStateTests/stArgsZeroOneBalance/"} declare_test!{BlockchainTests_GeneralStateTest_stAttackTest, "BlockchainTests/GeneralStateTests/stAttackTest/"} declare_test!{BlockchainTests_GeneralStateTest_stBadOpcodeTest, "BlockchainTests/GeneralStateTests/stBadOpcode/"} + declare_test!{BlockchainTests_GeneralStateTest_stBugsTest, "BlockchainTests/GeneralStateTests/stBugs/"} declare_test!{BlockchainTests_GeneralStateTest_stCallCodes, "BlockchainTests/GeneralStateTests/stCallCodes/"} + declare_test!{BlockchainTests_GeneralStateTest_stCallCreateCallCodeTest, "BlockchainTests/GeneralStateTests/stCallCreateCallCodeTest/"} declare_test!{BlockchainTests_GeneralStateTest_stCallDelegateCodesCallCodeHomestead, "BlockchainTests/GeneralStateTests/stCallDelegateCodesCallCodeHomestead/"} declare_test!{BlockchainTests_GeneralStateTest_stCallDelegateCodesHomestead, "BlockchainTests/GeneralStateTests/stCallDelegateCodesHomestead/"} declare_test!{BlockchainTests_GeneralStateTest_stChangedEIP150, "BlockchainTests/GeneralStateTests/stChangedEIP150/"} declare_test!{BlockchainTests_GeneralStateTest_stCodeSizeLimit, "BlockchainTests/GeneralStateTests/stCodeSizeLimit/"} + declare_test!{BlockchainTests_GeneralStateTest_stCreate2, "BlockchainTests/GeneralStateTests/stCreate2/"} declare_test!{BlockchainTests_GeneralStateTest_stCreateTest, "BlockchainTests/GeneralStateTests/stCreateTest/"} declare_test!{BlockchainTests_GeneralStateTest_stDelegatecallTestHomestead, "BlockchainTests/GeneralStateTests/stDelegatecallTestHomestead/"} declare_test!{BlockchainTests_GeneralStateTest_stEIP150singleCodeGasPrices, "BlockchainTests/GeneralStateTests/stEIP150singleCodeGasPrices/"} @@ -149,12 +163,15 @@ mod block_tests { declare_test!{BlockchainTests_GeneralStateTest_stMemoryTest, "BlockchainTests/GeneralStateTests/stMemoryTest/"} declare_test!{BlockchainTests_GeneralStateTest_stNonZeroCallsTest, "BlockchainTests/GeneralStateTests/stNonZeroCallsTest/"} declare_test!{BlockchainTests_GeneralStateTest_stPreCompiledContracts, "BlockchainTests/GeneralStateTests/stPreCompiledContracts/"} + declare_test!{BlockchainTests_GeneralStateTest_stPreCompiledContracts2, "BlockchainTests/GeneralStateTests/stPreCompiledContracts2/"} declare_test!{heavy => BlockchainTests_GeneralStateTest_stQuadraticComplexityTest, "BlockchainTests/GeneralStateTests/stQuadraticComplexityTest/"} declare_test!{BlockchainTests_GeneralStateTest_stRandom, "BlockchainTests/GeneralStateTests/stRandom/"} + declare_test!{BlockchainTests_GeneralStateTest_stRandom2, "BlockchainTests/GeneralStateTests/stRandom2/"} declare_test!{BlockchainTests_GeneralStateTest_stRecursiveCreate, "BlockchainTests/GeneralStateTests/stRecursiveCreate/"} declare_test!{BlockchainTests_GeneralStateTest_stRefundTest, "BlockchainTests/GeneralStateTests/stRefundTest/"} declare_test!{BlockchainTests_GeneralStateTest_stReturnDataTest, "BlockchainTests/GeneralStateTests/stReturnDataTest/"} declare_test!{BlockchainTests_GeneralStateTest_stRevertTest, "BlockchainTests/GeneralStateTests/stRevertTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stShift, "BlockchainTests/GeneralStateTests/stShift/"} declare_test!{BlockchainTests_GeneralStateTest_stSolidityTest, "BlockchainTests/GeneralStateTests/stSolidityTest/"} declare_test!{BlockchainTests_GeneralStateTest_stSpecialTest, "BlockchainTests/GeneralStateTests/stSpecialTest/"} declare_test!{BlockchainTests_GeneralStateTest_stStackTests, "BlockchainTests/GeneralStateTests/stStackTests/"} @@ -166,6 +183,7 @@ mod block_tests { declare_test!{BlockchainTests_GeneralStateTest_stZeroCallsRevert, "BlockchainTests/GeneralStateTests/stZeroCallsRevert/"} declare_test!{BlockchainTests_GeneralStateTest_stZeroCallsTest, "BlockchainTests/GeneralStateTests/stZeroCallsTest/"} declare_test!{BlockchainTests_GeneralStateTest_stZeroKnowledge, "BlockchainTests/GeneralStateTests/stZeroKnowledge/"} + declare_test!{BlockchainTests_GeneralStateTest_stZeroKnowledge2, "BlockchainTests/GeneralStateTests/stZeroKnowledge2/"} declare_test!{BlockchainTests_TransitionTests_bcEIP158ToByzantium, "BlockchainTests/TransitionTests/bcEIP158ToByzantium/"} declare_test!{BlockchainTests_TransitionTests_bcFrontierToHomestead, "BlockchainTests/TransitionTests/bcFrontierToHomestead/"} diff --git a/ethcore/src/json_tests/mod.rs b/ethcore/src/json_tests/mod.rs index fa1c822ce2a..35d5034806a 100644 --- a/ethcore/src/json_tests/mod.rs +++ b/ethcore/src/json_tests/mod.rs @@ -24,10 +24,12 @@ mod executive; mod state; mod chain; mod trie; +mod skip; #[cfg(test)] mod difficulty; + pub use self::test_common::HookType; pub use self::transaction::run_test_path as run_transaction_test_path; @@ -42,3 +44,4 @@ pub use self::trie::run_generic_test_path as run_generic_trie_test_path; pub use self::trie::run_generic_test_file as run_generic_trie_test_file; pub use self::trie::run_secure_test_path as run_secure_trie_test_path; pub use self::trie::run_secure_test_file as run_secure_trie_test_file; +use self::skip::SKIP_TEST_STATE; diff --git a/ethcore/src/json_tests/skip.rs b/ethcore/src/json_tests/skip.rs new file mode 100644 index 00000000000..784e2975d73 --- /dev/null +++ b/ethcore/src/json_tests/skip.rs @@ -0,0 +1,37 @@ +// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! State tests to skip. + +use ethjson; + +#[cfg(all(not(test), feature = "ci-skip-tests"))] +compile_error!("ci-skip-tests can only be enabled for testing builds."); + +#[cfg(feature="ci-skip-issue")] +lazy_static!{ + pub static ref SKIP_TEST_STATE: ethjson::test::SkipStates = { + let skip_data = include_bytes!("../../res/ethereum/tests-issues/currents.json"); + ethjson::test::SkipStates::load(&skip_data[..]).expect("No invalid json allowed") + }; +} + +#[cfg(not(feature="ci-skip-issue"))] +lazy_static!{ + pub static ref SKIP_TEST_STATE: ethjson::test::SkipStates = { + ethjson::test::SkipStates::empty() + }; +} diff --git a/ethcore/src/json_tests/state.rs b/ethcore/src/json_tests/state.rs index 5837f191c7d..04ca947bf19 100644 --- a/ethcore/src/json_tests/state.rs +++ b/ethcore/src/json_tests/state.rs @@ -22,7 +22,7 @@ use client::{EvmTestClient, EvmTestError, TransactResult}; use ethjson; use transaction::SignedTransaction; use vm::EnvInfo; - +use super::SKIP_TEST_STATE; use super::HookType; /// Run state jsontests on a given folder. @@ -35,6 +35,18 @@ pub fn run_test_file(p: &Path, h: &mut H) { ::json_tests::test_common::run_test_file(p, json_chain_test, h) } +fn skip_test(subname: &str, chain: &String, number: usize) -> bool { + SKIP_TEST_STATE.state.iter().any(|state_test|{ + if let Some(subtest) = state_test.subtests.get(subname) { + chain == &subtest.chain && + (subtest.subnumbers[0] == "*" + || subtest.subnumbers.contains(&number.to_string())) + } else { + false + } + }) +} + pub fn json_chain_test(json_data: &[u8], start_stop_hook: &mut H) -> Vec { ::ethcore_logger::init_log(); let tests = ethjson::state::test::Test::load(json_data).unwrap(); @@ -60,6 +72,10 @@ pub fn json_chain_test(json_data: &[u8], start_stop_ho for (i, state) in states.into_iter().enumerate() { let info = format!(" - {} | {:?} ({}/{}) ...", name, spec_name, i + 1, total); + if skip_test(&name, &spec.name, i + 1) { + println!("{} in skip list : SKIPPED", info); + continue; + } let post_root: H256 = state.hash.into(); let transaction: SignedTransaction = multitransaction.select(&state.indexes).into(); @@ -125,11 +141,13 @@ mod state_tests { declare_test!{GeneralStateTest_stChangedEIP150, "GeneralStateTests/stChangedEIP150/"} declare_test!{GeneralStateTest_stCodeCopyTest, "GeneralStateTests/stCodeCopyTest/"} declare_test!{GeneralStateTest_stCodeSizeLimit, "GeneralStateTests/stCodeSizeLimit/"} + declare_test!{GeneralStateTest_stCreate2Test, "GeneralStateTests/stCreate2/"} declare_test!{GeneralStateTest_stCreateTest, "GeneralStateTests/stCreateTest/"} declare_test!{GeneralStateTest_stDelegatecallTestHomestead, "GeneralStateTests/stDelegatecallTestHomestead/"} declare_test!{GeneralStateTest_stEIP150singleCodeGasPrices, "GeneralStateTests/stEIP150singleCodeGasPrices/"} declare_test!{GeneralStateTest_stEIP150Specific, "GeneralStateTests/stEIP150Specific/"} declare_test!{GeneralStateTest_stEIP158Specific, "GeneralStateTests/stEIP158Specific/"} + declare_test!{GeneralStateTest_stEWASMTests, "GeneralStateTests/stEWASMTests/"} declare_test!{GeneralStateTest_stExample, "GeneralStateTests/stExample/"} declare_test!{GeneralStateTest_stHomesteadSpecific, "GeneralStateTests/stHomesteadSpecific/"} declare_test!{GeneralStateTest_stInitCodeTest, "GeneralStateTests/stInitCodeTest/"} diff --git a/ethcore/src/json_tests/test_common.rs b/ethcore/src/json_tests/test_common.rs index ce5c68a73a0..ce16395d228 100644 --- a/ethcore/src/json_tests/test_common.rs +++ b/ethcore/src/json_tests/test_common.rs @@ -34,6 +34,18 @@ pub fn run_test_path( p: &Path, skip: &[&'static str], runner: fn(json_data: &[u8], start_stop_hook: &mut H) -> Vec, start_stop_hook: &mut H +) { + let mut errors = Vec::new(); + run_test_path_inner(p, skip, runner, start_stop_hook, &mut errors); + let empty: [String; 0] = []; + assert_eq!(errors, empty); +} + +fn run_test_path_inner( + p: &Path, skip: &[&'static str], + runner: fn(json_data: &[u8], start_stop_hook: &mut H) -> Vec, + start_stop_hook: &mut H, + errors: &mut Vec ) { let path = Path::new(p); let s: HashSet = skip.iter().map(|s| { @@ -50,17 +62,32 @@ pub fn run_test_path( } else { Some(e.path()) }}) { - run_test_path(&p, skip, runner, start_stop_hook) + run_test_path_inner(&p, skip, runner, start_stop_hook, errors); } } else if extension == Some("swp") || extension == None { // Ignore junk } else { let mut path = p.to_path_buf(); path.set_extension("json"); - run_test_file(&path, runner, start_stop_hook) + run_test_file_append(&path, runner, start_stop_hook, errors) } } +fn run_test_file_append( + path: &Path, + runner: fn(json_data: &[u8], start_stop_hook: &mut H) -> Vec, + start_stop_hook: &mut H, + errors: &mut Vec +) { + let mut data = Vec::new(); + let mut file = match File::open(&path) { + Ok(file) => file, + Err(_) => panic!("Error opening test file at: {:?}", path), + }; + file.read_to_end(&mut data).expect("Error reading test file"); + errors.append(&mut runner(&data, start_stop_hook)); +} + pub fn run_test_file( path: &Path, runner: fn(json_data: &[u8], start_stop_hook: &mut H) -> Vec, diff --git a/json/src/test/mod.rs b/json/src/test/mod.rs index 8f95a9aec49..e6148e0d08c 100644 --- a/json/src/test/mod.rs +++ b/json/src/test/mod.rs @@ -45,6 +45,7 @@ pub struct DifficultyTestCase { #[serde(rename="currentBlockNumber")] pub current_block_number: Uint, } + /// Blockchain test deserializer. #[derive(Debug, PartialEq, Deserialize)] pub struct DifficultyTest(BTreeMap); @@ -64,3 +65,59 @@ impl DifficultyTest { serde_json::from_reader(reader) } } + +/// Test to skip (only if issue ongoing) +#[derive(Debug, PartialEq, Deserialize)] +pub struct SkipStates { + /// Block tests + pub block: Vec, + /// State tests + pub state: Vec, + +} + +/// Block test to skip. +#[derive(Debug, PartialEq, Deserialize)] +pub struct BlockSkipStates { + /// Issue reference. + pub reference: String, + /// Test failing name. + pub failing: String, + /// Items failing for the test. + pub subtests: Vec, +} + +/// State test to skip. +#[derive(Debug, PartialEq, Deserialize)] +pub struct StateSkipStates { + /// Issue reference. + pub reference: String, + /// Test failing name. + pub failing: String, + /// Items failing for the test. + pub subtests: BTreeMap +} + +/// State subtest to skip. +#[derive(Debug, PartialEq, Deserialize)] +pub struct StateSkipSubStates { + /// State test number of this item. Or '*' for all state. + pub subnumbers: Vec, + /// Chain for this items. + pub chain: String, +} + +impl SkipStates { + /// Loads skip states from json. + pub fn load(reader: R) -> Result where R: Read { + serde_json::from_reader(reader) + } + + /// Empty skip states. + pub fn empty() -> Self { + SkipStates { + block: Vec::new(), + state: Vec::new(), + } + } +} diff --git a/test.sh b/test.sh index 63ea22d77f2..b49dfadafac 100755 --- a/test.sh +++ b/test.sh @@ -1,7 +1,7 @@ #!/bin/sh # Running Parity Full Test Suite -FEATURES="json-tests" +FEATURES="json-tests,ci-skip-issue" OPTIONS="--release" VALIDATE=1 THREADS=8 From c898463d212c47aeb2fd80cbbe9e478cd64fd676 Mon Sep 17 00:00:00 2001 From: Afri Schoedon <5chdn@users.noreply.github.com> Date: Sun, 30 Sep 2018 13:44:17 +0100 Subject: [PATCH 13/19] Hardfork the testnets (#9562) * ethcore: propose hardfork block number 4230000 for ropsten * ethcore: propose hardfork block number 9000000 for kovan * ethcore: enable kip-4 and kip-6 on kovan * etcore: bump kovan hardfork to block 9.2M * ethcore: fix ropsten constantinople block number to 4.2M * ethcore: disable difficulty_test_ropsten until ethereum/tests are updated upstream --- ethcore/res/ethereum/kovan.json | 8 +++++++- ethcore/res/ethereum/ropsten.json | 12 +++++++++--- ethcore/src/json_tests/difficulty.rs | 9 +++++---- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/ethcore/res/ethereum/kovan.json b/ethcore/res/ethereum/kovan.json index 28126713582..453974eaf2c 100644 --- a/ethcore/res/ethereum/kovan.json +++ b/ethcore/res/ethereum/kovan.json @@ -43,7 +43,13 @@ "eip211Transition": 5067000, "eip214Transition": 5067000, "eip658Transition": 5067000, - "wasmActivationTransition": 6600000 + "wasmActivationTransition": 6600000, + "eip145Transition": 9200000, + "eip1014Transition": 9200000, + "eip1052Transition": 9200000, + "eip1283Transition": 9200000, + "kip4Transition": 9200000, + "kip6Transition": 9200000 }, "genesis": { "seal": { diff --git a/ethcore/res/ethereum/ropsten.json b/ethcore/res/ethereum/ropsten.json index fd24bbe6d54..5aca6b2cbdc 100644 --- a/ethcore/res/ethereum/ropsten.json +++ b/ethcore/res/ethereum/ropsten.json @@ -9,9 +9,11 @@ "durationLimit": "0x0d", "blockReward": "0x4563918244F40000", "homesteadTransition": 0, - "eip649Reward": "0x29A2241AF62C0000", "eip100bTransition": 1700000, - "eip649Transition": 1700000 + "eip649Transition": 1700000, + "eip649Reward": "0x29A2241AF62C0000", + "eip1234Transition": 4200000, + "eip1234Reward": "0x1BC16D674EC80000" } } }, @@ -35,7 +37,11 @@ "eip140Transition": 1700000, "eip211Transition": 1700000, "eip214Transition": 1700000, - "eip658Transition": 1700000 + "eip658Transition": 1700000, + "eip145Transition": 4200000, + "eip1014Transition": 4200000, + "eip1052Transition": 4200000, + "eip1283Transition": 4200000 }, "genesis": { "seal": { diff --git a/ethcore/src/json_tests/difficulty.rs b/ethcore/src/json_tests/difficulty.rs index 0de1f1777b7..23a85594552 100644 --- a/ethcore/src/json_tests/difficulty.rs +++ b/ethcore/src/json_tests/difficulty.rs @@ -95,10 +95,11 @@ mod difficulty_test_foundation { declare_test!{DifficultyTests_difficultyMainNetwork, "BasicTests/difficultyMainNetwork.json"} } -mod difficulty_test_ropsten { - difficulty_json_test_nopath!(new_ropsten_test); - declare_test!{DifficultyTests_difficultyRopsten, "BasicTests/difficultyRopsten.json"} -} +// Disabling Ropsten diff tests; waiting for upstream ethereum/tests Constantinople update +//mod difficulty_test_ropsten { +// difficulty_json_test_nopath!(new_ropsten_test); +// declare_test!{DifficultyTests_difficultyRopsten, "BasicTests/difficultyRopsten.json"} +//} mod difficulty_test_frontier { difficulty_json_test_nopath!(new_frontier_test); From 5061017856a49111bc0c02f9461220151633ddc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 4 Oct 2018 13:32:04 +0200 Subject: [PATCH 14/19] Don't hash the init_code of CREATE. (#9688) --- ethcore/evm/src/interpreter/mod.rs | 3 +-- ethcore/evm/src/interpreter/shared_cache.rs | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/ethcore/evm/src/interpreter/mod.rs b/ethcore/evm/src/interpreter/mod.rs index 4d6c3cb6c3c..8e32c83fd67 100644 --- a/ethcore/evm/src/interpreter/mod.rs +++ b/ethcore/evm/src/interpreter/mod.rs @@ -186,8 +186,7 @@ impl vm::Vm for Interpreter { match result { InstructionResult::JumpToPosition(position) => { if valid_jump_destinations.is_none() { - let code_hash = params.code_hash.clone().unwrap_or_else(|| keccak(code.as_ref())); - valid_jump_destinations = Some(self.cache.jump_destinations(&code_hash, code)); + valid_jump_destinations = Some(self.cache.jump_destinations(¶ms.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/evm/src/interpreter/shared_cache.rs b/ethcore/evm/src/interpreter/shared_cache.rs index f4a7f47f90f..63c4f507d82 100644 --- a/ethcore/evm/src/interpreter/shared_cache.rs +++ b/ethcore/evm/src/interpreter/shared_cache.rs @@ -50,17 +50,22 @@ impl SharedCache { } /// Get jump destinations bitmap for a contract. - pub fn jump_destinations(&self, code_hash: &H256, code: &[u8]) -> Arc { - if code_hash == &KECCAK_EMPTY { - return Self::find_jump_destinations(code); - } + pub fn jump_destinations(&self, code_hash: &Option, code: &[u8]) -> Arc { + if let Some(ref code_hash) = code_hash { + if code_hash == &KECCAK_EMPTY { + return Self::find_jump_destinations(code); + } - if let Some(d) = self.jump_destinations.lock().get_mut(code_hash) { - return d.0.clone(); + if let Some(d) = self.jump_destinations.lock().get_mut(code_hash) { + return d.0.clone(); + } } let d = Self::find_jump_destinations(code); - self.jump_destinations.lock().insert(code_hash.clone(), Bits(d.clone())); + + if let Some(ref code_hash) = code_hash { + self.jump_destinations.lock().insert(*code_hash, Bits(d.clone())); + } d } From 1556356c55c3360583f96dd8f67cb6700aebcf27 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Thu, 4 Oct 2018 20:50:18 +0800 Subject: [PATCH 15/19] Implement CREATE2 gas changes and fix some potential overflowing (#9694) * Implement CREATE2 gas changes and fix some potential overflowing * Ignore create2 state tests * Split CREATE and CREATE2 in gasometer * Generalize rounding (x + 31) / 32 to to_word_size --- ethcore/evm/src/evm.rs | 2 +- ethcore/evm/src/interpreter/gasometer.rs | 40 ++++++-- .../res/ethereum/tests-issues/currents.json | 98 +++++++++++++++++++ 3 files changed, 131 insertions(+), 9 deletions(-) diff --git a/ethcore/evm/src/evm.rs b/ethcore/evm/src/evm.rs index 4c85b370281..d44d120e75e 100644 --- a/ethcore/evm/src/evm.rs +++ b/ethcore/evm/src/evm.rs @@ -57,7 +57,7 @@ impl Finalize for Result { /// Cost calculation type. For low-gas usage we calculate costs using usize instead of U256 pub trait CostType: Sized + From + Copy - + ops::Mul + ops::Div + ops::Add +ops::Sub + + ops::Mul + ops::Div + ops::Add + ops::Sub + ops::Shr + ops::Shl + cmp::Ord + fmt::Debug { /// Converts this cost into `U256` diff --git a/ethcore/evm/src/interpreter/gasometer.rs b/ethcore/evm/src/interpreter/gasometer.rs index db67556e38c..524791fe95c 100644 --- a/ethcore/evm/src/interpreter/gasometer.rs +++ b/ethcore/evm/src/interpreter/gasometer.rs @@ -176,9 +176,8 @@ impl Gasometer { Request::GasMem(default_gas, mem_needed(stack.peek(0), stack.peek(1))?) }, instructions::SHA3 => { - let w = overflowing!(add_gas_usize(Gas::from_u256(*stack.peek(1))?, 31)); - let words = w >> 5; - let gas = Gas::from(schedule.sha3_gas) + (Gas::from(schedule.sha3_word_gas) * words); + let words = overflowing!(to_word_size(Gas::from_u256(*stack.peek(1))?)); + let gas = overflowing!(Gas::from(schedule.sha3_gas).overflow_add(overflowing!(Gas::from(schedule.sha3_word_gas).overflow_mul(words)))); Request::GasMem(gas, mem_needed(stack.peek(0), stack.peek(1))?) }, instructions::CALLDATACOPY | instructions::CODECOPY | instructions::RETURNDATACOPY => { @@ -231,9 +230,24 @@ impl Gasometer { Request::GasMemProvide(gas, mem, Some(requested)) }, - instructions::CREATE | instructions::CREATE2 => { + instructions::CREATE => { + let start = stack.peek(1); + let len = stack.peek(2); + let gas = Gas::from(schedule.create_gas); - let mem = mem_needed(stack.peek(1), stack.peek(2))?; + let mem = mem_needed(start, len)?; + + Request::GasMemProvide(gas, mem, None) + }, + instructions::CREATE2 => { + let start = stack.peek(1); + let len = stack.peek(2); + + let base = Gas::from(schedule.create_gas); + let word = overflowing!(to_word_size(Gas::from_u256(*len)?)); + let word_gas = overflowing!(Gas::from(schedule.sha3_word_gas).overflow_mul(word)); + let gas = overflowing!(base.overflow_add(word_gas)); + let mem = mem_needed(start, len)?; Request::GasMemProvide(gas, mem, None) }, @@ -283,8 +297,8 @@ impl Gasometer { }, Request::GasMemCopy(gas, mem_size, copy) => { let (mem_gas_cost, new_mem_gas, new_mem_size) = self.mem_gas_cost(schedule, current_mem_size, &mem_size)?; - let copy = overflowing!(add_gas_usize(copy, 31)) >> 5; - let copy_gas = Gas::from(schedule.copy_gas) * copy; + let copy = overflowing!(to_word_size(copy)); + let copy_gas = overflowing!(Gas::from(schedule.copy_gas).overflow_mul(copy)); let gas = overflowing!(gas.overflow_add(copy_gas)); let gas = overflowing!(gas.overflow_add(mem_gas_cost)); @@ -311,7 +325,7 @@ impl Gasometer { }; let current_mem_size = Gas::from(current_mem_size); - let req_mem_size_rounded = (overflowing!(mem_size.overflow_add(Gas::from(31 as usize))) >> 5) << 5; + let req_mem_size_rounded = overflowing!(to_word_size(*mem_size)) << 5; let (mem_gas_cost, new_mem_gas) = if req_mem_size_rounded > current_mem_size { let new_mem_gas = gas_for_mem(req_mem_size_rounded)?; @@ -343,6 +357,16 @@ fn add_gas_usize(value: Gas, num: usize) -> (Gas, bool) { value.overflow_add(Gas::from(num)) } +#[inline] +fn to_word_size(value: Gas) -> (Gas, bool) { + let (gas, overflow) = add_gas_usize(value, 31); + if overflow { + return (gas, overflow); + } + + (gas >> 5, false) +} + #[inline] fn calculate_eip1283_sstore_gas(schedule: &Schedule, original: &U256, current: &U256, new: &U256) -> Gas { Gas::from( diff --git a/ethcore/res/ethereum/tests-issues/currents.json b/ethcore/res/ethereum/tests-issues/currents.json index 371211cab82..b6be610eb92 100644 --- a/ethcore/res/ethereum/tests-issues/currents.json +++ b/ethcore/res/ethereum/tests-issues/currents.json @@ -365,6 +365,104 @@ "chain": "Constantinople (test)" } } + }, + { + "reference": "9590", + "failing": "stCreate2Test", + "subtests": { + "call_then_create2_successful_then_returndatasize": { + "subnumbers": ["1"], + "chain": "Constantinople (test)" + }, + "returndatacopy_afterFailing_create": { + "subnumbers": ["1"], + "chain": "Constantinople (test)" + }, + "create2checkFieldsInInitcode": { + "subnumbers": ["1","2","3","5","6","7"], + "chain": "Constantinople (test)" + }, + "Create2Recursive": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "create2collisionBalance": { + "subnumbers": ["2","3"], + "chain": "Constantinople (test)" + }, + "create2InitCodes": { + "subnumbers": ["1","5","6","7","8","9"], + "chain": "Constantinople (test)" + }, + "Create2OOGafterInitCode": { + "subnumbers": ["2"], + "chain": "Constantinople (test)" + }, + "CreateMessageRevertedOOGInInit": { + "subnumbers": ["2"], + "chain": "Constantinople (test)" + }, + "returndatacopy_following_revert_in_create": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "create2collisionSelfdestructed": { + "subnumbers": ["2"], + "chain": "Constantinople (test)" + }, + "returndatacopy_0_0_following_successful_create": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "Create2OnDepth1023": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "Create2OOGafterInitCodeReturndata2": { + "subnumbers": ["2"], + "chain": "Constantinople (test)" + }, + "RevertOpcodeInCreateReturns": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "CREATE2_ContractSuicideDuringInit_ThenStoreThenReturn": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "returndatasize_following_successful_create": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "call_outsize_then_create2_successful_then_returndatasize": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "CreateMessageReverted": { + "subnumbers": ["2"], + "chain": "Constantinople (test)" + }, + "CREATE2_Suicide": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "Create2OOGafterInitCodeRevert": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "Create2OnDepth1024": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "create2collisionStorage": { + "subnumbers": ["2","3"], + "chain": "Constantinople (test)" + }, + "create2callPrecompiles": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + } + } } ] } From c0794979348293de55d3d9cb84f02d311694ca94 Mon Sep 17 00:00:00 2001 From: Afri Schoedon <5chdn@users.noreply.github.com> Date: Fri, 5 Oct 2018 08:09:42 +0100 Subject: [PATCH 16/19] ethcore: delay ropsten hardfork (#9704) --- ethcore/res/ethereum/ropsten.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ethcore/res/ethereum/ropsten.json b/ethcore/res/ethereum/ropsten.json index 5aca6b2cbdc..82709320b3d 100644 --- a/ethcore/res/ethereum/ropsten.json +++ b/ethcore/res/ethereum/ropsten.json @@ -12,7 +12,7 @@ "eip100bTransition": 1700000, "eip649Transition": 1700000, "eip649Reward": "0x29A2241AF62C0000", - "eip1234Transition": 4200000, + "eip1234Transition": 4230000, "eip1234Reward": "0x1BC16D674EC80000" } } @@ -38,10 +38,10 @@ "eip211Transition": 1700000, "eip214Transition": 1700000, "eip658Transition": 1700000, - "eip145Transition": 4200000, - "eip1014Transition": 4200000, - "eip1052Transition": 4200000, - "eip1283Transition": 4200000 + "eip145Transition": 4230000, + "eip1014Transition": 4230000, + "eip1052Transition": 4230000, + "eip1283Transition": 4230000 }, "genesis": { "seal": { From 4c74b4bdbc443788eb7fdcf507b1ab198798de2f Mon Sep 17 00:00:00 2001 From: Thibaut Sardan <33178835+Tbaut@users.noreply.github.com> Date: Wed, 10 Oct 2018 17:37:10 +0200 Subject: [PATCH 17/19] Add hardcoded headers (#9730) * add foundation hardcoded header #6486017 * add ropsten hardcoded headers #4202497 * add kovan hardcoded headers #9023489 --- ethcore/res/ethereum/foundation.json | 136 +++++++++++++- ethcore/res/ethereum/kovan.json | 256 ++++++++++++++++++++++++++- ethcore/res/ethereum/ropsten.json | 145 ++++++++++++++- 3 files changed, 528 insertions(+), 9 deletions(-) diff --git a/ethcore/res/ethereum/foundation.json b/ethcore/res/ethereum/foundation.json index 59e8daa8cbd..850e31f126a 100644 --- a/ethcore/res/ethereum/foundation.json +++ b/ethcore/res/ethereum/foundation.json @@ -173,8 +173,8 @@ "stateRoot": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544" }, "hardcodedSync": { - "header": "f9020ba0c7139a7f4b14c2e12dbe34aeb92711b37747bf8698ecdd6f2c3b1f5f3840e288a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479452e44f279f4203dcf680395379e5f9990a69f13ca06e817f8a9b206f93a393da76a3ece2a74b98eaecc4dae0cfa8f409455e88ccb4a0d739197170d2bc6bbb24fac0ce695982090702082fe1541bb7634f018dfe87b3a038503b7299fb1c113a78b4a3a5dfd997ef32e7fbf722fc178dfcb21e1af1f7f5b9010000020000000000000008000000000010000000000000000000000000000200000002000000000008000000000000000000000000000000000000000000000000000000000000000001004008000000000000000000000000000080000000000008000000080000000000008000000000000000000000000000040210004000000010000000400000000001040000000200000000000000440008000000040000000000000000000000000010000000000000000000000000000000800000000000100002000000000000000000002000000000000000000000000000000000000080000000100000000000000000040400000000000000004000000000000000870c90e059b181c6835ee8018379fb9583065150845b833d198a7777772e62772e636f6da0171fc2d066507ea10c8c2d7bedd5ccc3f0dfb4d590a3998a614013326c0b213a88b4fd884826187393", - "totalDifficulty": "6255555800944520547241", + "header": "f90206a0391c42ff4f047145a6b9a14179c3cc404b31d92f30693e28cf2bba41f47f6329a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794b2930b35844a230f00e51431acae96fe543a0347a0fb280d4457e60a0b96577e1dde9e00905102cfd36def5c5b31dcc2284636136ea077f739c324e35c7448b14aa02186973d3c74cc1ab081498cd0c487a604873723a0e462d76b5204d14b13d1f1b39ea048a3b637f91d42c729c367d5bbdbd0a72d70b90100008003410402005000200009400030c40490500208480008414000a40048806408000080802008204400010001800c0020080c0a00400105a9080820400900240000084012030a1504030508000200005c4404a0c3490820000010400811040004708a1006910211444040c28001a800e920d00000940c200119111a10401001008044214002002080c21081801e008a320848a204400042400898004004010028840181106210080254a081112480031000410202440092c880be3894000120050500860880000108000c0080009e0000204007212840808cb80200601024020000210280100c018540b28a1041a62400000108204084000008808040000004870bc009a1914d7f8362f801837a121d8379ee5a845bbd53ca8573696e6731a0abce0f90ce69f740080eeb94d1cb13981fafe3bc6d020a44815acd86cbd3fc0a889501b04c0614e053", + "totalDifficulty": "7128515864594819065361", "CHTs": [ "0x0eb474b7721727204978e92e27d31cddff56471911e424a4c8271c35f9c982cc", "0xe10e94515fb5ffb7ffa9bf50db4a959b3f50c2ff75e0b8bd5f5e038749e52a11", @@ -3212,7 +3212,137 @@ "0xf344c0cf6516f0fa6617e48076726aefbdaaf5a31f67ad8199bc3f6e426bf904", "0x3f3d2d33f36ba9009e9a72f3f5bbcb5df5392a19fc7afc8d37823aaf52b03477", "0x346a89411f090d559ff90e670bf0a385b1b09f117fc9ffa18b09d3b6d5d8e45c", - "0x5bc5689e2b4572b8ceea472cc7827e22cbfd018920beebf5c5b25f65f5cd5357" + "0x5bc5689e2b4572b8ceea472cc7827e22cbfd018920beebf5c5b25f65f5cd5357", + "0xda418efcaa0076f77e4d2f0c57fc32fa67179a5631d9df52d56497113d0e87af", + "0x5a8050832e835202695129f6f384652827e61ea5f1be7ff300183201d8bd6b4d", + "0xd9f444c382da42c310bd2f05955187163ae7b224e5efd44ab95af332e197d374", + "0x9ef2c5bad361117eedbc2adcb72a2ef5eba4caf3a99a0cbb2a65a94d185e48ae", + "0x7e3e089bc46b00a4174d90003379c382ab5bd84d092b9c4db3189d2bdc24f00b", + "0x94f50fb12eed909d251fe69adb1a1f214776cb029d487360b55c3a2abb663d7e", + "0xd3e1f4244dea40d0741255db2dae72103e263390e0ccfdefcbb2da59ecc5ec9f", + "0x6808bf0cb7d4b677527de762b6db8ddf74a1b272349f34f44505912bd95d62f3", + "0xbf7672ac474b5b849bc086ff8455216f015c8fc7660436dee153522ef6991c04", + "0xe79d27a369cdd5455ddbc6bd9158cd1870aa895b3c3971d07f1555b95ed02ac3", + "0xfa9e20a36c11b0dfbf7e9c62872a6423f5460dfd18e447481461a41176678262", + "0xaafb6c407910341bedc82c0f260cdef75ce5653f644b93a465cb990247a32986", + "0x5058e655e0c179e6c20f48fbd08c2f34f9341f6c07972ff40f55bfabbc783b12", + "0x28d2e7c852de8602a764ff693b6881af18ddadd67fc7eff481f48ac20ebf32f6", + "0xf82e09e7916f61b5cfdc3dcf193bf9d535f2b33f93a06c90fbdc78b3aac6b7ef", + "0x626f3cca9e1a9e5e123e34485c8697c758ffc32213a727665065dd6abd2babe5", + "0xb7f1c07f673d903daa61dec649eb12286a7a0568ee36ecfb1023ec41427c8dd0", + "0x8d1d42bfe88dbe4c621cf68d380dc57e7768121a815546bb4aab29b7486da9ee", + "0x79835acd7266bce85978f481aa3c58f3bab9106d72892df8579e472dc95c6899", + "0x0911c9c804bbe9be0aebab6c92f5b71a893f72a9d0cd35a51b0e8cd19ab0c02a", + "0x7fd2eff10936d8d12fd9a1c6d27e77cbec4e48253465eb7e65876134ff60c8ec", + "0xc739ad4255415e2831c6996673f3d02dc79f6e6d6822f7dee23bff5b94833c3a", + "0x2559faafbae0852fe5a1c924f0e4f6ccdf4fd22f483148b3672a3e7b3692b669", + "0xca37f0aa3d375dbddc0b426c9564fe68f10b0a4cbbf1ab87f97b27b44878f2fb", + "0x00ba40205d1bd46ad5b5e73cd5b1f3418bd892586d5a4647ac9a6d158f15bd93", + "0xfa6d25c829299535e6b80af81a2416d10ed6903117e73c656b979a5f5abe3ee0", + "0xfd82d8944315cfb228a8fa416c18ff82cbd8869c3babbd3389dca6dd66797785", + "0xd8834cc29788cb40ec901725419df8c031a13e190756a6352696de870eaf4671", + "0xdf6843a52bf55e0f4404e7bdf144bb17d5c47a72ef9482e712090ac9730a7f52", + "0x4c2c562f835966c72985f7cca89a3b1a7b0d4cb04623dc96e337daa35a2f5925", + "0x49d2afd87e83a04059dbf3ef4e2598b8d0c495ab1cf91ed3004e16a608e910c2", + "0x5be64774739c001c239efae1ce9f2a5706cc6e3054ddf24b03c09358f2f4852f", + "0x678f789dc8c409653b36f4d2015338165d3bc6a73f2a77ebfe438676b8412d7a", + "0xf87c8fbf02d8e84cf72680e6b9a8b8be39fbae9f1eb1047c536d77535494a301", + "0xe2428b952d2c6d60d4925f56b3d8227cd6bc608da2c1b20264befd8b1ad89454", + "0x561a95eb50c663462bb8af3aab336bd745b0571746b10fefa791bc11be777763", + "0x6945f40e3499d2769ceecf499c701015d93fddb607720b18dbbd5a6a2aa46639", + "0x9c35b0367a2b82270d64f11c5299336b21b9f454077dcf7af3b2e434677a31b6", + "0x454dc6bb2443509381e478f1836cb36808e2ecd1a9944072056c292b710072f4", + "0x0c80566f34a46477592560a883a9c01fa393f7a2c9dbb28a54e46a5c017e8596", + "0xeff6a1255090509eccfdea2e591516886c91191f1f02eaae4808ac95009086fc", + "0x37cf60888e5ec75841e7f0533feef7200185a1c9f3253073216d83923c864829", + "0xb169ebb9e418809a96529835bc293782e4fc6310dba450afe3e95a7abdf7cc01", + "0xa3c8d5c71ce0477a247f56bfe95272ea07f0b7f10a8526b6e3ff9a8de8faa9ab", + "0x2bf18db4ee84bafbbabaf05d1d4d383c0d5fc91be6ae902334496996eb3a8e48", + "0x6c116f0d5809a2c28351a737ef3dbd1808685e1fd656e37df6b6e524aa82c918", + "0x21e2c8e019c687fdb360c9bdd4e3a5133488cd2e0365aee3b823120734aa6f27", + "0x20c9a1db9de894ab4f576265da25f391b32c0805c3da76fbfdd0aaf300f88a39", + "0x23ef1f43af87be7396449fc1f89d9766c59e8adf2660812293c65a27482ddb8e", + "0x04a82d3a4a5e7f2507688ecdcdc300d7fb97aa8be92a671d7d42c0b60fa4532b", + "0x99e204c42afd6d4040faad384517d99bd0e077b03310d32223234d2251d6a07c", + "0xe342c0c4295665b9e25773fc9998e18c460e723d0a14efdb59c19b27b9c7011b", + "0xb654b1b8ede0d54a605cda54b4635d2b3c2bb8efd01ebd416e52cc87b590d4f3", + "0x5daabc41eeb6de98336411a03ec0323995e81549941cf32b7e15c765d1b7b39e", + "0x5103fc7f0fc6df43fb081b580bb01476f2b1cbde73e4d0f9d1fa6d8427fae789", + "0xe2ecf5daba51d2f7b22106033fc43f956bd1db0c5ad02bd941bd3d2b96ca21c5", + "0xf152bce5c6d1efb7e22cde72d6b8ca37f556ffb686a13770c5fab46e04837c92", + "0x306007d8091caa5baaa78643307f5abf9a5f03996fc072a9016ba6b487b2017c", + "0xf57308d0c02c6b8e2416c070554c7e29911fa84ef4cf2d934e2322ca262e987c", + "0xb234fe7433d7fd71fe0c6dfc834e4bcbf84a261b95760a6c4eb67d222b9ff392", + "0x753059f3405f60da3aa7cd1aa0cbcfa4d5ef4f2a6ed34b853b2c5ab2181fd383", + "0x096c6630e821816d9f4bd83fbe0ccfd223282f34aae5a49f969ba30b98c324c3", + "0xd3eec9dedb057fbc839c474fc99cb54d89f3f47d896e06e758c98f1cd194b61f", + "0x0d44cb2a83b9a3fa18daac280cf08b46cc637d705488fd9400cd7300475d0a1c", + "0x2e37a3036db99c4cb1c135f5ca6b527fa13b2e80ee421805b7be5d8b16983602", + "0x381e0ca505308b7d3a083e60b0f9cb44c89f84942430ec9e4c5571796ab6a8eb", + "0x90b04d35906c6f5a59c266c3bce7c2b63cea1486f714e272592ef9ecab25b0ee", + "0x9cbea70e760f2ee97537d058d57f395886a2c3a6e769ccd3433b797b8716517b", + "0x4e2167846e8d6f0f6495b5f1443f59bea143b63f242e40186fc6429434d1136e", + "0xcaa0512739d000bb9783fceb46d0427098886e2b7f2e1140855f1a91f843d5b3", + "0xc14df4e379e84591f618e60b5953aa6764146c7822aa1f0e3c2287e20753985a", + "0xf4443154c04fd378b2c3812fee84b774b37d6e12778674403fb5c995379df866", + "0x1a501c2733cc138fb6ff3716899e08dbcd4d75edc18af8972e8a749e45eaf67a", + "0xfc8cb80bb0d0fb490f29aae3067641eef72e9225c558e7e299e0796a2086969d", + "0x2b7895550febf03070485c02d521e7ddd80b94b7fe33a60b7d7ea3545b13e7dd", + "0xfc4137c3cccd45050b5770a40b2f38c43c62b70b07d17bb6d762b405f3d753dc", + "0x86ed22bbbb9fc6600112b91601af4fff56d0ecbe9b3099f91d4477cab8e300f5", + "0x2273a60405ffb04bd024d880c79010f18d58e3c8ca0dc82795a0125364679fa6", + "0x00dfbfe7be3bb2116d9a603a01ac428c0088a2c1477810cd5d3be0d1bd86beab", + "0x7acfb03315585c79e2a47dbe847d24cab0785791f6af7f179fea4f9d6ecb0e0f", + "0xbf6a2e20ee1da5eec12b792bbaec2531e20766ba54bac423011c1057215851db", + "0xb5e94d1e3ba7363d1d79fb62dedd0b6c26b0485052dd64a7093d41ad2d41b890", + "0x9b0cc26f08708814960de8f280ac26d8ed5089a19bcbd2d765059306da22c196", + "0x22d8af121d3e395d3cb4f6ee43c06e6292f1b5ffda672d2e40dba69a2885f5ac", + "0x04bc174272a57189d76aa17de0f76806e8481f4903575ed8c4df12b042637e0e", + "0x06ebd2b6ec4b80280969a92726df5f9cb12d4288b60af617b7040876116656d3", + "0x0e9430513e63b5173271c89b1c91af0b4818d5d14a3034e1228c56c94186a109", + "0x8dc5422ba98d9e58112b052a00d4b82b1db32e22dd7ff2d845619899bd47f277", + "0xde513d40bdbb1e4956b468cece598d77134626a900066b92fb2ecd6fcb5f81c2", + "0x90746299ec75af1eb444ad14ac666ee444aa020fac3fb57796516d8772ec8f45", + "0xaa91c30c62b24f943ee1eec7586b682289541c0355c2726e44424da8686ca24d", + "0x76eb68baae9fb7ed126097f93842dcadfe6e7188d61549d9c0922a9b3ef8e80a", + "0x5aa5b4045e7fe71559a6e93f4a89b135eaef38b9a7f3a84e383ab1ff902ceca9", + "0x504b78f8fc3646e9722e96a5e97d99f2560d4fa3337fa5faf1cc8c8a05f3520d", + "0xffd7a5d7c3b21e8144f7678a9ddc039cf85eb32b09000a600c9f12aa7d6083ed", + "0xcbb4010000e96ff0b50b9627dae032bd50782ccbd51af8af7cfcd6cd184675f7", + "0xb96fabbdd02371bf4a6a0dc00e3874cf43d47246e27163c910c141b6759a4249", + "0x7358419f4e994ff296a37f2e88b238b3de6ba73062073c9467dec52a2df64422", + "0xca90be9f190a1fd0548becfa719a6e4763e92de0e4da4283a33b5f7d2886b425", + "0xa629364f7d6329b008d9c6a0262327bcc12953aa515cdb7b8817e7fe1d746d46", + "0xc5167bd8cac1ea6d14f305c9d4fe075e1875d96353e5236473b6daca5ae9b4fe", + "0xaf4ce2490e9504172a4393cf14e691e947c86a0ec7b53416384a5832b213d6c5", + "0xbfa4853ef2eecc5d99a90e1abfef37ca10c1f823c1d0ad59a1bb19339861241f", + "0xbb5a6584cdc7e4d06ec5fc1514233cc42970f6c332c3a9590978dc9908e58c0a", + "0xe69d7a0766db411e504f09a8f39f0583b2869016bbe95f21dba432bbe8b88442", + "0x89cf4caaaf200881779f5fa6da8ae91ff1c962045dd0622b5ca65c830d3a9d4f", + "0x82d66c631f4c4167e5301d896dbdfe24d8245b1de041fc85eaeb6e35117ed9a0", + "0x957907bc93879681d8682a188622f9bf2c7d2595dbe3e2e34bb01711cc4124d1", + "0xccb3a3380550586696abd3ac267e85c7516b2b682b3c48f66aca94d57500f3b3", + "0xaf56d4650406e70748dc860a7879d8d522599081f8e7011056c976b860703e43", + "0x5d96ac1d2dff8a054d880a44f5d45a1bd18aba29085fcd633b0608351ff1876c", + "0xe051736dad8b9f93a8f1c13031c2b63249925e152685a2e7ec188ee089861b20", + "0x0db8987339e1fae41af5f08e6fa15da5fd80de3431b54e82cf8edbdc792f870e", + "0xcc99097678110af2be8dc07da8d642dce928b7d9e2728fe6fef1fe2eaa81a72a", + "0x2428c1f94ca57c7913b011a68281eee9ee4855e4ed2c97e34a370e649b21acb1", + "0x501ee9580c89b1f67c5b3b69ae5fd1f83852a2f9330f53565bcd04d8a7c0b776", + "0x16ae47cfa19e8046f93a579fa2557b17aeca7892fc7a82b6d539930c8b7c95c9", + "0xda62590043ca70c1cdfc7969cdfa853bddbcef0ef62aabb9f372805322511014", + "0x481b4aeaaa60504c94dcfea966840b381db85183c34cd25b4857300b5c189003", + "0x035dcc47f8670a9f648bcb0232e42fd4876243a7a3bf737b88d723ba187929a7", + "0xebe9bf09e3577865aeb341a06f67bb6e607f10b04ed9f9d733492a9d0e9ceb1a", + "0xad5d85b58af6aef7f81bd6b2407c6e4884ec82b2ae2aeaa24e379a3d35902375", + "0x0f0dd63d7c6c284659283825624140b31a3adaf7cdbb2255faca443e52ebfe84", + "0x40079be1c9394e95b4823895ed380d79333ca2085aed2abd0d766f84d21b7b42", + "0x7cc40ed01b436ce225a3f9c5c2bc7f6f81aee40bb83a54bca2fe899b15f3e2b6", + "0x1b6356e1a83ca5b0eefda1fd62fa959b118d2a19a6a90f182a53414b3fc7f9f0", + "0xae4a71712cc96a5b30b45e3b92c339c2e975e4ed683f4d1fcadcdc121ff7c6bf", + "0x226f6d8c71ec32c5eaab6b01c0fc1d00ae95e60b383d09560e90549b79eb1447", + "0xf3dec779841c9384df93bcefbba8700a292b570b29d286a7c9c5a442b4788a20", + "0x63ef48e80efa45383857adcb0f31076393260cbad058d1938345ad13faae50b4" ] }, "nodes": [ diff --git a/ethcore/res/ethereum/kovan.json b/ethcore/res/ethereum/kovan.json index 453974eaf2c..336d32baec0 100644 --- a/ethcore/res/ethereum/kovan.json +++ b/ethcore/res/ethereum/kovan.json @@ -62,8 +62,8 @@ "gasLimit": "0x5B8D80" }, "hardcodedSync": { - "header": "f9023ea00861b3771ffb84fce48b8ba3c54a09f81e91ccb38c401261f06d370098889a43a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479400e6d2b931f55a3f1701c7389d592a7778897879a071cc81d58cdd21d1e17f7389e55c530cd9f94cc15bb32af6477320682327dcffa06090021a7c09ae5e75e443410ebdb76de04f1eafb0ab910daae96ee6eec560eaa032510bf257dd03b11f3b4761b94b495a5b5a18cd6eb17c77785e0f46e2ffc882b901000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000400000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffd8381e001837a12008306697a845b83bd6096d583010b068650617269747986312e32372e30826c698416e0ef58b841117e2088e2835bf2afcd5d48f42b3bf2a1f33435f21f089ead2a6bae7d01c1486e645b460bb3c726a827ff1eb50e0579f3410563bae090fc256cf1d8d594b82100", - "totalDifficulty": "2845866505151538604560067685603735513869853136", + "header": "f90247a01865856fb6e4118598117560df31734c74cf725c8edae4db941055ac0afeb207a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479400e6d2b931f55a3f1701c7389d592a7778897879a054563efd593e9682943065880710af9187131127148575efc8bb51d80dfed41aa0a568a1653a6c7d559711be0b91a8e75db76c678dbdd286c75b88e4f0c0d31171a0dab32c5cbe9b9244a7af00afa7f6042a4ac923573e8f2f025b107abe1e3da999b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000004000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffd8389b001837a120083046540845bbd803c9fde830200048f5061726974792d457468657265756d86312e32382e30826c698416ef600fb841387b51dae8bc8daa6cde190d3f44797690b4da1ce5fcfcd54bdbb2a6ee6d8c1f7649081ca28b5cd70067ee9f61e27d8184db83705102d5e1a269f2b631b4d5db01", + "totalDifficulty": "3020091077015059097853315484608800838133866777", "CHTs": [ "0xdb9557458495268ddd69409fc1f66631ed5ff9bf6c479be6eabe5d83a460acac", "0xd413800c22172be6e0b7a36348c90098955991f119ddad32c5b928e8db4deb02", @@ -4220,7 +4220,257 @@ "0x3ef50c81169af169c100f58f3afcb8e2f926d957b2adbaca8787be5d4e8d7233", "0x8783eaeb56ca2d7fec84e0e272b77271fdfd6c14452a2e1dd83de770c5d99a1a", "0x861024460895378ba100c5d0c05e62bb6cac8b21ae529ab5cab39eb6c6cabd90", - "0x1c741ed9eda60e5ac585e2f48f06fb988367c2c40a0d8111bb04b260fe44ec6b" + "0x1c741ed9eda60e5ac585e2f48f06fb988367c2c40a0d8111bb04b260fe44ec6b", + "0x6051d77e0596a911bce132c4bc12be2ae5cf29d113dd52a41b3bc166861149ce", + "0x92c049df5ddb238644015d4e039e169614ed1d926de070952f2407912906cb4b", + "0xa897567fc1ee9437f2876deb3de2b11b8fc00aa07340564031573f0351ec556d", + "0x3e54a8e15218db168960d28369003cdb1a76f8db19384e9e2696ae66a6693d6e", + "0xc5db7ade97cf28f8b61f2c63a0773201ba64f37dadc19c03943b6772aa7a1a50", + "0xda784d1bf64b7efd06558b90cd2436f3e61dc0f7a8370ff92516ed062f461091", + "0xa1d10b0a36ec5169d2df740878d051bf4d38ebc5dc04ae5558daaabc2bfa1471", + "0xcc89a8be2ff74a7bb9e967cfea3cac067aa84cc455a2fdd5449577b52a2b4ff3", + "0xbd23a3e6d3198d81d798c2851c36b954fa6f359bc8fc6e04a0b757e3d0ba053a", + "0x74640f825b9d9f95be69763845aaa0269d3a6ed5aaec88bfd9b5c4139ba7ef41", + "0xc01a29e41af3cc0d0a13ea83f131f3e4828ec3e83dd2fdf9739c139938dfc2b3", + "0x832509e705972acc7efe91475e8d76ac00a12750e194847093825e6c4db9e83b", + "0x63139d1224766ada1318613b9ec5894308efa2473e809d9e37c8305c6965f2cc", + "0x76547e54dc59473093c3fcca1166307cc7d0f4f0e8a35d850507bec216b76476", + "0x3a6a14785272391982cfa690762f5b2aeccc1dc0bb13eab6b9fcfd056f40703a", + "0x603e32b52795c04416d800b6a936343aaaa09898fa97cadc2b157eeaaf3bd6f7", + "0xf241102a3d3f3a9fdc5a1a586b16fdce4280c6c6da04290541eb3cb9c28c7325", + "0x6db6de041bcc7c00104a21bbd487a1e1ddd5e4953f7a503aa992d68a8a7bbc43", + "0x8377d795c55eac07c0acca674e775ed7d8eea35867990c8a776f40965c9ddc68", + "0x48d62d562279641043e405f4d7fbd76050d773103871c5de2c8acc25992db502", + "0xa9ef42d314e15c419537e022753ab46d41318f1fa8784e4363494f395eb6d236", + "0x99572f567eb602a1d9839bd23b41562bb3782eccf9a8893e54b002e685ab378c", + "0xd8cf2fa2291efed46c1a36e1b8837be62e86caacc380aa6397792ae8baf8f3a1", + "0xed2e800df1acb7bba5ee6251592c397a604debd7b0bfc28c8b0002dc40faa8bf", + "0x9ccece195d9e67e318f6d2952bca9486d09f4207c6d8be266cc0eebe41290920", + "0xb20580a5c96c25bb59e1bae6ced3ea5cb69d903f64e648bcb38b799141b3cd5b", + "0x1488647e697452306d2744ca6c709007cf75e2e37da3c7c05006211ba0720824", + "0x009c3dfc5494962c77900fb8da67d7bf2a2f4b855c521b9d50c4aafb1e0735bb", + "0x482428835dfff3ee1da335b36ba3aa1969fa35e89150e5b3c1991f28272d14f5", + "0x6a972044f2076e98833b243c9ed18162d96b46823170ef7c20b1a02d8bbd48c5", + "0x676242effe0fae84110c4933beecfe5ff549b439e54ff5a588add229329e5365", + "0x2441bce77589ebf8019fa8ae870a8529479c6eaa0fed7e0fbd3cc7439dbd4a09", + "0x0b20c25d2c6897c1a8dc9ea1364d3c72d33c97b4d70b9176c3f0a1e3b6ce08a7", + "0x685aa4e279118f8326a90c78e9896e40d9baa62144e2425887dcc704106979c3", + "0xabcab60973f6bc9ec3b596452e7434c4dc89c55c8eea925fc0092d1103c6f86b", + "0xcbf44f106f3f2c0050906b5e344ad22f0e0034067d35402d447311d254516dd0", + "0xcaa67796a8ac69283d7b6304181a988992130ad8441d47b4fdaf236686dc1caa", + "0xad06e6db230bd0bfaa0df59d1ae517ced29d5f11b34f76ef9bb6a73407128b59", + "0x93ef56a4951e4e5c19230918b1219c1f07e9356363503c1410e71486ed338f87", + "0xc6fef02b5bdd4909906c40cf5b999fe9e08e4c0d8bfe59d3c9aa99011136f780", + "0xfed633749700ffdeb0921a537a215ae31c25b85e4f80727376e50c247b4c5a38", + "0xc39d8cc15f4331fb7db2c24ee1163bd164e81ad2ebc43271f841fb25d03835c6", + "0xb13962dcb364ee49e2d0a34dd1a555fa8df363041504ef1e987ce78646d64146", + "0x97e0d3047e2151d53cbd1358da627453558362c6a830910b33f241848b20cffc", + "0x587ea98cbd1da50c0af1986f6ee5e676658c06442e893304708db831fec8e804", + "0x0a1d21212d9bd85a1a39e046c897d1dafb496bfd80762beda2fd3eb1cdc72eb9", + "0x46aad83612f04e7a51fd642de742f713601992e58de4daf24148a3e6f3318aa2", + "0xa65a8a9ed4fb28fcab6ee3af5df4647083c2e735fc652568759fe0426e9a294e", + "0xacd7ed5525cad187f053ba98487cc4abf24f76c8c0e97e71a696d553a3a41b7f", + "0xdcbdcfbaee764bb404bfa5261b5037b9c7ce567a3c1aa9f7280071990320da18", + "0xf195aae79a232b2170a98602efaa2efbdebb3c40d2438e63bf0954e4dc779cb0", + "0xfbb2675a62e2e67baf85e56fcd4cdf2bf89ff7905952155d3cfd4e625fb674d9", + "0x5b955473a35f6b0d24fa8be8009734ecee62f6c4bcf0cafc2335f07c51752fb1", + "0x66f37b268338f4ba1e21eef6884aef245bc36935be1f5eb14ee1d23618f00f5b", + "0xaab809ee86773263043201b83bd445d98a634d8a6da4c389b2336f68381dd481", + "0x509fc38118491458e45c7e8ab1d60c687f50d85fc1c0bf104b531a3b352198ea", + "0x20d1e4f38e83b27b77d55281af40e9f96be098fdbb90730170638c88ab7e435a", + "0xb33711864d62709a98f81d9c5f0a301bd5808d0e8ecef1063c97347af754c8c2", + "0xd69fd6c0fea478bb380b948f5b054f91831cf26d304991d40ebdf0b00a97503c", + "0x87157d452bf57e617ac1dd2372438b0777b83f6087d8223008d823652c634882", + "0x9c54b0172ae0223e6b23f7e000cb6887144e615efb02c74596002dc26d43eb5c", + "0x5b0f87baa8e40f0a2bbc1a76afbe0b21b5e8aae1443f0d38c3ac55c5f942db42", + "0xeb68d93e19860fb9fb76847080edc345972e29ab1ffd417ae5727d3cec79c0eb", + "0xd27026033bba2557c79c4babaf669a399fbc72a2a5cc06c707e24eaacee83bce", + "0x420d887bd82cccac29711c52f4d362b6a7d854e694f8d597d208d0a094fbad8e", + "0x02ff085c6c3c47879a91f511ea4c54a214af8160e07dce8e82a6be9e8299e237", + "0x1f0384e0afaf47ba59aff9f224905950768674c48de0fb0312749b16edb0a347", + "0x55cefaac814e132ff335882a366ea6173bc21fa713e93d8ad92260c84cfd2d85", + "0x58a8dd6e036a05a937a7053be916c0e7f719f2a1905186e7586a9d2dafd5a1a4", + "0x8714d03549461e32a467cefdad60a96788c97172db05c18eb9debf6e6a4d39e8", + "0xd141656c1f57c12feed31dbff3817e1d2af4e1b5cf6aa75d1bb29ea2c0a3ae69", + "0x5ec365177e19fca3c1063e65a9342008aff04ba9d03d53837b598b143504b97a", + "0xc620e23ae73d423bf2628a3de70b1a1f915d80173e0c8d1443a44b91400c5a8a", + "0xc72c2356ed53eae5a4a56bc248d9d2f4e9154f1404780b84781f357cbc7ad2d2", + "0xe60bfe30e5a1a9457ccca65810675e129948b474f391ce64d270200be7ea6beb", + "0xf679887baad8f8e497d60b015156f194b94fc30c6cb1f83fbc4575e99b95a8d5", + "0x654463146799fcfa18a74ffe4f2423fa04c8747c16b789dd24da26d0338d381c", + "0xe8b5406278d9e4622d088976af8b5e6b14cc146a9530c862a42fa5566a247355", + "0x8ecb4735132f769663781f96fb531115190e68390c54e33b250db874e90aebaa", + "0xef13bf38c2ba993c9dea5777e5db348339273d0e6dd1f41867d3b258f24ac4d4", + "0xbbbbeedf7276a857c513f4ebce88e3b531c99cf206eacd1c6c29d3cabab45df4", + "0x89cd50cde2de3ef40de7502241b78e664de53dd4a5e2ed85db62c55be0a4d8a4", + "0x0da2cae061e7dff539c7e39b0b9f63af3217f1a51bc597db957b6a3972cf7186", + "0x57aa87a6daab3c65519de7c1c1360ab33b830d46f169d4e0d3c38e7dadef289b", + "0x85fb1241c4110b4f3a6c197450af8ac47bb24d531219f6cefcc079717b208c84", + "0x52194cfba6bd7d5eb8b438054fbaf5fef387cdb8b1a7ebafe44cdcf4da47b1dd", + "0x7d24eb47a1310f7f4244e825847f634fd4a4224f695a3609c5250dc6052de6d4", + "0x38edeacb93b10653624f77dc05063499daa770b74d6b63ebe656be5a3630b7b8", + "0x4e050f7b9d73c1aea3ce60c8eae8e46b55b6d4c1cd1eae22faf982895871dcd1", + "0xf22b284ed4d97b7d3553600388748721a328052daaf92a58ed5403fd4020a496", + "0xc5fcf858d9a9748045fa0ca1271ba5af780a788c51d693815e0490671be3885b", + "0x2342efdb88226e68173ef84060a0d4dc6c8aa9c9431883beef4a5588f3157fae", + "0xe1599bf452eaacb8dcd51ff835a9ef5761dbce83cfc719813d6a10772ca5fdb3", + "0xb754797393b3216778ea6389361ca5951f365ae4e7ed99ed4cd4c9c76ff442d3", + "0x3fb5f9f3754764155296c6ff4c469109512264c603ece7c78c1231942bb8ac35", + "0xbb347d23c7d703cd2801e2763f1a6c375b5cb2a666ba137c4d6442c3f94688dc", + "0xed3806645b55fd7027dfb7f5f796933049ae558d26ca695a01e1b11333f5e453", + "0xeadb7740432ede4f90c0bc490c15fb377b68de0fc1ee3a56e87e21e7771211fe", + "0xa8c0e907e0b544e7fc3116d47e4cdfc8e8688f5cc4a67cdf600f74be6b79775a", + "0xc6f6b94f2fb4c56066e3c722123b8e85f80ce8baa0427b62c5a2ff937702c481", + "0xfff0b94553a7daaee58a7e15daf9845d1a3ad4917d81d4f23dad27d0262b48ec", + "0xb9084676613e1a063c2b491bef1b984acfbd2dce60a8ed970688239524e31962", + "0x196af717eab2cf09b47db13605ca4864cb0c4189d40c9b618d8a7d3f92831d78", + "0x4fac369653dcfe74d86b7422354d68f7580b1ae0ab359a8b8f8be8582590ea7a", + "0x035ff04f84478354706945480266321d31790f5445028f3e964801fd9a16c78c", + "0x63df70a24370a408bffabbe1c7a4c9b9e40be1cb326ab10d63fe54bb9de50d34", + "0x37b5c558d31128595425ca68deddf5ae7539abc6da838837eb1e0457e092d9ea", + "0x41a9ce82ab27afbc84669368c2e75a15e6386b77034ec316795a896ef9de577d", + "0x08bc6cc18842df4130280823f7676f418f4797d3ddfc544e54267e6456cfac68", + "0xeabc09ffceeb35cc4ec18518d4920bea2f43bf746f23b5524fa405bd874e9d34", + "0x40336744dcfe6f312e17eea83f53538f9999864c41bec43576cfcbef68d12e7d", + "0x3e780dc9c8f2b708527f1eebca75d18507e00e226a00e1b1ddd0b715aa8dd561", + "0xfd6a3c50c4a4d6e1a6fe27fa96f6aa2654573cbb9b839ce8e09a75993e2bf8e5", + "0x166c03d381d6ab94666099024adc95de0ecc9818e5ceb49965767682ca0c73fe", + "0x9805810b802a51a3ae18ce44f6b2c68abfccef2119df2430e4693e291059e222", + "0x353ecd1a0922e819ffdcd634385ebbdb674d247c4fe75e2d5437b659c98424a4", + "0xe75fb8682b706ed6596699d6151db4dcb19f6e71a3b6e34aabc3508c919f5c17", + "0x6e9bab64b10a2341f49e81d862ef3322d3117842e3f1aabc8b774c68484a2a31", + "0x82b5e79ee8d72c3613458c975530bcbba359734a4e9f07015686dfc521230329", + "0x86d48d57ccbe1f1986a4043748b1a0d8d76fd56bc74e7c48c6fd742affa0ee11", + "0x46ee65b9c2fa3e69aa1cd6ba5aaafa7f7aef59224098b60e22994996c927c9c4", + "0xb6983761b177e21899799410dc018f1acd3d417fe35943fbe57207f9f799a100", + "0x594057a8386db6e159d43d136c464c5e3980eae75a73900f7a84ba94803fc6c4", + "0x53c78073c4a4c44d17db85be06f38ab47ecbb7f36ffa87b9db707fd2bc87f391", + "0x4a976673044732e3e8a0987fc8f3c36375e3c4fb3722fcde5259af492ec458c7", + "0x1e2fc8db341a4d9e123ae4ff4f4d8096d8afef47c5d2915c665922bd1de3b00c", + "0x565cd8eb410c6e0b4d67b54d37ff42f6189095965896b0f81566ca502bea34e3", + "0x32d030e4ff6b2f5a560cb7525b5e66ab1f34a1e06531f9b81c48b8a257bd5637", + "0x25a91d756023bb9ae538034bd39b6e698d05fb1393d1328c4fc7e5c14209cce1", + "0x8036f74c4cbaff3bd98820ddd84bc093c95e88d357b341154a3189715225d068", + "0x8bc6bc61f7a57a145b8d728f583e027c8630f0c07e003b189f390ffd11d6f150", + "0xfbeb53fa167d067c9b0a2c0710f7f5931484f7dd90b9456c52c578a15f402d9b", + "0x8d355b208a16b8aa3f7bc5d8864dc7d6a1c4917a97c523274b86e82998d60b63", + "0xc94e45da800d7b56456d55a9aa36ddf9df45e9cfeeacb1116b8c51a0cea34ebd", + "0x81761ec04a8d219aedb2f58aee529e876043b0a476e771957bc03fef9f0780de", + "0x29264094c720151f7448cae053a403aa86fc20649bcf383517e214d1677e893e", + "0x9ac97c7eef9b69dcd73ec7144a0cddfbf0973791beed405202fb4c2d932ec59e", + "0x89611f8e2f9e2e1629f83ec14aaec1656876718c05088e5087887c87b8414c39", + "0x67244fcdba97905472631378fa3a228b649880c2efdd57e5a6c95e9b70ad8456", + "0x0d554cfc4df02560c3e76159d1964c69c39f5df9489bba5516f28a32a4be202e", + "0xce9274a36a0f25a13edef679a5b286bf91a9dc5274354bb6f1ce0ac52557e650", + "0x6017e68689d9f6dca78f42b93a224b445c18b70288a6e4c0d6cc295627dbb1b9", + "0x76791c90f887355878d0a4d8c84ec3990a3159933ecc8d868d196b363153bd5f", + "0xacb6a6c9ec937b3d5cedba26ab6d581fc41cf9a58b0867232e2c8c73d9978cc3", + "0x89f17989ef556a0562c2aa5a2a1d71e5132b89d656bead1ef88ad31073b80cd1", + "0x06efcf8dbadaf28ee719a5b9c017a093fde84a7f4b9966fe3052c0b2fe410ea6", + "0xce16909616f1d97e5853818938b4798030259ddd41e3468f35b940ca901d6817", + "0xd3ff9e9ad14a605a94bdf05dd2639b6fbda28ccf7b2b228f064b0de52410df5b", + "0xb3e8ca9ee88d4c3ce347d82e8f22793ba22b7adc350fd694b1b00b0764c584f9", + "0xe690268a4ec089aced00f9654aa95acb7a8d7270d9428205b103c30a08d142eb", + "0xd685e1460799c51f14273361e31b9739e5212fa538fb8dfbb8e81e8b1d329bbe", + "0x664c293680fb7c5a89ff3c31e81ec8d0c30a6274ef44e4e76bdb9bba83f3c0b3", + "0x44027fd23526685d920d37b032f912159e308286eaac018244006690b4191d4e", + "0x7ea934c3d75a9ecb6a2055dcd5feaf2d4c851eaf360a648d5d87ef40fba2fbd0", + "0xfd97fc801315e5be630ccb3dc983c409a58fc1fc307adc1e4a48fc60c89ea40f", + "0x15aa0c3c732a2c6684d521729dfeb93f62e22e155d85d20e5488e2c86b043142", + "0xba235420ac54100da28cd6f30ff64b8594e73c42f45ca8494fb3d3c4d66651a9", + "0x9948e8489cd94bed4b8e90a8bd35e01ffe38e7c077f587c6c1949caa99cc98e0", + "0xcf66ccdfa85655d7d4c94cffd41f499afdfa2bbddcdaac547223e6ac4d1f9cf1", + "0x7e5382881f710530720b420a3f3ac08211565ecc8fead8ec649cea11f9385c3d", + "0x104576fbb1760c16ce85c3e5757832d53bda83d618500ef677a6a192ff14a5fb", + "0x9e4689bb1ee34635e1106e38ca41833d2dbc1cfacb7635ede5761048a8637c7c", + "0xc8c7f7ac271015da443320f4af650fc71ea0914f4c41252a5b7ec76f329d5268", + "0x46a93ae992001a54119c8d27788e3ef8927dee0a9949b22ece0196a90932c1da", + "0xa69467f9944f1a5e3a46718a99d3cb14930cab6d971baa37bb774cc757e55c2b", + "0x33f7272fdbfb91428a1344df5867300e256fc3cc2e439c777c3feae1cb27b781", + "0x0aaa367f4c7f399edc64ac1754f47aa5c28b0fa208238276de6bd9e424021ce3", + "0xf5f363c3bfa4a23bf221951f4b53a77b27613938babe40f0832d05fdfd252233", + "0xec315af99bdfdcb3cab1f1dcaa5b42ef53f4e3fcf4d921578892a5896fa20e9c", + "0xb580a8e51e875446d7096a20801dded1f7e5b5fac9f47e9361dfc9dd80214013", + "0xb877df38d8f4cebdfb89f26868bdb97ef945da187b44e1cbeafc1d4b7059d713", + "0x78613b9d2d6b639a54ecf1d50a56af80560b436fa632ae636cf354d4a6dd4af8", + "0x80a9d0a5e43558f1d24256baa6940c0074fa84d4b8e7e236054943f9ad5fbe2b", + "0x60f79f699ba1a740c9784f2a8f1b652d4e695ad2d230b110472b95914fd35c8d", + "0xae20de288eb7362a36a1ff236faaed6ddaacf58783d098118bc9fe66b8780651", + "0xcd08003531d6094cabdbe4d971a01b41552784c246bd2a2f749ee9947d1394d6", + "0x676720accf739c380f64748390c1acd2f88d454539866f7326a517c9b629b545", + "0x086b71ac681c0ea369c16b22ca49753b2083ec25b46ba659206433eb060d98c3", + "0x78910ab7d67e67da722ad53b669d8c3a312de3cf362c6254c09581088e920acb", + "0x5bc6e98a830c114cb432091679ac5b3efd25c362d6f99585ce3a027dff95e524", + "0x8d0daff5a97327b615d1535fea44fa33610fd645d93035e1e5e2bb49d4dcef24", + "0xbb46662b884bc6676d98ebf3f2a35ff9190339b72d68520fe40100b4eafaa2a2", + "0x9aa8faaf935c95a60ffae0487844860084a963792ae0bb90a831f825339810ac", + "0xfd77b5d6b6b87bfb0ddcad7b0ed3992e5fe897b16db06b118230b2d292e317e9", + "0xc465a3384c694bc50cbe97ce9f3bc364884651a97a491f7f64e65dc319d1c9f0", + "0xc4634431867d7a302be79e83fb50d01df7f3b950aeede21fcb59b883399b06e4", + "0xfd524c29525cb97a89026ff68048ca6e2a9f522791eadd74447a6c278151d7df", + "0xc7df516c295a58cf4cd5614eee3d2f773a412dcd4926eadad7e935ecae6d8907", + "0xfb915abde0108d6e84354e21a513fa564f5201277e060bb916a9153537fba1f7", + "0x1d3c6a780f1b259e096f4a141ab83cb6bd035407421e2468e743daec211e536f", + "0xb2f47534f060c70f61a7c16f920d0e11b957bb3ef912ed9292f35b8ceda2acea", + "0x03e0ebe6e9992f6921362d463b68f91518d91079c001c6bea7b3452879fdc29c", + "0xd9a7de173a1617ad813a554a56d7c7d2f010ac78d7782e524b35b5c676cb72dc", + "0x90d05d99167e53d34a02c5b66ed6920190370656905465f20efe56499aa0ba6b", + "0x17702606dc895aae35aef034fddf8f7235efcc66e5c9d252347063209c2177b0", + "0x3c416492193d81fc03b5c1964989a314e5ee6d689c638c996f6761b4d7acd6be", + "0x3c6c1162ea9b277f831989ea26e14bb23ce4d72bb9c865e354992559266ceb16", + "0x96de93f849613bb2ffc117bf111d4798b9252649f94f21187da324a3fe363833", + "0x91e50fc6e564cb9d6b7aab3a6e93f6b32944d5a781196a9a8b12ac7f6f527565", + "0xdbefa2bb2ee620d75295d0f3103e06b428f955dba1a792421e435051c46f7933", + "0x78f29df98ef7dce9fe7b4414da90fb4df5d99231ab0a3b7a3e70659986580fe4", + "0x56cf56899c2388d55eb1496ccbe62041d14cf655c9dbc53984d86c22ed281acd", + "0x099f52c675171088550a9e93e1ab17f003190fa3388d956724d422e5925c4813", + "0x9913e4ad8405b8a60fa512fb616c544c6cdc415cb1023aad0669d58cc3810161", + "0xbf5d51369b2510bb57f8fc8e9342890e8bb37049079dc79ab97afc0bcbf3cbf2", + "0x3a012d45d250c818b641fb18b71b622f5bdf0b7a541e0d8de54f61e516ee3ce7", + "0x0233833414d2cff3da0326f7baccf1bd522db5fee290ab4fc0a976934a20358e", + "0x38a0978c955f20cdc32e2013a5373efbfc50924e45e9c4c756291a903f4162b4", + "0x4107f33a14052662a0469ddd646ab6659006df131c4b0f6b0e6cfd331b46fea2", + "0x8074fb5054c755c912bc68b1dc22ae40ba13c06912c8af1c12652eb4d84c6503", + "0xf6d151b8f9c26c3a31366d967dd7338e80e8107b9b81da0a98faf16df9cbc91a", + "0xcebb0256d0a8a4b22d2341ec7c48292c3226caf4aeaa2003ee36dde25cff833b", + "0x5fa9ac499a2642b0cb7ca365062c02588f9c555bcdf584f533ee8e8544b9928d", + "0x800c7f04db30247318b8d4c11d575dca66bf615674fbeb9e8c20f387d907c8e2", + "0xb0a43de06c9d48afefd5411d759e3c6293cbea4a7c6d862b119182ea02af81b7", + "0xb6e7ca0075d28959cf87d716fea885e9e3a0062fc7da1b6e06089c808a632b8a", + "0x734c1b19f0b5972b5215f675cf60c68c12cf6d6bda7b5a95ee9a781482e68365", + "0x1995b08fffb20dedbef592ac23a81d87129ceb396e065265dd4a6cb876beaf09", + "0x051082047a6b579684b5444ce5b75bc630277ec06b0087779387b9d7fcd18fec", + "0x4aabfe145c368e6878e2ccbdfbecf2f1db5c9078650696bb3a584c14fe17177f", + "0x42811ab68b304ce30fe896c52b53d861abc3c8b5e4e740fa97b1695db9a6691f", + "0xd90cdb12ad64f86b2aa7afb781c00301f50206b05f1543b111c2b971ed209c94", + "0x385435507c2ef42b5f1760b97497e8a02a4b5ec4926c3cce8569fc0f4be59ce8", + "0x2d7a4908350c9cf022920cc51e0cad9c3c05d1d14a92d72310b52f984c857101", + "0xceea9c58106f4f806a256f64dc04e1c4b53e6cc5eb048f3df7a14f8de3506e96", + "0x7032f864eb3eae8d198c3f8edd9cc2dfe88b9971cd01b33318dcba004f9b044b", + "0x71bfeb4c183b20fba60e225524c809b0864fa14f5c0137accc36649ed0712e5c", + "0xef0ec5a2761c46827110c20e14fc4aecadc2407541ea046de09a58cda3b2e839", + "0x5e6debf328055c9413fc3eeca28583f917b361a5b5bda9af4306929931a4116a", + "0x1aab81df07eab969189333e5b2930fcc1b88a525ec5bc6af6626fdcb202b8f34", + "0xbdbf97e1558711d4872821b9400e03a811c61096bb838d3126b1c2154f8fb776", + "0x7d8aaee482933ffaa97777af3e4bf69ce7d99afb24e546d2e365d445d3d0190d", + "0x9da421621b14164582b2b877090c9a956f3a7c917031bf743a9ce457b6292369", + "0x050d717f0433a72b17a0e9a1340f26aed5bf17f90c08a5b73e675860ac9c24de", + "0x80551d3ff835aaf987b9ec056a73a3890985ef551431daa9d4aca10c81cac7fd", + "0x625a5b5aed2660d32d2fd8c4d1bfc248365a5cddaf9b5695e3f131629739ec60", + "0x7d86bc2dc5914d16b3d0d882a5db0230b4b688cbd8c81098d2efc5080e589646", + "0xfe42cd832cdffe56426031ba7d837c56d86be72b89ca9f5474bd08db80cfe903", + "0x0ca30e1fd3bf3e16a0e295ecbb442757248b2ad47baf88fc37d6c55901e709f6", + "0x2a83ed111b99844e17fb7aa69854525958255ffea04e0bfdc365264e72b349db", + "0x709779de19590b69864f5b9228b3a1c334724e20be006ef5ae38f8c05eb6f37e", + "0xf09c664d0e2e88ad5418d14481fefdc9e9c46158bc5439ffe0bf6d6d5ecb2eda", + "0xf350785dd3617ef73b0a5bf439ce5c49adca0c041b6b5047a664e5e33967ddf7", + "0x8fcf87571154dc4eb0a73c6ee31cc0db5f4e064cf23a255a408b2f2c7cc9c0e9", + "0x75801fc8867ce7c75b3148c6c022d7702143b93d93c1fc2349e3e969d0179cae", + "0xf14c18bf68ae881d3fb07f631340b00557a83860d0ba0efbfe55fe199176aff6", + "0xbe48c727fb6a32242229eaa09146c76522dcf6bed6d1c6fc1bebf86b5e4ccdb4", + "0x8487b971e383272df82cd812a0bf3a2026b85bc3897b4ce9ce48afa00849fe00", + "0x60d18b465172f59c0d71594b5273a90cb41db24a5d4c9fc37020f9d8c467a4a2", + "0xab4e36d9f17c748c87d89c23b667e3f4e3265e77b62dbd9c92659026f8a53d12" ] }, "accounts": { diff --git a/ethcore/res/ethereum/ropsten.json b/ethcore/res/ethereum/ropsten.json index 82709320b3d..cf418af19dc 100644 --- a/ethcore/res/ethereum/ropsten.json +++ b/ethcore/res/ethereum/ropsten.json @@ -58,8 +58,8 @@ "gasLimit": "0x1000000" }, "hardcodedSync":{ - "header": "f9020fa0a415a8dcd55fe9c93372da415ff6897036e48cd3c1a5ff8ffe119eea1096ecd6a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479443d58f2096e015db88e44346e73d8c59cb1753bda0100f05d66d36782b7c061c724d8d07619cc61053eda41badc8d2cb9292898ebaa00a60317b490365f40f0528e1f559b0f49facb6638c82a9490d368e963647c704a0118b536c3bdabf90273d527dfc26914c7878176fff16cee8fbb150e00ffcdd29b9010000000000000000040000002040000000000000000000000000000000000000000040020000000000010800000000000010000000000200000800000000600400000000080100c000004002080000000045000000008000080000000020000200404010010200010004000000000008020000008000000000000000108010440000800080000400010000080010820008000410800000100000000000000000000240244000000010000000000010010000000000002000000000000000000004000000020000001000002000000000000000013000000100000800008000200000104000000000000080000080200402010000000000000000001020000008008501602a8414833bc8018347b7a983476d40845b838083904d696e656420627920416e74506f6f6ca0f540bc9cfa258b97576bfb9a79518b2c07ed73a98bc6baa61cf7af4b40ad5b6988965658a406315a8a", - "totalDifficulty": "9811143388018700", + "header": "f90217a00f0e017311206b97b47403eba05a16ada760a691a36f844ab8bc9082a4efedc9a067baeee20ae4f4216ab4b0c41198efd376aca23e44b1d6575c5949955547b72a946a9ecfa04e99726ec105517ac7ae1aba550bea6ca0e64d4fe9bee34d98e127f7f94f17535582d5bc6eeb6219f323b046b9a98c72b5a02d33ce5daab0436707c6d958dcf0bcd311ec7a72d7b33c20784178d5d95bc6e9a0a5b9cd4802fafaa9381ec0aa745cdb7ac953675e9df89474e5fe14fee134cf87b90100000008018000100000000000800000010000000050004000800000800014200010000001000000000001009001000000000000000000000000000000006004020600000000200001000108088002260441000020204000000000000000000280000000000200010001000000041008002000000004004c000000001000000000008000000000000800000400000201000000044001145000000000000001000a0200c04000a00010080100000020000000400002040000000000040000000040200001020000401000000800080080000400010000000200000008020020200000101000000000100400000000004400010020000200000000000001000000008453461c8683402001837a1200832c5216845bbd359199d88301080f846765746888676f312e31302e31856c696e7578a0c1da176f6642888b4369e14349ca7dc125ef7d4f5f7abad61bd7f6b95bfd46bf887d1a171a9f55dd67", + "totalDifficulty": "12027449412394243", "CHTs": [ "0x614648fc0a459451850bdfe353a932b5ff824e1b568478394f78b3ed5427e37a", "0x1eae561c582dbb7f4e041998e084e165d0332c915d3a6da367638a8d24f3fafc", @@ -1973,7 +1973,146 @@ "0xb652952de1bf9e1174e5f6a37b069b437792672a37a9e0159c4f36b6e64306b4", "0xb72dd6cb5df1b00dbbd84e097e2da79af2ce60559697ab4c93b0a8b85b2ee406", "0xb96fd4a94ac30c10f757691f7f06f25a4900fe424f4eb7ccf322e2f95249b914", - "0x99fd442599036f161ccef1ae8088c5ef694c1819f5b76d9d2fa8f979935f69f8" + "0x99fd442599036f161ccef1ae8088c5ef694c1819f5b76d9d2fa8f979935f69f8", + "0x3e53574f6ae31a45ef928f9c37bea6c61e6d728a5ade9851567d3167f5ca3314", + "0xd7e3d08c5b71a7ad8338e8b51ec54cb11ad4d643d129a371af07376f8c47c1d4", + "0x1033c8aed4ec46377f75cc9a6b3297e1da0a7d1e74df20bae9fdf6d037afdc28", + "0x924d621544f3301f9e212fbb95872fce9eb4a4172a11693674de733bfc2b0018", + "0x7f61884149ea4def1444a70c022da1c23f31ecc51bb175905b492236a57c7fde", + "0x40c50785bc0665ab4eb3cec95405e17510c571570a5859ead804530dbcbd1387", + "0xf806491cf778f4796c0f73428e6eaf237da8488af99e9b61d72c56fa03e7051c", + "0x7a9670842dcb12c66f11e357a84849cee227ea5a7351e7c6c9370e9ef2560129", + "0x1c974da4e1073157c10deac8b256c8ced77a030e0500b2b8a90b6ca1d32ab4fa", + "0x97ebcc81ba9c1e04865ee4617daa967dec39f65501be21fbbe929db869d57dd8", + "0xa36e4506065d8b9c662697b18ffe50ed2f6ccfe6d07a065bdad048778cc53668", + "0xb9d5566eb0d40bbb03114d333d1d1dc85b0e780ec63229f3b93b2c84af5f9509", + "0xcd16693573724880c3c83834d516be65c35a861b76b43878e28aa7fcbc961361", + "0x4f60ecd7811acc087fc4557fdfaa1a0b522fe30da1cbae5e7740eec3cff04c00", + "0x9e58573b152bf5008e0ea3fc0d64573211916521a62fb08ba0f1b44c5da12e7d", + "0x2c6693cfd7e5bf9a3d8cef9e186b3da25d07af983564ced6238f9191b020f105", + "0x8cc6149caeafef85ec7b2456f33530459c52b30a5365a2a0022b1c308357f7b4", + "0x6f66863bd9909f687523128569cd0894c4cf41e2eddd5cd9c20d30c446b1711b", + "0x402317752053e7b6d7e2d5512d6397112d80ace0873f5f9d32c023a402ec03b3", + "0x2fcd50a79495057908bd34875e3531e6298488f0d06d043fb6fb0b140895d379", + "0x533ba9669dcee2c6e35713c7eca3bca168a326a36b0e39fcde76cbd35ab3d99d", + "0xdc2e86503e8066bc5fac91fe63544e33568a3c744967b9360458101c3d9df096", + "0xf994b38ba312d8bfb00d428b13a088738d93965b525eae81b45b9be344f99fd2", + "0x0721f3f772958d6a58dba638453b8d004e0c76dc8b4cf6d595b712edddcf002f", + "0x3c650c2c7ebbe7879a15882c3157552e8ae1adebea8f0c65a2dda272cc4ed838", + "0x649fe38e87546703245a7adf5925e8c7a07942750e14d39553a56ca3fcbd8c65", + "0xad204bf42d2a444faa864df8e9d023483a6b6daaa8001e00bb5373a45ed064a3", + "0x2c5cdc73d8ddef2e5c0d47358ac180043e7e246e590a7e8ad2b0a3f9b4e9375d", + "0xf38f6c364bbbbe626e849ca9bb9324c54cf0ba8dfc0b2741a3ff87ce7734adbc", + "0x317efc1cea774849d6219d31c8464a15956da4f3810bf15d4353443f79d98e75", + "0xb6796dccdf4d3cab16b5ec9567237cb988ee94131f3262c2a581180b775e76de", + "0x1fde3fdf2303d080d400c43345a424f50f6551a6a06ad50c6e277d49e8034df3", + "0x4d7bc44a3b56f5e69fd3e5e8c0cd8f5f839a775c4ee381b4b1d0a36656cf91cc", + "0x6051b60fdced0c51aa6a1cab2418c8f21c5d174109d514a4c6de758b2056611b", + "0x3c2f7be830078af3c2c6d1557b3da74d1d5bbfd8094f98886a959aa71ce70b15", + "0x8f296b90a0ece0a3dbec19a801072497c5840f9c0491062cd402db00c2b69f2a", + "0x6c14c4697f8291dbdfdbfea5522798e3f8b17204f80d8370e6d379e6ee659e77", + "0x4e98f63afaa50f8a30b0d352eb5fcb5403c635cf54b41545aa8b48465d23fb1d", + "0xad3059433e981ff12cd0d7dbc11a8d92a65cb39c6e936e9c7db5934d45806492", + "0x1cbb21f28ad2d191d6850c97487e5a733306f2f6ba370723fd5ed37cf6c880a0", + "0x82a0010a1b20d383bff0e5d7ba3751bc0d9161a4817554432558c5c2825babb3", + "0x33e54e93443e87c003d582dc51d0b9981ddcaeac4df0993877739651cbf52a58", + "0x1de8bc150f4142cd45b5d0784e5952abd8de7cba9654af959498c0fd0bcac404", + "0x3ee852f48a1a930d671e53c9c8d8c3c38353ee1737c093960c3f841e6c682e94", + "0xa9c6e05ec91e2a2f2f003419063fe033e37e5353c6e233706e29c08693e35eb8", + "0x649f7328064c55c03249d527dadaedcdbb4cb0e939d94c866844192d99469e05", + "0x3a407d00efcd5fe7bb765347b1a3f231b744349269b3aeb44099f4bdd068eb9e", + "0xa1a20af2f7e61082810ce7e7afe6118bc0ad95e9641e6129027f46af28048107", + "0x0d68fc5e58cacb2d16d99a0e9e612d674754ea51cbee2c68a21f4b0aa926688c", + "0x9b3e58144c014343271c9dc90daa8d2f642954b3eda223d64bbb0ac41380e512", + "0xd3de08b676d4f06bbf4322ed4340caab76e6ab7144c97af91c2bc9c749e65b38", + "0x21d626c9c38087aac6262b64f09398be6e4cbf246100d8c2416cab57e9ac1b68", + "0x563a450e35f40279f5946641a823f596ef3ad22a45b8ec280128546aeb0faf14", + "0xadd9c7128e14e670c7d21d6dfa5c09a11dfd237e90709b087e3329d3cd89b5fd", + "0x258cc0f845d8e7438a707f590f55203c6c51302cef4cfbf788b1c7054688da14", + "0x4309676aa14fa8244e0a089c7013b89c9adf57fa952295b8ddb23fc6545c9870", + "0x5db769765dfb41aefc0f40f06f3d005b30ce1f14f04f653e0c5500f651cd61cb", + "0xbef131c9f19572b05d295d7122fd1a09fe4a8afd4e20c5a0f3cd2785b7eb9882", + "0x3f235228ea537332a041ec75cc6cb5663edaa1c2ed1c1700273af73a5d49bf1c", + "0xc081811bb077c6ebe224b560eb6b81f3f813b26789cb06d96110071ffc25fcb4", + "0x912444c19a5e458b79c89969ed5336f2873267baf2fe729b6f218b74d269b797", + "0x5846fc726eb9627e9d070041b92d76191c4b32e315d33ad18121b8acd01634fd", + "0xc899f45494660034d343670856c13a32b230d047434a4d54a772132ddfe3e182", + "0x11a699c18b04e8cdcd96a43b7465f7bd81f8f64d7ebe79dcaf9201cc897f2746", + "0x8e09b134dc8a1735c060175e9688fd001974bf2e3baa5a8e88dc4c87365e0e07", + "0xa086797ebca0a1d446a9289b7eda920b926e1b595c288a9dea31ad225e6de86f", + "0x0cc04369b6036dff78a9856a5173bb2dde380359a8dbe0126e06d6e763a01c36", + "0x4b5efcac86e03d1f67774769b8bcc5d131c181cd4fa297eaa6cea5ec0cdfaa6f", + "0x47272a21a07ad5e14e3f97b237dab7e33344da4db5b2d31bc7cd0cc2d2c9f1db", + "0x9540755fd321d125b73cb6f1884c2f0b2a821d29362194f5029a5e7ba2d3ed44", + "0x229b88922fe52a78090673775f264cd665fe222002d6add2ed29b7ffd98de717", + "0x8fa2d755d5cc0efb01d9fd6f5ae1f7864404ae111d8ba17e23686ea9b6566336", + "0x33a8f2e0775fd19b1302b985bd6c29d4ab5fc63060bcf3df2c3685ab1b19ce67", + "0xf6d6bebb541ef9b84d779c62adb76774bb38a8eba3823e74e0790dc7401bebbc", + "0xa1f421108d49ed23996e55012613fc05e0f86e00f17251b1ff1e0824d35befc7", + "0x2cc572ed83dc6c604bb455ab050c550184a923f4b13815f06d10ef19dffb3c7a", + "0x28220e7d1a9583d68656f03ef4d6fa3e249c71d1b42698f87ba1fc582493e194", + "0xe8aa37b3214abb1bc167fdb6f10119a4019541f31c76b3b3f8c363bb138bd09e", + "0x825189c2c836dda454b457a03ff83d422bf78df1f368434768690fa7f51c57e0", + "0x5dad65d275e69478c81ecaec5b872660205735d9649ac020f65f5ea6ae972dda", + "0x84a1184d8f94fab280e0593479179348f9184d6fe5a2b2ea9697894c42574473", + "0xbef5a05bc7e1fb94465570144499672d95f31fa241b4c510011f6677e2bf72fb", + "0xd08235ebe6d79a8549bcd3d2414cd8afd2a3e2ca22ced226c60aacad1361ff89", + "0xbab5204ad45ec52860023e7474579e7c95397f3c4ac01db7e446e92c19dceef0", + "0x6c81acf2ff161d423a904c457166ff454ef41571d01e73d56bf9ab892790248d", + "0xaf4a603b808e3ddece42e3e123ea02defb9f8ef2546a95c5a617b6ecdb89c306", + "0xeecdbda25b04eb764e322d9a1e5eefad399c9ced8c77b1e4ecfbefcc90bb403d", + "0x9463f4677a2039ca372b61b16d5bcb7c043b26af04aea4d3f0dcdec7bd222070", + "0x27bfd92799b4cf9699d2bfcb158f6727bb986fc0dee780fc1052366ebc4e6364", + "0x63c3faa1a8fc0d531261cd241b1299d4fc13629abb4cd357eeb130505fbddf94", + "0x9a4535b07ff68862f3396b14b88fa07cff7abdd5744775aeeec6868606eb4712", + "0xae59e7c3e0a1df32f6e027da2983d3c55b4ba4d99e85329361561bd7f13ac629", + "0xcc5dc26b9be8fd8432537d967afe12fc668949e4fcf72d97a40f9214975fa57a", + "0x8f11634c83c7a43be8b98335ba617a64c6379f5f92664055c5e1620791134ddb", + "0x14ce2a69d844e6a46aa244c5aca9fb74c127f2151c7c16f4611ca030df365d8b", + "0xb06f220566a5e62570b9e9e49a8b9d5663501ba145b12260fbf9d4a18a4b19e3", + "0x6274f3cf553c45e6ba7ef644d75bf208e08a8c6325e336aefd35dda9cca3c4d2", + "0xd0d685497c2f2b923d0b9f1590a748da8c684a915a470db58c3105c83d8304e7", + "0xf37fab515f96e655f182f0b6e6aa3602f2cd74773329094772151e8c33d1f9a4", + "0xf6efd731481e8553f1d18b5735166499e787009b484b0dfbe4d35e7930f0d837", + "0xc96132b510863e553e08c54e98b5e9c0067f26e421980a6a3bfd4f07480c4396", + "0xdca9d8182c573871b6d6a184cb9819256398080bcb7fd765e6c69cd972a28d8d", + "0xd632ca6f5d45646726ecd2977ffea5c71a867890633f571b359657c0d096f840", + "0xfe3884dbca6bd3b0087466b04e6a5857ad59d7a25021e1d994d059d20005185b", + "0x7f40eb6fb94b05bb43873a98e9d4eb5f7ac90fb8913240bc0909c6be42922b30", + "0x5113a0808666815cfc52b8ed63c649d96f35c365def36ae623f536241b163c3f", + "0x8e6dbacfb5c593d7d7c2650d3d0115c3702cbb55f73011823a202e69ca33cc70", + "0x8f069ac7caa48bce09fe93f4aaef6784d8a6f7a3a09edb82c7512ec18acc3ab9", + "0xa5525e51fd789c59d3b208efffe09abca47cfd6981d36ab44084b86706c69888", + "0xcb4a7e60d5e8b9d22887ef1e8ce339cfcea0ae1fcbfa9adb766ad05d84182de7", + "0x0a14f23f9066ebdb67df31e66f6b8ab1c089025c0ba56ea56d15f73749f47cb7", + "0x0963e3eba12e41d21af7625b8dc487b637b1789a6ac05fb23062e0166942df68", + "0xcb7ec271b2f42cae0027d22b688b19b9288f2b5d9c43bc5b1ea23b35f5542828", + "0x9b97e6f4b2eeee29ecccf9584dc020c8caa3cae51c82f5b58d279eaf0c6ab4e3", + "0xad7f1963ce9993e6172c2ae90c6e1d4d3d3c52e14284fcc1b1e9a56776afb97e", + "0x52ef2ad7bc2921742dcbac9772f13d5c31be938eb1ad6aceb2fa8a163389cefa", + "0x369ead6d900e64ae0b5028df8574e59b67c61dca418c87ce6461eb4c8535fd30", + "0x7e1a18f6199f05f21f9eb5463e9ffd87637d2fd24a23047fe095895c533cb6a5", + "0xe1b8813a95e511aaec9b358d515e624fbc20e551c56328f843ae90b3c895d3a2", + "0xc2ea59f3d1e7bbe115390a4c210142fe9f9dcb1959764450f5b5292ad90e0fcf", + "0x97d235c3f18e6819c08dab4efe66d0f11f0d06f8ffc9686e3f28400e057e6f4a", + "0xea64f817770252b77b08ca2f579b440ec02e833fc88af7c9c96a8e1e07b2cb2c", + "0x185f5fd1f7001b533dc01783c83b7ab0828a4e2f188cc4e26768c515b4c421f6", + "0x0c9de9844e856a1e4340bf54dcaf9dc66b489304765b5c3c6ca20284f5a0dca6", + "0x4dd1d52da1d260d1f0f63bafc4c816b30cea8ec3434e7d4b63a0eff86997254c", + "0x0b3eb94aa246f7c8c871535ae2d3abe5c1b951e76b77510140ef52d5ea2457ee", + "0x27102708eea5d715799642f213049d8ac9abc3b12c76d147ce443dab28af96d8", + "0x81fb3c4e8dc6c658af2901b7aebf7467b9ae045dd0f58fe8d77f8770ac517fb6", + "0xf68dba4eee635d7494bae6fb9f0c44e739b3121d4bc6f6f21b495a716af3cf52", + "0xcf87b723dc473d313bf9ddfa233056036c5658777e831796f1f56647cd040c8d", + "0x49927c2100039ac496d9c16dd12f0a05c9441b8616c69c726fd2e79ae65e130c", + "0x088195c7251f6b9fa2105e77df5620211b8ca783a77f1a98de6752fc442c26c7", + "0x604de480bcb88e908b90451c4142b99b9cbb479167473befca7bea9b4ca427a3", + "0x642fdaf6bc1abbf261a9480fcf9bb48cf03fb80bdd434c6ab63401856c74fa39", + "0xe6b596393fce7a3023a316ac34a1fac18e18779ca5983791866f857f257592e1", + "0x40384a52564fae5df8c3e41827cdf584e38f3f555a54ca749b7b516619071d85", + "0xe52f7c17a4106594563ae7b724e5613e87d8442177f39a36b946b0e335be0e5b", + "0x7726202a7c255a9d7be47af6f3b44c1e379cda61237866554396fb6ec043482c", + "0x665da353f296cde80e3cbcb9c7f93b107d5676e5cd694b0bd33334d74789beb9" ] }, "nodes": [ From 07ccad5ba5b71dd677adf1f5e5afcf1805dbc658 Mon Sep 17 00:00:00 2001 From: gabriel klawitter Date: Wed, 10 Oct 2018 14:51:36 +0200 Subject: [PATCH 18/19] gitlab ci: releasable_branches: change variables condition to schedule (#9729) --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f80245bb0b0..625b5367554 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -24,6 +24,7 @@ cache: - stable - beta - tags + - schedules .collect_artifacts: &collect_artifacts artifacts: From 2b3d34fb7341334e445d9ff856ca35fbc097be2b Mon Sep 17 00:00:00 2001 From: Vadim Arasev <33550681+varasev@users.noreply.github.com> Date: Tue, 9 Oct 2018 18:17:39 +0300 Subject: [PATCH 19/19] HF in POA Core (2018-10-22) (#9724) https://github.com/poanetwork/poa-chain-spec/pull/87 --- ethcore/res/ethereum/poacore.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ethcore/res/ethereum/poacore.json b/ethcore/res/ethereum/poacore.json index b80b3a113fd..115108f27bb 100644 --- a/ethcore/res/ethereum/poacore.json +++ b/ethcore/res/ethereum/poacore.json @@ -15,9 +15,14 @@ }, "772000": { "safeContract": "0x83451c8bc04d4ee9745ccc58edfab88037bc48cc" + }, + "5329160": { + "safeContract": "0xa105Db0e6671C7B5f4f350ff1Af6460E6C696e71" } } - } + }, + "blockRewardContractAddress": "0x4d0153D434384128D17243409e02fca1B3EE21D6", + "blockRewardContractTransition": 5761140 } } },