Make the block header struct's internals private (#2000)

* Make the block header struct's internals private

Currently, this involves a lot of explicit cloning, but we
could migrate the return types of the get_* functions to
be copies rather than references since they are mostly copy
types anyway.

I opted to eliminate the constructor in favor of using
Default::default() plus calling a bunch of setters. This
is similar to the model that a Google Protobuf client uses
and I think it looks fine.

* Drop some unnecessary cloning by comparing references

* Fix compiler errors from callsites in tests.
This commit is contained in:
Nipunn Koorapati 2016-08-29 02:35:24 -07:00 committed by Arkadiy Paronyan
parent 2d883c43c9
commit 4389742ca3
21 changed files with 336 additions and 336 deletions

View File

@ -245,11 +245,11 @@ impl<'x> OpenBlock<'x> {
last_hashes: last_hashes, last_hashes: last_hashes,
}; };
r.block.base.header.parent_hash = parent.hash(); r.block.base.header.set_parent_hash(parent.hash());
r.block.base.header.number = parent.number + 1; r.block.base.header.set_number(parent.number() + 1);
r.block.base.header.author = author; r.block.base.header.set_author(author);
r.block.base.header.set_timestamp_now(parent.timestamp()); 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(); r.block.base.header.note_dirty();
engine.populate_from_parent(&mut r.block.base.header, parent, gas_range_target.0, gas_range_target.1); 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 { pub fn env_info(&self) -> EnvInfo {
// TODO: memoise. // TODO: memoise.
EnvInfo { EnvInfo {
number: self.block.base.header.number, number: self.block.base.header.number(),
author: self.block.base.header.author.clone(), author: self.block.base.header.author().clone(),
timestamp: self.block.base.header.timestamp, timestamp: self.block.base.header.timestamp(),
difficulty: self.block.base.header.difficulty.clone(), difficulty: self.block.base.header.difficulty().clone(),
last_hashes: self.last_hashes.clone(), last_hashes: self.last_hashes.clone(),
gas_used: self.block.receipts.last().map_or(U256::zero(), |r| r.gas_used), 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(); let unclosed_state = s.block.state.clone();
s.engine.on_close_block(&mut s.block); 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(); 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.set_uncles_hash(uncle_bytes.sha3());
s.block.base.header.state_root = s.block.state.root().clone(); s.block.base.header.set_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.set_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.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.gas_used = s.block.receipts.last().map_or(U256::zero(), |r| r.gas_used); s.block.base.header.set_gas_used(s.block.receipts.last().map_or(U256::zero(), |r| r.gas_used));
s.block.base.header.note_dirty();
ClosedBlock { ClosedBlock {
block: s.block, block: s.block,
@ -371,20 +370,19 @@ impl<'x> OpenBlock<'x> {
let mut s = self; let mut s = self;
s.engine.on_close_block(&mut s.block); 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 { 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()); 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(); 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() { if s.block.base.header.uncles_hash().is_zero() {
s.block.base.header.uncles_hash = uncle_bytes.sha3(); 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 { 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()); 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.set_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.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.gas_used = s.block.receipts.last().map_or(U256::zero(), |r| r.gas_used); s.block.base.header.set_gas_used(s.block.receipts.last().map_or(U256::zero(), |r| r.gas_used));
s.block.base.header.note_dirty();
LockedBlock { LockedBlock {
block: s.block, block: s.block,
@ -625,9 +623,9 @@ mod tests {
let last_hashes = Arc::new(vec![genesis_header.hash()]); 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 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(); 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(); 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(uncle1_header).unwrap();
open_block.push_uncle(uncle2_header).unwrap(); open_block.push_uncle(uncle2_header).unwrap();
let b = open_block.close_and_lock().seal(engine, vec![]).unwrap(); let b = open_block.close_and_lock().seal(engine, vec![]).unwrap();
@ -643,7 +641,7 @@ mod tests {
let bytes = e.rlp_bytes(); let bytes = e.rlp_bytes();
assert_eq!(bytes, orig_bytes); assert_eq!(bytes, orig_bytes);
let uncles = BlockView::new(&bytes).uncles(); 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(); let db = e.drain();
assert_eq!(orig_db.keys(), db.keys()); assert_eq!(orig_db.keys(), db.keys());

View File

@ -260,7 +260,7 @@ impl BlockQueue {
fn drain_verifying(verifying: &mut VecDeque<VerifyingBlock>, verified: &mut VecDeque<PreverifiedBlock>, bad: &mut HashSet<H256>) { fn drain_verifying(verifying: &mut VecDeque<VerifyingBlock>, verified: &mut VecDeque<PreverifiedBlock>, bad: &mut HashSet<H256>) {
while !verifying.is_empty() && verifying.front().unwrap().block.is_some() { while !verifying.is_empty() && verifying.front().unwrap().block.is_some() {
let block = verifying.pop_front().unwrap().block.unwrap(); 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()); bad.insert(block.header.hash());
} }
else { else {
@ -313,7 +313,7 @@ impl BlockQueue {
return Err(ImportError::KnownBad.into()); return Err(ImportError::KnownBad.into());
} }
if bad.contains(&header.parent_hash) { if bad.contains(header.parent_hash()) {
bad.insert(h.clone()); bad.insert(h.clone());
return Err(ImportError::KnownBad.into()); return Err(ImportError::KnownBad.into());
} }
@ -351,7 +351,7 @@ impl BlockQueue {
let mut new_verified = VecDeque::new(); let mut new_verified = VecDeque::new();
for block in verified.drain(..) { for block in verified.drain(..) {
if bad.contains(&block.header.parent_hash) { if bad.contains(block.header.parent_hash()) {
bad.insert(block.header.hash()); bad.insert(block.header.hash());
processing.remove(&block.header.hash()); processing.remove(&block.header.hash());
} else { } else {

View File

@ -1434,7 +1434,7 @@ mod tests {
let mut block_header = bc.block_header(&best_hash); let mut block_header = bc.block_header(&best_hash);
while !block_header.is_none() { 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); assert!(bc.cache_size().blocks > 1024 * 1024);

View File

@ -44,21 +44,22 @@ impl Encodable for Block {
impl Forkable for Block { impl Forkable for Block {
fn fork(mut self, fork_number: usize) -> Self where Self: Sized { 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 self
} }
} }
impl WithBloom for Block { impl WithBloom for Block {
fn with_bloom(mut self, bloom: H2048) -> Self where Self: Sized { fn with_bloom(mut self, bloom: H2048) -> Self where Self: Sized {
self.header.log_bloom = bloom; self.header.set_log_bloom(bloom);
self self
} }
} }
impl CompleteBlock for Block { impl CompleteBlock for Block {
fn complete(mut self, parent_hash: H256) -> Bytes { 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() encode(&self).to_vec()
} }
} }

View File

@ -73,8 +73,8 @@ pub struct ChainGenerator {
impl ChainGenerator { impl ChainGenerator {
fn prepare_block(&self) -> Block { fn prepare_block(&self) -> Block {
let mut block = Block::default(); let mut block = Block::default();
block.header.number = self.number; block.header.set_number(self.number);
block.header.difficulty = self.difficulty; block.header.set_difficulty(self.difficulty);
block block
} }
} }

View File

@ -99,7 +99,7 @@ impl ClientReport {
pub fn accrue_block(&mut self, block: &PreverifiedBlock) { pub fn accrue_block(&mut self, block: &PreverifiedBlock) {
self.blocks_imported += 1; self.blocks_imported += 1;
self.transactions_applied += block.transactions.len(); 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 // 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 { 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(()); return Err(());
}; };
// Enact Verified Block // Enact Verified Block
let parent = chain_has_parent.unwrap(); 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 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()); 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 { for block in blocks {
let header = &block.header; let header = &block.header;
if invalid_blocks.contains(&header.parent_hash) { if invalid_blocks.contains(header.parent_hash()) {
invalid_blocks.insert(header.hash()); invalid_blocks.insert(header.hash());
continue; continue;
} }

View File

@ -169,19 +169,19 @@ impl TestBlockChainClient {
let len = self.numbers.read().len(); let len = self.numbers.read().len();
for n in len..(len + count) { for n in len..(len + count) {
let mut header = BlockHeader::new(); let mut header = BlockHeader::new();
header.difficulty = From::from(n); header.set_difficulty(From::from(n));
header.parent_hash = self.last_hash.read().clone(); header.set_parent_hash(self.last_hash.read().clone());
header.number = n as BlockNumber; header.set_number(n as BlockNumber);
header.gas_limit = U256::from(1_000_000); header.set_gas_limit(U256::from(1_000_000));
let uncles = match with { let uncles = match with {
EachBlockWith::Uncle | EachBlockWith::UncleAndTransaction => { EachBlockWith::Uncle | EachBlockWith::UncleAndTransaction => {
let mut uncles = RlpStream::new_list(1); let mut uncles = RlpStream::new_list(1);
let mut uncle_header = BlockHeader::new(); let mut uncle_header = BlockHeader::new();
uncle_header.difficulty = From::from(n); uncle_header.set_difficulty(From::from(n));
uncle_header.parent_hash = self.last_hash.read().clone(); uncle_header.set_parent_hash(self.last_hash.read().clone());
uncle_header.number = n as BlockNumber; uncle_header.set_number(n as BlockNumber);
uncles.append(&uncle_header); uncles.append(&uncle_header);
header.uncles_hash = uncles.as_raw().sha3(); header.set_uncles_hash(uncles.as_raw().sha3());
uncles uncles
}, },
_ => RlpStream::new_list(0) _ => RlpStream::new_list(0)
@ -219,7 +219,7 @@ impl TestBlockChainClient {
pub fn corrupt_block(&mut self, n: BlockNumber) { pub fn corrupt_block(&mut self, n: BlockNumber) {
let hash = self.block_hash(BlockID::Number(n)).unwrap(); let hash = self.block_hash(BlockID::Number(n)).unwrap();
let mut header: BlockHeader = decode(&self.block_header(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); let mut rlp = RlpStream::new_list(3);
rlp.append(&header); rlp.append(&header);
rlp.append_raw(&rlp::NULL_RLP, 1); rlp.append_raw(&rlp::NULL_RLP, 1);
@ -231,7 +231,7 @@ impl TestBlockChainClient {
pub fn corrupt_block_parent(&mut self, n: BlockNumber) { pub fn corrupt_block_parent(&mut self, n: BlockNumber) {
let hash = self.block_hash(BlockID::Number(n)).unwrap(); let hash = self.block_hash(BlockID::Number(n)).unwrap();
let mut header: BlockHeader = decode(&self.block_header(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); let mut rlp = RlpStream::new_list(3);
rlp.append(&header); rlp.append(&header);
rlp.append_raw(&rlp::NULL_RLP, 1); rlp.append_raw(&rlp::NULL_RLP, 1);
@ -470,20 +470,20 @@ impl BlockChainClient for TestBlockChainClient {
fn import_block(&self, b: Bytes) -> Result<H256, BlockImportError> { fn import_block(&self, b: Bytes) -> Result<H256, BlockImportError> {
let header = Rlp::new(&b).val_at::<BlockHeader>(0); let header = Rlp::new(&b).val_at::<BlockHeader>(0);
let h = header.hash(); let h = header.hash();
let number: usize = header.number as usize; let number: usize = header.number() as usize;
if number > self.blocks.read().len() { if number > self.blocks.read().len() {
panic!("Unexpected block number. Expected {}, got {}", self.blocks.read().len(), number); panic!("Unexpected block number. Expected {}, got {}", self.blocks.read().len(), number);
} }
if number > 0 { if number > 0 {
match self.blocks.read().get(&header.parent_hash) { match self.blocks.read().get(header.parent_hash()) {
Some(parent) => { Some(parent) => {
let parent = Rlp::new(parent).val_at::<BlockHeader>(0); let parent = Rlp::new(parent).val_at::<BlockHeader>(0);
if parent.number != (header.number - 1) { if parent.number() != (header.number() - 1) {
panic!("Unexpected block parent"); panic!("Unexpected block parent");
} }
}, },
None => { 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 { if number == len {
{ {
let mut difficulty = self.difficulty.write(); let mut difficulty = self.difficulty.write();
*difficulty = *difficulty + header.difficulty; *difficulty = *difficulty + header.difficulty().clone();
} }
mem::replace(&mut *self.last_hash.write(), h.clone()); mem::replace(&mut *self.last_hash.write(), h.clone());
self.blocks.write().insert(h.clone(), b); self.blocks.write().insert(h.clone(), b);
self.numbers.write().insert(number, h.clone()); 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 { if number > 0 {
let mut n = number - 1; let mut n = number - 1;
while n > 0 && self.numbers.read()[&n] != parent_hash { while n > 0 && self.numbers.read()[&n] != parent_hash {
*self.numbers.write().get_mut(&n).unwrap() = parent_hash.clone(); *self.numbers.write().get_mut(&n).unwrap() = parent_hash.clone();
n -= 1; n -= 1;
parent_hash = Rlp::new(&self.blocks.read()[&parent_hash]).val_at::<BlockHeader>(0).parent_hash; parent_hash = Rlp::new(&self.blocks.read()[&parent_hash]).val_at::<BlockHeader>(0).parent_hash().clone();
} }
} }
} }

View File

@ -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) { fn populate_from_parent(&self, header: &mut Header, parent: &Header, gas_floor_target: U256, _gas_ceil_target: U256) {
header.difficulty = parent.difficulty; header.set_difficulty(parent.difficulty().clone());
header.gas_limit = { header.set_gas_limit({
let gas_limit = parent.gas_limit; let gas_limit = parent.gas_limit().clone();
let bound_divisor = self.our_params.gas_limit_bound_divisor; let bound_divisor = self.our_params.gas_limit_bound_divisor;
if gas_limit < gas_floor_target { if gas_limit < gas_floor_target {
min(gas_floor_target, gas_limit + gas_limit / bound_divisor - 1.into()) min(gas_floor_target, gas_limit + gas_limit / bound_divisor - 1.into())
} else { } else {
max(gas_floor_target, gas_limit - gas_limit / bound_divisor + 1.into()) 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); // 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> { fn verify_block_basic(&self, header: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> {
// check the seal fields. // check the seal fields.
// TODO: pull this out into common code. // 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( 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(()) Ok(())
@ -133,7 +132,7 @@ impl Engine for BasicAuthority {
fn verify_block_unordered(&self, header: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> { fn verify_block_unordered(&self, header: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> {
// check the signature is legit. // check the signature is legit.
let sig = try!(UntrustedRlp::new(&header.seal[0]).as_val::<H520>()); let sig = try!(UntrustedRlp::new(&header.seal()[0]).as_val::<H520>());
let signer = public_to_address(&try!(recover(&sig.into(), &header.bare_hash()))); let signer = public_to_address(&try!(recover(&sig.into(), &header.bare_hash())));
if !self.our_params.authorities.contains(&signer) { if !self.our_params.authorities.contains(&signer) {
return try!(Err(BlockError::InvalidSeal)); 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() }))) 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 gas_limit_divisor = self.our_params.gas_limit_bound_divisor;
let min_gas = parent.gas_limit - parent.gas_limit / gas_limit_divisor; let min_gas = parent.gas_limit().clone() - parent.gas_limit().clone() / gas_limit_divisor;
let max_gas = parent.gas_limit + parent.gas_limit / 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 { 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 }))); return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds { min: Some(min_gas), max: Some(max_gas), found: header.gas_limit().clone() })));
} }
Ok(()) Ok(())
} }

View File

@ -108,9 +108,8 @@ pub trait Engine : Sync + Send {
/// Don't forget to call Super::populate_from_parent when subclassing & overriding. /// Don't forget to call Super::populate_from_parent when subclassing & overriding.
// TODO: consider including State in the params. // 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) { fn populate_from_parent(&self, header: &mut Header, parent: &Header, _gas_floor_target: U256, _gas_ceil_target: U256) {
header.difficulty = parent.difficulty; header.set_difficulty(parent.difficulty().clone());
header.gas_limit = parent.gas_limit; header.set_gas_limit(parent.gas_limit().clone());
header.note_dirty();
} }
// TODO: builtin contract routing - to do this properly, it will require removing the built-in configuration-reading logic // TODO: builtin contract routing - to do this properly, it will require removing the built-in configuration-reading logic

View File

@ -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) { 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); let difficulty = self.calculate_difficulty(header, parent);
header.gas_limit = { let gas_limit = {
let gas_limit = parent.gas_limit; let gas_limit = parent.gas_limit().clone();
let bound_divisor = self.ethash_params.gas_limit_bound_divisor; let bound_divisor = self.ethash_params.gas_limit_bound_divisor;
if gas_limit < gas_floor_target { if gas_limit < gas_floor_target {
min(gas_floor_target, gas_limit + gas_limit / bound_divisor - 1.into()) min(gas_floor_target, gas_limit + gas_limit / bound_divisor - 1.into())
@ -126,21 +126,23 @@ impl Engine for Ethash {
min(gas_ceil_target, min(gas_ceil_target,
max(gas_floor_target, max(gas_floor_target,
gas_limit - gas_limit / bound_divisor + 1.into() + 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.set_difficulty(difficulty);
header.number <= self.ethash_params.dao_hardfork_transition + 9 { header.set_gas_limit(gas_limit);
header.extra_data = b"dao-hard-fork"[..].to_owned(); 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(); 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) { 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? // 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; let mut state = block.fields_mut().state;
for child in &self.ethash_params.dao_hardfork_accounts { for child in &self.ethash_params.dao_hardfork_accounts {
let b = state.balance(child); let b = state.balance(child);
@ -157,7 +159,7 @@ impl Engine for Ethash {
let fields = block.fields_mut(); let fields = block.fields_mut();
// Bestow block reward // 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 // Bestow uncle rewards
let current_number = fields.header.number(); 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> { fn verify_block_basic(&self, header: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> {
// check the seal fields. // check the seal fields.
if header.seal.len() != self.seal_fields() { if header.seal().len() != self.seal_fields() {
return Err(From::from(BlockError::InvalidSealArity( 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::<H256>()); try!(UntrustedRlp::new(&header.seal()[0]).as_val::<H256>());
try!(UntrustedRlp::new(&header.seal[1]).as_val::<H64>()); try!(UntrustedRlp::new(&header.seal()[1]).as_val::<H64>());
// TODO: consider removing these lines. // TODO: consider removing these lines.
let min_difficulty = self.ethash_params.minimum_difficulty; let min_difficulty = self.ethash_params.minimum_difficulty;
if header.difficulty < min_difficulty { if header.difficulty() < &min_difficulty {
return Err(From::from(BlockError::DifficultyOutOfBounds(OutOfBounds { min: Some(min_difficulty), max: None, found: header.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( let difficulty = Ethash::boundary_to_difficulty(&Ethash::from_ethash(quick_get_difficulty(
@ -190,37 +192,37 @@ impl Engine for Ethash {
header.nonce().low_u64(), header.nonce().low_u64(),
&Ethash::to_ethash(header.mix_hash()) &Ethash::to_ethash(header.mix_hash())
))); )));
if difficulty < header.difficulty { if &difficulty < header.difficulty() {
return Err(From::from(BlockError::InvalidProofOfWork(OutOfBounds { min: Some(header.difficulty), max: None, found: 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 && if header.number() >= self.ethash_params.dao_hardfork_transition &&
header.number <= self.ethash_params.dao_hardfork_transition + 9 && header.number() <= self.ethash_params.dao_hardfork_transition + 9 &&
header.extra_data[..] != b"dao-hard-fork"[..] { header.extra_data()[..] != b"dao-hard-fork"[..] {
return Err(From::from(BlockError::ExtraDataOutOfBounds(OutOfBounds { min: None, max: None, found: 0 }))); return Err(From::from(BlockError::ExtraDataOutOfBounds(OutOfBounds { min: None, max: None, found: 0 })));
} }
if header.gas_limit > 0x7fffffffffffffffu64.into() { if header.gas_limit() > &0x7fffffffffffffffu64.into() {
return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds { min: None, max: Some(0x7fffffffffffffffu64.into()), found: header.gas_limit }))); return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds { min: None, max: Some(0x7fffffffffffffffu64.into()), found: header.gas_limit().clone() })));
} }
Ok(()) Ok(())
} }
fn verify_block_unordered(&self, header: &Header, _block: Option<&[u8]>) -> result::Result<(), Error> { 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( 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 mix = Ethash::from_ethash(result.mix_hash);
let difficulty = Ethash::boundary_to_difficulty(&Ethash::from_ethash(result.value)); let difficulty = Ethash::boundary_to_difficulty(&Ethash::from_ethash(result.value));
if mix != header.mix_hash() { if mix != header.mix_hash() {
return Err(From::from(BlockError::MismatchedH256SealElement(Mismatch { expected: mix, found: header.mix_hash() }))); return Err(From::from(BlockError::MismatchedH256SealElement(Mismatch { expected: mix, found: header.mix_hash() })));
} }
if difficulty < header.difficulty { if &difficulty < header.difficulty() {
return Err(From::from(BlockError::InvalidProofOfWork(OutOfBounds { min: Some(header.difficulty), max: None, found: difficulty }))); return Err(From::from(BlockError::InvalidProofOfWork(OutOfBounds { min: Some(header.difficulty().clone()), max: None, found: difficulty })));
} }
Ok(()) Ok(())
} }
@ -232,15 +234,15 @@ impl Engine for Ethash {
} }
// Check difficulty is correct given the two timestamps. // Check difficulty is correct given the two timestamps.
let expected_difficulty = self.calculate_difficuty(header, parent); let expected_difficulty = self.calculate_difficulty(header, parent);
if header.difficulty != expected_difficulty { if header.difficulty() != &expected_difficulty {
return Err(From::from(BlockError::InvalidDifficulty(Mismatch { expected: expected_difficulty, found: header.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 gas_limit_divisor = self.ethash_params.gas_limit_bound_divisor;
let min_gas = parent.gas_limit - parent.gas_limit / gas_limit_divisor; let min_gas = parent.gas_limit().clone() - parent.gas_limit().clone() / gas_limit_divisor;
let max_gas = parent.gas_limit + parent.gas_limit / 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 { 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 }))); return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds { min: Some(min_gas), max: Some(max_gas), found: header.gas_limit().clone() })));
} }
Ok(()) Ok(())
} }
@ -259,9 +261,9 @@ impl Engine for Ethash {
#[cfg_attr(feature="dev", allow(wrong_self_convention))] // to_ethash should take self #[cfg_attr(feature="dev", allow(wrong_self_convention))] // to_ethash should take self
impl Ethash { 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; const EXP_DIFF_PERIOD: u64 = 100000;
if header.number == 0 { if header.number() == 0 {
panic!("Can't calculate genesis block difficulty"); panic!("Can't calculate genesis block difficulty");
} }
@ -270,25 +272,25 @@ impl Ethash {
let duration_limit = self.ethash_params.duration_limit; let duration_limit = self.ethash_params.duration_limit;
let frontier_limit = self.ethash_params.frontier_compatibility_mode_limit; let frontier_limit = self.ethash_params.frontier_compatibility_mode_limit;
let mut target = if header.number < frontier_limit { let mut target = if header.number() < frontier_limit {
if header.timestamp >= parent.timestamp + duration_limit { if header.timestamp() >= parent.timestamp() + duration_limit {
parent.difficulty - (parent.difficulty / difficulty_bound_divisor) parent.difficulty().clone() - (parent.difficulty().clone() / difficulty_bound_divisor)
} else { } else {
parent.difficulty + (parent.difficulty / difficulty_bound_divisor) parent.difficulty().clone() + (parent.difficulty().clone() / difficulty_bound_divisor)
} }
} }
else { 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) //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 { 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 { } 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); 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 { if period > 1 {
target = max(min_difficulty, target + (U256::from(1) << (period - 2))); 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. /// Set the nonce and mix hash fields of the header.
pub fn set_nonce_and_mix_hash(&mut self, nonce: &H64, mix_hash: &H256) { 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 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 mut uncle = Header::new();
let uncle_author: Address = "ef2d6d194084c2de36e0dabfce45d046b37d1106".into(); let uncle_author: Address = "ef2d6d194084c2de36e0dabfce45d046b37d1106".into();
uncle.author = uncle_author.clone(); uncle.set_author(uncle_author);
b.push_uncle(uncle).unwrap(); b.push_uncle(uncle).unwrap();
let b = b.close(); let b = b.close();

View File

@ -68,7 +68,7 @@ mod tests {
let mut db_result = get_temp_journal_db(); let mut db_result = get_temp_journal_db();
let mut db = db_result.take(); let mut db = db_result.take();
spec.ensure_db_good(db.as_hashdb_mut()).unwrap(); 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(&"0000000000000000000000000000000000000001".into()), 1u64.into());
assert_eq!(s.balance(&"0000000000000000000000000000000000000002".into()), 1u64.into()); assert_eq!(s.balance(&"0000000000000000000000000000000000000002".into()), 1u64.into());
assert_eq!(s.balance(&"0000000000000000000000000000000000000003".into()), 1u64.into()); assert_eq!(s.balance(&"0000000000000000000000000000000000000003".into()), 1u64.into());

View File

@ -33,43 +33,42 @@ pub type BlockNumber = u64;
/// Doesn't do all that much on its own. /// Doesn't do all that much on its own.
#[derive(Debug, Clone, Eq)] #[derive(Debug, Clone, Eq)]
pub struct Header { pub struct Header {
// TODO: make all private.
/// Parent hash. /// Parent hash.
pub parent_hash: H256, parent_hash: H256,
/// Block timestamp. /// Block timestamp.
pub timestamp: u64, timestamp: u64,
/// Block number. /// Block number.
pub number: BlockNumber, number: BlockNumber,
/// Block author. /// Block author.
pub author: Address, author: Address,
/// Transactions root. /// Transactions root.
pub transactions_root: H256, transactions_root: H256,
/// Block uncles hash. /// Block uncles hash.
pub uncles_hash: H256, uncles_hash: H256,
/// Block extra data. /// Block extra data.
pub extra_data: Bytes, extra_data: Bytes,
/// State root. /// State root.
pub state_root: H256, state_root: H256,
/// Block receipts root. /// Block receipts root.
pub receipts_root: H256, receipts_root: H256,
/// Block bloom. /// Block bloom.
pub log_bloom: LogBloom, log_bloom: LogBloom,
/// Gas used for contracts execution. /// Gas used for contracts execution.
pub gas_used: U256, gas_used: U256,
/// Block gas limit. /// Block gas limit.
pub gas_limit: U256, gas_limit: U256,
/// Block difficulty. /// Block difficulty.
pub difficulty: U256, difficulty: U256,
/// Vector of post-RLP-encoded fields. /// Vector of post-RLP-encoded fields.
pub seal: Vec<Bytes>, seal: Vec<Bytes>,
/// The memoized hash of the RLP representation *including* the seal fields. /// The memoized hash of the RLP representation *including* the seal fields.
pub hash: RefCell<Option<H256>>, hash: RefCell<Option<H256>>,
/// The memoized hash of the RLP representation *without* the seal fields. /// The memoized hash of the RLP representation *without* the seal fields.
pub bare_hash: RefCell<Option<H256>>, bare_hash: RefCell<Option<H256>>,
} }
impl PartialEq for Header { impl PartialEq for Header {
@ -134,15 +133,21 @@ impl Header {
/// Get the extra data field of the header. /// Get the extra data field of the header.
pub fn extra_data(&self) -> &Bytes { &self.extra_data } 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. /// Get the state root field of the header.
pub fn state_root(&self) -> &H256 { &self.state_root } pub fn state_root(&self) -> &H256 { &self.state_root }
/// Get the receipts root field of the header. /// Get the receipts root field of the header.
pub fn receipts_root(&self) -> &H256 { &self.receipts_root } 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. /// Get the transactions root field of the header.
pub fn transactions_root(&self) -> &H256 { &self.transactions_root } pub fn transactions_root(&self) -> &H256 { &self.transactions_root }
/// Get the uncles hash field of the header. /// Get the uncles hash field of the header.
pub fn uncles_hash(&self) -> &H256 { &self.uncles_hash } 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. /// Get the gas limit field of the header.
pub fn gas_limit(&self) -> &U256 { &self.gas_limit } pub fn gas_limit(&self) -> &U256 { &self.gas_limit }

View File

@ -90,27 +90,26 @@ impl AbridgedBlock {
let rlp = UntrustedRlp::new(&self.rlp).decompress(RlpType::Blocks); let rlp = UntrustedRlp::new(&self.rlp).decompress(RlpType::Blocks);
let rlp = UntrustedRlp::new(&rlp); let rlp = UntrustedRlp::new(&rlp);
let mut header = Header { let mut header: Header = Default::default();
parent_hash: parent_hash, header.set_parent_hash(parent_hash);
author: try!(rlp.val_at(0)), header.set_author(try!(rlp.val_at(0)));
state_root: try!(rlp.val_at(1)), header.set_state_root(try!(rlp.val_at(1)));
transactions_root: try!(rlp.val_at(2)), header.set_transactions_root(try!(rlp.val_at(2)));
receipts_root: try!(rlp.val_at(3)), header.set_receipts_root(try!(rlp.val_at(3)));
log_bloom: try!(rlp.val_at(4)), header.set_log_bloom(try!(rlp.val_at(4)));
difficulty: try!(rlp.val_at(5)), header.set_difficulty(try!(rlp.val_at(5)));
number: number, header.set_number(number);
gas_limit: try!(rlp.val_at(6)), header.set_gas_limit(try!(rlp.val_at(6)));
gas_used: try!(rlp.val_at(7)), header.set_gas_used(try!(rlp.val_at(7)));
timestamp: try!(rlp.val_at(8)), header.set_timestamp(try!(rlp.val_at(8)));
extra_data: try!(rlp.val_at(9)), header.set_extra_data(try!(rlp.val_at(9)));
..Default::default()
};
let transactions = try!(rlp.val_at(10)); let transactions = try!(rlp.val_at(10));
let uncles: Vec<Header> = try!(rlp.val_at(11)); let uncles: Vec<Header> = try!(rlp.val_at(11));
let mut uncles_rlp = RlpStream::new(); let mut uncles_rlp = RlpStream::new();
uncles_rlp.append(&uncles); 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(); let mut seal_fields = Vec::new();
for i in (HEADER_FIELDS + BLOCK_FIELDS)..rlp.item_count() { for i in (HEADER_FIELDS + BLOCK_FIELDS)..rlp.item_count() {

View File

@ -25,8 +25,6 @@ use super::seal::Generic as GenericSeal;
use ethereum; use ethereum;
use ethjson; use ethjson;
use std::cell::RefCell;
/// Parameters common to all engines. /// Parameters common to all engines.
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
#[cfg_attr(test, derive(Default))] #[cfg_attr(test, derive(Default))]
@ -161,21 +159,21 @@ impl Spec {
/// Get the header of the genesis block. /// Get the header of the genesis block.
pub fn genesis_header(&self) -> Header { pub fn genesis_header(&self) -> Header {
Header { let mut header: Header = Default::default();
parent_hash: self.parent_hash.clone(), header.set_parent_hash(self.parent_hash.clone());
timestamp: self.timestamp, header.set_timestamp(self.timestamp);
number: 0, header.set_number(0);
author: self.author.clone(), header.set_author(self.author.clone());
transactions_root: self.transactions_root.clone(), header.set_transactions_root(self.transactions_root.clone());
uncles_hash: RlpStream::new_list(0).out().sha3(), header.set_uncles_hash(RlpStream::new_list(0).out().sha3());
extra_data: self.extra_data.clone(), header.set_extra_data(self.extra_data.clone());
state_root: self.state_root().clone(), header.set_state_root(self.state_root().clone());
receipts_root: self.receipts_root.clone(), header.set_receipts_root(self.receipts_root.clone());
log_bloom: H2048::new().clone(), header.set_log_bloom(H2048::new().clone());
gas_used: self.gas_used.clone(), header.set_gas_used(self.gas_used.clone());
gas_limit: self.gas_limit.clone(), header.set_gas_limit(self.gas_limit.clone());
difficulty: self.difficulty.clone(), header.set_difficulty(self.difficulty.clone());
seal: { header.set_seal({
let seal = { let seal = {
let mut s = RlpStream::new_list(self.seal_fields); let mut s = RlpStream::new_list(self.seal_fields);
s.append_raw(&self.seal_rlp, self.seal_fields); s.append_raw(&self.seal_rlp, self.seal_fields);
@ -183,10 +181,8 @@ impl Spec {
}; };
let r = Rlp::new(&seal); let r = Rlp::new(&seal);
(0..self.seal_fields).map(|i| r.at(i).as_raw().to_vec()).collect() (0..self.seal_fields).map(|i| r.at(i).as_raw().to_vec()).collect()
}, });
hash: RefCell::new(None), return header;
bare_hash: RefCell::new(None),
}
} }
/// Compose the genesis block for this chain. /// Compose the genesis block for this chain.

View File

@ -45,9 +45,9 @@ fn returns_state_root_basic() {
let client_result = generate_dummy_client(6); let client_result = generate_dummy_client(6);
let client = client_result.reference(); let client = client_result.reference();
let test_spec = get_test_spec(); 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] #[test]

View File

@ -84,26 +84,26 @@ pub fn create_test_block(header: &Header) -> Bytes {
fn create_unverifiable_block_header(order: u32, parent_hash: H256) -> Header { fn create_unverifiable_block_header(order: u32, parent_hash: H256) -> Header {
let mut header = Header::new(); let mut header = Header::new();
header.gas_limit = 0.into(); header.set_gas_limit(0.into());
header.difficulty = (order * 100).into(); header.set_difficulty((order * 100).into());
header.timestamp = (order * 10) as u64; header.set_timestamp((order * 10) as u64);
header.number = order as u64; header.set_number(order as u64);
header.parent_hash = parent_hash; header.set_parent_hash(parent_hash);
header.state_root = H256::zero(); header.set_state_root(H256::zero());
header header
} }
fn create_unverifiable_block_with_extra(order: u32, parent_hash: H256, extra: Option<Bytes>) -> Bytes { fn create_unverifiable_block_with_extra(order: u32, parent_hash: H256, extra: Option<Bytes>) -> Bytes {
let mut header = create_unverifiable_block_header(order, parent_hash); 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, Some(extra_data) => extra_data,
None => { None => {
let base = (order & 0x000000ff) as u8; let base = (order & 0x000000ff) as u8;
let generated: Vec<u8> = vec![base + 1, base + 2, base + 3]; let generated: Vec<u8> = vec![base + 1, base + 2, base + 3];
generated generated
} }
}; });
create_test_block(&header) create_test_block(&header)
} }
@ -204,7 +204,7 @@ pub fn push_blocks_to_client(client: &Arc<Client>, timestamp_salt: u64, starting
let test_spec = get_test_spec(); let test_spec = get_test_spec();
let test_engine = &test_spec.engine; let test_engine = &test_spec.engine;
//let test_engine = test_spec.to_engine().unwrap(); //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_hash = client.chain_info().best_block_hash;
let mut rolling_block_number = starting_number as u64; let mut rolling_block_number = starting_number as u64;
let mut rolling_timestamp = timestamp_salt + starting_number as u64 * 10; let mut rolling_timestamp = timestamp_salt + starting_number as u64 * 10;
@ -212,12 +212,12 @@ pub fn push_blocks_to_client(client: &Arc<Client>, timestamp_salt: u64, starting
for _ in 0..block_number { for _ in 0..block_number {
let mut header = Header::new(); let mut header = Header::new();
header.gas_limit = test_engine.params().min_gas_limit; header.set_gas_limit(test_engine.params().min_gas_limit);
header.difficulty = U256::from(0x20000); header.set_difficulty(U256::from(0x20000));
header.timestamp = rolling_timestamp; header.set_timestamp(rolling_timestamp);
header.number = rolling_block_number; header.set_number(rolling_block_number);
header.parent_hash = rolling_hash; header.set_parent_hash(rolling_hash);
header.state_root = state_root.clone(); header.set_state_root(state_root);
rolling_hash = header.hash(); rolling_hash = header.hash();
rolling_block_number = rolling_block_number + 1; 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(); let mut r = Vec::new();
for i in start_number .. start_number + count + 1 { for i in start_number .. start_number + count + 1 {
let mut block_header = Header::new(); let mut block_header = Header::new();
block_header.gas_limit = test_engine.params().min_gas_limit; block_header.set_gas_limit(test_engine.params().min_gas_limit);
block_header.difficulty = U256::from(i).mul(U256([0, 1, 0, 0])); block_header.set_difficulty(U256::from(i).mul(U256([0, 1, 0, 0])));
block_header.timestamp = rolling_timestamp; block_header.set_timestamp(rolling_timestamp);
block_header.number = i as u64; block_header.set_number(i as u64);
block_header.parent_hash = parent; block_header.set_parent_hash(parent);
block_header.state_root = test_spec.genesis_header().state_root; block_header.set_state_root(test_spec.genesis_header().state_root().clone());
parent = block_header.hash(); parent = block_header.hash();
rolling_timestamp = rolling_timestamp + 10; rolling_timestamp = rolling_timestamp + 10;
@ -365,12 +365,12 @@ pub fn get_good_dummy_block() -> Bytes {
let mut block_header = Header::new(); let mut block_header = Header::new();
let test_spec = get_test_spec(); let test_spec = get_test_spec();
let test_engine = &test_spec.engine; let test_engine = &test_spec.engine;
block_header.gas_limit = test_engine.params().min_gas_limit; block_header.set_gas_limit(test_engine.params().min_gas_limit);
block_header.difficulty = U256::from(0x20000); block_header.set_difficulty(U256::from(0x20000));
block_header.timestamp = 40; block_header.set_timestamp(40);
block_header.number = 1; block_header.set_number(1);
block_header.parent_hash = test_spec.genesis_header().hash(); block_header.set_parent_hash(test_spec.genesis_header().hash());
block_header.state_root = test_spec.genesis_header().state_root; block_header.set_state_root(test_spec.genesis_header().state_root().clone());
create_test_block(&block_header) create_test_block(&block_header)
} }
@ -379,12 +379,12 @@ pub fn get_bad_state_dummy_block() -> Bytes {
let mut block_header = Header::new(); let mut block_header = Header::new();
let test_spec = get_test_spec(); let test_spec = get_test_spec();
let test_engine = &test_spec.engine; let test_engine = &test_spec.engine;
block_header.gas_limit = test_engine.params().min_gas_limit; block_header.set_gas_limit(test_engine.params().min_gas_limit);
block_header.difficulty = U256::from(0x20000); block_header.set_difficulty(U256::from(0x20000));
block_header.timestamp = 40; block_header.set_timestamp(40);
block_header.number = 1; block_header.set_number(1);
block_header.parent_hash = test_spec.genesis_header().hash(); block_header.set_parent_hash(test_spec.genesis_header().hash());
block_header.state_root = 0xbad.into(); block_header.set_state_root(0xbad.into());
create_test_block(&block_header) create_test_block(&block_header)
} }

View File

@ -38,7 +38,7 @@ pub struct PreverifiedBlock {
/// Phase 1 quick block verification. Only does checks that are cheap. Operates on a single block /// 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> { pub fn verify_block_basic(header: &Header, bytes: &[u8], engine: &Engine) -> Result<(), Error> {
try!(verify_header(&header, engine)); 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))); try!(engine.verify_block_basic(&header, Some(bytes)));
for u in try!(UntrustedRlp::new(bytes).at(2)).iter().map(|rlp| rlp.as_val::<Header>()) { for u in try!(UntrustedRlp::new(bytes).at(2)).iter().map(|rlp| rlp.as_val::<Header>()) {
let u = try!(u); 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. /// 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> { pub fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, bc: &BlockProvider) -> Result<(), Error> {
// TODO: verify timestamp // 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!(verify_parent(&header, &parent));
try!(engine.verify_block_family(&header, &parent, Some(bytes))); 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(); let mut excluded = HashSet::new();
excluded.insert(header.hash()); excluded.insert(header.hash());
let mut hash = header.parent_hash.clone(); let mut hash = header.parent_hash().clone();
excluded.insert(hash.clone()); excluded.insert(hash.clone());
for _ in 0..engine.maximum_uncle_age() { for _ in 0..engine.maximum_uncle_age() {
match bc.block_details(&hash) { match bc.block_details(&hash) {
@ -122,12 +122,12 @@ pub fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, bc: &
// 6 7 // 6 7
// (8 Invalid) // (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 { 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 { 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 // cB
@ -139,8 +139,8 @@ pub fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, bc: &
// cB.p^6 -----------/ 6 // cB.p^6 -----------/ 6
// cB.p^7 -------------/ // cB.p^7 -------------/
// cB.p^8 // cB.p^8
let mut expected_uncle_parent = header.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())))); 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 { for _ in 0..depth {
match bc.block_details(&expected_uncle_parent) { match bc.block_details(&expected_uncle_parent) {
Some(details) => { 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, /// Phase 4 verification. Check block information against transaction enactment results,
pub fn verify_block_final(expected: &Header, got: &Header) -> Result<(), Error> { pub fn verify_block_final(expected: &Header, got: &Header) -> Result<(), Error> {
if expected.gas_used != got.gas_used { if expected.gas_used() != got.gas_used() {
return Err(From::from(BlockError::InvalidGasUsed(Mismatch { expected: expected.gas_used, found: 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 { if expected.log_bloom() != got.log_bloom() {
return Err(From::from(BlockError::InvalidLogBloom(Mismatch { expected: expected.log_bloom.clone(), found: got.log_bloom.clone() }))) return Err(From::from(BlockError::InvalidLogBloom(Mismatch { expected: expected.log_bloom().clone(), found: got.log_bloom().clone() })))
} }
if expected.state_root != got.state_root { if expected.state_root() != got.state_root() {
return Err(From::from(BlockError::InvalidStateRoot(Mismatch { expected: expected.state_root.clone(), found: got.state_root.clone() }))) return Err(From::from(BlockError::InvalidStateRoot(Mismatch { expected: expected.state_root().clone(), found: got.state_root().clone() })))
} }
if expected.receipts_root != got.receipts_root { if expected.receipts_root() != got.receipts_root() {
return Err(From::from(BlockError::InvalidReceiptsRoot(Mismatch { expected: expected.receipts_root.clone(), found: got.receipts_root.clone() }))) return Err(From::from(BlockError::InvalidReceiptsRoot(Mismatch { expected: expected.receipts_root().clone(), found: got.receipts_root().clone() })))
} }
Ok(()) Ok(())
} }
/// Check basic header parameters. /// Check basic header parameters.
fn verify_header(header: &Header, engine: &Engine) -> Result<(), Error> { fn verify_header(header: &Header, engine: &Engine) -> Result<(), Error> {
if header.number >= From::from(BlockNumber::max_value()) { 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 }))) 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 { 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 }))); 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; let min_gas_limit = engine.params().min_gas_limit;
if header.gas_limit < 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 }))); 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(); let maximum_extra_data_size = engine.maximum_extra_data_size();
if header.number != 0 && header.extra_data.len() > 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() }))); return Err(From::from(BlockError::ExtraDataOutOfBounds(OutOfBounds { min: None, max: Some(maximum_extra_data_size), found: header.extra_data().len() })));
} }
Ok(()) Ok(())
} }
/// Check header parameters agains parent header. /// Check header parameters agains parent header.
fn verify_parent(header: &Header, parent: &Header) -> Result<(), Error> { fn verify_parent(header: &Header, parent: &Header) -> Result<(), Error> {
if !header.parent_hash.is_zero() && parent.hash() != header.parent_hash { 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() }))) return Err(From::from(BlockError::InvalidParentHash(Mismatch { expected: parent.hash(), found: header.parent_hash().clone() })))
} }
if header.timestamp <= parent.timestamp { if header.timestamp() <= parent.timestamp() {
return Err(From::from(BlockError::InvalidTimestamp(OutOfBounds { max: None, min: Some(parent.timestamp + 1), found: header.timestamp }))) return Err(From::from(BlockError::InvalidTimestamp(OutOfBounds { max: None, min: Some(parent.timestamp() + 1), found: header.timestamp() })))
} }
if header.number != parent.number + 1 { if header.number() != parent.number() + 1 {
return Err(From::from(BlockError::InvalidNumber(Mismatch { expected: parent.number + 1, found: header.number }))); return Err(From::from(BlockError::InvalidNumber(Mismatch { expected: parent.number() + 1, found: header.number() })));
} }
Ok(()) Ok(())
} }
@ -307,9 +307,9 @@ mod tests {
self.blocks.get(hash).map(|bytes| { self.blocks.get(hash).map(|bytes| {
let header = BlockView::new(bytes).header(); let header = BlockView::new(bytes).header();
BlockDetails { BlockDetails {
number: header.number, number: header.number(),
total_difficulty: header.difficulty, total_difficulty: header.difficulty().clone(),
parent: header.parent_hash, parent: header.parent_hash().clone(),
children: Vec::new(), children: Vec::new(),
} }
}) })
@ -352,9 +352,9 @@ mod tests {
let engine = &*spec.engine; let engine = &*spec.engine;
let min_gas_limit = engine.params().min_gas_limit; let min_gas_limit = engine.params().min_gas_limit;
good.gas_limit = min_gas_limit; good.set_gas_limit(min_gas_limit);
good.timestamp = 40; good.set_timestamp(40);
good.number = 10; good.set_number(10);
let keypair = Random.generate().unwrap(); let keypair = Random.generate().unwrap();
@ -381,31 +381,31 @@ mod tests {
let diff_inc = U256::from(0x40); let diff_inc = U256::from(0x40);
let mut parent6 = good.clone(); let mut parent6 = good.clone();
parent6.number = 6; parent6.set_number(6);
let mut parent7 = good.clone(); let mut parent7 = good.clone();
parent7.number = 7; parent7.set_number(7);
parent7.parent_hash = parent6.hash(); parent7.set_parent_hash(parent6.hash());
parent7.difficulty = parent6.difficulty + diff_inc; parent7.set_difficulty(parent6.difficulty().clone() + diff_inc);
parent7.timestamp = parent6.timestamp + 10; parent7.set_timestamp(parent6.timestamp() + 10);
let mut parent8 = good.clone(); let mut parent8 = good.clone();
parent8.number = 8; parent8.set_number(8);
parent8.parent_hash = parent7.hash(); parent8.set_parent_hash(parent7.hash());
parent8.difficulty = parent7.difficulty + diff_inc; parent8.set_difficulty(parent7.difficulty().clone() + diff_inc);
parent8.timestamp = parent7.timestamp + 10; parent8.set_timestamp(parent7.timestamp() + 10);
let mut good_uncle1 = good.clone(); let mut good_uncle1 = good.clone();
good_uncle1.number = 9; good_uncle1.set_number(9);
good_uncle1.parent_hash = parent8.hash(); good_uncle1.set_parent_hash(parent8.hash());
good_uncle1.difficulty = parent8.difficulty + diff_inc; good_uncle1.set_difficulty(parent8.difficulty().clone() + diff_inc);
good_uncle1.timestamp = parent8.timestamp + 10; good_uncle1.set_timestamp(parent8.timestamp() + 10);
good_uncle1.extra_data.push(1u8); good_uncle1.extra_data_mut().push(1u8);
let mut good_uncle2 = good.clone(); let mut good_uncle2 = good.clone();
good_uncle2.number = 8; good_uncle2.set_number(8);
good_uncle2.parent_hash = parent7.hash(); good_uncle2.set_parent_hash(parent7.hash());
good_uncle2.difficulty = parent7.difficulty + diff_inc; good_uncle2.set_difficulty(parent7.difficulty().clone() + diff_inc);
good_uncle2.timestamp = parent7.timestamp + 10; good_uncle2.set_timestamp(parent7.timestamp() + 10);
good_uncle2.extra_data.push(2u8); good_uncle2.extra_data_mut().push(2u8);
let good_uncles = vec![ good_uncle1.clone(), good_uncle2.clone() ]; let good_uncles = vec![ good_uncle1.clone(), good_uncle2.clone() ];
let mut uncles_rlp = RlpStream::new(); 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::<SignedTransaction>(t).to_vec()).collect()); let good_transactions_root = ordered_trie_root(good_transactions.iter().map(|t| encode::<SignedTransaction>(t).to_vec()).collect());
let mut parent = good.clone(); let mut parent = good.clone();
parent.number = 9; parent.set_number(9);
parent.timestamp = parent8.timestamp + 10; parent.set_timestamp(parent8.timestamp() + 10);
parent.parent_hash = parent8.hash(); parent.set_parent_hash(parent8.hash());
parent.difficulty = parent8.difficulty + diff_inc; parent.set_difficulty(parent8.difficulty().clone() + diff_inc);
good.parent_hash = parent.hash(); good.set_parent_hash(parent.hash());
good.difficulty = parent.difficulty + diff_inc; good.set_difficulty(parent.difficulty().clone() + diff_inc);
good.timestamp = parent.timestamp + 10; good.set_timestamp(parent.timestamp() + 10);
let mut bc = TestBlockChain::new(); let mut bc = TestBlockChain::new();
bc.insert(create_test_block(&good)); bc.insert(create_test_block(&good));
@ -433,61 +433,62 @@ mod tests {
check_ok(basic_test(&create_test_block(&good), engine)); check_ok(basic_test(&create_test_block(&good), engine));
let mut header = good.clone(); let mut header = good.clone();
header.transactions_root = good_transactions_root.clone(); header.set_transactions_root(good_transactions_root.clone());
header.uncles_hash = good_uncles_hash.clone(); header.set_uncles_hash(good_uncles_hash.clone());
check_ok(basic_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine)); 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), 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 = good.clone();
header.number = BlockNumber::max_value(); header.set_number(BlockNumber::max_value());
check_fail(basic_test(&create_test_block(&header), engine), 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 = 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), 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 = 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), 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 = 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), 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 = 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), 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 = 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), 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(&good), engine, &bc));
check_ok(family_test(&create_test_block_with_data(&good, &good_transactions, &good_uncles), engine, &bc)); check_ok(family_test(&create_test_block_with_data(&good, &good_transactions, &good_uncles), engine, &bc));
header = good.clone(); 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), 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 = 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), 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 = 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), 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(); header = good.clone();
let mut bad_uncles = good_uncles.clone(); let mut bad_uncles = good_uncles.clone();

View File

@ -169,7 +169,7 @@ impl ChainNotify for Informant {
Colour::White.bold().paint(format!("#{}", header.number())), Colour::White.bold().paint(format!("#{}", header.number())),
Colour::White.bold().paint(format!("{}", header.hash())), Colour::White.bold().paint(format!("{}", header.hash())),
Colour::Yellow.bold().paint(format!("{}", tx_count)), 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::Purple.bold().paint(format!("{:.2}", duration as f32 / 1000000f32)),
Colour::Blue.bold().paint(format!("{:.2}", size as f32 / 1024f32)), 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() } if skipped > 0 { format!(" + another {} block(s)", Colour::Red.bold().paint(format!("{}", skipped))) } else { String::new() }

View File

@ -158,22 +158,22 @@ impl<C, S: ?Sized, M, EM> EthClient<C, S, M, EM> where
let block = Block { let block = Block {
hash: Some(uncle.hash().into()), hash: Some(uncle.hash().into()),
size: None, size: None,
parent_hash: uncle.parent_hash.into(), parent_hash: uncle.parent_hash().clone().into(),
uncles_hash: uncle.uncles_hash.into(), uncles_hash: uncle.uncles_hash().clone().into(),
author: uncle.author.into(), author: uncle.author().clone().into(),
miner: uncle.author.into(), miner: uncle.author().clone().into(),
state_root: uncle.state_root.into(), state_root: uncle.state_root().clone().into(),
transactions_root: uncle.transactions_root.into(), transactions_root: uncle.transactions_root().clone().into(),
number: Some(uncle.number.into()), number: Some(uncle.number().into()),
gas_used: uncle.gas_used.into(), gas_used: uncle.gas_used().clone().into(),
gas_limit: uncle.gas_limit.into(), gas_limit: uncle.gas_limit().clone().into(),
logs_bloom: uncle.log_bloom.into(), logs_bloom: uncle.log_bloom().clone().into(),
timestamp: uncle.timestamp.into(), timestamp: uncle.timestamp().into(),
difficulty: uncle.difficulty.into(), difficulty: uncle.difficulty().clone().into(),
total_difficulty: (uncle.difficulty + parent_difficulty).into(), total_difficulty: (uncle.difficulty().clone() + parent_difficulty).into(),
receipts_root: uncle.receipts_root.into(), receipts_root: uncle.receipts_root().clone().into(),
extra_data: uncle.extra_data.into(), extra_data: uncle.extra_data().clone().into(),
seal_fields: uncle.seal.into_iter().map(|f| decode(&f)).map(Bytes::new).collect(), seal_fields: uncle.seal().clone().into_iter().map(|f| decode(&f)).map(Bytes::new).collect(),
uncles: vec![], uncles: vec![],
transactions: BlockTransactions::Hashes(vec![]), transactions: BlockTransactions::Hashes(vec![]),
}; };

View File

@ -270,7 +270,7 @@ impl BlockCollection {
match self.head { match self.head {
None if hash == self.heads[0] => { None if hash == self.heads[0] => {
trace!("New head {}", hash); 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, body: None,
}; };
let header_id = HeaderId { let header_id = HeaderId {
transactions_root: info.transactions_root, transactions_root: info.transactions_root().clone(),
uncles: info.uncles_hash uncles: info.uncles_hash().clone(),
}; };
if header_id.transactions_root == rlp::SHA3_NULL_RLP && header_id.uncles == rlp::SHA3_EMPTY_LIST_RLP { if header_id.transactions_root == rlp::SHA3_NULL_RLP && header_id.uncles == rlp::SHA3_EMPTY_LIST_RLP {
// empty body, just mark as downloaded // empty body, just mark as downloaded
@ -294,7 +294,7 @@ impl BlockCollection {
self.header_ids.insert(header_id, hash.clone()); 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); self.blocks.insert(hash.clone(), block);
trace!(target: "sync", "New header: {}", hash.hex()); trace!(target: "sync", "New header: {}", hash.hex());
Ok(hash) Ok(hash)

View File

@ -503,7 +503,7 @@ impl ChainSync {
let mut valid_response = item_count == 0; //empty response is valid let mut valid_response = item_count == 0; //empty response is valid
for i in 0..item_count { for i in 0..item_count {
let info: BlockHeader = try!(r.val_at(i)); 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 // Check if any of the headers matches the hash we requested
if !valid_response { if !valid_response {
if let Some(expected) = expected_hash { if let Some(expected) = expected_hash {
@ -645,11 +645,11 @@ impl ChainSync {
trace!(target: "sync", "New block already queued {:?}", h); trace!(target: "sync", "New block already queued {:?}", h);
}, },
Ok(_) => { Ok(_) => {
if header.number == self.last_imported_block + 1 { if header.number() == self.last_imported_block + 1 {
self.last_imported_block = header.number; self.last_imported_block = header.number();
self.last_imported_hash = header.hash(); 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))) => { Err(BlockImportError::Block(BlockError::UnknownParent(p))) => {
unknown = true; unknown = true;
@ -1539,12 +1539,12 @@ mod tests {
fn get_dummy_block(order: u32, parent_hash: H256) -> Bytes { fn get_dummy_block(order: u32, parent_hash: H256) -> Bytes {
let mut header = Header::new(); let mut header = Header::new();
header.gas_limit = 0.into(); header.set_gas_limit(0.into());
header.difficulty = (order * 100).into(); header.set_difficulty((order * 100).into());
header.timestamp = (order * 10) as u64; header.set_timestamp((order * 10) as u64);
header.number = order as u64; header.set_number(order as u64);
header.parent_hash = parent_hash; header.set_parent_hash(parent_hash);
header.state_root = H256::zero(); header.set_state_root(H256::zero());
let mut rlp = RlpStream::new_list(3); let mut rlp = RlpStream::new_list(3);
rlp.append(&header); rlp.append(&header);