hide CHT internals from header chain

This commit is contained in:
Robert Habermeier 2017-02-03 19:50:23 +01:00
parent 1baa824d1e
commit e874df5155
6 changed files with 62 additions and 14 deletions

16
Cargo.lock generated
View File

@ -285,6 +285,11 @@ name = "dtoa"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "either"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "elastic-array"
version = "0.6.0"
@ -515,6 +520,7 @@ dependencies = [
"ethcore-network 1.6.0",
"ethcore-util 1.6.0",
"futures 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.1.0",
@ -943,6 +949,14 @@ name = "itertools"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "itertools"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"either 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "itoa"
version = "0.1.1"
@ -2424,6 +2438,7 @@ dependencies = [
"checksum deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1614659040e711785ed8ea24219140654da1729f3ec8a47a9719d041112fe7bf"
"checksum docopt 0.6.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4cc0acb4ce0828c6a5a11d47baa432fe885881c27428c3a4e473e454ffe57a76"
"checksum dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0dd841b58510c9618291ffa448da2e4e0f699d984d436122372f446dae62263d"
"checksum either 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3d2b503c86dad62aaf414ecf2b8c527439abedb3f8d812537f0b12bfd6f32a91"
"checksum elastic-array 0.6.0 (git+https://github.com/ethcore/elastic-array)" = "<none>"
"checksum env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "aba65b63ffcc17ffacd6cf5aa843da7c5a25e3bd4bbe0b7def8b214e411250e5"
"checksum eth-secp256k1 0.5.4 (git+https://github.com/ethcore/rust-secp256k1)" = "<none>"
@ -2445,6 +2460,7 @@ dependencies = [
"checksum igd 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c8c12b1795b8b168f577c45fa10379b3814dcb11b7ab702406001f0d63f40484"
"checksum isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7408a548dc0e406b7912d9f84c261cc533c1866e047644a811c133c56041ac0c"
"checksum itertools 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "086e1fa5fe48840b1cfdef3a20c7e3115599f8d5c4c87ef32a794a7cdd184d76"
"checksum itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d95557e7ba6b71377b0f2c3b3ae96c53f1b75a926a6901a500f557a370af730a"
"checksum itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae3088ea4baeceb0284ee9eea42f591226e6beaecf65373e41b38d95a1b8e7a1"
"checksum jsonrpc-core 5.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>"
"checksum jsonrpc-http-server 7.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "<none>"

View File

@ -22,6 +22,7 @@ time = "0.1"
smallvec = "0.3.1"
futures = "0.1"
rand = "0.3"
itertools = "0.5"
[features]
default = []

View File

@ -34,7 +34,7 @@ macro_rules! val {
($hash: expr, $td: expr) => {{
let mut stream = RlpStream::new_list(2);
stream.append(&$hash).append(&$td);
stream.out()
stream.drain()
}}
}
@ -116,6 +116,26 @@ pub fn build<F>(cht_num: u64, mut fetcher: F) -> Option<CHT<MemoryDB>>
})
}
/// Compute a CHT root from an iterator of (hash, td) pairs. Fails if shorter than
/// SIZE items. The items are assumed to proceed sequentially from `start_number(cht_num)`.
/// Discards the trie's nodes.
pub fn compute_root<I>(cht_num: u64, iterable: I) -> Option<H256>
where I: IntoIterator<Item=(H256, U256)>
{
let mut v = Vec::with_capacity(SIZE as usize);
let start_num = start_number(cht_num) as usize;
for (i, (h, td)) in iterable.into_iter().take(SIZE as usize).enumerate() {
v.push((key!(i + start_num).to_vec(), val!(h, td).to_vec()))
}
if v.len() == SIZE as usize {
Some(::util::triehash::trie_root(v))
} else {
None
}
}
/// Convert a block number to a CHT number.
/// Returns `None` for `block_num` == 0, `Some` otherwise.
pub fn block_to_cht_number(block_num: u64) -> Option<u64> {

View File

@ -173,26 +173,34 @@ impl HeaderChain {
// produce next CHT root if it's time.
let earliest_era = *candidates.keys().next().expect("at least one era just created; qed");
if earliest_era + HISTORY + cht::SIZE <= number {
let mut values = Vec::with_capacity(cht::SIZE as usize);
{
let cht_num = cht::block_to_cht_number(earliest_era)
.expect("fails only for number == 0; genesis never imported; qed");
debug_assert_eq!(cht_num as usize, self.cht_roots.lock().len());
let mut headers = self.headers.write();
for i in (0..cht::SIZE).map(|x| x + earliest_era) {
let cht_root = {
let mut i = earliest_era;
// iterable function which removes the candidates as it goes
// along. this will only be called until the CHT is complete.
let iter = || {
let era_entry = candidates.remove(&i)
.expect("all eras are sequential with no gaps; qed");
i += 1;
for ancient in &era_entry.candidates {
headers.remove(&ancient.hash);
}
values.push((
::rlp::encode(&i).to_vec(),
::rlp::encode(&era_entry.canonical_hash).to_vec(),
));
}
}
let canon = &era_entry.candidates[0];
(canon.hash, canon.total_difficulty)
};
cht::compute_root(cht_num, ::itertools::repeat_call(iter))
.expect("fails only when too few items; this is checked; qed")
};
let cht_root = ::util::triehash::trie_root(values);
debug!(target: "chain", "Produced CHT {} root: {:?}", (earliest_era - 1) % cht::SIZE, cht_root);
debug!(target: "chain", "Produced CHT {} root: {:?}", cht_num, cht_root);
self.cht_roots.lock().push(cht_root);
}

View File

@ -68,6 +68,7 @@ extern crate smallvec;
extern crate time;
extern crate futures;
extern crate rand;
extern crate itertools;
#[cfg(feature = "ipc")]
extern crate ethcore_ipc as ipc;

View File

@ -77,7 +77,9 @@ pub fn ordered_trie_root<I>(input: I) -> H256
/// assert_eq!(trie_root(v), H256::from_str(root).unwrap());
/// }
/// ```
pub fn trie_root(input: Vec<(Vec<u8>, Vec<u8>)>) -> H256 {
pub fn trie_root<I>(input: I) -> H256
where I: IntoIterator<Item=(Vec<u8>, Vec<u8>)>
{
let gen_input = input
// first put elements into btree to sort them and to remove duplicates
.into_iter()