diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index cd02b9a1b..784e71dc0 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -245,11 +245,11 @@ impl<'x> OpenBlock<'x> { last_hashes: last_hashes, }; - r.block.base.header.parent_hash = parent.hash(); - r.block.base.header.number = parent.number + 1; - r.block.base.header.author = author; + r.block.base.header.set_parent_hash(parent.hash()); + r.block.base.header.set_number(parent.number() + 1); + r.block.base.header.set_author(author); r.block.base.header.set_timestamp_now(parent.timestamp()); - r.block.base.header.extra_data = extra_data; + r.block.base.header.set_extra_data(extra_data); r.block.base.header.note_dirty(); engine.populate_from_parent(&mut r.block.base.header, parent, gas_range_target.0, gas_range_target.1); @@ -309,13 +309,13 @@ impl<'x> OpenBlock<'x> { pub fn env_info(&self) -> EnvInfo { // TODO: memoise. EnvInfo { - number: self.block.base.header.number, - author: self.block.base.header.author.clone(), - timestamp: self.block.base.header.timestamp, - difficulty: self.block.base.header.difficulty.clone(), + number: self.block.base.header.number(), + author: self.block.base.header.author().clone(), + timestamp: self.block.base.header.timestamp(), + difficulty: self.block.base.header.difficulty().clone(), last_hashes: self.last_hashes.clone(), gas_used: self.block.receipts.last().map_or(U256::zero(), |r| r.gas_used), - gas_limit: self.block.base.header.gas_limit.clone(), + gas_limit: self.block.base.header.gas_limit().clone(), } } @@ -349,14 +349,13 @@ impl<'x> OpenBlock<'x> { let unclosed_state = s.block.state.clone(); s.engine.on_close_block(&mut s.block); - s.block.base.header.transactions_root = ordered_trie_root(s.block.base.transactions.iter().map(|e| e.rlp_bytes().to_vec()).collect()); + s.block.base.header.set_transactions_root(ordered_trie_root(s.block.base.transactions.iter().map(|e| e.rlp_bytes().to_vec()).collect())); let uncle_bytes = s.block.base.uncles.iter().fold(RlpStream::new_list(s.block.base.uncles.len()), |mut s, u| {s.append_raw(&u.rlp(Seal::With), 1); s} ).out(); - s.block.base.header.uncles_hash = uncle_bytes.sha3(); - s.block.base.header.state_root = s.block.state.root().clone(); - s.block.base.header.receipts_root = ordered_trie_root(s.block.receipts.iter().map(|r| r.rlp_bytes().to_vec()).collect()); - s.block.base.header.log_bloom = s.block.receipts.iter().fold(LogBloom::zero(), |mut b, r| {b = &b | &r.log_bloom; b}); //TODO: use |= operator - s.block.base.header.gas_used = s.block.receipts.last().map_or(U256::zero(), |r| r.gas_used); - s.block.base.header.note_dirty(); + s.block.base.header.set_uncles_hash(uncle_bytes.sha3()); + s.block.base.header.set_state_root(s.block.state.root().clone()); + s.block.base.header.set_receipts_root(ordered_trie_root(s.block.receipts.iter().map(|r| r.rlp_bytes().to_vec()).collect())); + s.block.base.header.set_log_bloom(s.block.receipts.iter().fold(LogBloom::zero(), |mut b, r| {b = &b | &r.log_bloom; b})); //TODO: use |= operator + s.block.base.header.set_gas_used(s.block.receipts.last().map_or(U256::zero(), |r| r.gas_used)); ClosedBlock { block: s.block, @@ -371,20 +370,19 @@ impl<'x> OpenBlock<'x> { let mut s = self; s.engine.on_close_block(&mut s.block); - if s.block.base.header.transactions_root.is_zero() || s.block.base.header.transactions_root == SHA3_NULL_RLP { - s.block.base.header.transactions_root = ordered_trie_root(s.block.base.transactions.iter().map(|e| e.rlp_bytes().to_vec()).collect()); + if s.block.base.header.transactions_root().is_zero() || s.block.base.header.transactions_root() == &SHA3_NULL_RLP { + s.block.base.header.set_transactions_root(ordered_trie_root(s.block.base.transactions.iter().map(|e| e.rlp_bytes().to_vec()).collect())); } let uncle_bytes = s.block.base.uncles.iter().fold(RlpStream::new_list(s.block.base.uncles.len()), |mut s, u| {s.append_raw(&u.rlp(Seal::With), 1); s} ).out(); - if s.block.base.header.uncles_hash.is_zero() { - s.block.base.header.uncles_hash = uncle_bytes.sha3(); + if s.block.base.header.uncles_hash().is_zero() { + s.block.base.header.set_uncles_hash(uncle_bytes.sha3()); } - if s.block.base.header.receipts_root.is_zero() || s.block.base.header.receipts_root == SHA3_NULL_RLP { - s.block.base.header.receipts_root = ordered_trie_root(s.block.receipts.iter().map(|r| r.rlp_bytes().to_vec()).collect()); + if s.block.base.header.receipts_root().is_zero() || s.block.base.header.receipts_root() == &SHA3_NULL_RLP { + s.block.base.header.set_receipts_root(ordered_trie_root(s.block.receipts.iter().map(|r| r.rlp_bytes().to_vec()).collect())); } - s.block.base.header.state_root = s.block.state.root().clone(); - s.block.base.header.log_bloom = s.block.receipts.iter().fold(LogBloom::zero(), |mut b, r| {b = &b | &r.log_bloom; b}); //TODO: use |= operator - s.block.base.header.gas_used = s.block.receipts.last().map_or(U256::zero(), |r| r.gas_used); - s.block.base.header.note_dirty(); + s.block.base.header.set_state_root(s.block.state.root().clone()); + s.block.base.header.set_log_bloom(s.block.receipts.iter().fold(LogBloom::zero(), |mut b, r| {b = &b | &r.log_bloom; b})); //TODO: use |= operator + s.block.base.header.set_gas_used(s.block.receipts.last().map_or(U256::zero(), |r| r.gas_used)); LockedBlock { block: s.block, @@ -625,9 +623,9 @@ mod tests { 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 mut uncle1_header = Header::new(); - uncle1_header.extra_data = b"uncle1".to_vec(); + uncle1_header.set_extra_data(b"uncle1".to_vec()); let mut uncle2_header = Header::new(); - uncle2_header.extra_data = b"uncle2".to_vec(); + uncle2_header.set_extra_data(b"uncle2".to_vec()); open_block.push_uncle(uncle1_header).unwrap(); open_block.push_uncle(uncle2_header).unwrap(); let b = open_block.close_and_lock().seal(engine, vec![]).unwrap(); @@ -643,7 +641,7 @@ mod tests { let bytes = e.rlp_bytes(); assert_eq!(bytes, orig_bytes); let uncles = BlockView::new(&bytes).uncles(); - assert_eq!(uncles[1].extra_data, b"uncle2"); + assert_eq!(uncles[1].extra_data(), b"uncle2"); let db = e.drain(); assert_eq!(orig_db.keys(), db.keys()); diff --git a/ethcore/src/block_queue.rs b/ethcore/src/block_queue.rs index 89a620493..7d686cec0 100644 --- a/ethcore/src/block_queue.rs +++ b/ethcore/src/block_queue.rs @@ -260,7 +260,7 @@ impl BlockQueue { fn drain_verifying(verifying: &mut VecDeque, verified: &mut VecDeque, bad: &mut HashSet) { while !verifying.is_empty() && verifying.front().unwrap().block.is_some() { let block = verifying.pop_front().unwrap().block.unwrap(); - if bad.contains(&block.header.parent_hash) { + if bad.contains(block.header.parent_hash()) { bad.insert(block.header.hash()); } else { @@ -313,7 +313,7 @@ impl BlockQueue { return Err(ImportError::KnownBad.into()); } - if bad.contains(&header.parent_hash) { + if bad.contains(header.parent_hash()) { bad.insert(h.clone()); return Err(ImportError::KnownBad.into()); } @@ -351,7 +351,7 @@ impl BlockQueue { let mut new_verified = VecDeque::new(); for block in verified.drain(..) { - if bad.contains(&block.header.parent_hash) { + if bad.contains(block.header.parent_hash()) { bad.insert(block.header.hash()); processing.remove(&block.header.hash()); } else { diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index 379d77407..a581e59e9 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -1434,7 +1434,7 @@ mod tests { let mut block_header = bc.block_header(&best_hash); while !block_header.is_none() { - block_header = bc.block_header(&block_header.unwrap().parent_hash); + block_header = bc.block_header(&block_header.unwrap().parent_hash()); } assert!(bc.cache_size().blocks > 1024 * 1024); diff --git a/ethcore/src/blockchain/generator/block.rs b/ethcore/src/blockchain/generator/block.rs index 0a3dad399..238051d2a 100644 --- a/ethcore/src/blockchain/generator/block.rs +++ b/ethcore/src/blockchain/generator/block.rs @@ -44,21 +44,22 @@ impl Encodable for Block { impl Forkable for Block { fn fork(mut self, fork_number: usize) -> Self where Self: Sized { - self.header.difficulty = self.header.difficulty - U256::from(fork_number); + let difficulty = self.header.difficulty().clone() - U256::from(fork_number); + self.header.set_difficulty(difficulty); self } } impl WithBloom for Block { fn with_bloom(mut self, bloom: H2048) -> Self where Self: Sized { - self.header.log_bloom = bloom; + self.header.set_log_bloom(bloom); self } } impl CompleteBlock for Block { fn complete(mut self, parent_hash: H256) -> Bytes { - self.header.parent_hash = parent_hash; + self.header.set_parent_hash(parent_hash); encode(&self).to_vec() } } diff --git a/ethcore/src/blockchain/generator/generator.rs b/ethcore/src/blockchain/generator/generator.rs index 07ce7242b..179839b5a 100644 --- a/ethcore/src/blockchain/generator/generator.rs +++ b/ethcore/src/blockchain/generator/generator.rs @@ -73,8 +73,8 @@ pub struct ChainGenerator { impl ChainGenerator { fn prepare_block(&self) -> Block { let mut block = Block::default(); - block.header.number = self.number; - block.header.difficulty = self.difficulty; + block.header.set_number(self.number); + block.header.set_difficulty(self.difficulty); block } } diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 78669912c..edd671b70 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -99,7 +99,7 @@ impl ClientReport { pub fn accrue_block(&mut self, block: &PreverifiedBlock) { self.blocks_imported += 1; self.transactions_applied += block.transactions.len(); - self.gas_processed = self.gas_processed + block.header.gas_used; + self.gas_processed = self.gas_processed + block.header.gas_used().clone(); } } @@ -284,15 +284,15 @@ impl Client { }; // Check if Parent is in chain - let chain_has_parent = self.chain.block_header(&header.parent_hash); + let chain_has_parent = self.chain.block_header(header.parent_hash()); if let None = chain_has_parent { - warn!(target: "client", "Block import failed for #{} ({}): Parent not found ({}) ", header.number(), header.hash(), header.parent_hash); + warn!(target: "client", "Block import failed for #{} ({}): Parent not found ({}) ", header.number(), header.hash(), header.parent_hash()); return Err(()); }; // Enact Verified Block let parent = chain_has_parent.unwrap(); - let last_hashes = self.build_last_hashes(header.parent_hash.clone()); + let last_hashes = self.build_last_hashes(header.parent_hash().clone()); let db = self.state_db.lock().boxed_clone(); let enact_result = enact_verified(block, engine, self.tracedb.tracing_enabled(), db, &parent, last_hashes, self.factories.clone()); @@ -352,7 +352,7 @@ impl Client { for block in blocks { let header = &block.header; - if invalid_blocks.contains(&header.parent_hash) { + if invalid_blocks.contains(header.parent_hash()) { invalid_blocks.insert(header.hash()); continue; } diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 8e26a6b0c..fb7f9083e 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -169,19 +169,19 @@ impl TestBlockChainClient { let len = self.numbers.read().len(); for n in len..(len + count) { let mut header = BlockHeader::new(); - header.difficulty = From::from(n); - header.parent_hash = self.last_hash.read().clone(); - header.number = n as BlockNumber; - header.gas_limit = U256::from(1_000_000); + header.set_difficulty(From::from(n)); + header.set_parent_hash(self.last_hash.read().clone()); + header.set_number(n as BlockNumber); + header.set_gas_limit(U256::from(1_000_000)); let uncles = match with { EachBlockWith::Uncle | EachBlockWith::UncleAndTransaction => { let mut uncles = RlpStream::new_list(1); let mut uncle_header = BlockHeader::new(); - uncle_header.difficulty = From::from(n); - uncle_header.parent_hash = self.last_hash.read().clone(); - uncle_header.number = n as BlockNumber; + uncle_header.set_difficulty(From::from(n)); + uncle_header.set_parent_hash(self.last_hash.read().clone()); + uncle_header.set_number(n as BlockNumber); uncles.append(&uncle_header); - header.uncles_hash = uncles.as_raw().sha3(); + header.set_uncles_hash(uncles.as_raw().sha3()); uncles }, _ => RlpStream::new_list(0) @@ -219,7 +219,7 @@ impl TestBlockChainClient { pub fn corrupt_block(&mut self, n: BlockNumber) { let hash = self.block_hash(BlockID::Number(n)).unwrap(); let mut header: BlockHeader = decode(&self.block_header(BlockID::Number(n)).unwrap()); - header.extra_data = b"This extra data is way too long to be considered valid".to_vec(); + header.set_extra_data(b"This extra data is way too long to be considered valid".to_vec()); let mut rlp = RlpStream::new_list(3); rlp.append(&header); rlp.append_raw(&rlp::NULL_RLP, 1); @@ -231,7 +231,7 @@ impl TestBlockChainClient { pub fn corrupt_block_parent(&mut self, n: BlockNumber) { let hash = self.block_hash(BlockID::Number(n)).unwrap(); let mut header: BlockHeader = decode(&self.block_header(BlockID::Number(n)).unwrap()); - header.parent_hash = H256::from(42); + header.set_parent_hash(H256::from(42)); let mut rlp = RlpStream::new_list(3); rlp.append(&header); rlp.append_raw(&rlp::NULL_RLP, 1); @@ -470,20 +470,20 @@ impl BlockChainClient for TestBlockChainClient { fn import_block(&self, b: Bytes) -> Result { let header = Rlp::new(&b).val_at::(0); let h = header.hash(); - let number: usize = header.number as usize; + let number: usize = header.number() as usize; if number > self.blocks.read().len() { panic!("Unexpected block number. Expected {}, got {}", self.blocks.read().len(), number); } if number > 0 { - match self.blocks.read().get(&header.parent_hash) { + match self.blocks.read().get(header.parent_hash()) { Some(parent) => { let parent = Rlp::new(parent).val_at::(0); - if parent.number != (header.number - 1) { + if parent.number() != (header.number() - 1) { panic!("Unexpected block parent"); } }, None => { - panic!("Unknown block parent {:?} for block {}", header.parent_hash, number); + panic!("Unknown block parent {:?} for block {}", header.parent_hash(), number); } } } @@ -491,18 +491,18 @@ impl BlockChainClient for TestBlockChainClient { if number == len { { let mut difficulty = self.difficulty.write(); - *difficulty = *difficulty + header.difficulty; + *difficulty = *difficulty + header.difficulty().clone(); } mem::replace(&mut *self.last_hash.write(), h.clone()); self.blocks.write().insert(h.clone(), b); self.numbers.write().insert(number, h.clone()); - let mut parent_hash = header.parent_hash; + let mut parent_hash = header.parent_hash().clone(); if number > 0 { let mut n = number - 1; while n > 0 && self.numbers.read()[&n] != parent_hash { *self.numbers.write().get_mut(&n).unwrap() = parent_hash.clone(); n -= 1; - parent_hash = Rlp::new(&self.blocks.read()[&parent_hash]).val_at::(0).parent_hash; + parent_hash = Rlp::new(&self.blocks.read()[&parent_hash]).val_at::(0).parent_hash().clone(); } } } diff --git a/ethcore/src/engines/basic_authority.rs b/ethcore/src/engines/basic_authority.rs index 926399d7b..332d947c3 100644 --- a/ethcore/src/engines/basic_authority.rs +++ b/ethcore/src/engines/basic_authority.rs @@ -82,17 +82,16 @@ impl Engine for BasicAuthority { } fn populate_from_parent(&self, header: &mut Header, parent: &Header, gas_floor_target: U256, _gas_ceil_target: U256) { - header.difficulty = parent.difficulty; - header.gas_limit = { - let gas_limit = parent.gas_limit; + header.set_difficulty(parent.difficulty().clone()); + header.set_gas_limit({ + let gas_limit = parent.gas_limit().clone(); let bound_divisor = self.our_params.gas_limit_bound_divisor; if gas_limit < gas_floor_target { min(gas_floor_target, gas_limit + gas_limit / bound_divisor - 1.into()) } else { max(gas_floor_target, gas_limit - gas_limit / bound_divisor + 1.into()) } - }; - header.note_dirty(); + }); // info!("ethash: populate_from_parent #{}: difficulty={} and gas_limit={}", header.number, header.difficulty, header.gas_limit); } @@ -123,9 +122,9 @@ impl Engine for BasicAuthority { fn verify_block_basic(&self, header: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> { // check the seal fields. // TODO: pull this out into common code. - if header.seal.len() != self.seal_fields() { + if header.seal().len() != self.seal_fields() { return Err(From::from(BlockError::InvalidSealArity( - Mismatch { expected: self.seal_fields(), found: header.seal.len() } + Mismatch { expected: self.seal_fields(), found: header.seal().len() } ))); } Ok(()) @@ -133,7 +132,7 @@ impl Engine for BasicAuthority { fn verify_block_unordered(&self, header: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> { // check the signature is legit. - let sig = try!(UntrustedRlp::new(&header.seal[0]).as_val::()); + let sig = try!(UntrustedRlp::new(&header.seal()[0]).as_val::()); let signer = public_to_address(&try!(recover(&sig.into(), &header.bare_hash()))); if !self.our_params.authorities.contains(&signer) { return try!(Err(BlockError::InvalidSeal)); @@ -152,10 +151,10 @@ impl Engine for BasicAuthority { return Err(From::from(BlockError::InvalidDifficulty(Mismatch { expected: *parent.difficulty(), found: *header.difficulty() }))) } let gas_limit_divisor = self.our_params.gas_limit_bound_divisor; - let min_gas = parent.gas_limit - parent.gas_limit / gas_limit_divisor; - let max_gas = parent.gas_limit + parent.gas_limit / gas_limit_divisor; - if header.gas_limit <= min_gas || header.gas_limit >= max_gas { - return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds { min: Some(min_gas), max: Some(max_gas), found: header.gas_limit }))); + let min_gas = parent.gas_limit().clone() - parent.gas_limit().clone() / gas_limit_divisor; + let max_gas = parent.gas_limit().clone() + parent.gas_limit().clone() / gas_limit_divisor; + if header.gas_limit() <= &min_gas || header.gas_limit() >= &max_gas { + return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds { min: Some(min_gas), max: Some(max_gas), found: header.gas_limit().clone() }))); } Ok(()) } diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index e7738fbaa..6414ba5e4 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -108,9 +108,8 @@ pub trait Engine : Sync + Send { /// Don't forget to call Super::populate_from_parent when subclassing & overriding. // TODO: consider including State in the params. fn populate_from_parent(&self, header: &mut Header, parent: &Header, _gas_floor_target: U256, _gas_ceil_target: U256) { - header.difficulty = parent.difficulty; - header.gas_limit = parent.gas_limit; - header.note_dirty(); + header.set_difficulty(parent.difficulty().clone()); + header.set_gas_limit(parent.gas_limit().clone()); } // TODO: builtin contract routing - to do this properly, it will require removing the built-in configuration-reading logic diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index c658432a2..82a74d9ea 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -114,9 +114,9 @@ impl Engine for Ethash { } fn populate_from_parent(&self, header: &mut Header, parent: &Header, gas_floor_target: U256, gas_ceil_target: U256) { - header.difficulty = self.calculate_difficuty(header, parent); - header.gas_limit = { - let gas_limit = parent.gas_limit; + let difficulty = self.calculate_difficulty(header, parent); + let gas_limit = { + let gas_limit = parent.gas_limit().clone(); let bound_divisor = self.ethash_params.gas_limit_bound_divisor; if gas_limit < gas_floor_target { min(gas_floor_target, gas_limit + gas_limit / bound_divisor - 1.into()) @@ -126,21 +126,23 @@ impl Engine for Ethash { min(gas_ceil_target, max(gas_floor_target, gas_limit - gas_limit / bound_divisor + 1.into() + - (header.gas_used * 6.into() / 5.into()) / bound_divisor)) + (header.gas_used().clone() * 6.into() / 5.into()) / bound_divisor)) } }; - if header.number >= self.ethash_params.dao_hardfork_transition && - header.number <= self.ethash_params.dao_hardfork_transition + 9 { - header.extra_data = b"dao-hard-fork"[..].to_owned(); + header.set_difficulty(difficulty); + header.set_gas_limit(gas_limit); + if header.number() >= self.ethash_params.dao_hardfork_transition && + header.number() <= self.ethash_params.dao_hardfork_transition + 9 { + header.set_extra_data(b"dao-hard-fork"[..].to_owned()); } header.note_dirty(); -// info!("ethash: populate_from_parent #{}: difficulty={} and gas_limit={}", header.number, header.difficulty, header.gas_limit); +// info!("ethash: populate_from_parent #{}: difficulty={} and gas_limit={}", header.number(), header.difficulty(), header.gas_limit()); } fn on_new_block(&self, block: &mut ExecutedBlock) { - if block.fields().header.number == self.ethash_params.dao_hardfork_transition { + if block.fields().header.number() == self.ethash_params.dao_hardfork_transition { // TODO: enable trigger function maybe? -// if block.fields().header.gas_limit <= 4_000_000.into() { +// if block.fields().header.gas_limit() <= 4_000_000.into() { let mut state = block.fields_mut().state; for child in &self.ethash_params.dao_hardfork_accounts { let b = state.balance(child); @@ -157,7 +159,7 @@ impl Engine for Ethash { let fields = block.fields_mut(); // Bestow block reward - fields.state.add_balance(&fields.header.author, &(reward + reward / U256::from(32) * U256::from(fields.uncles.len()))); + fields.state.add_balance(&fields.header.author(), &(reward + reward / U256::from(32) * U256::from(fields.uncles.len()))); // Bestow uncle rewards let current_number = fields.header.number(); @@ -171,18 +173,18 @@ impl Engine for Ethash { fn verify_block_basic(&self, header: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> { // check the seal fields. - if header.seal.len() != self.seal_fields() { + if header.seal().len() != self.seal_fields() { return Err(From::from(BlockError::InvalidSealArity( - Mismatch { expected: self.seal_fields(), found: header.seal.len() } + Mismatch { expected: self.seal_fields(), found: header.seal().len() } ))); } - try!(UntrustedRlp::new(&header.seal[0]).as_val::()); - try!(UntrustedRlp::new(&header.seal[1]).as_val::()); + try!(UntrustedRlp::new(&header.seal()[0]).as_val::()); + try!(UntrustedRlp::new(&header.seal()[1]).as_val::()); // TODO: consider removing these lines. let min_difficulty = self.ethash_params.minimum_difficulty; - if header.difficulty < min_difficulty { - return Err(From::from(BlockError::DifficultyOutOfBounds(OutOfBounds { min: Some(min_difficulty), max: None, found: header.difficulty }))) + if header.difficulty() < &min_difficulty { + return Err(From::from(BlockError::DifficultyOutOfBounds(OutOfBounds { min: Some(min_difficulty), max: None, found: header.difficulty().clone() }))) } let difficulty = Ethash::boundary_to_difficulty(&Ethash::from_ethash(quick_get_difficulty( @@ -190,37 +192,37 @@ impl Engine for Ethash { header.nonce().low_u64(), &Ethash::to_ethash(header.mix_hash()) ))); - if difficulty < header.difficulty { - return Err(From::from(BlockError::InvalidProofOfWork(OutOfBounds { min: Some(header.difficulty), max: None, found: difficulty }))); + if &difficulty < header.difficulty() { + return Err(From::from(BlockError::InvalidProofOfWork(OutOfBounds { min: Some(header.difficulty().clone()), max: None, found: difficulty }))); } - if header.number >= self.ethash_params.dao_hardfork_transition && - header.number <= self.ethash_params.dao_hardfork_transition + 9 && - header.extra_data[..] != b"dao-hard-fork"[..] { + if header.number() >= self.ethash_params.dao_hardfork_transition && + header.number() <= self.ethash_params.dao_hardfork_transition + 9 && + header.extra_data()[..] != b"dao-hard-fork"[..] { return Err(From::from(BlockError::ExtraDataOutOfBounds(OutOfBounds { min: None, max: None, found: 0 }))); } - if header.gas_limit > 0x7fffffffffffffffu64.into() { - return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds { min: None, max: Some(0x7fffffffffffffffu64.into()), found: header.gas_limit }))); + if header.gas_limit() > &0x7fffffffffffffffu64.into() { + return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds { min: None, max: Some(0x7fffffffffffffffu64.into()), found: header.gas_limit().clone() }))); } Ok(()) } fn verify_block_unordered(&self, header: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> { - if header.seal.len() != self.seal_fields() { + if header.seal().len() != self.seal_fields() { return Err(From::from(BlockError::InvalidSealArity( - Mismatch { expected: self.seal_fields(), found: header.seal.len() } + Mismatch { expected: self.seal_fields(), found: header.seal().len() } ))); } - let result = self.pow.compute_light(header.number as u64, &Ethash::to_ethash(header.bare_hash()), header.nonce().low_u64()); + let result = self.pow.compute_light(header.number() as u64, &Ethash::to_ethash(header.bare_hash()), header.nonce().low_u64()); let mix = Ethash::from_ethash(result.mix_hash); let difficulty = Ethash::boundary_to_difficulty(&Ethash::from_ethash(result.value)); if mix != header.mix_hash() { return Err(From::from(BlockError::MismatchedH256SealElement(Mismatch { expected: mix, found: header.mix_hash() }))); } - if difficulty < header.difficulty { - return Err(From::from(BlockError::InvalidProofOfWork(OutOfBounds { min: Some(header.difficulty), max: None, found: difficulty }))); + if &difficulty < header.difficulty() { + return Err(From::from(BlockError::InvalidProofOfWork(OutOfBounds { min: Some(header.difficulty().clone()), max: None, found: difficulty }))); } Ok(()) } @@ -232,15 +234,15 @@ impl Engine for Ethash { } // Check difficulty is correct given the two timestamps. - let expected_difficulty = self.calculate_difficuty(header, parent); - if header.difficulty != expected_difficulty { - return Err(From::from(BlockError::InvalidDifficulty(Mismatch { expected: expected_difficulty, found: header.difficulty }))) + let expected_difficulty = self.calculate_difficulty(header, parent); + if header.difficulty() != &expected_difficulty { + return Err(From::from(BlockError::InvalidDifficulty(Mismatch { expected: expected_difficulty, found: header.difficulty().clone() }))) } let gas_limit_divisor = self.ethash_params.gas_limit_bound_divisor; - let min_gas = parent.gas_limit - parent.gas_limit / gas_limit_divisor; - let max_gas = parent.gas_limit + parent.gas_limit / gas_limit_divisor; - if header.gas_limit <= min_gas || header.gas_limit >= max_gas { - return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds { min: Some(min_gas), max: Some(max_gas), found: header.gas_limit }))); + let min_gas = parent.gas_limit().clone() - parent.gas_limit().clone() / gas_limit_divisor; + let max_gas = parent.gas_limit().clone() + parent.gas_limit().clone() / gas_limit_divisor; + if header.gas_limit() <= &min_gas || header.gas_limit() >= &max_gas { + return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds { min: Some(min_gas), max: Some(max_gas), found: header.gas_limit().clone() }))); } Ok(()) } @@ -259,9 +261,9 @@ impl Engine for Ethash { #[cfg_attr(feature="dev", allow(wrong_self_convention))] // to_ethash should take self impl Ethash { - fn calculate_difficuty(&self, header: &Header, parent: &Header) -> U256 { + fn calculate_difficulty(&self, header: &Header, parent: &Header) -> U256 { const EXP_DIFF_PERIOD: u64 = 100000; - if header.number == 0 { + if header.number() == 0 { panic!("Can't calculate genesis block difficulty"); } @@ -270,25 +272,25 @@ impl Ethash { let duration_limit = self.ethash_params.duration_limit; let frontier_limit = self.ethash_params.frontier_compatibility_mode_limit; - let mut target = if header.number < frontier_limit { - if header.timestamp >= parent.timestamp + duration_limit { - parent.difficulty - (parent.difficulty / difficulty_bound_divisor) + let mut target = if header.number() < frontier_limit { + if header.timestamp() >= parent.timestamp() + duration_limit { + parent.difficulty().clone() - (parent.difficulty().clone() / difficulty_bound_divisor) } else { - parent.difficulty + (parent.difficulty / difficulty_bound_divisor) + parent.difficulty().clone() + (parent.difficulty().clone() / difficulty_bound_divisor) } } else { - trace!(target: "ethash", "Calculating difficulty parent.difficulty={}, header.timestamp={}, parent.timestamp={}", parent.difficulty, header.timestamp, parent.timestamp); + trace!(target: "ethash", "Calculating difficulty parent.difficulty={}, header.timestamp={}, parent.timestamp={}", parent.difficulty(), header.timestamp(), parent.timestamp()); //block_diff = parent_diff + parent_diff // 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99) - let diff_inc = (header.timestamp - parent.timestamp) / 10; + let diff_inc = (header.timestamp() - parent.timestamp()) / 10; if diff_inc <= 1 { - parent.difficulty + parent.difficulty / From::from(2048) * From::from(1 - diff_inc) + parent.difficulty().clone() + parent.difficulty().clone() / From::from(2048) * From::from(1 - diff_inc) } else { - parent.difficulty - parent.difficulty / From::from(2048) * From::from(min(diff_inc - 1, 99)) + parent.difficulty().clone() - parent.difficulty().clone() / From::from(2048) * From::from(min(diff_inc - 1, 99)) } }; target = max(min_difficulty, target); - let period = ((parent.number + 1) / EXP_DIFF_PERIOD) as usize; + let period = ((parent.number() + 1) / EXP_DIFF_PERIOD) as usize; if period > 1 { target = max(min_difficulty, target + (U256::from(1) << (period - 2))); } @@ -336,7 +338,7 @@ impl Header { /// Set the nonce and mix hash fields of the header. pub fn set_nonce_and_mix_hash(&mut self, nonce: &H64, mix_hash: &H256) { - self.seal = vec![encode(mix_hash).to_vec(), encode(nonce).to_vec()]; + self.set_seal(vec![encode(mix_hash).to_vec(), encode(nonce).to_vec()]); } } @@ -374,7 +376,7 @@ mod tests { let mut b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap(); let mut uncle = Header::new(); let uncle_author: Address = "ef2d6d194084c2de36e0dabfce45d046b37d1106".into(); - uncle.author = uncle_author.clone(); + uncle.set_author(uncle_author); b.push_uncle(uncle).unwrap(); let b = b.close(); diff --git a/ethcore/src/ethereum/mod.rs b/ethcore/src/ethereum/mod.rs index 40e85d619..1efe001e5 100644 --- a/ethcore/src/ethereum/mod.rs +++ b/ethcore/src/ethereum/mod.rs @@ -68,7 +68,7 @@ mod tests { let mut db_result = get_temp_journal_db(); let mut db = db_result.take(); spec.ensure_db_good(db.as_hashdb_mut()).unwrap(); - let s = State::from_existing(db, genesis_header.state_root.clone(), engine.account_start_nonce(), Default::default()).unwrap(); + let s = State::from_existing(db, genesis_header.state_root().clone(), engine.account_start_nonce(), Default::default()).unwrap(); assert_eq!(s.balance(&"0000000000000000000000000000000000000001".into()), 1u64.into()); assert_eq!(s.balance(&"0000000000000000000000000000000000000002".into()), 1u64.into()); assert_eq!(s.balance(&"0000000000000000000000000000000000000003".into()), 1u64.into()); diff --git a/ethcore/src/header.rs b/ethcore/src/header.rs index a123197a9..9b0e155f4 100644 --- a/ethcore/src/header.rs +++ b/ethcore/src/header.rs @@ -33,43 +33,42 @@ pub type BlockNumber = u64; /// Doesn't do all that much on its own. #[derive(Debug, Clone, Eq)] pub struct Header { - // TODO: make all private. /// Parent hash. - pub parent_hash: H256, + parent_hash: H256, /// Block timestamp. - pub timestamp: u64, + timestamp: u64, /// Block number. - pub number: BlockNumber, + number: BlockNumber, /// Block author. - pub author: Address, + author: Address, /// Transactions root. - pub transactions_root: H256, + transactions_root: H256, /// Block uncles hash. - pub uncles_hash: H256, + uncles_hash: H256, /// Block extra data. - pub extra_data: Bytes, + extra_data: Bytes, /// State root. - pub state_root: H256, + state_root: H256, /// Block receipts root. - pub receipts_root: H256, + receipts_root: H256, /// Block bloom. - pub log_bloom: LogBloom, + log_bloom: LogBloom, /// Gas used for contracts execution. - pub gas_used: U256, + gas_used: U256, /// Block gas limit. - pub gas_limit: U256, + gas_limit: U256, /// Block difficulty. - pub difficulty: U256, + difficulty: U256, /// Vector of post-RLP-encoded fields. - pub seal: Vec, + seal: Vec, /// The memoized hash of the RLP representation *including* the seal fields. - pub hash: RefCell>, + hash: RefCell>, /// The memoized hash of the RLP representation *without* the seal fields. - pub bare_hash: RefCell>, + bare_hash: RefCell>, } impl PartialEq for Header { @@ -134,15 +133,21 @@ impl Header { /// Get the extra data field of the header. pub fn extra_data(&self) -> &Bytes { &self.extra_data } + /// Get a mutable reference to extra_data + pub fn extra_data_mut(&mut self) -> &mut Bytes { self.note_dirty(); &mut self.extra_data } /// Get the state root field of the header. pub fn state_root(&self) -> &H256 { &self.state_root } /// Get the receipts root field of the header. pub fn receipts_root(&self) -> &H256 { &self.receipts_root } + /// Get the log bloom field of the header. + pub fn log_bloom(&self) -> &LogBloom { &self.log_bloom } /// Get the transactions root field of the header. pub fn transactions_root(&self) -> &H256 { &self.transactions_root } /// Get the uncles hash field of the header. pub fn uncles_hash(&self) -> &H256 { &self.uncles_hash } + /// Get the gas used field of the header. + pub fn gas_used(&self) -> &U256 { &self.gas_used } /// Get the gas limit field of the header. pub fn gas_limit(&self) -> &U256 { &self.gas_limit } diff --git a/ethcore/src/snapshot/block.rs b/ethcore/src/snapshot/block.rs index f317cf54e..66fc06066 100644 --- a/ethcore/src/snapshot/block.rs +++ b/ethcore/src/snapshot/block.rs @@ -90,27 +90,26 @@ impl AbridgedBlock { let rlp = UntrustedRlp::new(&self.rlp).decompress(RlpType::Blocks); let rlp = UntrustedRlp::new(&rlp); - let mut header = Header { - parent_hash: parent_hash, - author: try!(rlp.val_at(0)), - state_root: try!(rlp.val_at(1)), - transactions_root: try!(rlp.val_at(2)), - receipts_root: try!(rlp.val_at(3)), - log_bloom: try!(rlp.val_at(4)), - difficulty: try!(rlp.val_at(5)), - number: number, - gas_limit: try!(rlp.val_at(6)), - gas_used: try!(rlp.val_at(7)), - timestamp: try!(rlp.val_at(8)), - extra_data: try!(rlp.val_at(9)), - ..Default::default() - }; + let mut header: Header = Default::default(); + header.set_parent_hash(parent_hash); + header.set_author(try!(rlp.val_at(0))); + header.set_state_root(try!(rlp.val_at(1))); + header.set_transactions_root(try!(rlp.val_at(2))); + header.set_receipts_root(try!(rlp.val_at(3))); + header.set_log_bloom(try!(rlp.val_at(4))); + header.set_difficulty(try!(rlp.val_at(5))); + header.set_number(number); + header.set_gas_limit(try!(rlp.val_at(6))); + header.set_gas_used(try!(rlp.val_at(7))); + header.set_timestamp(try!(rlp.val_at(8))); + header.set_extra_data(try!(rlp.val_at(9))); + let transactions = try!(rlp.val_at(10)); let uncles: Vec
= try!(rlp.val_at(11)); let mut uncles_rlp = RlpStream::new(); uncles_rlp.append(&uncles); - header.uncles_hash = uncles_rlp.as_raw().sha3(); + header.set_uncles_hash(uncles_rlp.as_raw().sha3()); let mut seal_fields = Vec::new(); for i in (HEADER_FIELDS + BLOCK_FIELDS)..rlp.item_count() { diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index a0c32d51a..7a03a2acd 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -25,8 +25,6 @@ use super::seal::Generic as GenericSeal; use ethereum; use ethjson; -use std::cell::RefCell; - /// Parameters common to all engines. #[derive(Debug, PartialEq, Clone)] #[cfg_attr(test, derive(Default))] @@ -161,32 +159,30 @@ impl Spec { /// Get the header of the genesis block. pub fn genesis_header(&self) -> Header { - Header { - parent_hash: self.parent_hash.clone(), - timestamp: self.timestamp, - number: 0, - author: self.author.clone(), - transactions_root: self.transactions_root.clone(), - uncles_hash: RlpStream::new_list(0).out().sha3(), - extra_data: self.extra_data.clone(), - state_root: self.state_root().clone(), - receipts_root: self.receipts_root.clone(), - log_bloom: H2048::new().clone(), - gas_used: self.gas_used.clone(), - gas_limit: self.gas_limit.clone(), - difficulty: self.difficulty.clone(), - seal: { - let seal = { - let mut s = RlpStream::new_list(self.seal_fields); - s.append_raw(&self.seal_rlp, self.seal_fields); - s.out() - }; - let r = Rlp::new(&seal); - (0..self.seal_fields).map(|i| r.at(i).as_raw().to_vec()).collect() - }, - hash: RefCell::new(None), - bare_hash: RefCell::new(None), - } + let mut header: Header = Default::default(); + header.set_parent_hash(self.parent_hash.clone()); + header.set_timestamp(self.timestamp); + header.set_number(0); + header.set_author(self.author.clone()); + header.set_transactions_root(self.transactions_root.clone()); + header.set_uncles_hash(RlpStream::new_list(0).out().sha3()); + header.set_extra_data(self.extra_data.clone()); + header.set_state_root(self.state_root().clone()); + header.set_receipts_root(self.receipts_root.clone()); + header.set_log_bloom(H2048::new().clone()); + header.set_gas_used(self.gas_used.clone()); + header.set_gas_limit(self.gas_limit.clone()); + header.set_difficulty(self.difficulty.clone()); + header.set_seal({ + let seal = { + let mut s = RlpStream::new_list(self.seal_fields); + s.append_raw(&self.seal_rlp, self.seal_fields); + s.out() + }; + let r = Rlp::new(&seal); + (0..self.seal_fields).map(|i| r.at(i).as_raw().to_vec()).collect() + }); + return header; } /// Compose the genesis block for this chain. diff --git a/ethcore/src/tests/client.rs b/ethcore/src/tests/client.rs index 1ac26c83b..26256a760 100644 --- a/ethcore/src/tests/client.rs +++ b/ethcore/src/tests/client.rs @@ -45,9 +45,9 @@ fn returns_state_root_basic() { let client_result = generate_dummy_client(6); let client = client_result.reference(); let test_spec = get_test_spec(); - let state_root = test_spec.genesis_header().state_root; + let genesis_header = test_spec.genesis_header(); - assert!(client.state_data(&state_root).is_some()); + assert!(client.state_data(genesis_header.state_root()).is_some()); } #[test] diff --git a/ethcore/src/tests/helpers.rs b/ethcore/src/tests/helpers.rs index 4942ace5a..f3975a0d0 100644 --- a/ethcore/src/tests/helpers.rs +++ b/ethcore/src/tests/helpers.rs @@ -84,26 +84,26 @@ pub fn create_test_block(header: &Header) -> Bytes { fn create_unverifiable_block_header(order: u32, parent_hash: H256) -> Header { let mut header = Header::new(); - header.gas_limit = 0.into(); - header.difficulty = (order * 100).into(); - header.timestamp = (order * 10) as u64; - header.number = order as u64; - header.parent_hash = parent_hash; - header.state_root = H256::zero(); + header.set_gas_limit(0.into()); + header.set_difficulty((order * 100).into()); + header.set_timestamp((order * 10) as u64); + header.set_number(order as u64); + header.set_parent_hash(parent_hash); + header.set_state_root(H256::zero()); header } fn create_unverifiable_block_with_extra(order: u32, parent_hash: H256, extra: Option) -> Bytes { let mut header = create_unverifiable_block_header(order, parent_hash); - header.extra_data = match extra { + header.set_extra_data(match extra { Some(extra_data) => extra_data, None => { let base = (order & 0x000000ff) as u8; let generated: Vec = vec![base + 1, base + 2, base + 3]; generated } - }; + }); create_test_block(&header) } @@ -204,7 +204,7 @@ pub fn push_blocks_to_client(client: &Arc, timestamp_salt: u64, starting let test_spec = get_test_spec(); let test_engine = &test_spec.engine; //let test_engine = test_spec.to_engine().unwrap(); - let state_root = test_spec.genesis_header().state_root; + let state_root = test_spec.genesis_header().state_root().clone(); let mut rolling_hash = client.chain_info().best_block_hash; let mut rolling_block_number = starting_number as u64; let mut rolling_timestamp = timestamp_salt + starting_number as u64 * 10; @@ -212,12 +212,12 @@ pub fn push_blocks_to_client(client: &Arc, timestamp_salt: u64, starting for _ in 0..block_number { let mut header = Header::new(); - header.gas_limit = test_engine.params().min_gas_limit; - header.difficulty = U256::from(0x20000); - header.timestamp = rolling_timestamp; - header.number = rolling_block_number; - header.parent_hash = rolling_hash; - header.state_root = state_root.clone(); + header.set_gas_limit(test_engine.params().min_gas_limit); + header.set_difficulty(U256::from(0x20000)); + header.set_timestamp(rolling_timestamp); + header.set_number(rolling_block_number); + header.set_parent_hash(rolling_hash); + header.set_state_root(state_root); rolling_hash = header.hash(); rolling_block_number = rolling_block_number + 1; @@ -345,12 +345,12 @@ pub fn get_good_dummy_block_fork_seq(start_number: usize, count: usize, parent_h let mut r = Vec::new(); for i in start_number .. start_number + count + 1 { let mut block_header = Header::new(); - block_header.gas_limit = test_engine.params().min_gas_limit; - block_header.difficulty = U256::from(i).mul(U256([0, 1, 0, 0])); - block_header.timestamp = rolling_timestamp; - block_header.number = i as u64; - block_header.parent_hash = parent; - block_header.state_root = test_spec.genesis_header().state_root; + block_header.set_gas_limit(test_engine.params().min_gas_limit); + block_header.set_difficulty(U256::from(i).mul(U256([0, 1, 0, 0]))); + block_header.set_timestamp(rolling_timestamp); + block_header.set_number(i as u64); + block_header.set_parent_hash(parent); + block_header.set_state_root(test_spec.genesis_header().state_root().clone()); parent = block_header.hash(); rolling_timestamp = rolling_timestamp + 10; @@ -365,12 +365,12 @@ pub fn get_good_dummy_block() -> Bytes { let mut block_header = Header::new(); let test_spec = get_test_spec(); let test_engine = &test_spec.engine; - block_header.gas_limit = test_engine.params().min_gas_limit; - block_header.difficulty = U256::from(0x20000); - block_header.timestamp = 40; - block_header.number = 1; - block_header.parent_hash = test_spec.genesis_header().hash(); - block_header.state_root = test_spec.genesis_header().state_root; + block_header.set_gas_limit(test_engine.params().min_gas_limit); + block_header.set_difficulty(U256::from(0x20000)); + block_header.set_timestamp(40); + block_header.set_number(1); + block_header.set_parent_hash(test_spec.genesis_header().hash()); + block_header.set_state_root(test_spec.genesis_header().state_root().clone()); create_test_block(&block_header) } @@ -379,12 +379,12 @@ pub fn get_bad_state_dummy_block() -> Bytes { let mut block_header = Header::new(); let test_spec = get_test_spec(); let test_engine = &test_spec.engine; - block_header.gas_limit = test_engine.params().min_gas_limit; - block_header.difficulty = U256::from(0x20000); - block_header.timestamp = 40; - block_header.number = 1; - block_header.parent_hash = test_spec.genesis_header().hash(); - block_header.state_root = 0xbad.into(); + block_header.set_gas_limit(test_engine.params().min_gas_limit); + block_header.set_difficulty(U256::from(0x20000)); + block_header.set_timestamp(40); + block_header.set_number(1); + block_header.set_parent_hash(test_spec.genesis_header().hash()); + block_header.set_state_root(0xbad.into()); create_test_block(&block_header) } diff --git a/ethcore/src/verification/verification.rs b/ethcore/src/verification/verification.rs index 9cea3bede..aa719cf23 100644 --- a/ethcore/src/verification/verification.rs +++ b/ethcore/src/verification/verification.rs @@ -38,7 +38,7 @@ pub struct PreverifiedBlock { /// Phase 1 quick block verification. Only does checks that are cheap. Operates on a single block pub fn verify_block_basic(header: &Header, bytes: &[u8], engine: &Engine) -> Result<(), Error> { try!(verify_header(&header, engine)); - try!(verify_block_integrity(bytes, &header.transactions_root, &header.uncles_hash)); + try!(verify_block_integrity(bytes, &header.transactions_root(), &header.uncles_hash())); try!(engine.verify_block_basic(&header, Some(bytes))); for u in try!(UntrustedRlp::new(bytes).at(2)).iter().map(|rlp| rlp.as_val::
()) { let u = try!(u); @@ -81,7 +81,7 @@ pub fn verify_block_unordered(header: Header, bytes: Bytes, engine: &Engine) -> /// Phase 3 verification. Check block information against parent and uncles. pub fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, bc: &BlockProvider) -> Result<(), Error> { // TODO: verify timestamp - let parent = try!(bc.block_header(&header.parent_hash).ok_or_else(|| Error::from(BlockError::UnknownParent(header.parent_hash.clone())))); + let parent = try!(bc.block_header(&header.parent_hash()).ok_or_else(|| Error::from(BlockError::UnknownParent(header.parent_hash().clone())))); try!(verify_parent(&header, &parent)); try!(engine.verify_block_family(&header, &parent, Some(bytes))); @@ -93,7 +93,7 @@ pub fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, bc: & let mut excluded = HashSet::new(); excluded.insert(header.hash()); - let mut hash = header.parent_hash.clone(); + let mut hash = header.parent_hash().clone(); excluded.insert(hash.clone()); for _ in 0..engine.maximum_uncle_age() { match bc.block_details(&hash) { @@ -122,12 +122,12 @@ pub fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, bc: & // 6 7 // (8 Invalid) - let depth = if header.number > uncle.number { header.number - uncle.number } else { 0 }; + let depth = if header.number() > uncle.number() { header.number() - uncle.number() } else { 0 }; if depth > engine.maximum_uncle_age() as u64 { - return Err(From::from(BlockError::UncleTooOld(OutOfBounds { min: Some(header.number - depth), max: Some(header.number - 1), found: uncle.number }))); + return Err(From::from(BlockError::UncleTooOld(OutOfBounds { min: Some(header.number() - depth), max: Some(header.number() - 1), found: uncle.number() }))); } else if depth < 1 { - return Err(From::from(BlockError::UncleIsBrother(OutOfBounds { min: Some(header.number - depth), max: Some(header.number - 1), found: uncle.number }))); + return Err(From::from(BlockError::UncleIsBrother(OutOfBounds { min: Some(header.number() - depth), max: Some(header.number() - 1), found: uncle.number() }))); } // cB @@ -139,8 +139,8 @@ pub fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, bc: & // cB.p^6 -----------/ 6 // cB.p^7 -------------/ // cB.p^8 - let mut expected_uncle_parent = header.parent_hash.clone(); - let uncle_parent = try!(bc.block_header(&uncle.parent_hash).ok_or_else(|| Error::from(BlockError::UnknownUncleParent(uncle.parent_hash.clone())))); + let mut expected_uncle_parent = header.parent_hash().clone(); + let uncle_parent = try!(bc.block_header(&uncle.parent_hash()).ok_or_else(|| Error::from(BlockError::UnknownUncleParent(uncle.parent_hash().clone())))); for _ in 0..depth { match bc.block_details(&expected_uncle_parent) { Some(details) => { @@ -162,50 +162,50 @@ pub fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, bc: & /// Phase 4 verification. Check block information against transaction enactment results, pub fn verify_block_final(expected: &Header, got: &Header) -> Result<(), Error> { - if expected.gas_used != got.gas_used { - return Err(From::from(BlockError::InvalidGasUsed(Mismatch { expected: expected.gas_used, found: got.gas_used }))) + if expected.gas_used() != got.gas_used() { + return Err(From::from(BlockError::InvalidGasUsed(Mismatch { expected: expected.gas_used().clone(), found: got.gas_used().clone() }))) } - if expected.log_bloom != got.log_bloom { - return Err(From::from(BlockError::InvalidLogBloom(Mismatch { expected: expected.log_bloom.clone(), found: got.log_bloom.clone() }))) + if expected.log_bloom() != got.log_bloom() { + return Err(From::from(BlockError::InvalidLogBloom(Mismatch { expected: expected.log_bloom().clone(), found: got.log_bloom().clone() }))) } - if expected.state_root != got.state_root { - return Err(From::from(BlockError::InvalidStateRoot(Mismatch { expected: expected.state_root.clone(), found: got.state_root.clone() }))) + if expected.state_root() != got.state_root() { + return Err(From::from(BlockError::InvalidStateRoot(Mismatch { expected: expected.state_root().clone(), found: got.state_root().clone() }))) } - if expected.receipts_root != got.receipts_root { - return Err(From::from(BlockError::InvalidReceiptsRoot(Mismatch { expected: expected.receipts_root.clone(), found: got.receipts_root.clone() }))) + if expected.receipts_root() != got.receipts_root() { + return Err(From::from(BlockError::InvalidReceiptsRoot(Mismatch { expected: expected.receipts_root().clone(), found: got.receipts_root().clone() }))) } Ok(()) } /// Check basic header parameters. fn verify_header(header: &Header, engine: &Engine) -> Result<(), Error> { - if header.number >= From::from(BlockNumber::max_value()) { - return Err(From::from(BlockError::RidiculousNumber(OutOfBounds { max: Some(From::from(BlockNumber::max_value())), min: None, found: header.number }))) + if header.number() >= From::from(BlockNumber::max_value()) { + return Err(From::from(BlockError::RidiculousNumber(OutOfBounds { max: Some(From::from(BlockNumber::max_value())), min: None, found: header.number() }))) } - if header.gas_used > header.gas_limit { - return Err(From::from(BlockError::TooMuchGasUsed(OutOfBounds { max: Some(header.gas_limit), min: None, found: header.gas_used }))); + if header.gas_used() > header.gas_limit() { + return Err(From::from(BlockError::TooMuchGasUsed(OutOfBounds { max: Some(header.gas_limit().clone()), min: None, found: header.gas_used().clone() }))); } let min_gas_limit = engine.params().min_gas_limit; - if header.gas_limit < min_gas_limit { - return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds { min: Some(min_gas_limit), max: None, found: header.gas_limit }))); + if header.gas_limit() < &min_gas_limit { + return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds { min: Some(min_gas_limit), max: None, found: header.gas_limit().clone() }))); } let maximum_extra_data_size = engine.maximum_extra_data_size(); - if header.number != 0 && header.extra_data.len() > maximum_extra_data_size { - return Err(From::from(BlockError::ExtraDataOutOfBounds(OutOfBounds { min: None, max: Some(maximum_extra_data_size), found: header.extra_data.len() }))); + if header.number() != 0 && header.extra_data().len() > maximum_extra_data_size { + return Err(From::from(BlockError::ExtraDataOutOfBounds(OutOfBounds { min: None, max: Some(maximum_extra_data_size), found: header.extra_data().len() }))); } Ok(()) } /// Check header parameters agains parent header. fn verify_parent(header: &Header, parent: &Header) -> Result<(), Error> { - if !header.parent_hash.is_zero() && parent.hash() != header.parent_hash { - return Err(From::from(BlockError::InvalidParentHash(Mismatch { expected: parent.hash(), found: header.parent_hash.clone() }))) + if !header.parent_hash().is_zero() && &parent.hash() != header.parent_hash() { + return Err(From::from(BlockError::InvalidParentHash(Mismatch { expected: parent.hash(), found: header.parent_hash().clone() }))) } - if header.timestamp <= parent.timestamp { - return Err(From::from(BlockError::InvalidTimestamp(OutOfBounds { max: None, min: Some(parent.timestamp + 1), found: header.timestamp }))) + if header.timestamp() <= parent.timestamp() { + return Err(From::from(BlockError::InvalidTimestamp(OutOfBounds { max: None, min: Some(parent.timestamp() + 1), found: header.timestamp() }))) } - if header.number != parent.number + 1 { - return Err(From::from(BlockError::InvalidNumber(Mismatch { expected: parent.number + 1, found: header.number }))); + if header.number() != parent.number() + 1 { + return Err(From::from(BlockError::InvalidNumber(Mismatch { expected: parent.number() + 1, found: header.number() }))); } Ok(()) } @@ -307,9 +307,9 @@ mod tests { self.blocks.get(hash).map(|bytes| { let header = BlockView::new(bytes).header(); BlockDetails { - number: header.number, - total_difficulty: header.difficulty, - parent: header.parent_hash, + number: header.number(), + total_difficulty: header.difficulty().clone(), + parent: header.parent_hash().clone(), children: Vec::new(), } }) @@ -352,9 +352,9 @@ mod tests { let engine = &*spec.engine; let min_gas_limit = engine.params().min_gas_limit; - good.gas_limit = min_gas_limit; - good.timestamp = 40; - good.number = 10; + good.set_gas_limit(min_gas_limit); + good.set_timestamp(40); + good.set_number(10); let keypair = Random.generate().unwrap(); @@ -381,31 +381,31 @@ mod tests { let diff_inc = U256::from(0x40); let mut parent6 = good.clone(); - parent6.number = 6; + parent6.set_number(6); let mut parent7 = good.clone(); - parent7.number = 7; - parent7.parent_hash = parent6.hash(); - parent7.difficulty = parent6.difficulty + diff_inc; - parent7.timestamp = parent6.timestamp + 10; + parent7.set_number(7); + parent7.set_parent_hash(parent6.hash()); + parent7.set_difficulty(parent6.difficulty().clone() + diff_inc); + parent7.set_timestamp(parent6.timestamp() + 10); let mut parent8 = good.clone(); - parent8.number = 8; - parent8.parent_hash = parent7.hash(); - parent8.difficulty = parent7.difficulty + diff_inc; - parent8.timestamp = parent7.timestamp + 10; + parent8.set_number(8); + parent8.set_parent_hash(parent7.hash()); + parent8.set_difficulty(parent7.difficulty().clone() + diff_inc); + parent8.set_timestamp(parent7.timestamp() + 10); let mut good_uncle1 = good.clone(); - good_uncle1.number = 9; - good_uncle1.parent_hash = parent8.hash(); - good_uncle1.difficulty = parent8.difficulty + diff_inc; - good_uncle1.timestamp = parent8.timestamp + 10; - good_uncle1.extra_data.push(1u8); + good_uncle1.set_number(9); + good_uncle1.set_parent_hash(parent8.hash()); + good_uncle1.set_difficulty(parent8.difficulty().clone() + diff_inc); + good_uncle1.set_timestamp(parent8.timestamp() + 10); + good_uncle1.extra_data_mut().push(1u8); let mut good_uncle2 = good.clone(); - good_uncle2.number = 8; - good_uncle2.parent_hash = parent7.hash(); - good_uncle2.difficulty = parent7.difficulty + diff_inc; - good_uncle2.timestamp = parent7.timestamp + 10; - good_uncle2.extra_data.push(2u8); + good_uncle2.set_number(8); + good_uncle2.set_parent_hash(parent7.hash()); + good_uncle2.set_difficulty(parent7.difficulty().clone() + diff_inc); + good_uncle2.set_timestamp(parent7.timestamp() + 10); + good_uncle2.extra_data_mut().push(2u8); let good_uncles = vec![ good_uncle1.clone(), good_uncle2.clone() ]; let mut uncles_rlp = RlpStream::new(); @@ -414,14 +414,14 @@ mod tests { let good_transactions_root = ordered_trie_root(good_transactions.iter().map(|t| encode::(t).to_vec()).collect()); let mut parent = good.clone(); - parent.number = 9; - parent.timestamp = parent8.timestamp + 10; - parent.parent_hash = parent8.hash(); - parent.difficulty = parent8.difficulty + diff_inc; + parent.set_number(9); + parent.set_timestamp(parent8.timestamp() + 10); + parent.set_parent_hash(parent8.hash()); + parent.set_difficulty(parent8.difficulty().clone() + diff_inc); - good.parent_hash = parent.hash(); - good.difficulty = parent.difficulty + diff_inc; - good.timestamp = parent.timestamp + 10; + good.set_parent_hash(parent.hash()); + good.set_difficulty(parent.difficulty().clone() + diff_inc); + good.set_timestamp(parent.timestamp() + 10); let mut bc = TestBlockChain::new(); bc.insert(create_test_block(&good)); @@ -433,61 +433,62 @@ mod tests { check_ok(basic_test(&create_test_block(&good), engine)); let mut header = good.clone(); - header.transactions_root = good_transactions_root.clone(); - header.uncles_hash = good_uncles_hash.clone(); + header.set_transactions_root(good_transactions_root.clone()); + header.set_uncles_hash(good_uncles_hash.clone()); check_ok(basic_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine)); - header.gas_limit = min_gas_limit - From::from(1); + header.set_gas_limit(min_gas_limit - From::from(1)); check_fail(basic_test(&create_test_block(&header), engine), - InvalidGasLimit(OutOfBounds { min: Some(min_gas_limit), max: None, found: header.gas_limit })); + InvalidGasLimit(OutOfBounds { min: Some(min_gas_limit), max: None, found: header.gas_limit().clone() })); header = good.clone(); - header.number = BlockNumber::max_value(); + header.set_number(BlockNumber::max_value()); check_fail(basic_test(&create_test_block(&header), engine), - RidiculousNumber(OutOfBounds { max: Some(BlockNumber::max_value()), min: None, found: header.number })); + RidiculousNumber(OutOfBounds { max: Some(BlockNumber::max_value()), min: None, found: header.number() })); header = good.clone(); - header.gas_used = header.gas_limit + From::from(1); + let gas_used = header.gas_limit().clone() + 1.into(); + header.set_gas_used(gas_used); check_fail(basic_test(&create_test_block(&header), engine), - TooMuchGasUsed(OutOfBounds { max: Some(header.gas_limit), min: None, found: header.gas_used })); + TooMuchGasUsed(OutOfBounds { max: Some(header.gas_limit().clone()), min: None, found: header.gas_used().clone() })); header = good.clone(); - header.extra_data.resize(engine.maximum_extra_data_size() + 1, 0u8); + header.extra_data_mut().resize(engine.maximum_extra_data_size() + 1, 0u8); check_fail(basic_test(&create_test_block(&header), engine), - ExtraDataOutOfBounds(OutOfBounds { max: Some(engine.maximum_extra_data_size()), min: None, found: header.extra_data.len() })); + ExtraDataOutOfBounds(OutOfBounds { max: Some(engine.maximum_extra_data_size()), min: None, found: header.extra_data().len() })); header = good.clone(); - header.extra_data.resize(engine.maximum_extra_data_size() + 1, 0u8); + header.extra_data_mut().resize(engine.maximum_extra_data_size() + 1, 0u8); check_fail(basic_test(&create_test_block(&header), engine), - ExtraDataOutOfBounds(OutOfBounds { max: Some(engine.maximum_extra_data_size()), min: None, found: header.extra_data.len() })); + ExtraDataOutOfBounds(OutOfBounds { max: Some(engine.maximum_extra_data_size()), min: None, found: header.extra_data().len() })); header = good.clone(); - header.uncles_hash = good_uncles_hash.clone(); + header.set_uncles_hash(good_uncles_hash.clone()); check_fail(basic_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine), - InvalidTransactionsRoot(Mismatch { expected: good_transactions_root.clone(), found: header.transactions_root })); + InvalidTransactionsRoot(Mismatch { expected: good_transactions_root.clone(), found: header.transactions_root().clone() })); header = good.clone(); - header.transactions_root = good_transactions_root.clone(); + header.set_transactions_root(good_transactions_root.clone()); check_fail(basic_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine), - InvalidUnclesHash(Mismatch { expected: good_uncles_hash.clone(), found: header.uncles_hash })); + InvalidUnclesHash(Mismatch { expected: good_uncles_hash.clone(), found: header.uncles_hash().clone() })); check_ok(family_test(&create_test_block(&good), engine, &bc)); check_ok(family_test(&create_test_block_with_data(&good, &good_transactions, &good_uncles), engine, &bc)); header = good.clone(); - header.parent_hash = H256::random(); + header.set_parent_hash(H256::random()); check_fail(family_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine, &bc), - UnknownParent(header.parent_hash)); + UnknownParent(header.parent_hash().clone())); header = good.clone(); - header.timestamp = 10; + header.set_timestamp(10); check_fail(family_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine, &bc), - InvalidTimestamp(OutOfBounds { max: None, min: Some(parent.timestamp + 1), found: header.timestamp })); + InvalidTimestamp(OutOfBounds { max: None, min: Some(parent.timestamp() + 1), found: header.timestamp() })); header = good.clone(); - header.number = 9; + header.set_number(9); check_fail(family_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine, &bc), - InvalidNumber(Mismatch { expected: parent.number + 1, found: header.number })); + InvalidNumber(Mismatch { expected: parent.number() + 1, found: header.number() })); header = good.clone(); let mut bad_uncles = good_uncles.clone(); diff --git a/parity/informant.rs b/parity/informant.rs index b6e8b7a84..58accd140 100644 --- a/parity/informant.rs +++ b/parity/informant.rs @@ -169,7 +169,7 @@ impl ChainNotify for Informant { Colour::White.bold().paint(format!("#{}", header.number())), Colour::White.bold().paint(format!("{}", header.hash())), Colour::Yellow.bold().paint(format!("{}", tx_count)), - Colour::Yellow.bold().paint(format!("{:.2}", header.gas_used.low_u64() as f32 / 1000000f32)), + Colour::Yellow.bold().paint(format!("{:.2}", header.gas_used().low_u64() as f32 / 1000000f32)), Colour::Purple.bold().paint(format!("{:.2}", duration as f32 / 1000000f32)), Colour::Blue.bold().paint(format!("{:.2}", size as f32 / 1024f32)), if skipped > 0 { format!(" + another {} block(s)", Colour::Red.bold().paint(format!("{}", skipped))) } else { String::new() } diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 3628f99a9..d805d57ee 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -158,22 +158,22 @@ impl EthClient where let block = Block { hash: Some(uncle.hash().into()), size: None, - parent_hash: uncle.parent_hash.into(), - uncles_hash: uncle.uncles_hash.into(), - author: uncle.author.into(), - miner: uncle.author.into(), - state_root: uncle.state_root.into(), - transactions_root: uncle.transactions_root.into(), - number: Some(uncle.number.into()), - gas_used: uncle.gas_used.into(), - gas_limit: uncle.gas_limit.into(), - logs_bloom: uncle.log_bloom.into(), - timestamp: uncle.timestamp.into(), - difficulty: uncle.difficulty.into(), - total_difficulty: (uncle.difficulty + parent_difficulty).into(), - receipts_root: uncle.receipts_root.into(), - extra_data: uncle.extra_data.into(), - seal_fields: uncle.seal.into_iter().map(|f| decode(&f)).map(Bytes::new).collect(), + parent_hash: uncle.parent_hash().clone().into(), + uncles_hash: uncle.uncles_hash().clone().into(), + author: uncle.author().clone().into(), + miner: uncle.author().clone().into(), + state_root: uncle.state_root().clone().into(), + transactions_root: uncle.transactions_root().clone().into(), + number: Some(uncle.number().into()), + gas_used: uncle.gas_used().clone().into(), + gas_limit: uncle.gas_limit().clone().into(), + logs_bloom: uncle.log_bloom().clone().into(), + timestamp: uncle.timestamp().into(), + difficulty: uncle.difficulty().clone().into(), + total_difficulty: (uncle.difficulty().clone() + parent_difficulty).into(), + receipts_root: uncle.receipts_root().clone().into(), + extra_data: uncle.extra_data().clone().into(), + seal_fields: uncle.seal().clone().into_iter().map(|f| decode(&f)).map(Bytes::new).collect(), uncles: vec![], transactions: BlockTransactions::Hashes(vec![]), }; diff --git a/sync/src/blocks.rs b/sync/src/blocks.rs index 2e0aa5d4e..498b35f43 100644 --- a/sync/src/blocks.rs +++ b/sync/src/blocks.rs @@ -270,7 +270,7 @@ impl BlockCollection { match self.head { None if hash == self.heads[0] => { trace!("New head {}", hash); - self.head = Some(info.parent_hash); + self.head = Some(info.parent_hash().clone()); }, _ => () } @@ -280,8 +280,8 @@ impl BlockCollection { body: None, }; let header_id = HeaderId { - transactions_root: info.transactions_root, - uncles: info.uncles_hash + transactions_root: info.transactions_root().clone(), + uncles: info.uncles_hash().clone(), }; if header_id.transactions_root == rlp::SHA3_NULL_RLP && header_id.uncles == rlp::SHA3_EMPTY_LIST_RLP { // empty body, just mark as downloaded @@ -294,7 +294,7 @@ impl BlockCollection { self.header_ids.insert(header_id, hash.clone()); } - self.parents.insert(info.parent_hash.clone(), hash.clone()); + self.parents.insert(info.parent_hash().clone(), hash.clone()); self.blocks.insert(hash.clone(), block); trace!(target: "sync", "New header: {}", hash.hex()); Ok(hash) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 80ed82596..9abd05398 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -503,7 +503,7 @@ impl ChainSync { let mut valid_response = item_count == 0; //empty response is valid for i in 0..item_count { let info: BlockHeader = try!(r.val_at(i)); - let number = BlockNumber::from(info.number); + let number = BlockNumber::from(info.number()); // Check if any of the headers matches the hash we requested if !valid_response { if let Some(expected) = expected_hash { @@ -645,11 +645,11 @@ impl ChainSync { trace!(target: "sync", "New block already queued {:?}", h); }, Ok(_) => { - if header.number == self.last_imported_block + 1 { - self.last_imported_block = header.number; + if header.number() == self.last_imported_block + 1 { + self.last_imported_block = header.number(); self.last_imported_hash = header.hash(); } - trace!(target: "sync", "New block queued {:?} ({})", h, header.number); + trace!(target: "sync", "New block queued {:?} ({})", h, header.number()); }, Err(BlockImportError::Block(BlockError::UnknownParent(p))) => { unknown = true; @@ -1539,12 +1539,12 @@ mod tests { fn get_dummy_block(order: u32, parent_hash: H256) -> Bytes { let mut header = Header::new(); - header.gas_limit = 0.into(); - header.difficulty = (order * 100).into(); - header.timestamp = (order * 10) as u64; - header.number = order as u64; - header.parent_hash = parent_hash; - header.state_root = H256::zero(); + header.set_gas_limit(0.into()); + header.set_difficulty((order * 100).into()); + header.set_timestamp((order * 10) as u64); + header.set_number(order as u64); + header.set_parent_hash(parent_hash); + header.set_state_root(H256::zero()); let mut rlp = RlpStream::new_list(3); rlp.append(&header);