use encoded::Header in HeaderChain
This commit is contained in:
parent
3b9ac7648c
commit
83de16da88
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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> {
|
||||||
|
@ -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) }
|
||||||
|
Loading…
Reference in New Issue
Block a user