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

View File

@ -148,7 +148,7 @@ impl Client {
} }
/// Get a block header by Id. /// 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) self.chain.get_header(id)
} }
@ -173,7 +173,7 @@ impl Client {
for verified_header in self.queue.drain(MAX) { for verified_header in self.queue.drain(MAX) {
let (num, hash) = (verified_header.number(), verified_header.hash()); 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(()) => { Ok(()) => {
good.push(hash); good.push(hash);
self.report.write().blocks_imported += 1; self.report.write().blocks_imported += 1;
@ -245,7 +245,7 @@ impl Provider for Client {
} }
fn block_header(&self, id: BlockId) -> Option<encoded::Header> { 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> { 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 transaction::UnverifiedTransaction;
use views; use views;
use util::{Address, Hashable, H256, H2048, U256}; use util::{Address, Hashable, H256, H2048, U256, HeapSizeOf};
use rlp::{Rlp, View}; use rlp::{Rlp, View};
/// Owning header view. /// Owning header view.
@ -36,6 +36,10 @@ use rlp::{Rlp, View};
#[cfg_attr(feature = "ipc", binary)] #[cfg_attr(feature = "ipc", binary)]
pub struct Header(Vec<u8>); pub struct Header(Vec<u8>);
impl HeapSizeOf for Header {
fn heap_size_of_children(&self) -> usize { self.0.heap_size_of_children() }
}
impl Header { impl Header {
/// Create a new owning header view. /// Create a new owning header view.
/// Expects the data to be an RLP-encoded header -- any other case will likely lead to /// 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)] #[cfg_attr(feature = "ipc", binary)]
pub struct Body(Vec<u8>); pub struct Body(Vec<u8>);
impl HeapSizeOf for Body {
fn heap_size_of_children(&self) -> usize { self.0.heap_size_of_children() }
}
impl Body { impl Body {
/// Create a new owning block body view. The raw bytes passed in must be an rlp-encoded block /// Create a new owning block body view. The raw bytes passed in must be an rlp-encoded block
/// body. /// body.
@ -172,6 +180,10 @@ impl Body {
#[cfg_attr(feature = "ipc", binary)] #[cfg_attr(feature = "ipc", binary)]
pub struct Block(Vec<u8>); pub struct Block(Vec<u8>);
impl HeapSizeOf for Block {
fn heap_size_of_children(&self) -> usize { self.0.heap_size_of_children() }
}
impl Block { impl Block {
/// Create a new owning block view. The raw bytes passed in must be an rlp-encoded 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) } pub fn new(raw: Vec<u8>) -> Self { Block(raw) }