prove_transaction function on state

This commit is contained in:
Robert Habermeier 2017-08-15 00:12:40 +02:00
parent 0abf2abc81
commit 1e269c94a6
3 changed files with 48 additions and 16 deletions

View File

@ -1884,27 +1884,23 @@ impl ProvingBlockChainClient for Client {
} }
fn prove_transaction(&self, transaction: SignedTransaction, id: BlockId) -> Option<(Bytes, Vec<DBValue>)> { fn prove_transaction(&self, transaction: SignedTransaction, id: BlockId) -> Option<(Bytes, Vec<DBValue>)> {
let (state, mut env_info) = match (self.state_at(id), self.env_info(id)) { let (header, mut env_info) = match (self.block_header(id), self.env_info(id)) {
(Some(s), Some(e)) => (s, e), (Some(s), Some(e)) => (s, e),
_ => return None, _ => return None,
}; };
env_info.gas_limit = transaction.gas.clone(); env_info.gas_limit = transaction.gas.clone();
let mut jdb = self.state_db.lock().journal_db().boxed_clone(); let mut jdb = self.state_db.lock().journal_db().boxed_clone();
let backend = state::backend::Proving::new(jdb.as_hashdb_mut());
let mut state = state.replace_backend(backend); state::prove_transaction(
let options = TransactOptions { tracing: false, vm_tracing: false, check_nonce: false }; jdb.as_hashdb_mut(),
let res = Executive::new(&mut state, &env_info, &*self.engine).transact(&transaction, options); header.state_root().clone(),
&transaction,
match res { &*self.engine,
Err(ExecutionError::Internal(_)) => None, &env_info,
Err(e) => { self.factories.clone(),
trace!(target: "client", "Proved call failed: {}", e); false,
Some((Vec::new(), state.drop().1.extract_proof())) )
}
Ok(res) => Some((res.output, state.drop().1.extract_proof())),
}
} }
} }

View File

@ -32,7 +32,6 @@ use factory::Factories;
use header::{BlockNumber, Header}; use header::{BlockNumber, Header};
use pod_state::*; use pod_state::*;
use rlp::{Rlp, RlpStream}; use rlp::{Rlp, RlpStream};
use state_db::StateDB;
use state::{Backend, State, Substate}; use state::{Backend, State, Substate};
use state::backend::Basic as BasicBackend; use state::backend::Basic as BasicBackend;
use trace::{NoopTracer, NoopVMTracer}; use trace::{NoopTracer, NoopVMTracer};
@ -421,7 +420,7 @@ impl Spec {
} }
/// Ensure that the given state DB has the trie nodes in for the genesis state. /// Ensure that the given state DB has the trie nodes in for the genesis state.
pub fn ensure_db_good(&self, db: StateDB, factories: &Factories) -> Result<StateDB, Error> { pub fn ensure_db_good<T: Backend>(&self, db: T, factories: &Factories) -> Result<T, Error> {
if db.as_hashdb().contains(&self.state_root()) { if db.as_hashdb().contains(&self.state_root()) {
return Ok(db) return Ok(db)
} }

View File

@ -209,6 +209,43 @@ pub fn check_proof(
} }
} }
/// Prove a transaction on the given state.
/// Returns `None` when the transacion could not be proved,
/// and a proof otherwise.
pub fn prove_transaction<H: AsHashDB + Send + Sync>(
db: H,
root: H256,
transaction: &SignedTransaction,
engine: &Engine,
env_info: &EnvInfo,
factories: Factories,
virt: bool,
) -> Option<(Bytes, Vec<DBValue>)> {
use self::backend::Proving;
let backend = Proving::new(db);
let res = State::from_existing(
backend,
root,
engine.account_start_nonce(env_info.number),
factories,
);
let mut state = match res {
Ok(state) => state,
Err(_) => return None,
};
match state.execute(env_info, engine, transaction, false, virt) {
Err(ExecutionError::Internal(_)) => None,
Err(e) => {
trace!(target: "state", "Proved call failed: {}", e);
Some((Vec::new(), state.drop().1.extract_proof()))
}
Ok(res) => Some((res.output, state.drop().1.extract_proof())),
}
}
/// Representation of the entire state of all accounts in the system. /// Representation of the entire state of all accounts in the system.
/// ///
/// `State` can work together with `StateDB` to share account cache. /// `State` can work together with `StateDB` to share account cache.