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

EIP-100 #4954

Closed
wants to merge 5 commits into from
Closed

EIP-100 #4954

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
30 changes: 20 additions & 10 deletions ethcore/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ impl<'x> OpenBlock<'x> {
tracing: bool,
db: StateDB,
parent: &Header,
parent_uncles: usize,
last_hashes: Arc<LastHashes>,
author: Address,
gas_range_target: (U256, U256),
Expand All @@ -278,7 +279,7 @@ 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);
engine.populate_from_parent(&mut r.block.header, parent, parent_uncles, gas_floor_target, gas_ceil_target);
engine.on_new_block(&mut r.block);
Ok(r)
}
Expand Down Expand Up @@ -534,6 +535,7 @@ pub fn enact(
tracing: bool,
db: StateDB,
parent: &Header,
parent_uncles: usize,
last_hashes: Arc<LastHashes>,
factories: Factories,
) -> Result<LockedBlock, Error> {
Expand All @@ -545,7 +547,7 @@ pub fn enact(
}
}

let mut b = OpenBlock::new(engine, factories, tracing, db, parent, last_hashes, Address::new(), (3141562.into(), 31415620.into()), vec![])?;
let mut b = OpenBlock::new(engine, factories, tracing, db, parent, parent_uncles, last_hashes, Address::new(), (3141562.into(), 31415620.into()), vec![])?;
b.set_difficulty(*header.difficulty());
b.set_gas_limit(*header.gas_limit());
b.set_timestamp(header.timestamp());
Expand Down Expand Up @@ -598,11 +600,12 @@ pub fn enact_verified(
tracing: bool,
db: StateDB,
parent: &Header,
parent_uncles: usize,
last_hashes: Arc<LastHashes>,
factories: Factories,
) -> Result<LockedBlock, Error> {
let view = BlockView::new(&block.bytes);
enact(&block.header, &block.transactions, &view.uncles(), engine, tracing, db, parent, last_hashes, factories)
enact(&block.header, &block.transactions, &view.uncles(), engine, tracing, db, parent, parent_uncles, last_hashes, factories)
}

#[cfg(test)]
Expand All @@ -628,14 +631,15 @@ mod tests {
tracing: bool,
db: StateDB,
parent: &Header,
parent_uncles: usize,
last_hashes: Arc<LastHashes>,
factories: Factories,
) -> Result<LockedBlock, Error> {
let block = BlockView::new(block_bytes);
let header = block.header();
let transactions: Result<Vec<_>, Error> = block.transactions().into_iter().map(SignedTransaction::new).collect();
let transactions = transactions?;
enact(&header, &transactions, &block.uncles(), engine, tracing, db, parent, last_hashes, factories)
enact(&header, &transactions, &block.uncles(), engine, tracing, db, parent, parent_uncles, last_hashes, factories)
}

/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header. Seal the block aferwards
Expand All @@ -646,11 +650,12 @@ mod tests {
tracing: bool,
db: StateDB,
parent: &Header,
parent_uncles: usize,
last_hashes: Arc<LastHashes>,
factories: Factories,
) -> Result<SealedBlock, Error> {
let header = BlockView::new(block_bytes).header_view();
Ok(enact_bytes(block_bytes, engine, tracing, db, parent, last_hashes, factories)?.seal(engine, header.seal())?)
Ok(enact_bytes(block_bytes, engine, tracing, db, parent, parent_uncles, last_hashes, factories)?.seal(engine, header.seal())?)
}

