Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cherry-pick open-ethereum#9140 #186

Merged
merged 6 commits into from
Mar 10, 2020
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ethcore/evm/src/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ lazy_static! {
arr[DELEGATECALL as usize] = InstructionInfo::new("DELEGATECALL", 6, 1, GasPriceTier::Special);
arr[STATICCALL as usize] = InstructionInfo::new("STATICCALL", 6, 1, GasPriceTier::Special);
arr[SUICIDE as usize] = InstructionInfo::new("SUICIDE", 1, 0, GasPriceTier::Special);
arr[CREATE2 as usize] = InstructionInfo::new("CREATE2", 3, 1, GasPriceTier::Special);
arr[CREATE2 as usize] = InstructionInfo::new("CREATE2", 4, 1, GasPriceTier::Special);
arr[REVERT as usize] = InstructionInfo::new("REVERT", 2, 0, GasPriceTier::Zero);
arr
};
Expand Down
6 changes: 5 additions & 1 deletion ethcore/evm/src/interpreter/gasometer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,11 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
}
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)
}
Expand Down
12 changes: 7 additions & 5 deletions ethcore/evm/src/interpreter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,13 @@ impl<Cost: CostType> Interpreter<Cost> {
}
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();

Expand All @@ -381,11 +388,6 @@ impl<Cost: CostType> Interpreter<Cost> {
}

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(),
Expand Down
10 changes: 6 additions & 4 deletions ethcore/src/executive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,12 @@ pub fn contract_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 => {
Expand Down Expand Up @@ -386,7 +388,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 !t.is_unsigned() {
self.state.inc_nonce(&sender)?;
}
self.state.sub_balance(
Expand Down
84 changes: 83 additions & 1 deletion ethcore/src/externalities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ where
};

if !self.static_flag {
if !self.schedule.eip86 || params.sender != UNSIGNED_SENDER {
if 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;
Expand Down Expand Up @@ -901,4 +901,86 @@ 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 mut ext_tracer = NoopExtTracer;

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,
&mut ext_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 mut ext_tracer = NoopExtTracer;

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,
&mut ext_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()
);
}
}
10 changes: 3 additions & 7 deletions ethcore/src/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use transaction::{self, SignedTransaction, UnverifiedTransaction, SYSTEM_ADDRESS
// use tx_filter::TransactionFilter;

use bytes::BytesRef;
use ethereum_types::{Address, U256};
use ethereum_types::{Address, H256, U256};
use rlp::Rlp;
use vm::{ActionParams, ActionValue, CallType, OasisContract, ParamsType};
use vm::{CreateContractAddress, EnvInfo, Schedule};
Expand Down Expand Up @@ -371,12 +371,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.
Expand Down
18 changes: 2 additions & 16 deletions ethcore/src/spec/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,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.
Expand Down Expand Up @@ -179,7 +177,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 = true;
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;
Expand All @@ -200,16 +198,7 @@ impl CommonParams {

/// Whether these params contain any bug-fix hard forks.
pub fn contains_bugfix_hard_fork(&self) -> bool {
self.eip98_transition != 0
&& self.eip155_transition != 0
&& self.validate_receipts_transition != 0
&& self.eip86_transition != 0
&& self.eip140_transition != 0
&& self.eip210_transition != 0
&& self.eip211_transition != 0
&& self.eip214_transition != 0
&& self.validate_chain_id_transition != 0
&& self.dust_protection_transition != 0
true
}
}

Expand Down Expand Up @@ -239,9 +228,6 @@ impl From<ethjson::spec::Params> 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),
Expand Down
4 changes: 4 additions & 0 deletions ethcore/src/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1602,6 +1602,10 @@ mod tests {
let mut state = get_temp_state();

let mut info = EnvInfo::default();
info.last_hashes = Arc::new(vec![H256::from_str(
"9f1897f227a8a843c0961a5227709fa962dc6860a2129750fdb450f48d7459bb",
)
.unwrap()]);
nhynes marked this conversation as resolved.
Show resolved Hide resolved
info.gas_limit = 1_000_000.into();
let machine = make_frontier_machine(5);

Expand Down
8 changes: 4 additions & 4 deletions ethcore/vm/src/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}

Expand Down
6 changes: 1 addition & 5 deletions ethcore/vm/src/schedule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,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,
Expand Down Expand Up @@ -115,8 +115,6 @@ 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,
/// Wasm extra schedule settings, if wasm activated
pub wasm: Option<WasmCosts>,
/// Default storage duration (in seconds)
Expand Down Expand Up @@ -262,7 +260,6 @@ impl Schedule {
blockhash_gas: 20,
have_static_call: false,
kill_dust: CleanDustMode::Off,
eip86: false,
wasm: None,
default_storage_duration: 3155695200, // 100 years
}
Expand Down Expand Up @@ -334,7 +331,6 @@ impl Schedule {
blockhash_gas: 20,
have_static_call: false,
kill_dust: CleanDustMode::Off,
eip86: false,
wasm: None,
default_storage_duration: 3155695200, // 100 years
}
Expand Down
3 changes: 0 additions & 3 deletions json/src/spec/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,6 @@ pub struct Params {
#[serde(rename = "validateReceiptsTransition")]
pub validate_receipts_transition: Option<Uint>,
/// See `CommonParams` docs.
#[serde(rename = "eip86Transition")]
pub eip86_transition: Option<Uint>,
/// See `CommonParams` docs.
#[serde(rename = "eip140Transition")]
pub eip140_transition: Option<Uint>,
/// See `CommonParams` docs.
Expand Down
Loading