request transaction proofs from on_demand

This commit is contained in:
Robert Habermeier
2017-02-25 20:10:38 +01:00
parent 7c541117b3
commit 69e82e15a3
7 changed files with 178 additions and 13 deletions

View File

@@ -1616,7 +1616,6 @@ impl ::client::ProvingBlockChainClient for Client {
let options = TransactOptions { tracing: false, vm_tracing: false, check_nonce: false };
let res = Executive::new(&mut state, &env_info, &*self.engine, &self.factories.vm).transact(&transaction, options);
match res {
Err(ExecutionError::Internal(_)) => return None,
_ => return Some(state.drop().1.extract_proof()),

View File

@@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Environment information for transaction execution.
use std::cmp;
use std::sync::Arc;
use util::{U256, Address, H256, Hashable};
@@ -25,7 +27,7 @@ use ethjson;
pub type LastHashes = Vec<H256>;
/// Information concerning the execution environment for a message-call/contract-creation.
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct EnvInfo {
/// The block number.
pub number: BlockNumber,

View File

@@ -79,7 +79,6 @@
//! cargo build --release
//! ```
extern crate ethcore_io as io;
extern crate rustc_serialize;
extern crate crypto;
@@ -140,12 +139,12 @@ pub mod action_params;
pub mod db;
pub mod verification;
pub mod state;
pub mod env_info;
#[macro_use] pub mod evm;
mod cache_manager;
mod blooms;
mod basic_types;
mod env_info;
mod pod_account;
mod state_db;
mod account_db;

View File

@@ -31,6 +31,7 @@ use factory::Factories;
use trace::FlatTrace;
use pod_account::*;
use pod_state::{self, PodState};
use types::executed::{Executed, ExecutionError};
use types::state_diff::StateDiff;
use transaction::SignedTransaction;
use state_db::StateDB;
@@ -60,6 +61,17 @@ pub struct ApplyOutcome {
/// Result type for the execution ("application") of a transaction.
pub type ApplyResult = Result<ApplyOutcome, Error>;
/// Return type of proof validity check.
#[derive(Debug, Clone)]
pub enum ProvedExecution {
/// Proof wasn't enough to complete execution.
BadProof,
/// The transaction failed, but not due to a bad proof.
Failed(ExecutionError),
/// The transaction successfully completd with the given proof.
Complete(Executed),
}
#[derive(Eq, PartialEq, Clone, Copy, Debug)]
/// Account modification state. Used to check if the account was
/// Modified in between commits and overall.
@@ -150,6 +162,39 @@ impl AccountEntry {
}
}
/// Check the given proof of execution.
/// `Err(ExecutionError::Internal)` indicates failure, everything else indicates
/// a successful proof (as the transaction itself may be poorly chosen).
pub fn check_proof(
proof: &[::util::DBValue],
root: H256,
transaction: &SignedTransaction,
engine: &Engine,
env_info: &EnvInfo,
) -> ProvedExecution {
let backend = self::backend::ProofCheck::new(proof);
let mut factories = Factories::default();
factories.accountdb = ::account_db::Factory::Plain;
let res = State::from_existing(
backend,
root,
engine.account_start_nonce(),
factories
);
let mut state = match res {
Ok(state) => state,
Err(_) => return ProvedExecution::BadProof,
};
match state.execute(env_info, engine, transaction, false) {
Ok(executed) => ProvedExecution::Complete(executed),
Err(ExecutionError::Internal(_)) => ProvedExecution::BadProof,
Err(e) => ProvedExecution::Failed(e),
}
}
/// Representation of the entire state of all accounts in the system.
///
/// `State` can work together with `StateDB` to share account cache.
@@ -548,16 +593,12 @@ impl<B: Backend> State<B> {
Ok(())
}
/// Execute a given transaction.
/// Execute a given transaction, producing a receipt and an optional trace.
/// This will change the state accordingly.
pub fn apply(&mut self, env_info: &EnvInfo, engine: &Engine, t: &SignedTransaction, tracing: bool) -> ApplyResult {
// let old = self.to_pod();
let options = TransactOptions { tracing: tracing, vm_tracing: false, check_nonce: true };
let vm_factory = self.factories.vm.clone();
let e = Executive::new(self, env_info, engine, &vm_factory).transact(t, options)?;
// TODO uncomment once to_pod() works correctly.
let e = self.execute(env_info, engine, t, tracing)?;
// trace!("Applied transaction. Diff:\n{}\n", state_diff::diff_pod(&old, &self.to_pod()));
let state_root = if env_info.number < engine.params().eip98_transition {
self.commit()?;
@@ -570,6 +611,15 @@ impl<B: Backend> State<B> {
Ok(ApplyOutcome{receipt: receipt, trace: e.trace})
}
// Execute a given transaction.
fn execute(&mut self, env_info: &EnvInfo, engine: &Engine, t: &SignedTransaction, tracing: bool) -> Result<Executed, ExecutionError> {
let options = TransactOptions { tracing: tracing, vm_tracing: false, check_nonce: true };
let vm_factory = self.factories.vm.clone();
Executive::new(self, env_info, engine, &vm_factory).transact(t, options)
}
/// Commit accounts to SecTrieDBMut. This is similar to cpp-ethereum's dev::eth::commit.
/// `accounts` is mutable because we may need to commit the code or storage and record that.
#[cfg_attr(feature="dev", allow(match_ref_pats))]