diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index af56bb7f7..2695ad84a 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -1884,27 +1884,23 @@ impl ProvingBlockChainClient for Client { } fn prove_transaction(&self, transaction: SignedTransaction, id: BlockId) -> Option<(Bytes, Vec)> { - 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), _ => return None, }; env_info.gas_limit = transaction.gas.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); - let options = TransactOptions { tracing: false, vm_tracing: false, check_nonce: false }; - let res = Executive::new(&mut state, &env_info, &*self.engine).transact(&transaction, options); - - match res { - Err(ExecutionError::Internal(_)) => None, - Err(e) => { - trace!(target: "client", "Proved call failed: {}", e); - Some((Vec::new(), state.drop().1.extract_proof())) - } - Ok(res) => Some((res.output, state.drop().1.extract_proof())), - } + state::prove_transaction( + jdb.as_hashdb_mut(), + header.state_root().clone(), + &transaction, + &*self.engine, + &env_info, + self.factories.clone(), + false, + ) } } diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index 7d3900f2c..df83d2e4f 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -32,7 +32,6 @@ use factory::Factories; use header::{BlockNumber, Header}; use pod_state::*; use rlp::{Rlp, RlpStream}; -use state_db::StateDB; use state::{Backend, State, Substate}; use state::backend::Basic as BasicBackend; 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. - pub fn ensure_db_good(&self, db: StateDB, factories: &Factories) -> Result { + pub fn ensure_db_good(&self, db: T, factories: &Factories) -> Result { if db.as_hashdb().contains(&self.state_root()) { return Ok(db) } diff --git a/ethcore/src/state/mod.rs b/ethcore/src/state/mod.rs index 354da2cc3..f15846b73 100644 --- a/ethcore/src/state/mod.rs +++ b/ethcore/src/state/mod.rs @@ -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( + db: H, + root: H256, + transaction: &SignedTransaction, + engine: &Engine, + env_info: &EnvInfo, + factories: Factories, + virt: bool, +) -> Option<(Bytes, Vec)> { + 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. /// /// `State` can work together with `StateDB` to share account cache.