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

Commit

Permalink
EIP-210
Browse files Browse the repository at this point in the history
  • Loading branch information
arkpar committed Apr 25, 2017
1 parent 154fe76 commit 9282c19
Show file tree
Hide file tree
Showing 22 changed files with 310 additions and 126 deletions.
7 changes: 4 additions & 3 deletions ethcore/res/ethereum/metropolis_test.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b",
"homesteadTransition": "0x0",
"eip150Transition": "0x0",
"eip155Transition": "0x7fffffffffffffff",
"eip155Transition": "0x0",
"eip160Transition": "0x0",
"eip161abcTransition": "0x0",
"eip161dTransition": "0x0",
Expand All @@ -24,9 +24,10 @@
"maximumExtraDataSize": "0x20",
"minGasLimit": "0x1388",
"networkID" : "0x1",
"eip98Transition": "0x7fffffffffffffff",
"eip98Transition": "0x0",
"eip86Transition": "0x0",
"eip140Transition": "0x0"
"eip140Transition": "0x0",
"eip210Transition": "0x0"
},
"genesis": {
"seal": {
Expand Down
57 changes: 53 additions & 4 deletions ethcore/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use std::sync::Arc;
use std::collections::HashSet;

use rlp::{UntrustedRlp, RlpStream, Encodable, Decodable, DecoderError};
use util::{Bytes, Address, Uint, Hashable, U256, H256, ordered_trie_root, SHA3_NULL_RLP};
use util::{Bytes, BytesRef, Address, Uint, Hashable, U256, H256, ordered_trie_root, SHA3_NULL_RLP};
use util::error::{Mismatch, OutOfBounds};

use basic_types::{LogBloom, Seal};
Expand All @@ -31,12 +31,16 @@ use error::{Error, BlockError, TransactionError};
use factory::Factories;
use header::Header;
use receipt::Receipt;
use state::State;
use state::{State, Substate};
use state_db::StateDB;
use trace::FlatTrace;
use transaction::{UnverifiedTransaction, SignedTransaction};
use transaction::{UnverifiedTransaction, SignedTransaction, SYSTEM_ADDRESS};
use verification::PreverifiedBlock;
use views::BlockView;
use executive::Executive;
use types::executed::CallType;
use action_params::{ActionParams, ActionValue};
use trace::{NoopTracer, NoopVMTracer};

/// A block, encoded as it is on the block chain.
#[derive(Default, Debug, Clone, PartialEq)]
Expand Down Expand Up @@ -265,7 +269,7 @@ impl<'x> OpenBlock<'x> {
let mut r = OpenBlock {
block: ExecutedBlock::new(state, tracing),
engine: engine,
last_hashes: last_hashes,
last_hashes: last_hashes.clone(),
};

r.block.header.set_parent_hash(parent.hash());
Expand All @@ -278,10 +282,55 @@ impl<'x> OpenBlock<'x> {
let gas_floor_target = cmp::max(gas_range_target.0, engine.params().min_gas_limit);
let gas_ceil_target = cmp::max(gas_range_target.1, gas_floor_target);
engine.populate_from_parent(&mut r.block.header, parent, gas_floor_target, gas_ceil_target);
Self::push_last_hash(&mut r.block, last_hashes, engine, &parent.hash())?;
engine.on_new_block(&mut r.block);
Ok(r)
}


fn push_last_hash(block: &mut ExecutedBlock, last_hashes: Arc<LastHashes>, engine: &Engine, hash: &H256) -> Result<(), Error> {
if block.fields().header.number() == engine.params().eip210_transition {
let state = block.fields_mut().state;
state.init_code(&engine.params().eip210_contract_address, engine.params().eip210_contract_code.clone())?;
}
if block.fields().header.number() >= engine.params().eip210_transition {
let env_info = {
let header = block.fields().header;
EnvInfo {
number: header.number(),
author: header.author().clone(),
timestamp: header.timestamp(),
difficulty: header.difficulty().clone(),
last_hashes: last_hashes,
gas_used: U256::zero(),
gas_limit: engine.params().eip210_contract_gas,
}
};
let mut state = block.fields_mut().state;
let contract_address = engine.params().eip210_contract_address;
let params = ActionParams {
code_address: contract_address.clone(),
address: contract_address.clone(),
sender: SYSTEM_ADDRESS.clone(),
origin: SYSTEM_ADDRESS.clone(),
gas: engine.params().eip210_contract_gas,
gas_price: 0.into(),
value: ActionValue::Transfer(0.into()),
code: state.code(&contract_address)?,
code_hash: state.code_hash(&contract_address)?,
data: Some(hash.to_vec()),
call_type: CallType::Call,
};
let mut ex = Executive::new(&mut state, &env_info, engine);
let mut substate = Substate::new();
let mut output = [];
if let Err(e) = ex.call(params, &mut substate, BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer) {
warn!("Encountered error on updating last hashes: {}", e);
}
}
Ok(())
}

/// Alter the author for the block.
pub fn set_author(&mut self, author: Address) { self.block.header.set_author(author); }

Expand Down
10 changes: 5 additions & 5 deletions ethcore/src/client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -906,7 +906,7 @@ impl BlockChainClient for Client {
.map_err(|_| CallError::StateCorrupt)?;
}
let options = TransactOptions { tracing: analytics.transaction_tracing, vm_tracing: analytics.vm_tracing, check_nonce: false };
let mut ret = Executive::new(&mut state, &env_info, &*self.engine, &self.factories.vm).transact(t, options)?;
let mut ret = Executive::new(&mut state, &env_info, &*self.engine).transact(t, options)?;

// TODO gav move this into Executive.
if let Some(original) = original_state {
Expand Down Expand Up @@ -944,7 +944,7 @@ impl BlockChainClient for Client {
.map_err(ExecutionError::from)?;
}

Ok(Executive::new(&mut state, &env_info, &*self.engine, &self.factories.vm)
Ok(Executive::new(&mut state, &env_info, &*self.engine)
.transact(&tx, options.clone())
.map(|r| r.exception.is_none())
.unwrap_or(false))
Expand Down Expand Up @@ -1006,13 +1006,13 @@ impl BlockChainClient for Client {
let rest = txs.split_off(address.index);
for t in txs {
let t = SignedTransaction::new(t).expect(PROOF);
let x = Executive::new(&mut state, &env_info, &*self.engine, &self.factories.vm).transact(&t, Default::default())?;
let x = Executive::new(&mut state, &env_info, &*self.engine).transact(&t, Default::default())?;
env_info.gas_used = env_info.gas_used + x.gas_used;
}
let first = rest.into_iter().next().expect("We split off < `address.index`; Length is checked earlier; qed");
let t = SignedTransaction::new(first).expect(PROOF);
let original_state = if analytics.state_diffing { Some(state.clone()) } else { None };
let mut ret = Executive::new(&mut state, &env_info, &*self.engine, &self.factories.vm).transact(&t, options)?;
let mut ret = Executive::new(&mut state, &env_info, &*self.engine).transact(&t, options)?;
if let Some(original) = original_state {
ret.state_diff = Some(state.diff_from(original).map_err(ExecutionError::from)?)
}
Expand Down Expand Up @@ -1643,7 +1643,7 @@ impl ::client::ProvingBlockChainClient for Client {

let mut state = state.replace_backend(backend);
let options = TransactOptions { tracing: false, vm_tracing: false, check_nonce: false };
let res = Executive::new(&mut state, &env_info, &*self.engine, &self.factories.vm).transact(&transaction, options);
let res = Executive::new(&mut state, &env_info, &*self.engine).transact(&transaction, options);

match res {
Err(ExecutionError::Internal(_)) => return None,
Expand Down
4 changes: 2 additions & 2 deletions ethcore/src/client/test_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ impl BlockChainClient for TestBlockChainClient {

fn nonce(&self, address: &Address, id: BlockId) -> Option<U256> {
match id {
BlockId::Latest => Some(self.nonces.read().get(address).cloned().unwrap_or(self.spec.params.account_start_nonce)),
BlockId::Latest => Some(self.nonces.read().get(address).cloned().unwrap_or(self.spec.params().account_start_nonce)),
_ => None,
}
}
Expand Down Expand Up @@ -747,7 +747,7 @@ impl BlockChainClient for TestBlockChainClient {
value: U256::default(),
data: data,
};
let network_id = Some(self.spec.params.network_id);
let network_id = Some(self.spec.params().network_id);
let sig = self.spec.engine.sign(transaction.hash(network_id)).unwrap();
let signed = SignedTransaction::new(transaction.with_signature(sig, network_id)).unwrap();
self.miner.import_own_transaction(self, signed.into())
Expand Down
4 changes: 4 additions & 0 deletions ethcore/src/engines/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ use header::{Header, BlockNumber};
use transaction::{UnverifiedTransaction, SignedTransaction};
use client::Client;

/// Default EIP-210 contrat code
pub const DEFAULT_BLOCKHASH_CONTRACT: &'static str = "73fffffffffffffffffffffffffffffffffffffffe33141561007a57600143036020526000356101006020510755600061010060205107141561005057600035610100610100602051050761010001555b6000620100006020510714156100755760003561010062010000602051050761020001555b610161565b436000351215801561008c5780610095565b623567e0600035125b9050156100a757600060605260206060f35b610100600035430312156100ca57610100600035075460805260206080f3610160565b62010000600035430312156100e857600061010060003507146100eb565b60005b1561010d576101006101006000350507610100015460a052602060a0f361015f565b63010000006000354303121561012d576000620100006000350714610130565b60005b1561015357610100620100006000350507610200015460c052602060c0f361015e565b600060e052602060e0f35b5b5b5b5b";

/// Voting errors.
#[derive(Debug)]
pub enum EngineError {
Expand Down Expand Up @@ -125,6 +128,7 @@ pub trait Engine : Sync + Send {

/// Block transformation functions, before the transactions.
fn on_new_block(&self, _block: &mut ExecutedBlock) {}

/// Block transformation functions, after the transactions.
fn on_close_block(&self, _block: &mut ExecutedBlock) {}

Expand Down
16 changes: 8 additions & 8 deletions ethcore/src/ethereum/ethash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -713,7 +713,7 @@ mod tests {
fn difficulty_frontier() {
let spec = new_homestead_test();
let ethparams = get_default_ethash_params();
let ethash = Ethash::new(spec.params, ethparams, BTreeMap::new());
let ethash = Ethash::new(spec.params().clone(), ethparams, BTreeMap::new());

let mut parent_header = Header::default();
parent_header.set_number(1000000);
Expand All @@ -731,7 +731,7 @@ mod tests {
fn difficulty_homestead() {
let spec = new_homestead_test();
let ethparams = get_default_ethash_params();
let ethash = Ethash::new(spec.params, ethparams, BTreeMap::new());
let ethash = Ethash::new(spec.params().clone(), ethparams, BTreeMap::new());

let mut parent_header = Header::default();
parent_header.set_number(1500000);
Expand All @@ -752,7 +752,7 @@ mod tests {
ecip1010_pause_transition: 3000000,
..get_default_ethash_params()
};
let ethash = Ethash::new(spec.params, ethparams, BTreeMap::new());
let ethash = Ethash::new(spec.params().clone(), ethparams, BTreeMap::new());

let mut parent_header = Header::default();
parent_header.set_number(3500000);
Expand Down Expand Up @@ -786,7 +786,7 @@ mod tests {
ecip1010_continue_transition: 5000000,
..get_default_ethash_params()
};
let ethash = Ethash::new(spec.params, ethparams, BTreeMap::new());
let ethash = Ethash::new(spec.params().clone(), ethparams, BTreeMap::new());

let mut parent_header = Header::default();
parent_header.set_number(5000102);
Expand Down Expand Up @@ -831,7 +831,7 @@ mod tests {
#[test]
fn gas_limit_is_multiple_of_determinant() {
let spec = new_homestead_test();
let ethash = Ethash::new(spec.params, get_default_ethash_params(), BTreeMap::new());
let ethash = Ethash::new(spec.params().clone(), get_default_ethash_params(), BTreeMap::new());
let mut parent = Header::new();
let mut header = Header::new();
header.set_number(1);
Expand Down Expand Up @@ -875,7 +875,7 @@ mod tests {
fn difficulty_max_timestamp() {
let spec = new_homestead_test();
let ethparams = get_default_ethash_params();
let ethash = Ethash::new(spec.params, ethparams, BTreeMap::new());
let ethash = Ethash::new(spec.params().clone(), ethparams, BTreeMap::new());

let mut parent_header = Header::default();
parent_header.set_number(1000000);
Expand Down Expand Up @@ -903,7 +903,7 @@ mod tests {
header.set_number(parent_header.number() + 1);
header.set_gas_limit(100_001.into());
header.set_difficulty(ethparams.minimum_difficulty);
let ethash = Ethash::new(spec.params, ethparams, BTreeMap::new());
let ethash = Ethash::new(spec.params().clone(), ethparams, BTreeMap::new());
assert!(ethash.verify_block_family(&header, &parent_header, None).is_ok());

parent_header.set_number(9);
Expand Down Expand Up @@ -958,7 +958,7 @@ mod tests {
nonce: U256::zero(),
}.sign(keypair.secret(), None).into();

let ethash = Ethash::new(spec.params, ethparams, BTreeMap::new());
let ethash = Ethash::new(spec.params().clone(), ethparams, BTreeMap::new());
assert!(ethash.verify_transaction_basic(&tx1, &header).is_ok());
assert!(ethash.verify_transaction_basic(&tx2, &header).is_ok());

Expand Down
14 changes: 7 additions & 7 deletions ethcore/src/evm/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,13 @@ impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::Error::*;
let message = match *self {
OutOfGas => "Out of gas",
BadJumpDestination { .. } => "Bad jump destination",
BadInstruction { .. } => "Bad instruction",
StackUnderflow { .. } => "Stack underflow",
OutOfStack { .. } => "Out of stack",
BuiltIn { .. } => "Built-in failed",
Internal(ref msg) => msg,
OutOfGas => "Out of gas".into(),
BadJumpDestination { destination } => format!("Bad jump destination {:x}", destination),
BadInstruction { instruction } => format!("Bad instruction {:x}", instruction),
StackUnderflow { instruction, wanted, on_stack } => format!("Stack underflow {} {}/{}", instruction, wanted, on_stack),
OutOfStack { instruction, wanted, limit } => format!("Out of stack {} {}/{}", instruction, wanted, limit),
BuiltIn(name) => format!("Built-in failed: {}", name),
Internal(ref msg) => msg.clone(),
};
message.fmt(f)
}
Expand Down
2 changes: 1 addition & 1 deletion ethcore/src/evm/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ pub trait Ext {
fn balance(&self, address: &Address) -> trie::Result<U256>;

/// Returns the hash of one of the 256 most recent complete blocks.
fn blockhash(&self, number: &U256) -> H256;
fn blockhash(&mut self, number: &U256) -> H256;

/// Creates new contract.
///
Expand Down
3 changes: 3 additions & 0 deletions ethcore/src/evm/interpreter/gasometer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,9 @@ impl<Gas: CostType> Gasometer<Gas> {
let gas = Gas::from(schedule.exp_gas + schedule.exp_byte_gas * bytes);
Request::Gas(gas)
},
instructions::BLOCKHASH => {
Request::Gas(Gas::from(schedule.blockhash_gas))
},
_ => Request::Gas(default_gas),
};

Expand Down
4 changes: 4 additions & 0 deletions ethcore/src/evm/schedule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ pub struct Schedule {
pub kill_empty: bool,
/// Contract address generation scheme
pub create_address: CreateContractAddress,
/// Blockhash instruction gas cost.
pub blockhash_gas: usize,
}

impl Schedule {
Expand Down Expand Up @@ -165,6 +167,7 @@ impl Schedule {
no_empty: no_empty,
kill_empty: kill_empty,
create_address: if have_metropolis_instructions { CreateContractAddress::FromCodeHash } else { CreateContractAddress::FromSenderAndNonce },
blockhash_gas: if have_metropolis_instructions { 350 } else { 20 },
}
}

Expand Down Expand Up @@ -218,6 +221,7 @@ impl Schedule {
no_empty: false,
kill_empty: false,
create_address: CreateContractAddress::FromSenderAndNonce,
blockhash_gas: 20,
}
}
}
Expand Down
Loading

0 comments on commit 9282c19

Please sign in to comment.