diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index 9d3528bb0d5..bbcfa473eb7 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -31,7 +31,7 @@ //! `ExecutedBlock` is an underlaying data structure used by all structs above to store block //! related info. -use std::cmp; +use std::{cmp, ops}; use std::collections::HashSet; use std::sync::Arc; @@ -52,7 +52,6 @@ use vm::{EnvInfo, LastHashes}; use hash::keccak; use rlp::{RlpStream, Encodable, encode_list}; use types::transaction::{SignedTransaction, Error as TransactionError}; -use types::block::Block; use types::header::{Header, ExtendedHeader}; use types::receipt::{Receipt, TransactionOutcome}; @@ -155,46 +154,12 @@ impl ExecutedBlock { } } -/// Trait for a object that is a `ExecutedBlock`. -pub trait IsBlock { - /// Get the `ExecutedBlock` associated with this object. - fn block(&self) -> &ExecutedBlock; - - /// Get the base `Block` object associated with this. - fn to_base(&self) -> Block { - Block { - header: self.header().clone(), - transactions: self.transactions().iter().cloned().map(Into::into).collect(), - uncles: self.uncles().to_vec(), - } - } - - /// Get the header associated with this object's block. - fn header(&self) -> &Header { &self.block().header } - - /// Get the final state associated with this object's block. - fn state(&self) -> &State { &self.block().state } - - /// Get all information on transactions in this block. - fn transactions(&self) -> &[SignedTransaction] { &self.block().transactions } - - /// Get all information on receipts in this block. - fn receipts(&self) -> &[Receipt] { &self.block().receipts } - - /// Get all uncles in this block. - fn uncles(&self) -> &[Header] { &self.block().uncles } -} - /// Trait for an object that owns an `ExecutedBlock` pub trait Drain { /// Returns `ExecutedBlock` fn drain(self) -> ExecutedBlock; } -impl IsBlock for ExecutedBlock { - fn block(&self) -> &ExecutedBlock { self } -} - impl<'x> OpenBlock<'x> { /// Create a new `OpenBlock` ready for transaction pushing. pub fn new<'a>( @@ -250,7 +215,7 @@ impl<'x> OpenBlock<'x> { /// NOTE Will check chain constraints and the uncle number but will NOT check /// that the header itself is actually valid. pub fn push_uncle(&mut self, valid_uncle_header: Header) -> Result<(), BlockError> { - let max_uncles = self.engine.maximum_uncle_count(self.block.header().number()); + let max_uncles = self.engine.maximum_uncle_count(self.block.header.number()); if self.block.uncles.len() + 1 > max_uncles { return Err(BlockError::TooManyUncles(OutOfBounds{ min: None, @@ -264,11 +229,6 @@ impl<'x> OpenBlock<'x> { Ok(()) } - /// Get the environment info concerning this block. - pub fn env_info(&self) -> EnvInfo { - self.block.env_info() - } - /// Push a transaction into the block. /// /// If valid, it will be executed, and archived together with the receipt. @@ -277,7 +237,7 @@ impl<'x> OpenBlock<'x> { return Err(TransactionError::AlreadyImported.into()); } - let env_info = self.env_info(); + let env_info = self.block.env_info(); let outcome = self.block.state.apply(&env_info, self.engine.machine(), &t, self.block.traces.is_enabled())?; self.block.transactions_set.insert(h.unwrap_or_else(||t.hash())); @@ -374,22 +334,39 @@ impl<'x> OpenBlock<'x> { pub fn block_mut(&mut self) -> &mut ExecutedBlock { &mut self.block } } -impl<'x> IsBlock for OpenBlock<'x> { - fn block(&self) -> &ExecutedBlock { &self.block } +impl<'a> ops::Deref for OpenBlock<'a> { + type Target = ExecutedBlock; + + fn deref(&self) -> &Self::Target { + &self.block + } } -impl IsBlock for ClosedBlock { - fn block(&self) -> &ExecutedBlock { &self.block } +impl ops::Deref for ClosedBlock { + type Target = ExecutedBlock; + + fn deref(&self) -> &Self::Target { + &self.block + } } -impl IsBlock for LockedBlock { - fn block(&self) -> &ExecutedBlock { &self.block } +impl ops::Deref for LockedBlock { + type Target = ExecutedBlock; + + fn deref(&self) -> &Self::Target { + &self.block + } } -impl ClosedBlock { - /// Get the hash of the header without seal arguments. - pub fn hash(&self) -> H256 { self.header().bare_hash() } +impl ops::Deref for SealedBlock { + type Target = ExecutedBlock; + fn deref(&self) -> &Self::Target { + &self.block + } +} + +impl ClosedBlock { /// Turn this into a `LockedBlock`, unable to be reopened again. pub fn lock(self) -> LockedBlock { LockedBlock { @@ -423,18 +400,13 @@ impl LockedBlock { self.block.header.set_receipts_root( ordered_trie_root(self.block.receipts.iter().map(|r| r.rlp_bytes())) ); - // compute hash and cache it. - self.block.header.compute_hash(); } - /// Get the hash of the header without seal arguments. - pub fn hash(&self) -> H256 { self.header().bare_hash() } - /// Provide a valid seal in order to turn this into a `SealedBlock`. /// /// NOTE: This does not check the validity of `seal` with the engine. pub fn seal(self, engine: &EthEngine, seal: Vec) -> Result { - let expected_seal_fields = engine.seal_fields(self.header()); + let expected_seal_fields = engine.seal_fields(&self.block.header); let mut s = self; if seal.len() != expected_seal_fields { return Err(BlockError::InvalidSealArity( @@ -490,10 +462,6 @@ impl Drain for SealedBlock { } } -impl IsBlock for SealedBlock { - fn block(&self) -> &ExecutedBlock { &self.block } -} - /// Enact the block given by block header, transactions and uncles fn enact( header: Header, diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index f0fdacfe86f..29d642477ac 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -45,7 +45,7 @@ use types::receipt::{Receipt, LocalizedReceipt}; use types::{BlockNumber, header::{Header, ExtendedHeader}}; use vm::{EnvInfo, LastHashes}; -use block::{IsBlock, LockedBlock, Drain, ClosedBlock, OpenBlock, enact_verified, SealedBlock}; +use block::{LockedBlock, Drain, ClosedBlock, OpenBlock, enact_verified, SealedBlock}; use client::ancient_import::AncientVerifier; use client::{ Nonce, Balance, ChainInfo, BlockInfo, TransactionInfo, @@ -299,7 +299,7 @@ impl Importer { match self.check_and_lock_block(&bytes, block, client) { Ok((closed_block, pending)) => { imported_blocks.push(hash); - let transactions_len = closed_block.transactions().len(); + let transactions_len = closed_block.transactions.len(); let route = self.commit_block(closed_block, &header, encoded::Block::new(bytes), pending, client); import_results.push(route); client.report.write().accrue_block(&header, transactions_len); @@ -423,13 +423,13 @@ impl Importer { // if the expected receipts root header does not match. // (i.e. allow inconsistency in receipts outcome before the transition block) if header.number() < engine.params().validate_receipts_transition - && header.receipts_root() != locked_block.block().header().receipts_root() + && header.receipts_root() != locked_block.header.receipts_root() { locked_block.strip_receipts_outcomes(); } // Final Verification - if let Err(e) = self.verifier.verify_block_final(&header, locked_block.block().header()) { + if let Err(e) = self.verifier.verify_block_final(&header, &locked_block.header) { warn!(target: "client", "Stage 5 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); bail!(e); } @@ -437,8 +437,8 @@ impl Importer { let pending = self.check_epoch_end_signal( &header, bytes, - locked_block.receipts(), - locked_block.state().db(), + &locked_block.receipts, + locked_block.state.db(), client )?; @@ -2276,8 +2276,8 @@ impl ReopenBlock for Client { fn reopen_block(&self, block: ClosedBlock) -> OpenBlock { let engine = &*self.engine; let mut block = block.reopen(engine); - let max_uncles = engine.maximum_uncle_count(block.header().number()); - if block.uncles().len() < max_uncles { + let max_uncles = engine.maximum_uncle_count(block.header.number()); + if block.uncles.len() < max_uncles { let chain = self.chain.read(); let h = chain.best_block_hash(); // Add new uncles @@ -2286,14 +2286,14 @@ impl ReopenBlock for Client { .unwrap_or_else(Vec::new); for h in uncles { - if !block.uncles().iter().any(|header| header.hash() == h) { + if !block.uncles.iter().any(|header| header.hash() == h) { let uncle = chain.block_header_data(&h).expect("find_uncle_hashes only returns hashes for existing headers; qed"); let uncle = uncle.decode().expect("decoding failure"); block.push_uncle(uncle).expect("pushing up to maximum_uncle_count; push_uncle is not ok only if more than maximum_uncle_count is pushed; so all push_uncle are Ok; qed"); - if block.uncles().len() >= max_uncles { break } + if block.uncles.len() >= max_uncles { break } } } @@ -2329,7 +2329,7 @@ impl PrepareOpenBlock for Client { .find_uncle_headers(&h, MAX_UNCLE_AGE) .unwrap_or_else(Vec::new) .into_iter() - .take(engine.maximum_uncle_count(open_block.header().number())) + .take(engine.maximum_uncle_count(open_block.header.number())) .foreach(|h| { open_block.push_uncle(h.decode().expect("decoding failure")).expect("pushing maximum_uncle_count; open_block was just created; @@ -2354,7 +2354,7 @@ impl ImportSealedBlock for Client { fn import_sealed_block(&self, block: SealedBlock) -> EthcoreResult { let start = Instant::now(); let raw = block.rlp_bytes(); - let header = block.header().clone(); + let header = block.header.clone(); let hash = header.hash(); self.notify(|n| n.block_pre_import(&raw, &hash, header.difficulty())); @@ -2377,8 +2377,8 @@ impl ImportSealedBlock for Client { let pending = self.importer.check_epoch_end_signal( &header, &block_data, - block.receipts(), - block.state().db(), + &block.receipts, + block.state.db(), self )?; let route = self.importer.commit_block( diff --git a/ethcore/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs index 31062d80f3d..db25380aa85 100644 --- a/ethcore/src/engines/authority_round/mod.rs +++ b/ethcore/src/engines/authority_round/mod.rs @@ -1030,7 +1030,7 @@ impl Engine for AuthorityRound { return Seal::None; } - let header = block.header(); + let header = &block.header; let parent_step = header_step(parent, self.empty_steps_transition) .expect("Header has been verified; qed"); @@ -1076,7 +1076,7 @@ impl Engine for AuthorityRound { // `EmptyStep(step, parent_hash)` message. If we exceed the maximum amount of `empty_step` rounds we proceed // with the seal. if header.number() >= self.empty_steps_transition && - block.transactions().is_empty() && + block.transactions.is_empty() && empty_steps.len() < self.maximum_empty_steps { if self.step.can_propose.compare_and_swap(true, false, AtomicOrdering::SeqCst) { @@ -1146,7 +1146,7 @@ impl Engine for AuthorityRound { if self.immediate_transitions || !epoch_begin { return Ok(()) } // genesis is never a new block, but might as well check. - let header = block.header().clone(); + let header = block.header.clone(); let first = header.number() == 0; let mut call = |to, data| { @@ -1166,8 +1166,8 @@ impl Engine for AuthorityRound { /// Apply the block reward on finalisation of the block. fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> { let mut beneficiaries = Vec::new(); - if block.header().number() >= self.empty_steps_transition { - let empty_steps = if block.header().seal().is_empty() { + if block.header.number() >= self.empty_steps_transition { + let empty_steps = if block.header.seal().is_empty() { // this is a new block, calculate rewards based on the empty steps messages we have accumulated let client = match self.client.read().as_ref().and_then(|weak| weak.upgrade()) { Some(client) => client, @@ -1177,7 +1177,7 @@ impl Engine for AuthorityRound { }, }; - let parent = client.block_header(::client::BlockId::Hash(*block.header().parent_hash())) + let parent = client.block_header(::client::BlockId::Hash(*block.header.parent_hash())) .expect("hash is from parent; parent header must exist; qed") .decode()?; @@ -1186,7 +1186,7 @@ impl Engine for AuthorityRound { self.empty_steps(parent_step.into(), current_step.into(), parent.hash()) } else { // we're verifying a block, extract empty steps from the seal - header_empty_steps(block.header())? + header_empty_steps(&block.header)? }; for empty_step in empty_steps { @@ -1195,11 +1195,11 @@ impl Engine for AuthorityRound { } } - let author = *block.header().author(); + let author = *block.header.author(); beneficiaries.push((author, RewardKind::Author)); let rewards: Vec<_> = match self.block_reward_contract { - Some(ref c) if block.header().number() >= self.block_reward_contract_transition => { + Some(ref c) if block.header.number() >= self.block_reward_contract_transition => { let mut call = super::default_system_or_code_call(&self.machine, block); let rewards = c.reward(&beneficiaries, &mut call)?; @@ -1634,17 +1634,17 @@ mod tests { let b2 = b2.close_and_lock().unwrap(); engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); - if let Seal::Regular(seal) = engine.generate_seal(b1.block(), &genesis_header) { + if let Seal::Regular(seal) = engine.generate_seal(&b1, &genesis_header) { assert!(b1.clone().try_seal(engine, seal).is_ok()); // Second proposal is forbidden. - assert!(engine.generate_seal(b1.block(), &genesis_header) == Seal::None); + assert!(engine.generate_seal(&b1, &genesis_header) == Seal::None); } engine.set_signer(Box::new((tap, addr2, "2".into()))); - if let Seal::Regular(seal) = engine.generate_seal(b2.block(), &genesis_header) { + if let Seal::Regular(seal) = engine.generate_seal(&b2, &genesis_header) { assert!(b2.clone().try_seal(engine, seal).is_ok()); // Second proposal is forbidden. - assert!(engine.generate_seal(b2.block(), &genesis_header) == Seal::None); + assert!(engine.generate_seal(&b2, &genesis_header) == Seal::None); } } @@ -1668,13 +1668,13 @@ mod tests { let b2 = b2.close_and_lock().unwrap(); engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); - match engine.generate_seal(b1.block(), &genesis_header) { + match engine.generate_seal(&b1, &genesis_header) { Seal::None | Seal::Proposal(_) => panic!("wrong seal"), Seal::Regular(_) => { engine.step(); engine.set_signer(Box::new((tap.clone(), addr2, "0".into()))); - match engine.generate_seal(b2.block(), &genesis_header) { + match engine.generate_seal(&b2, &genesis_header) { Seal::Regular(_) | Seal::Proposal(_) => panic!("sealed despite wrong difficulty"), Seal::None => {} } @@ -1902,7 +1902,7 @@ mod tests { let b1 = b1.close_and_lock().unwrap(); // the block is empty so we don't seal and instead broadcast an empty step message - assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None); + assert_eq!(engine.generate_seal(&b1, &genesis_header), Seal::None); // spec starts with step 2 let empty_step_rlp = encode(&empty_step(engine, 2, &genesis_header.hash())); @@ -1912,7 +1912,7 @@ mod tests { let len = notify.messages.read().len(); // make sure that we don't generate empty step for the second time - assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None); + assert_eq!(engine.generate_seal(&b1, &genesis_header), Seal::None); assert_eq!(len, notify.messages.read().len()); } @@ -1941,7 +1941,7 @@ mod tests { // since the block is empty it isn't sealed and we generate empty steps engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); - assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None); + assert_eq!(engine.generate_seal(&b1, &genesis_header), Seal::None); engine.step(); // step 3 @@ -1958,7 +1958,7 @@ mod tests { // we will now seal a block with 1tx and include the accumulated empty step message engine.set_signer(Box::new((tap.clone(), addr2, "0".into()))); - if let Seal::Regular(seal) = engine.generate_seal(b2.block(), &genesis_header) { + if let Seal::Regular(seal) = engine.generate_seal(&b2, &genesis_header) { engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); let empty_step2 = sealed_empty_step(engine, 2, &genesis_header.hash()); let empty_steps = ::rlp::encode_list(&vec![empty_step2]); @@ -1994,14 +1994,14 @@ mod tests { // since the block is empty it isn't sealed and we generate empty steps engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); - assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None); + assert_eq!(engine.generate_seal(&b1, &genesis_header), Seal::None); engine.step(); // step 3 let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr2, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); let b2 = b2.close_and_lock().unwrap(); engine.set_signer(Box::new((tap.clone(), addr2, "0".into()))); - assert_eq!(engine.generate_seal(b2.block(), &genesis_header), Seal::None); + assert_eq!(engine.generate_seal(&b2, &genesis_header), Seal::None); engine.step(); // step 4 @@ -2010,7 +2010,7 @@ mod tests { let b3 = b3.close_and_lock().unwrap(); engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); - if let Seal::Regular(seal) = engine.generate_seal(b3.block(), &genesis_header) { + if let Seal::Regular(seal) = engine.generate_seal(&b3, &genesis_header) { let empty_step2 = sealed_empty_step(engine, 2, &genesis_header.hash()); engine.set_signer(Box::new((tap.clone(), addr2, "0".into()))); let empty_step3 = sealed_empty_step(engine, 3, &genesis_header.hash()); @@ -2044,19 +2044,19 @@ mod tests { // since the block is empty it isn't sealed and we generate empty steps engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); - assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None); + assert_eq!(engine.generate_seal(&b1, &genesis_header), Seal::None); engine.step(); // step 3 // the signer of the accumulated empty step message should be rewarded let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); - let addr1_balance = b2.block().state().balance(&addr1).unwrap(); + let addr1_balance = b2.state.balance(&addr1).unwrap(); // after closing the block `addr1` should be reward twice, one for the included empty step message and another for block creation let b2 = b2.close_and_lock().unwrap(); // the spec sets the block reward to 10 - assert_eq!(b2.block().state().balance(&addr1).unwrap(), addr1_balance + (10 * 2)) + assert_eq!(b2.state.balance(&addr1).unwrap(), addr1_balance + (10 * 2)) } #[test] @@ -2155,7 +2155,7 @@ mod tests { // since the block is empty it isn't sealed and we generate empty steps engine.set_signer(Box::new((tap.clone(), addr1, "1".into()))); - assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None); + assert_eq!(engine.generate_seal(&b1, &genesis_header), Seal::None); engine.step(); // step 3 @@ -2173,7 +2173,7 @@ mod tests { false, &mut Vec::new().into_iter(), ).unwrap(); - let addr1_balance = b2.block().state().balance(&addr1).unwrap(); + let addr1_balance = b2.state.balance(&addr1).unwrap(); // after closing the block `addr1` should be reward twice, one for the included empty step // message and another for block creation @@ -2181,7 +2181,7 @@ mod tests { // the contract rewards (1000 + kind) for each benefactor/reward kind assert_eq!( - b2.block().state().balance(&addr1).unwrap(), + b2.state.balance(&addr1).unwrap(), addr1_balance + (1000 + 0) + (1000 + 2), ) } diff --git a/ethcore/src/engines/basic_authority.rs b/ethcore/src/engines/basic_authority.rs index 1a4bdb55a90..e907e7834f3 100644 --- a/ethcore/src/engines/basic_authority.rs +++ b/ethcore/src/engines/basic_authority.rs @@ -104,7 +104,7 @@ impl Engine for BasicAuthority { /// Attempt to seal the block internally. fn generate_seal(&self, block: &ExecutedBlock, _parent: &Header) -> Seal { - let header = block.header(); + let header = &block.header; let author = header.author(); if self.validators.contains(header.parent_hash(), author) { // account should be pernamently unlocked, otherwise sealing will fail @@ -266,7 +266,7 @@ mod tests { 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![], false, &mut Vec::new().into_iter()).unwrap(); let b = b.close_and_lock().unwrap(); - if let Seal::Regular(seal) = engine.generate_seal(b.block(), &genesis_header) { + if let Seal::Regular(seal) = engine.generate_seal(&b, &genesis_header) { assert!(b.try_seal(engine, seal).is_ok()); } } diff --git a/ethcore/src/engines/instant_seal.rs b/ethcore/src/engines/instant_seal.rs index 93e20196a46..e792c5860e7 100644 --- a/ethcore/src/engines/instant_seal.rs +++ b/ethcore/src/engines/instant_seal.rs @@ -110,7 +110,7 @@ mod tests { 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![], false, &mut Vec::new().into_iter()).unwrap(); let b = b.close_and_lock().unwrap(); - if let Seal::Regular(seal) = engine.generate_seal(b.block(), &genesis_header) { + if let Seal::Regular(seal) = engine.generate_seal(&b, &genesis_header) { assert!(b.try_seal(engine, seal).is_ok()); } } diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 561b3493be8..226747acbb0 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -542,7 +542,7 @@ mod tests { let last_hashes = Arc::new(vec![genesis_header.hash()]); let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); let b = b.close().unwrap(); - assert_eq!(b.state().balance(&Address::zero()).unwrap(), U256::from_str("4563918244f40000").unwrap()); + assert_eq!(b.state.balance(&Address::zero()).unwrap(), U256::from_str("4563918244f40000").unwrap()); } #[test] @@ -596,8 +596,8 @@ mod tests { b.push_uncle(uncle).unwrap(); let b = b.close().unwrap(); - assert_eq!(b.state().balance(&Address::zero()).unwrap(), "478eae0e571ba000".into()); - assert_eq!(b.state().balance(&uncle_author).unwrap(), "3cb71f51fc558000".into()); + assert_eq!(b.state.balance(&Address::zero()).unwrap(), "478eae0e571ba000".into()); + assert_eq!(b.state.balance(&uncle_author).unwrap(), "3cb71f51fc558000".into()); } #[test] @@ -612,9 +612,9 @@ mod tests { let ubi_contract: Address = "00efdd5883ec628983e9063c7d969fe268bbf310".into(); let dev_contract: Address = "00756cf8159095948496617f5fb17ed95059f536".into(); - assert_eq!(b.state().balance(&Address::zero()).unwrap(), U256::from_str("d8d726b7177a80000").unwrap()); - assert_eq!(b.state().balance(&ubi_contract).unwrap(), U256::from_str("2b5e3af16b1880000").unwrap()); - assert_eq!(b.state().balance(&dev_contract).unwrap(), U256::from_str("c249fdd327780000").unwrap()); + assert_eq!(b.state.balance(&Address::zero()).unwrap(), U256::from_str("d8d726b7177a80000").unwrap()); + assert_eq!(b.state.balance(&ubi_contract).unwrap(), U256::from_str("2b5e3af16b1880000").unwrap()); + assert_eq!(b.state.balance(&dev_contract).unwrap(), U256::from_str("c249fdd327780000").unwrap()); } #[test] diff --git a/ethcore/src/machine/impls.rs b/ethcore/src/machine/impls.rs index 90d410c70d2..72f20ecdf7d 100644 --- a/ethcore/src/machine/impls.rs +++ b/ethcore/src/machine/impls.rs @@ -28,7 +28,7 @@ use types::header::Header; use vm::{CallType, ActionParams, ActionValue, ParamsType}; use vm::{EnvInfo, Schedule, CreateContractAddress}; -use block::{ExecutedBlock, IsBlock}; +use block::ExecutedBlock; use builtin::Builtin; use call_contract::CallContract; use client::BlockInfo; @@ -126,7 +126,7 @@ impl EthereumMachine { data: Option>, ) -> Result, Error> { let (code, code_hash) = { - let state = block.state(); + let state = &block.state; (state.code(&contract_address)?, state.code_hash(&contract_address)?) @@ -193,12 +193,12 @@ impl EthereumMachine { /// Push last known block hash to the state. fn push_last_hash(&self, block: &mut ExecutedBlock) -> Result<(), Error> { let params = self.params(); - if block.header().number() == params.eip210_transition { + if block.header.number() == params.eip210_transition { let state = block.state_mut(); state.init_code(¶ms.eip210_contract_address, params.eip210_contract_code.clone())?; } - if block.header().number() >= params.eip210_transition { - let parent_hash = block.header().parent_hash().clone(); + if block.header.number() >= params.eip210_transition { + let parent_hash = *block.header.parent_hash(); let _ = self.execute_as_system( block, params.eip210_contract_address, @@ -215,7 +215,7 @@ impl EthereumMachine { self.push_last_hash(block)?; if let Some(ref ethash_params) = self.ethash_extensions { - if block.header().number() == ethash_params.dao_hardfork_transition { + if block.header.number() == ethash_params.dao_hardfork_transition { let state = block.state_mut(); for child in ðash_params.dao_hardfork_accounts { let beneficiary = ðash_params.dao_hardfork_beneficiary; @@ -434,7 +434,7 @@ impl super::Machine for EthereumMachine { type Error = Error; fn balance(&self, live: &ExecutedBlock, address: &Address) -> Result { - live.state().balance(address).map_err(Into::into) + live.state.balance(address).map_err(Into::into) } fn add_balance(&self, live: &mut ExecutedBlock, address: &Address, amount: &U256) -> Result<(), Error> { diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 7d6bcbe496d..ce1c9ef6ee7 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -46,7 +46,7 @@ use types::header::Header; use types::receipt::RichReceipt; use using_queue::{UsingQueue, GetAction}; -use block::{ClosedBlock, IsBlock, SealedBlock}; +use block::{ClosedBlock, SealedBlock}; use client::{ BlockChain, ChainInfo, BlockProducer, SealedBlockImporter, Nonce, TransactionInfo, TransactionId }; @@ -362,7 +362,7 @@ impl Miner { .and_then(|b| { // to prevent a data race between block import and updating pending block // we allow the number to be equal. - if b.block().header().number() >= latest_block_number { + if b.header.number() >= latest_block_number { Some(f(b)) } else { None @@ -392,7 +392,7 @@ impl Miner { // Open block let (mut open_block, original_work_hash) = { let mut sealing = self.sealing.lock(); - let last_work_hash = sealing.queue.peek_last_ref().map(|pb| pb.block().header().hash()); + let last_work_hash = sealing.queue.peek_last_ref().map(|pb| pb.header.hash()); let best_hash = chain_info.best_block_hash; // check to see if last ClosedBlock in would_seals is actually same parent block. @@ -401,7 +401,7 @@ impl Miner { // if at least one was pushed successfully, close and enqueue new ClosedBlock; // otherwise, leave everything alone. // otherwise, author a fresh block. - let mut open_block = match sealing.queue.get_pending_if(|b| b.block().header().parent_hash() == &best_hash) { + let mut open_block = match sealing.queue.get_pending_if(|b| b.header.parent_hash() == &best_hash) { Some(old_block) => { trace!(target: "miner", "prepare_block: Already have previous work; updating and returning"); // add transactions to old_block @@ -436,7 +436,7 @@ impl Miner { let mut invalid_transactions = HashSet::new(); let mut not_allowed_transactions = HashSet::new(); let mut senders_to_penalize = HashSet::new(); - let block_number = open_block.block().header().number(); + let block_number = open_block.header.number(); let mut tx_count = 0usize; let mut skipped_transactions = 0usize; @@ -453,7 +453,7 @@ impl Miner { let max_transactions = if min_tx_gas.is_zero() { usize::max_value() } else { - MAX_SKIPPED_TRANSACTIONS.saturating_add(cmp::min(*open_block.block().header().gas_limit() / min_tx_gas, u64::max_value().into()).as_u64() as usize) + MAX_SKIPPED_TRANSACTIONS.saturating_add(cmp::min(*open_block.header.gas_limit() / min_tx_gas, u64::max_value().into()).as_u64() as usize) }; let pending: Vec> = self.transaction_queue.pending( @@ -636,7 +636,7 @@ impl Miner { { { let sealing = self.sealing.lock(); - if block.transactions().is_empty() + if block.transactions.is_empty() && !self.forced_sealing() && Instant::now() <= sealing.next_mandatory_reseal { @@ -646,7 +646,7 @@ impl Miner { trace!(target: "miner", "seal_block_internally: attempting internal seal."); - let parent_header = match chain.block_header(BlockId::Hash(*block.header().parent_hash())) { + let parent_header = match chain.block_header(BlockId::Hash(*block.header.parent_hash())) { Some(h) => { match h.decode() { Ok(decoded_hdr) => decoded_hdr, @@ -656,7 +656,7 @@ impl Miner { None => return false, }; - match self.engine.generate_seal(block.block(), &parent_header) { + match self.engine.generate_seal(&block, &parent_header) { // Save proposal for later seal submission and broadcast it. Seal::Proposal(seal) => { trace!(target: "miner", "Received a Proposal seal."); @@ -705,11 +705,11 @@ impl Miner { /// Prepares work which has to be done to seal. fn prepare_work(&self, block: ClosedBlock, original_work_hash: Option) { let (work, is_new) = { - let block_header = block.block().header().clone(); + let block_header = block.header.clone(); let block_hash = block_header.hash(); let mut sealing = self.sealing.lock(); - let last_work_hash = sealing.queue.peek_last_ref().map(|pb| pb.block().header().hash()); + let last_work_hash = sealing.queue.peek_last_ref().map(|pb| pb.header.hash()); trace!( target: "miner", @@ -742,7 +742,7 @@ impl Miner { trace!( target: "miner", "prepare_work: leaving (last={:?})", - sealing.queue.peek_last_ref().map(|b| b.block().header().hash()) + sealing.queue.peek_last_ref().map(|b| b.header.hash()) ); (work, is_new) }; @@ -994,7 +994,7 @@ impl miner::MinerService for Miner { let from_pending = || { self.map_existing_pending_block(|sealing| { - sealing.transactions() + sealing.transactions .iter() .map(|signed| signed.hash()) .collect() @@ -1041,7 +1041,7 @@ impl miner::MinerService for Miner { let from_pending = || { self.map_existing_pending_block(|sealing| { - sealing.transactions() + sealing.transactions .iter() .map(|signed| pool::VerifiedTransaction::from_pending_block_transaction(signed.clone())) .map(Arc::new) @@ -1086,9 +1086,9 @@ impl miner::MinerService for Miner { fn pending_receipts(&self, best_block: BlockNumber) -> Option> { self.map_existing_pending_block(|pending| { - let receipts = pending.receipts(); - pending.transactions() - .into_iter() + let receipts = &pending.receipts; + pending.transactions + .iter() .enumerate() .map(|(index, tx)| { let prev_gas = if index == 0 { Default::default() } else { receipts[index - 1].gas_used }; @@ -1102,7 +1102,7 @@ impl miner::MinerService for Miner { Action::Call(_) => None, Action::Create => { let sender = tx.sender(); - Some(contract_address(self.engine.create_address_scheme(pending.header().number()), &sender, &tx.nonce, &tx.data).0) + Some(contract_address(self.engine.create_address_scheme(pending.header.number()), &sender, &tx.nonce, &tx.data).0) } }, logs: receipt.logs.clone(), @@ -1139,7 +1139,7 @@ impl miner::MinerService for Miner { // refuse to seal the first block of the chain if it contains hard forks // which should be on by default. - if block.block().header().number() == 1 { + if block.header.number() == 1 { if let Some(name) = self.engine.params().nonzero_bugfix_hard_fork() { warn!("Your chain specification contains one or more hard forks which are required to be \ on by default. Please remove these forks and start your chain again: {}.", name); @@ -1180,7 +1180,7 @@ impl miner::MinerService for Miner { self.prepare_pending_block(chain); self.sealing.lock().queue.use_last_ref().map(|b| { - let header = b.header(); + let header = &b.header; (header.hash(), header.number(), header.timestamp(), *header.difficulty()) }) } @@ -1194,9 +1194,9 @@ impl miner::MinerService for Miner { } else { GetAction::Take }, - |b| &b.hash() == &block_hash + |b| &b.header.bare_hash() == &block_hash ) { - trace!(target: "miner", "Submitted block {}={}={} with seal {:?}", block_hash, b.hash(), b.header().bare_hash(), seal); + trace!(target: "miner", "Submitted block {}={} with seal {:?}", block_hash, b.header.bare_hash(), seal); b.lock().try_seal(&*self.engine, seal).or_else(|e| { warn!(target: "miner", "Mined solution rejected: {}", e); Err(ErrorKind::PowInvalid.into()) @@ -1207,8 +1207,8 @@ impl miner::MinerService for Miner { }; result.and_then(|sealed| { - let n = sealed.header().number(); - let h = sealed.header().hash(); + let n = sealed.header.number(); + let h = sealed.header.hash(); info!(target: "miner", "Submitted block imported OK. #{}: {}", Colour::White.bold().paint(format!("{}", n)), Colour::White.bold().paint(format!("{:x}", h))); Ok(sealed) }) @@ -1304,19 +1304,25 @@ impl miner::MinerService for Miner { } fn pending_state(&self, latest_block_number: BlockNumber) -> Option { - self.map_existing_pending_block(|b| b.state().clone(), latest_block_number) + self.map_existing_pending_block(|b| b.state.clone(), latest_block_number) } fn pending_block_header(&self, latest_block_number: BlockNumber) -> Option
{ - self.map_existing_pending_block(|b| b.header().clone(), latest_block_number) + self.map_existing_pending_block(|b| b.header.clone(), latest_block_number) } fn pending_block(&self, latest_block_number: BlockNumber) -> Option { - self.map_existing_pending_block(|b| b.to_base(), latest_block_number) + self.map_existing_pending_block(|b| { + Block { + header: b.header.clone(), + transactions: b.transactions.iter().cloned().map(Into::into).collect(), + uncles: b.uncles.to_vec(), + } + }, latest_block_number) } fn pending_transactions(&self, latest_block_number: BlockNumber) -> Option> { - self.map_existing_pending_block(|b| b.transactions().into_iter().cloned().collect(), latest_block_number) + self.map_existing_pending_block(|b| b.transactions.iter().cloned().collect(), latest_block_number) } } diff --git a/ethcore/src/tests/client.rs b/ethcore/src/tests/client.rs index 60ea5e1f0e9..4d12bb1385e 100644 --- a/ethcore/src/tests/client.rs +++ b/ethcore/src/tests/client.rs @@ -27,7 +27,6 @@ use types::filter::Filter; use types::view; use types::views::BlockView; -use block::IsBlock; use client::{BlockChainClient, Client, ClientConfig, BlockId, ChainInfo, BlockInfo, PrepareOpenBlock, ImportSealedBlock, ImportBlock}; use ethereum; use executive::{Executive, TransactOptions}; @@ -254,7 +253,7 @@ fn can_mine() { let b = client.prepare_open_block(Address::default(), (3141562.into(), 31415620.into()), vec![]).unwrap().close().unwrap(); - assert_eq!(*b.block().header().parent_hash(), view!(BlockView, &dummy_blocks[0]).header_view().hash()); + assert_eq!(*b.header.parent_hash(), view!(BlockView, &dummy_blocks[0]).header_view().hash()); } #[test] diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index 77618c85328..b16651bd9c5 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -20,7 +20,7 @@ use std::sync::Arc; use std::collections::{BTreeMap, BTreeSet, HashMap}; use bytes::Bytes; -use ethcore::block::{SealedBlock, IsBlock}; +use ethcore::block::SealedBlock; use ethcore::client::{Nonce, PrepareOpenBlock, StateClient, EngineInfo}; use ethcore::engines::{EthEngine, signer::EngineSigner}; use ethcore::error::Error; @@ -193,7 +193,7 @@ impl MinerService for TestMinerService { let params = self.authoring_params(); let open_block = chain.prepare_open_block(params.author, params.gas_range_target, params.extra_data).unwrap(); let closed = open_block.close().unwrap(); - let header = closed.header(); + let header = &closed.header; Some((header.hash(), header.number(), header.timestamp(), *header.difficulty())) }