From dabfa2c6634cc70845f6875b86db48a1af74c98c Mon Sep 17 00:00:00 2001 From: David Date: Thu, 29 Aug 2019 13:19:55 +0200 Subject: [PATCH] EIP 1884 Re-pricing of trie-size dependent operations (#10992) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add client-traits crate Move the BlockInfo trait to new crate * New crate `machine` Contains code extracted from ethcore that defines `Machine`, `Externalities` and other execution related code. * Use new machine and client-traits crates in ethcore * Use new crates machine and client-traits instead of ethcore where appropriate * Fix tests * Don't re-export so many types from ethcore::client * Fixing more fallout from removing re-export * fix test * More fallout from not re-exporting types * Add some docs * cleanup * import the macro edition style * Tweak docs * Add missing import * remove unused ethabi_derive imports * Use latest ethabi-contract * Move many traits from ethcore/client/traits to client-traits crate Initial version of extracted Engine trait * Move snapshot related traits to the engine crate (eew) * Move a few snapshot related types to common_types Cleanup Executed as exported from machine crate * fix warning * Gradually introduce new engine crate: snapshot * ethcore typechecks with new engine crate * Sort out types outside ethcore * Add an EpochVerifier to ethash and use that in Engine.epoch_verifier() Cleanup * Document pub members * Sort out tests Sort out default impls for EpochVerifier * Add test-helpers feature and move EngineSigner impl to the right place * Sort out tests * Sort out tests and refactor verification types * Fix missing traits * More missing traits Fix Histogram * Fix tests and cleanup * cleanup * Put back needed logger import * Don't rexport common_types from ethcore/src/client Don't export ethcore::client::* * Remove files no longer used Use types from the engine crate Explicit exports from engine::engine * Get rid of itertools * Move a few more traits from ethcore to client-traits: BlockChainReset, ScheduleInfo, StateClient * Move ProvingBlockChainClient to client-traits * Don't re-export ForkChoice and Transition from ethcore * Address grumbles: sort imports, remove commented out code * Fix merge resolution error * Extract the Clique engine to own crate * Extract NullEngine and the block_reward module from ethcore * Extract InstantSeal engine to own crate * Extract remaining engines * Extract executive_state to own crate so it can be used by engine crates * Remove snapshot stuff from the engine crate * Put snapshot traits back in ethcore * cleanup * Remove stuff from ethcore * Don't use itertools * itertools in aura is legit-ish * More post-merge fixes * Re-export less types in client * cleanup * Extract spec to own crate * Put back the test-helpers from basic-authority * Fix ethcore benchmarks * Reduce the public api of ethcore/verification * WIP * Add Cargo.toml * Fix compilation outside ethcore * Audit uses of import_verified_blocks() and remove unneeded calls Cleanup * cleanup * Remove unused imports from ethcore * Cleanup * remove double semi-colons * Add missing generic param * More missing generics * Update ethcore/block-reward/Cargo.toml Co-Authored-By: Tomasz Drwięga * Update ethcore/engines/basic-authority/Cargo.toml Co-Authored-By: Tomasz Drwięga * Update ethcore/engines/ethash/Cargo.toml Co-Authored-By: Tomasz Drwięga * Update ethcore/engines/clique/src/lib.rs Co-Authored-By: Tomasz Drwięga * signers is already a ref * Add an EngineType enum to tighten up Engine.name() * Add CHAINID opcode * Introduce Snapshotting enum to distinguish the type of snapshots a chain uses * Rename supports_warp to snapshot_mode * Missing import * Add chain_id wherever we instantiate EnvInfo * more missing chain_id * Tell serde to ignore the chain_id field on Env * Update ethcore/src/snapshot/consensus/mod.rs Co-Authored-By: Tomasz Drwięga * Use the chain_id from the machine by adding chain_id() to the Ext trait * cleanup * add missing impl cleanup * missing import * Fix import * Add transition marker for EIP 1344 * double semi * Fix merge problem * cleanup * reprice SLOAD to 800 gas * Reprice BALANCE and EXTCODEHASH * Add SELFBALANCE opcode * Add test for SELFBALANCE Use InstructionParams.address as the self-address * Use easier to read values in test * merge conflict error * Fix a few warnings * Update ethcore/vm/src/schedule.rs Co-Authored-By: Andronik Ordian * more merge fallout --- ethcore/evm/src/evm.rs | 18 ++++++++++++------ ethcore/evm/src/instructions.rs | 3 +++ ethcore/evm/src/interpreter/mod.rs | 15 ++++++++++++--- ethcore/evm/src/tests.rs | 26 ++++++++++++++++++++++++++ ethcore/types/src/engines/params.rs | 13 +++++++++++++ ethcore/vm/src/ext.rs | 2 +- ethcore/vm/src/return_data.rs | 6 +----- ethcore/vm/src/schedule.rs | 17 ++++++++++++++--- json/src/spec/params.rs | 2 ++ 9 files changed, 84 insertions(+), 18 deletions(-) diff --git a/ethcore/evm/src/evm.rs b/ethcore/evm/src/evm.rs index f8a08b2b2..3c88155f2 100644 --- a/ethcore/evm/src/evm.rs +++ b/ethcore/evm/src/evm.rs @@ -44,12 +44,18 @@ pub trait Finalize { impl Finalize for Result { fn finalize(self, ext: E) -> Result { match self { - Ok(GasLeft::Known(gas_left)) => Ok(FinalizationResult { gas_left: gas_left, apply_state: true, return_data: ReturnData::empty() }), - Ok(GasLeft::NeedsReturn { gas_left, data, apply_state }) => ext.ret(&gas_left, &data, apply_state).map(|gas_left| FinalizationResult { - gas_left: gas_left, - apply_state: apply_state, - return_data: data, - }), + Ok(GasLeft::Known(gas_left)) => { + Ok(FinalizationResult { + gas_left, + apply_state: true, + return_data: ReturnData::empty() + }) + }, + Ok(GasLeft::NeedsReturn { gas_left, data, apply_state }) => { + ext.ret(&gas_left, &data, apply_state).map(|gas_left| + FinalizationResult { gas_left, apply_state, return_data: data } + ) + }, Err(err) => Err(err), } } diff --git a/ethcore/evm/src/instructions.rs b/ethcore/evm/src/instructions.rs index 1580f7b59..b0a66c159 100644 --- a/ethcore/evm/src/instructions.rs +++ b/ethcore/evm/src/instructions.rs @@ -151,6 +151,8 @@ enum_with_from_u8! { GASLIMIT = 0x45, #[doc = "get chain ID"] CHAINID = 0x46, + #[doc = "get balance of own account"] + SELFBALANCE = 0x47, #[doc = "remove item from stack"] POP = 0x50, @@ -502,6 +504,7 @@ lazy_static! { arr[DIFFICULTY as usize] = Some(InstructionInfo::new("DIFFICULTY", 0, 1, GasPriceTier::Base)); arr[GASLIMIT as usize] = Some(InstructionInfo::new("GASLIMIT", 0, 1, GasPriceTier::Base)); arr[CHAINID as usize] = Some(InstructionInfo::new("CHAINID", 0, 1, GasPriceTier::Base)); + arr[SELFBALANCE as usize] = Some(InstructionInfo::new("SELFBALANCE", 0, 1, GasPriceTier::Low)); arr[POP as usize] = Some(InstructionInfo::new("POP", 1, 0, GasPriceTier::Base)); arr[MLOAD as usize] = Some(InstructionInfo::new("MLOAD", 1, 1, GasPriceTier::VeryLow)); arr[MSTORE as usize] = Some(InstructionInfo::new("MSTORE", 2, 0, GasPriceTier::VeryLow)); diff --git a/ethcore/evm/src/interpreter/mod.rs b/ethcore/evm/src/interpreter/mod.rs index 855643855..472601395 100644 --- a/ethcore/evm/src/interpreter/mod.rs +++ b/ethcore/evm/src/interpreter/mod.rs @@ -299,7 +299,12 @@ impl Interpreter { let result = if self.gasometer.is_none() { InterpreterResult::Done(Err(vm::Error::OutOfGas)) } else if self.reader.len() == 0 { - InterpreterResult::Done(Ok(GasLeft::Known(self.gasometer.as_ref().expect("Gasometer None case is checked above; qed").current_gas.as_u256()))) + let current_gas = self.gasometer + .as_ref() + .expect("Gasometer None case is checked above; qed") + .current_gas + .as_u256(); + InterpreterResult::Done(Ok(GasLeft::Known(current_gas))) } else { self.step_inner(ext) }; @@ -308,7 +313,7 @@ impl Interpreter { self.done = true; self.informant.done(); } - return result; + result } /// Inner helper function for step. @@ -429,7 +434,8 @@ impl Interpreter { (instruction == instructions::REVERT && !schedule.have_revert) || ((instruction == instructions::SHL || instruction == instructions::SHR || instruction == instructions::SAR) && !schedule.have_bitwise_shifting) || (instruction == instructions::EXTCODEHASH && !schedule.have_extcodehash) || - (instruction == instructions::CHAINID && !schedule.have_chain_id) + (instruction == instructions::CHAINID && !schedule.have_chain_id) || + (instruction == instructions::SELFBALANCE && !schedule.have_selfbalance) { return Err(vm::Error::BadInstruction { instruction: instruction as u8 @@ -847,6 +853,9 @@ impl Interpreter { instructions::CHAINID => { self.stack.push(ext.chain_id().into()) }, + instructions::SELFBALANCE => { + self.stack.push(ext.balance(&self.params.address)?); + } // Stack instructions diff --git a/ethcore/evm/src/tests.rs b/ethcore/evm/src/tests.rs index 05a39e1b5..d226b7c1a 100644 --- a/ethcore/evm/src/tests.rs +++ b/ethcore/evm/src/tests.rs @@ -124,6 +124,32 @@ fn test_origin(factory: super::Factory) { assert_store(&ext, 0, "000000000000000000000000cd1722f2947def4cf144679da39c4c32bdc35681"); } +evm_test!{test_selfbalance: test_selfbalance_int} +fn test_selfbalance(factory: super::Factory) { + let own_addr = Address::from_str("1337000000000000000000000000000000000000").unwrap(); + // 47 SELFBALANCE + // 60 ff PUSH ff + // 55 SSTORE + let code = hex!("47 60 ff 55").to_vec(); + + let mut params = ActionParams::default(); + params.address = own_addr.clone(); + params.gas = U256::from(100_000); + params.code = Some(Arc::new(code)); + let mut ext = FakeExt::new_istanbul(); + ext.balances = { + let mut x = HashMap::new(); + x.insert(own_addr, U256::from(1_025)); // 0x401 + x + }; + let gas_left = { + let vm = factory.create(params, ext.schedule(), ext.depth()); + test_finalize(vm.exec(&mut ext).ok().unwrap()).unwrap() + }; + assert_eq!(gas_left, U256::from(79_992)); // TODO[dvdplm]: do the sums here, SELFBALANCE-5 + PUSH1-3 + ONEBYTE-4 + SSTORE-?? = 100_000 - 79_992 + assert_store(&ext, 0xff, "0000000000000000000000000000000000000000000000000000000000000401"); +} + evm_test!{test_sender: test_sender_int} fn test_sender(factory: super::Factory) { let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); diff --git a/ethcore/types/src/engines/params.rs b/ethcore/types/src/engines/params.rs index fc8eb9667..7176093f3 100644 --- a/ethcore/types/src/engines/params.rs +++ b/ethcore/types/src/engines/params.rs @@ -92,6 +92,8 @@ pub struct CommonParams { pub eip1014_transition: BlockNumber, /// Number of first block where EIP-1344 rules begin: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1344.md pub eip1344_transition: BlockNumber, + /// Number of first block where EIP-1884 rules begin:https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1884.md + pub eip1884_transition: BlockNumber, /// Number of first block where EIP-2028 rules begin. pub eip2028_transition: BlockNumber, /// Number of first block where dust cleanup rules (EIP-168 and EIP169) begin. @@ -165,6 +167,13 @@ impl CommonParams { schedule.have_extcodehash = block_number >= self.eip1052_transition; schedule.have_chain_id = block_number >= self.eip1344_transition; schedule.eip1283 = block_number >= self.eip1283_transition && !(block_number >= self.eip1283_disable_transition); + + if block_number >= self.eip1884_transition { + schedule.have_selfbalance = true; + schedule.sload_gas = 800; + schedule.balance_gas = 700; + schedule.extcodehash_gas = 700; + } if block_number >= self.eip2028_transition { schedule.tx_data_non_zero_gas = 16; } @@ -289,6 +298,10 @@ impl From for CommonParams { BlockNumber::max_value, Into::into, ), + eip1884_transition: p.eip1884_transition.map_or_else( + BlockNumber::max_value, + Into::into, + ), eip2028_transition: p.eip2028_transition.map_or_else( BlockNumber::max_value, Into::into, diff --git a/ethcore/vm/src/ext.rs b/ethcore/vm/src/ext.rs index 63d9595fb..68e5822e4 100644 --- a/ethcore/vm/src/ext.rs +++ b/ethcore/vm/src/ext.rs @@ -91,7 +91,7 @@ pub trait Ext { /// Creates new contract. /// - /// Returns gas_left and contract address if contract creation was succesfull. + /// Returns gas_left and contract address if contract creation was successful. fn create( &mut self, gas: &U256, diff --git a/ethcore/vm/src/return_data.rs b/ethcore/vm/src/return_data.rs index 85fdb361d..38ac23ffd 100644 --- a/ethcore/vm/src/return_data.rs +++ b/ethcore/vm/src/return_data.rs @@ -44,11 +44,7 @@ impl ReturnData { } /// Create `ReturnData` from give buffer and slice. pub fn new(mem: Vec, offset: usize, size: usize) -> Self { - ReturnData { - mem: mem, - offset: offset, - size: size, - } + ReturnData { mem, offset, size } } } diff --git a/ethcore/vm/src/schedule.rs b/ethcore/vm/src/schedule.rs index e11603ecd..877ef145b 100644 --- a/ethcore/vm/src/schedule.rs +++ b/ethcore/vm/src/schedule.rs @@ -19,11 +19,13 @@ use std::collections::HashMap; use ethereum_types::U256; /// Definition of schedules that can be applied to a version. +#[derive(Debug)] pub enum VersionedSchedule { PWasm, } /// Definition of the cost schedule and other parameterisations for the EVM. +#[derive(Debug)] pub struct Schedule { /// Does it support exceptional failed code deposit pub exceptional_failed_code_deposit: bool, @@ -124,6 +126,8 @@ pub struct Schedule { pub have_bitwise_shifting: bool, /// CHAINID opcode enabled. pub have_chain_id: bool, + /// SELFBALANCE opcode enabled. + pub have_selfbalance: bool, /// Kill basic accounts below this balance if touched. pub kill_dust: CleanDustMode, /// Enable EIP-1283 rules @@ -139,6 +143,7 @@ pub struct Schedule { } /// Wasm cost table +#[derive(Debug)] pub struct WasmCosts { /// Default opcode cost pub regular: u32, @@ -192,7 +197,7 @@ impl Default for WasmCosts { } /// Dust accounts cleanup mode. -#[derive(PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq)] pub enum CleanDustMode { /// Dust cleanup is disabled. Off, @@ -223,6 +228,7 @@ impl Schedule { have_return_data: false, have_bitwise_shifting: false, have_chain_id: false, + have_selfbalance: false, have_extcodehash: false, stack_limit: 1024, max_depth: 1024, @@ -294,8 +300,12 @@ impl Schedule { /// Schedule for the Istanbul fork of the Ethereum main net. pub fn new_istanbul() -> Schedule { let mut schedule = Self::new_constantinople(); - schedule.have_chain_id = true; - schedule.tx_data_non_zero_gas = 16; + schedule.have_chain_id = true; // EIP 1344 + schedule.tx_data_non_zero_gas = 16; // EIP 2028 + schedule.sload_gas = 800; // EIP 1884 + schedule.balance_gas = 700; // EIP 1884 + schedule.extcodehash_gas = 700; // EIP 1884 + schedule.have_selfbalance = true; // EIP 1884 schedule } @@ -308,6 +318,7 @@ impl Schedule { have_return_data: false, have_bitwise_shifting: false, have_chain_id: false, + have_selfbalance: false, have_extcodehash: false, stack_limit: 1024, max_depth: 1024, diff --git a/json/src/spec/params.rs b/json/src/spec/params.rs index 29c842b87..7b1cd1c18 100644 --- a/json/src/spec/params.rs +++ b/json/src/spec/params.rs @@ -96,6 +96,8 @@ pub struct Params { /// See `CommonParams` docs. pub eip1344_transition: Option, /// See `CommonParams` docs. + pub eip1884_transition: Option, + /// See `CommonParams` docs. pub eip2028_transition: Option, /// See `CommonParams` docs. pub dust_protection_transition: Option,