Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Comply EIP-86 with the new definition #9140

Merged
merged 9 commits into from
Aug 1, 2018
Merged
Show file tree
Hide file tree
Changes from all 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 @@ -591,7 +591,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
};
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 @@ -225,7 +225,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
6 changes: 5 additions & 1 deletion ethcore/evm/src/interpreter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,11 @@ 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 @@ -335,7 +340,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(), &endowment, contract_code, address_scheme);
return match create_result {
Expand Down
8 changes: 5 additions & 3 deletions ethcore/src/executive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 => {
Expand Down
40 changes: 40 additions & 0 deletions ethcore/src/externalities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -570,4 +570,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());
}
}
8 changes: 2 additions & 6 deletions ethcore/src/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
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
2 changes: 1 addition & 1 deletion ethcore/vm/src/schedule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
6 changes: 2 additions & 4 deletions rpc/src/v1/helpers/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,7 @@ impl<C: miner::BlockChainClient + BlockChainClient, M: MinerService> 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<H256> {
Expand Down Expand Up @@ -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<H256> {
Expand Down
8 changes: 4 additions & 4 deletions rpc/src/v1/helpers/light_fetch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,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<Transaction> {
pub fn extract_transaction_at_index(block: encoded::Block, index: usize) -> Option<Transaction> {
block.transactions().into_iter().nth(index)
// Verify if transaction signature is correct.
.and_then(|tx| SignedTransaction::new(tx).ok())
Expand All @@ -85,7 +85,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.
Expand Down Expand Up @@ -365,7 +365,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<Item = Option<(Transaction, usize)>, Error = Error> + Send
{
let params = (self.sync.clone(), self.on_demand.clone());
Expand Down Expand Up @@ -397,7 +397,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
Expand Down
11 changes: 4 additions & 7 deletions rpc/src/v1/impls/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ pub struct EthClient<C, SN: ?Sized, S: ?Sized, M, EM> where
external_miner: Arc<EM>,
seed_compute: Mutex<SeedHashCompute>,
options: EthClientOptions,
eip86_transition: u64,
}

#[derive(Debug)]
Expand Down Expand Up @@ -169,7 +168,6 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> EthClient<C, SN, S
external_miner: em.clone(),
seed_compute: Mutex::new(SeedHashCompute::default()),
options: options,
eip86_transition: client.eip86_transition(),
}
}

Expand Down Expand Up @@ -254,7 +252,7 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> EthClient<C, SN, S
seal_fields: view.seal().into_iter().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, 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()),
Expand All @@ -268,7 +266,7 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> EthClient<C, SN, S

fn transaction(&self, id: PendingTransactionId) -> Result<Option<Transaction>> {
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),
};

Expand Down Expand Up @@ -305,7 +303,7 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> EthClient<C, SN, S
cached_sender,
}
})
.map(|tx| Transaction::from_localized(tx, self.eip86_transition));
.map(|tx| Transaction::from_localized(tx));

Ok(transaction)
}
Expand Down Expand Up @@ -658,10 +656,9 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> Eth for EthClient<

fn transaction_by_hash(&self, hash: RpcH256) -> BoxFuture<Option<Transaction>> {
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))
Expand Down
17 changes: 5 additions & 12 deletions rpc/src/v1/impls/light/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ impl<T: LightChainClient + 'static> EthClient<T> {
fn rich_block(&self, id: BlockId, include_txs: bool) -> BoxFuture<RichBlock> {
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<U256>| {
Expand All @@ -169,7 +168,7 @@ impl<T: LightChainClient + 'static> EthClient<T> {
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()),
Expand Down Expand Up @@ -419,40 +418,34 @@ impl<T: LightChainClient + 'static> Eth for EthClient<T> {

fn transaction_by_hash(&self, hash: RpcH256) -> BoxFuture<Option<Transaction>> {
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<Option<Transaction>> {
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<Option<Transaction>> {
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<Option<Receipt>> {
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.
Expand Down
8 changes: 3 additions & 5 deletions rpc/src/v1/impls/light/parity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ pub struct ParityClient {
health: NodeHealth,
signer: Option<Arc<SignerService>>,
ws_address: Option<Host>,
eip86_transition: u64,
gas_price_percentile: usize,
}

Expand All @@ -84,7 +83,6 @@ impl ParityClient {
health,
signer,
ws_address,
eip86_transition: client.eip86_transition(),
client,
gas_price_percentile,
}
Expand Down Expand Up @@ -268,7 +266,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::<Vec<_>>()
)
}
Expand All @@ -283,7 +281,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::<Vec<_>>()
)
}
Expand All @@ -294,7 +292,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::<Vec<_>>()
)
}
Expand Down
Loading