From b960152d5b099c08367b2933cc52c5a42a258d07 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Mon, 16 Jan 2017 17:10:30 +0100 Subject: [PATCH] CHT calculations for full nodes --- ethcore/light/src/on_demand/mod.rs | 2 +- ethcore/light/src/provider.rs | 45 ++++++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/ethcore/light/src/on_demand/mod.rs b/ethcore/light/src/on_demand/mod.rs index aadb43c0e..dfc78a629 100644 --- a/ethcore/light/src/on_demand/mod.rs +++ b/ethcore/light/src/on_demand/mod.rs @@ -112,7 +112,7 @@ impl OnDemand { // dispatch the request, completing the request if no peers available. fn dispatch_header_by_number(&self, ctx: &BasicContext, req: request::HeaderByNumber, sender: Sender) { let num = req.num; - let cht_num = ::client::cht::block_to_cht_number(req.num); + let cht_num = ::cht::block_to_cht_number(req.num); let les_req = LesRequest::HeaderProofs(les_request::HeaderProofs { requests: vec![les_request::HeaderProof { cht_number: cht_num, diff --git a/ethcore/light/src/provider.rs b/ethcore/light/src/provider.rs index 9a05d3499..14f8a148d 100644 --- a/ethcore/light/src/provider.rs +++ b/ethcore/light/src/provider.rs @@ -226,8 +226,49 @@ impl Provider for T { self.code_by_hash(req.account_key, BlockId::Hash(req.block_hash)) } - fn header_proof(&self, _req: request::HeaderProof) -> Option<(encoded::Header, Vec)> { - None + fn header_proof(&self, req: request::HeaderProof) -> Option<(encoded::Header, Vec)> { + use util::MemoryDB; + use util::trie::{Trie, TrieMut, TrieDB, TrieDBMut, Recorder}; + + if req.cht_number != ::cht::block_to_cht_number(req.block_number) { + debug!(target: "les_provider", "Requested CHT number mismatch with block number."); + return None; + } + + let mut memdb = MemoryDB::new(); + let mut root = H256::default(); + let mut needed_hdr = None; + { + let mut t = TrieDBMut::new(&mut memdb, &mut root); + let start_num = ::cht::start_number(req.cht_number); + for i in (0..::cht::SIZE).map(|x| x + start_num) { + match self.block_header(BlockId::Number(i)) { + None => return None, + Some(hdr) => { + t.insert( + &*::rlp::encode(&i), + &*::rlp::encode(&hdr.hash()), + ).expect("fresh in-memory database is infallible; qed"); + + if i == req.block_number { needed_hdr = Some(hdr) } + } + } + } + } + let needed_hdr = needed_hdr.expect("`needed_hdr` always set in loop, number checked before; qed"); + + let mut recorder = Recorder::new(); + let t = TrieDB::new(&memdb, &root) + .expect("Same DB and root as just produced by TrieDBMut; qed"); + + if let Err(e) = t.get_with(&*::rlp::encode(&req.block_number), &mut recorder) { + debug!(target: "les_provider", "Error looking up number in freshly-created CHT: {}", e); + return None; + } + + // TODO: cache calculated CHT if possible. + let proof = recorder.drain().into_iter().map(|x| x.data).collect(); + Some((needed_hdr, proof)) } fn ready_transactions(&self) -> Vec {