implement provider for client

This commit is contained in:
Robert Habermeier
2016-11-15 14:53:30 +01:00
parent 3c7533831e
commit abf39fde0a
9 changed files with 227 additions and 87 deletions

View File

@@ -437,6 +437,27 @@ impl Account {
}
}
// light client storage proof.
impl Account {
/// Prove a storage key's existence or nonexistence in the account's storage
/// trie.
/// `storage_key` is the hash of the desired storage key, meaning
/// this will only work correctly under a secure trie.
/// Returns a merkle proof of the storage trie node with all nodes before `from_level`
/// omitted.
pub fn prove_storage(&self, db: &HashDB, storage_key: H256, from_level: u32) -> Result<Vec<Bytes>, Box<TrieError>> {
use util::trie::{Trie, TrieDB};
use util::trie::recorder::{Recorder, BasicRecorder as TrieRecorder};
let mut recorder = TrieRecorder::with_depth(from_level);
let trie = try!(TrieDB::new(db, &self.storage_root));
let _ = try!(trie.get_recorded(&storage_key, &mut recorder));
Ok(recorder.drain().into_iter().map(|r| r.data).collect())
}
}
impl fmt::Debug for Account {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", PodAccount::from_account(self))

View File

@@ -16,7 +16,7 @@
use std::cell::{RefCell, RefMut};
use std::collections::hash_map::Entry;
use util::*;
use receipt::Receipt;
use engines::Engine;
use env_info::EnvInfo;
@@ -30,6 +30,9 @@ use types::state_diff::StateDiff;
use transaction::SignedTransaction;
use state_db::StateDB;
use util::*;
use util::trie::recorder::{Recorder, BasicRecorder as TrieRecorder};
mod account;
mod substate;
@@ -751,6 +754,53 @@ impl State {
}
}
// LES state proof implementations.
impl State {
/// Prove an account's existence or nonexistence in the state trie.
/// Returns a merkle proof of the account's trie node with all nodes before `from_level`
/// omitted or an encountered trie error.
/// Requires a secure trie to be used for accurate results.
/// `account_key` == sha3(address)
pub fn prove_account(&self, account_key: H256, from_level: u32) -> Result<Vec<Bytes>, Box<TrieError>> {
let mut recorder = TrieRecorder::with_depth(from_level);
let trie = try!(TrieDB::new(self.db.as_hashdb(), &self.root));
let _ = try!(trie.get_recorded(&account_key, &mut recorder));
Ok(recorder.drain().into_iter().map(|r| r.data).collect())
}
/// Prove an account's storage key's existence or nonexistence in the state.
/// Returns a merkle proof of the account's storage trie with all nodes before
/// `from_level` omitted. Requires a secure trie to be used for correctness.
/// `account_key` == sha3(address)
/// `storage_key` == sha3(key)
pub fn prove_storage(&self, account_key: H256, storage_key: H256, from_level: u32) -> Result<Vec<Bytes>, Box<TrieError>> {
// TODO: probably could look into cache somehow but it's keyed by
// address, not sha3(address).
let trie = try!(TrieDB::new(self.db.as_hashdb(), &self.root));
let acc = match try!(trie.get(&account_key)) {
Some(rlp) => Account::from_rlp(&rlp),
None => return Ok(Vec::new()),
};
let account_db = self.factories.accountdb.readonly(self.db.as_hashdb(), account_key);
acc.prove_storage(account_db.as_hashdb(), storage_key, from_level)
}
/// Get code by address hash.
/// Only works when backed by a secure trie.
pub fn code_by_address_hash(&self, account_key: H256) -> Result<Option<Bytes>, Box<TrieError>> {
let trie = try!(TrieDB::new(self.db.as_hashdb(), &self.root));
let mut acc = match try!(trie.get(&account_key)) {
Some(rlp) => Account::from_rlp(&rlp),
None => return Ok(None),
};
let account_db = self.factories.accountdb.readonly(self.db.as_hashdb(), account_key);
Ok(acc.cache_code(account_db.as_hashdb()).map(|c| (&*c).clone()))
}
}
impl fmt::Debug for State {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self.cache.borrow())