From ee7779df171e69fe2eb5f022b9f8e119cb55aa84 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Fri, 24 Feb 2017 20:16:32 +0100 Subject: [PATCH] proving state backend --- ethcore/src/state/backend.rs | 94 +++++++++++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) diff --git a/ethcore/src/state/backend.rs b/ethcore/src/state/backend.rs index 81a770fe7..dfb4465fa 100644 --- a/ethcore/src/state/backend.rs +++ b/ethcore/src/state/backend.rs @@ -21,10 +21,12 @@ //! should become general over time to the point where not even a //! merkle trie is strictly necessary. +use std::collections::{HashSet, HashMap}; use std::sync::Arc; use state::Account; -use util::{Address, AsHashDB, HashDB, H256}; +use util::{Address, MemoryDB, Mutex, H256}; +use util::hashdb::{AsHashDB, HashDB, DBValue}; /// State backend. See module docs for more details. pub trait Backend: Send { @@ -91,3 +93,93 @@ impl Backend for NoCache { fn note_non_null_account(&self, _address: &Address) {} fn is_known_null(&self, _address: &Address) -> bool { false } } + +/// Proving state backend. +/// See module docs for more details. +/// +/// This doesn't cache anything or rely on the canonical state caches. +#[derive(Debug, Clone, PartialEq)] +pub struct Proving { + base: H, // state we're proving values from. + changed: MemoryDB, // changed state via insertions. + proof: Mutex>, +} + +impl HashDB for Proving { + fn keys(&self) -> HashMap { + self.base.as_hashdb().keys() + .extend(self.changed.keys()) + } + + fn get(&self, key: &H256) -> Option { + match self.base.as_hashdb().get(key) { + Some(val) => { + self.proof.lock().insert(val.clone()); + Some(val) + } + None => self.changed.get(key) + } + } + + fn contains(&self, key: &H256) -> bool { + self.get(key).is_some() + } + + fn insert(&mut self, value: &[u8]) -> H256 { + self.changed.insert(value) + } + + fn emplace(&mut self, key: H256, value: DBValue) { + self.changed.emplace(key, value) + } + + fn remove(&mut self, key: &H256) { + // only remove from `changed` + if self.changed.contains(key) { + self.changed.remove(key) + } + } +} + +impl Backend for Proving { + fn as_hashdb(&self) -> &HashDB { + self + } + + fn as_hashdb_mut(&mut self) -> &mut HashDB { + self + } + + fn add_to_account_cache(&mut self, _: Address, _: Option, _: bool) { } + + fn cache_code(&self, _: H256, _: Arc>) { } + + fn get_cached_account(&self, _: &Address) -> Option> { None } + + fn get_cached(&self, _: &Address, _: F) -> Option + where F: FnOnce(Option<&mut Account>) -> U + { + None + } + + fn get_cached_code(&self, _: &H256) -> Option>> { None } + fn note_non_null_account(&self, _: &Address) { } + fn is_known_null(&self, _: &Address) -> bool { false } +} + +impl Proving { + /// Create a new `Proving` over a base database. + /// This will store all values ever fetched from that base. + pub fn new(base: H) -> Self { + Proving { + base: base, + changed: MemoryDB::new(), + proof: Mutex::new(HashSet::new()), + } + } + + /// Consume the backend, extracting the gathered proof. + pub fn extract_proof(self) -> Vec { + self.proof.into_inner().into_iter().collect() + } +}