* EIP-86

* Disable EIP-86 auto activation for now
This commit is contained in:
Arkadiy Paronyan
2017-04-19 14:30:00 +02:00
committed by GitHub
parent 0180b21dd1
commit b50fb71dd1
59 changed files with 433 additions and 289 deletions

View File

@@ -41,6 +41,17 @@ pub enum MessageCallResult {
Failed
}
/// 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)
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.
FromSenderAndCodeHash,
}
/// Externalities interface for EVMs
// TODO: [rob] associated error type instead of `trie::Result`. Not all EVMs are trie powered.
pub trait Ext {
@@ -68,7 +79,7 @@ pub trait Ext {
/// Creates new contract.
///
/// Returns gas_left and contract address if contract creation was succesfull.
fn create(&mut self, gas: &U256, value: &U256, code: &[u8]) -> ContractCreateResult;
fn create(&mut self, gas: &U256, value: &U256, code: &[u8], address: CreateContractAddress) -> ContractCreateResult;
/// Message call.
///

View File

@@ -278,6 +278,7 @@ lazy_static! {
arr[RETURN as usize] = InstructionInfo::new("RETURN", 0, 2, 0, true, GasPriceTier::Zero);
arr[DELEGATECALL as usize] = InstructionInfo::new("DELEGATECALL", 0, 6, 1, true, GasPriceTier::Special);
arr[SUICIDE as usize] = InstructionInfo::new("SUICIDE", 0, 1, 0, true, GasPriceTier::Special);
arr[CREATE_P2SH as usize] = InstructionInfo::new("CREATE_P2SH", 0, 3, 1, true, GasPriceTier::Special);
arr
};
}
@@ -553,6 +554,8 @@ pub const CALLCODE: Instruction = 0xf2;
pub const RETURN: Instruction = 0xf3;
/// like CALLCODE but keeps caller's value and sender
pub const DELEGATECALL: Instruction = 0xf4;
/// create a new account and set creation address to sha3(sender + sha3(init code)) % 2**160
pub const CREATE_P2SH: Instruction = 0xfb;
/// halt execution and register account for later deletion
pub const SUICIDE: Instruction = 0xff;

View File

@@ -223,7 +223,7 @@ impl<Gas: CostType> Gasometer<Gas> {
Request::GasMemProvide(gas, mem, Some(requested))
},
instructions::CREATE => {
instructions::CREATE | instructions::CREATE_P2SH => {
let gas = Gas::from(schedule.create_gas);
let mem = mem_needed(stack.peek(1), stack.peek(2))?;

View File

@@ -32,7 +32,7 @@ use std::marker::PhantomData;
use action_params::{ActionParams, ActionValue};
use types::executed::CallType;
use evm::instructions::{self, Instruction, InstructionInfo};
use evm::{self, MessageCallResult, ContractCreateResult, GasLeft, CostType};
use evm::{self, MessageCallResult, ContractCreateResult, GasLeft, CostType, CreateContractAddress};
use bit_set::BitSet;
use util::*;
@@ -182,7 +182,9 @@ impl<Cost: CostType> Interpreter<Cost> {
fn verify_instruction(&self, ext: &evm::Ext, instruction: Instruction, info: &InstructionInfo, stack: &Stack<U256>) -> evm::Result<()> {
let schedule = ext.schedule();
if !schedule.have_delegate_call && instruction == instructions::DELEGATECALL {
if (instruction == instructions::DELEGATECALL && !schedule.have_delegate_call) ||
(instruction == instructions::CREATE_P2SH && !schedule.have_create_p2sh) {
return Err(evm::Error::BadInstruction {
instruction: instruction
});
@@ -266,10 +268,12 @@ impl<Cost: CostType> Interpreter<Cost> {
instructions::JUMPDEST => {
// ignore
},
instructions::CREATE => {
instructions::CREATE | instructions::CREATE_P2SH => {
let endowment = stack.pop_back();
let init_off = stack.pop_back();
let init_size = stack.pop_back();
let address_scheme = if instruction == instructions::CREATE { ext.schedule().create_address } else { CreateContractAddress::FromSenderAndCodeHash };
let create_gas = provided.expect("`provided` comes through Self::exec from `Gasometer::get_gas_cost_mem`; `gas_gas_mem_cost` guarantees `Some` when instruction is `CALL`/`CALLCODE`/`DELEGATECALL`/`CREATE`; this is `CREATE`; qed");
let contract_code = self.mem.read_slice(init_off, init_size);
@@ -280,7 +284,7 @@ impl<Cost: CostType> Interpreter<Cost> {
return Ok(InstructionResult::UnusedGas(create_gas));
}
let create_result = ext.create(&create_gas.as_u256(), &endowment, contract_code);
let create_result = ext.create(&create_gas.as_u256(), &endowment, contract_code, address_scheme);
return match create_result {
ContractCreateResult::Created(address, gas_left) => {
stack.push(address_to_u256(address));

View File

@@ -32,7 +32,7 @@ mod tests;
mod benches;
pub use self::evm::{Evm, Error, Finalize, GasLeft, Result, CostType};
pub use self::ext::{Ext, ContractCreateResult, MessageCallResult};
pub use self::ext::{Ext, ContractCreateResult, MessageCallResult, CreateContractAddress};
pub use self::factory::{Factory, VMType};
pub use self::schedule::Schedule;
pub use types::executed::CallType;

View File

@@ -15,6 +15,7 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Cost schedule and other parameterisations for the EVM.
use evm::CreateContractAddress;
/// Definition of the cost schedule and other parameterisations for the EVM.
pub struct Schedule {
@@ -22,6 +23,8 @@ 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
pub have_create_p2sh: bool,
/// VM stack limit
pub stack_limit: usize,
/// Max number of nested calls/creates
@@ -99,6 +102,8 @@ pub struct Schedule {
pub no_empty: bool,
/// Kill empty accounts if touched.
pub kill_empty: bool,
/// Contract address generation scheme
pub create_address: CreateContractAddress,
}
impl Schedule {
@@ -113,10 +118,11 @@ impl Schedule {
}
/// Schedule for the post-EIP-150-era of the Ethereum main net.
pub fn new_post_eip150(max_code_size: usize, fix_exp: bool, no_empty: bool, kill_empty: bool) -> Schedule {
pub fn new_post_eip150(max_code_size: usize, fix_exp: bool, no_empty: bool, kill_empty: bool, have_create_p2sh: bool) -> Schedule {
Schedule {
exceptional_failed_code_deposit: true,
have_delegate_call: true,
have_create_p2sh: have_create_p2sh,
stack_limit: 1024,
max_depth: 1024,
tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0],
@@ -155,13 +161,20 @@ impl Schedule {
sub_gas_cap_divisor: Some(64),
no_empty: no_empty,
kill_empty: kill_empty,
create_address: if have_create_p2sh { CreateContractAddress::FromCodeHash } else { CreateContractAddress::FromSenderAndNonce },
}
}
/// Schedule for the Metropolis of the Ethereum main net.
pub fn new_metropolis() -> Schedule {
Self::new_post_eip150(24576, true, true, true, true)
}
fn new(efcd: bool, hdc: bool, tcg: usize) -> Schedule {
Schedule {
exceptional_failed_code_deposit: efcd,
have_delegate_call: hdc,
have_create_p2sh: false,
stack_limit: 1024,
max_depth: 1024,
tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0],
@@ -200,6 +213,7 @@ impl Schedule {
sub_gas_cap_divisor: None,
no_empty: false,
kill_empty: false,
create_address: CreateContractAddress::FromSenderAndNonce,
}
}
}

View File

@@ -18,7 +18,7 @@ use util::*;
use action_params::{ActionParams, ActionValue};
use env_info::EnvInfo;
use types::executed::CallType;
use evm::{self, Ext, Schedule, Factory, GasLeft, VMType, ContractCreateResult, MessageCallResult};
use evm::{self, Ext, Schedule, Factory, GasLeft, VMType, ContractCreateResult, MessageCallResult, CreateContractAddress};
use std::fmt::Debug;
pub struct FakeLogEntry {
@@ -111,7 +111,7 @@ impl Ext for FakeExt {
self.blockhashes.get(number).unwrap_or(&H256::new()).clone()
}
fn create(&mut self, gas: &U256, value: &U256, code: &[u8]) -> ContractCreateResult {
fn create(&mut self, gas: &U256, value: &U256, code: &[u8], _address: CreateContractAddress) -> ContractCreateResult {
self.calls.insert(FakeCall {
call_type: FakeCallType::Create,
gas: *gas,