use encoded::Header in HeaderChain

This commit is contained in:
Robert Habermeier 2017-02-03 15:32:22 +01:00
parent 3b9ac7648c
commit 83de16da88
3 changed files with 51 additions and 39 deletions

View File

@ -32,9 +32,10 @@ use cht;
use ethcore::block_status::BlockStatus;
use ethcore::error::BlockError;
use ethcore::encoded;
use ethcore::header::Header;
use ethcore::ids::BlockId;
use ethcore::views::HeaderView;
use util::{Bytes, H256, U256, HeapSizeOf, Mutex, RwLock};
use util::{H256, U256, HeapSizeOf, Mutex, RwLock};
use smallvec::SmallVec;
@ -77,9 +78,9 @@ impl HeapSizeOf for Entry {
/// Header chain. See module docs for more details.
pub struct HeaderChain {
genesis_header: Bytes, // special-case the genesis.
genesis_header: encoded::Header, // special-case the genesis.
candidates: RwLock<BTreeMap<u64, Entry>>,
headers: RwLock<HashMap<H256, Bytes>>,
headers: RwLock<HashMap<H256, encoded::Header>>,
best_block: RwLock<BlockDescriptor>,
cht_roots: Mutex<Vec<H256>>,
}
@ -87,10 +88,12 @@ pub struct HeaderChain {
impl HeaderChain {
/// Create a new header chain given this genesis block.
pub fn new(genesis: &[u8]) -> Self {
use ethcore::views::HeaderView;
let g_view = HeaderView::new(genesis);
HeaderChain {
genesis_header: genesis.to_owned(),
genesis_header: encoded::Header::new(genesis.to_owned()),
best_block: RwLock::new(BlockDescriptor {
hash: g_view.hash(),
number: 0,
@ -104,14 +107,11 @@ impl HeaderChain {
/// Insert a pre-verified header.
///
/// This blindly trusts that the data given to it is
/// a) valid RLP encoding of a header and
/// b) has sensible data contained within it.
pub fn insert(&self, header: Bytes) -> Result<(), BlockError> {
let view = HeaderView::new(&header);
let hash = view.hash();
let number = view.number();
let parent_hash = view.parent_hash();
/// This blindly trusts that the data given to it is sensible.
pub fn insert(&self, header: Header) -> Result<(), BlockError> {
let hash = header.hash();
let number = header.number();
let parent_hash = *header.parent_hash();
// hold candidates the whole time to guard import order.
let mut candidates = self.candidates.write();
@ -119,8 +119,7 @@ impl HeaderChain {
// find parent details.
let parent_td =
if number == 1 {
let g_view = HeaderView::new(&self.genesis_header);
g_view.difficulty()
self.genesis_header.difficulty()
} else {
candidates.get(&(number - 1))
.and_then(|entry| entry.candidates.iter().find(|c| c.hash == parent_hash))
@ -128,7 +127,7 @@ impl HeaderChain {
.ok_or_else(|| BlockError::UnknownParent(parent_hash))?
};
let total_difficulty = parent_td + view.difficulty();
let total_difficulty = parent_td + *header.difficulty();
// insert headers and candidates entries.
candidates.entry(number).or_insert_with(|| Entry { candidates: SmallVec::new(), canonical_hash: hash })
@ -138,7 +137,8 @@ impl HeaderChain {
total_difficulty: total_difficulty,
});
self.headers.write().insert(hash, header.clone());
let raw = ::rlp::encode(&header).to_vec();
self.headers.write().insert(hash, encoded::Header::new(raw));
// reorganize ancestors so canonical entries are first in their
// respective candidates vectors.
@ -203,19 +203,19 @@ impl HeaderChain {
/// Get a block header. In the case of query by number, only canonical blocks
/// will be returned.
pub fn get_header(&self, id: BlockId) -> Option<Bytes> {
pub fn get_header(&self, id: BlockId) -> Option<encoded::Header> {
match id {
BlockId::Earliest | BlockId::Number(0) => Some(self.genesis_header.clone()),
BlockId::Hash(hash) => self.headers.read().get(&hash).map(|x| x.to_vec()),
BlockId::Hash(hash) => self.headers.read().get(&hash).cloned(),
BlockId::Number(num) => {
if self.best_block.read().number < num { return None }
self.candidates.read().get(&num).map(|entry| entry.canonical_hash)
.and_then(|hash| self.headers.read().get(&hash).map(|x| x.to_vec()))
.and_then(|hash| self.headers.read().get(&hash).cloned())
}
BlockId::Latest | BlockId::Pending => {
let hash = self.best_block.read().hash;
self.headers.read().get(&hash).map(|x| x.to_vec())
self.headers.read().get(&hash).cloned()
}
}
}
@ -296,10 +296,10 @@ mod tests {
header.set_number(i);
header.set_timestamp(rolling_timestamp);
header.set_difficulty(*genesis_header.difficulty() * i.into());
chain.insert(::rlp::encode(&header).to_vec()).unwrap();
parent_hash = header.hash();
chain.insert(header).unwrap();
rolling_timestamp += 10;
}
@ -324,10 +324,10 @@ mod tests {
header.set_number(i);
header.set_timestamp(rolling_timestamp);
header.set_difficulty(*genesis_header.difficulty() * i.into());
chain.insert(::rlp::encode(&header).to_vec()).unwrap();
parent_hash = header.hash();
chain.insert(header).unwrap();
rolling_timestamp += 10;
}
@ -340,10 +340,10 @@ mod tests {
header.set_number(i);
header.set_timestamp(rolling_timestamp);
header.set_difficulty(*genesis_header.difficulty() * i.into());
chain.insert(::rlp::encode(&header).to_vec()).unwrap();
parent_hash = header.hash();
chain.insert(header).unwrap();
rolling_timestamp += 10;
}
}
@ -361,10 +361,10 @@ mod tests {
header.set_number(i);
header.set_timestamp(rolling_timestamp);
header.set_difficulty(*genesis_header.difficulty() * (i * i).into());
chain.insert(::rlp::encode(&header).to_vec()).unwrap();
parent_hash = header.hash();
chain.insert(header).unwrap();
rolling_timestamp += 11;
}
}
@ -373,10 +373,10 @@ mod tests {
assert_eq!(num, 12);
while num > 0 {
let header: Header = ::rlp::decode(&chain.get_header(BlockId::Number(num)).unwrap());
let header = chain.get_header(BlockId::Number(num)).unwrap();
assert_eq!(header.hash(), canon_hash);
canon_hash = *header.parent_hash();
canon_hash = header.parent_hash();
num -= 1;
}
}

View File

@ -148,7 +148,7 @@ impl Client {
}
/// Get a block header by Id.
pub fn get_header(&self, id: BlockId) -> Option<Bytes> {
pub fn get_header(&self, id: BlockId) -> Option<encoded::Header> {
self.chain.get_header(id)
}
@ -173,7 +173,7 @@ impl Client {
for verified_header in self.queue.drain(MAX) {
let (num, hash) = (verified_header.number(), verified_header.hash());
match self.chain.insert(::rlp::encode(&verified_header).to_vec()) {
match self.chain.insert(verified_header) {
Ok(()) => {
good.push(hash);
self.report.write().blocks_imported += 1;
@ -245,7 +245,7 @@ impl Provider for Client {
}
fn block_header(&self, id: BlockId) -> Option<encoded::Header> {
self.chain.get_header(id).map(encoded::Header::new)
self.chain.get_header(id)
}
fn block_body(&self, _id: BlockId) -> Option<encoded::Body> {

View File

@ -28,7 +28,7 @@ use header::{BlockNumber, Header as FullHeader};
use transaction::UnverifiedTransaction;
use views;
use util::{Address, Hashable, H256, H2048, U256};
use util::{Address, Hashable, H256, H2048, U256, HeapSizeOf};
use rlp::{Rlp, View};
/// Owning header view.
@ -36,6 +36,10 @@ use rlp::{Rlp, View};
#[cfg_attr(feature = "ipc", binary)]
pub struct Header(Vec<u8>);
impl HeapSizeOf for Header {
fn heap_size_of_children(&self) -> usize { self.0.heap_size_of_children() }
}
impl Header {
/// Create a new owning header view.
/// Expects the data to be an RLP-encoded header -- any other case will likely lead to
@ -116,6 +120,10 @@ impl Hashable for Header {
#[cfg_attr(feature = "ipc", binary)]
pub struct Body(Vec<u8>);
impl HeapSizeOf for Body {
fn heap_size_of_children(&self) -> usize { self.0.heap_size_of_children() }
}
impl Body {
/// Create a new owning block body view. The raw bytes passed in must be an rlp-encoded block
/// body.
@ -172,6 +180,10 @@ impl Body {
#[cfg_attr(feature = "ipc", binary)]
pub struct Block(Vec<u8>);
impl HeapSizeOf for Block {
fn heap_size_of_children(&self) -> usize { self.0.heap_size_of_children() }
}
impl Block {
/// Create a new owning block view. The raw bytes passed in must be an rlp-encoded block.
pub fn new(raw: Vec<u8>) -> Self { Block(raw) }