#[test]
Expand All @@ -661,7 +666,8 @@ mod tests {
let mut db_result = get_temp_state_db();
let db = spec.ensure_db_good(db_result.take(), &Default::default()).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b = OpenBlock::new(&*spec.engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap();
let parent_uncles = 0;
let b = OpenBlock::new(&*spec.engine, Default::default(), false, db, &genesis_header, parent_uncles, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap();
let b = b.close_and_lock();
let _ = b.seal(&*spec.engine, vec![]);
}
Expand All @@ -676,14 +682,16 @@ mod tests {
let mut db_result = get_temp_state_db();
let db = spec.ensure_db_good(db_result.take(), &Default::default()).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap()
let parent_uncles = 0;
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, parent_uncles, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap()
.close_and_lock().seal(engine, vec![]).unwrap();
let orig_bytes = b.rlp_bytes();
let orig_db = b.drain();

let mut db_result = get_temp_state_db();
let db = spec.ensure_db_good(db_result.take(), &Default::default()).unwrap();
let e = enact_and_seal(&orig_bytes, engine, false, db, &genesis_header, last_hashes, Default::default()).unwrap();
let parent_uncles = 0;
let e = enact_and_seal(&orig_bytes, engine, false, db, &genesis_header, parent_uncles, last_hashes, Default::default()).unwrap();

assert_eq!(e.rlp_bytes(), orig_bytes);

Expand All @@ -702,7 +710,8 @@ mod tests {
let mut db_result = get_temp_state_db();
let db = spec.ensure_db_good(db_result.take(), &Default::default()).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let mut open_block = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap();
let parent_uncles = 0;
let mut open_block = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, parent_uncles, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap();
let mut uncle1_header = Header::new();
uncle1_header.set_extra_data(b"uncle1".to_vec());
let mut uncle2_header = Header::new();
Expand All @@ -716,7 +725,8 @@ mod tests {

let mut db_result = get_temp_state_db();
let db = spec.ensure_db_good(db_result.take(), &Default::default()).unwrap();
let e = enact_and_seal(&orig_bytes, engine, false, db, &genesis_header, last_hashes, Default::default()).unwrap();
let parent_uncles = 0;
let e = enact_and_seal(&orig_bytes, engine, false, db, &genesis_header, parent_uncles, last_hashes, Default::default()).unwrap();

let bytes = e.rlp_bytes();
assert_eq!(bytes, orig_bytes);
Expand Down
5 changes: 5 additions & 0 deletions ethcore/src/blockchain/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@ pub trait BlockProvider {
self.block_body(hash).map(|body| body.uncle_hashes())
}

/// Get number of uncles for a given block.
fn uncles_count(&self, hash: &H256) -> Option<usize> {
self.block_body(hash).map(|body| body.uncles_count())
}

/// Get the number of given block's hash.
fn block_number(&self, hash: &H256) -> Option<BlockNumber> {
self.block_details(hash).map(|details| details.number)
Expand Down
5 changes: 4 additions & 1 deletion ethcore/src/client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,9 +385,11 @@ impl Client {
if let Some(parent) = chain_has_parent {
// Enact Verified Block
let last_hashes = self.build_last_hashes(header.parent_hash().clone());
let uncles_count = chain.uncles_count(header.parent_hash())
.expect("chain_has_parent.is_some() so block body must exist; qed");
let db = self.state_db.lock().boxed_clone_canon(header.parent_hash());

let enact_result = enact_verified(block, engine, self.tracedb.read().tracing_enabled(), db, &parent, last_hashes, self.factories.clone());
let enact_result = enact_verified(block, engine, self.tracedb.read().tracing_enabled(), db, &parent, uncles_count, last_hashes, self.factories.clone());
let locked_block = enact_result.map_err(|e| {
warn!(target: "client", "Block import failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e);
})?;
Expand Down Expand Up @@ -1510,6 +1512,7 @@ impl MiningBlockChainClient for Client {
false, // TODO: this will need to be parameterised once we want to do immediate mining insertion.
self.state_db.lock().boxed_clone_canon(&h),
&chain.block_header(&h).expect("h is best block hash: so its header must exist: qed"),
chain.uncles_count(&h).expect("h is best block hash; qed"),
self.build_last_hashes(h.clone()),
author,
gas_range_target,
Expand Down
2 changes: 2 additions & 0 deletions ethcore/src/client/test_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ impl MiningBlockChainClient for TestBlockChainClient {
fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes) -> OpenBlock {
let engine = &*self.spec.engine;
let genesis_header = self.spec.genesis_header();
let parent_uncles = 0;
let mut db_result = get_temp_state_db();
let db = self.spec.ensure_db_good(db_result.take(), &Default::default()).unwrap();

Expand All @@ -368,6 +369,7 @@ impl MiningBlockChainClient for TestBlockChainClient {
false,
db,
&genesis_header,
parent_uncles,
Arc::new(last_hashes),
author,
gas_range_target,
Expand Down
19 changes: 10 additions & 9 deletions ethcore/src/engines/authority_round.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ impl Engine for AuthorityRound {
Schedule::new_post_eip150(usize::max_value(), true, true, true)
}

fn populate_from_parent(&self, header: &mut Header, parent: &Header, gas_floor_target: U256, _gas_ceil_target: U256) {
fn populate_from_parent(&self, header: &mut Header, parent: &Header, _parent_uncles: usize, gas_floor_target: U256, _gas_ceil_target: U256) {
// Chain scoring: total weight is sqrt(U256::max_value())*height - step
let new_difficulty = U256::from(U128::max_value()) + header_step(parent).expect("Header has been verified; qed").into() - self.step.load(AtomicOrdering::SeqCst).into();
header.set_difficulty(new_difficulty);
Expand Down Expand Up @@ -305,7 +305,7 @@ impl Engine for AuthorityRound {
}

/// Do the validator and gas limit validation.
fn verify_block_family(&self, header: &Header, parent: &Header, _block: Option<&[u8]>) -> Result<(), Error> {
fn verify_block_family(&self, header: &Header, parent: &Header, _parent_uncles: usize, _block: Option<&[u8]>) -> Result<(), Error> {
let step = header_step(header)?;
// Give one step slack if step is lagging, double vote is still not possible.
if self.is_future_step(step) {
Expand Down Expand Up @@ -413,7 +413,7 @@ mod tests {
let mut header: Header = Header::default();
header.set_seal(vec![encode(&H520::default()).to_vec()]);

let verify_result = engine.verify_block_family(&header, &Default::default(), None);
let verify_result = engine.verify_block_family(&header, &Default::default(), 0, None);
assert!(verify_result.is_err());
}

Expand All @@ -429,9 +429,10 @@ mod tests {
let db1 = spec.ensure_db_good(get_temp_state_db().take(), &Default::default()).unwrap();
let db2 = spec.ensure_db_good(get_temp_state_db().take(), &Default::default()).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![]).unwrap();
let parent_uncles = 0;
let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, parent_uncles, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![]).unwrap();
let b1 = b1.close_and_lock();
let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes, addr2, (3141562.into(), 31415620.into()), vec![]).unwrap();
let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, parent_uncles, last_hashes, addr2, (3141562.into(), 31415620.into()), vec![]).unwrap();
let b2 = b2.close_and_lock();

engine.set_signer(tap.clone(), addr1, "1".into());
Expand Down Expand Up @@ -467,9 +468,9 @@ mod tests {
// Two validators.
// Spec starts with step 2.
header.set_seal(vec![encode(&2usize).to_vec(), encode(&(&*signature as &[u8])).to_vec()]);
assert!(engine.verify_block_family(&header, &parent_header, None).is_err());
assert!(engine.verify_block_family(&header, &parent_header, 0, None).is_err());
header.set_seal(vec![encode(&1usize).to_vec(), encode(&(&*signature as &[u8])).to_vec()]);
assert!(engine.verify_block_family(&header, &parent_header, None).is_ok());
assert!(engine.verify_block_family(&header, &parent_header, 0, None).is_ok());
}

#[test]
Expand All @@ -491,8 +492,8 @@ mod tests {
// Two validators.
// Spec starts with step 2.
header.set_seal(vec![encode(&1usize).to_vec(), encode(&(&*signature as &[u8])).to_vec()]);
assert!(engine.verify_block_family(&header, &parent_header, None).is_ok());
assert!(engine.verify_block_family(&header, &parent_header, 0, None).is_ok());
header.set_seal(vec![encode(&5usize).to_vec(), encode(&(&*signature as &[u8])).to_vec()]);
assert!(engine.verify_block_family(&header, &parent_header, None).is_err());
assert!(engine.verify_block_family(&header, &parent_header, 0, None).is_err());
}
}
9 changes: 5 additions & 4 deletions ethcore/src/engines/basic_authority.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ impl Engine for BasicAuthority {
Schedule::new_homestead()
}

fn populate_from_parent(&self, header: &mut Header, parent: &Header, gas_floor_target: U256, _gas_ceil_target: U256) {
fn populate_from_parent(&self, header: &mut Header, parent: &Header, _parent_uncles: usize, gas_floor_target: U256, _gas_ceil_target: U256) {
header.set_difficulty(parent.difficulty().clone());
header.set_gas_limit({
let gas_limit = parent.gas_limit().clone();
Expand Down Expand Up @@ -137,7 +137,7 @@ impl Engine for BasicAuthority {
Ok(())
}

fn verify_block_family(&self, header: &Header, parent: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> {
fn verify_block_family(&self, header: &Header, parent: &Header, _parent_uncles: usize, _block: Option<&[u8]>) -> result::Result<(), Error> {
use rlp::{UntrustedRlp, View};
// Check if the signature belongs to a validator, can depend on parent state.
let sig = UntrustedRlp::new(&header.seal()[0]).as_val::<H520>()?;
Expand Down Expand Up @@ -239,7 +239,7 @@ mod tests {
let mut header: Header = Header::default();
header.set_seal(vec![::rlp::encode(&H520::default()).to_vec()]);

let verify_result = engine.verify_block_family(&header, &Default::default(), None);
let verify_result = engine.verify_block_family(&header, &Default::default(), 0, None);
assert!(verify_result.is_err());
}

Expand All @@ -255,7 +255,8 @@ mod tests {
let mut db_result = get_temp_state_db();
let db = spec.ensure_db_good(db_result.take(), &Default::default()).unwrap();
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![]).unwrap();
let parent_uncles = 0;
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, parent_uncles, last_hashes, addr, (3141562.into(), 31415620.into()), vec![]).unwrap();
let b = b.close_and_lock();
if let Seal::Regular(seal) = engine.generate_seal(b.block()) {
assert!(b.try_seal(engine, seal).is_ok());
Expand Down
3 changes: 2 additions & 1 deletion ethcore/src/engines/instant_seal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ mod tests {
let db = spec.ensure_db_good(db_result.take(), &Default::default()).unwrap();
let genesis_header = spec.genesis_header();
let last_hashes = Arc::new(vec![genesis_header.hash()]);
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::default(), (3141562.into(), 31415620.into()), vec![]).unwrap();
let parent_uncles = 0;
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, parent_uncles, last_hashes, Address::default(), (3141562.into(), 31415620.into()), vec![]).unwrap();
let b = b.close_and_lock();
if let Seal::Regular(seal) = engine.generate_seal(b.block()) {
assert!(b.try_seal(engine, seal).is_ok());
Expand Down
4 changes: 2 additions & 2 deletions ethcore/src/engines/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ pub trait Engine : Sync + Send {

/// Phase 3 verification. Check block information against parent and uncles. `block` (the header's full block)
/// may be provided for additional checks. Returns either a null `Ok` or a general error detailing the problem with import.
fn verify_block_family(&self, _header: &Header, _parent: &Header, _block: Option<&[u8]>) -> Result<(), Error> { Ok(()) }
fn verify_block_family(&self, _header: &Header, _parent: &Header, _parent_uncles: usize, _block: Option<&[u8]>) -> Result<(), Error> { Ok(()) }

/// Additional verification for transactions in blocks.
// TODO: Add flags for which bits of the transaction to check.
Expand Down Expand Up @@ -180,7 +180,7 @@ pub trait Engine : Sync + Send {
/// Populate a header's fields based on its parent's header.
/// Usually implements the chain scoring rule based on weight.
/// The gas floor target must not be lower than the engine's minimum gas limit.
fn populate_from_parent(&self, header: &mut Header, parent: &Header, _gas_floor_target: U256, _gas_ceil_target: U256) {
fn populate_from_parent(&self, header: &mut Header, parent: &Header, _parent_uncles: usize, _gas_floor_target: U256, _gas_ceil_target: U256) {
header.set_difficulty(parent.difficulty().clone());
header.set_gas_limit(parent.gas_limit().clone());
}
Expand Down
Loading