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" version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "elastic-array" name = "elastic-array"
version = "0.6.0" version = "0.6.0"
@ -515,6 +520,7 @@ dependencies = [
"ethcore-network 1.6.0", "ethcore-network 1.6.0",
"ethcore-util 1.6.0", "ethcore-util 1.6.0",
"futures 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.1.0", "rlp 0.1.0",
@ -943,6 +949,14 @@ name = "itertools"
version = "0.4.13" version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "itoa" name = "itoa"
version = "0.1.1" 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 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 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 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 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 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>" "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 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 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.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 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-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>" "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" smallvec = "0.3.1"
futures = "0.1" futures = "0.1"
rand = "0.3" rand = "0.3"
itertools = "0.5"
[features] [features]
default = [] default = []

View File

@ -34,7 +34,7 @@ macro_rules! val {
($hash: expr, $td: expr) => {{ ($hash: expr, $td: expr) => {{
let mut stream = RlpStream::new_list(2); let mut stream = RlpStream::new_list(2);
stream.append(&$hash).append(&$td); 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. /// Convert a block number to a CHT number.
/// Returns `None` for `block_num` == 0, `Some` otherwise. /// Returns `None` for `block_num` == 0, `Some` otherwise.
pub fn block_to_cht_number(block_num: u64) -> Option<u64> { 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. // produce next CHT root if it's time.
let earliest_era = *candidates.keys().next().expect("at least one era just created; qed"); let earliest_era = *candidates.keys().next().expect("at least one era just created; qed");
if earliest_era + HISTORY + cht::SIZE <= number { 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");
let mut headers = self.headers.write(); debug_assert_eq!(cht_num as usize, self.cht_roots.lock().len());
for i in (0..cht::SIZE).map(|x| x + earliest_era) {
let mut headers = self.headers.write();
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) let era_entry = candidates.remove(&i)
.expect("all eras are sequential with no gaps; qed"); .expect("all eras are sequential with no gaps; qed");
i += 1;
for ancient in &era_entry.candidates { for ancient in &era_entry.candidates {
headers.remove(&ancient.hash); headers.remove(&ancient.hash);
} }
values.push(( let canon = &era_entry.candidates[0];
::rlp::encode(&i).to_vec(), (canon.hash, canon.total_difficulty)
::rlp::encode(&era_entry.canonical_hash).to_vec(), };
)); 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: {:?}", cht_num, cht_root);
debug!(target: "chain", "Produced CHT {} root: {:?}", (earliest_era - 1) % cht::SIZE, cht_root);
self.cht_roots.lock().push(cht_root); self.cht_roots.lock().push(cht_root);
} }

View File

@ -68,6 +68,7 @@ extern crate smallvec;
extern crate time; extern crate time;
extern crate futures; extern crate futures;
extern crate rand; extern crate rand;
extern crate itertools;
#[cfg(feature = "ipc")] #[cfg(feature = "ipc")]
extern crate ethcore_ipc as 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()); /// 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 let gen_input = input
// first put elements into btree to sort them and to remove duplicates // first put elements into btree to sort them and to remove duplicates
.into_iter() .into_iter()