Merge branch 'master' of github.com:ethcore/parity into move_hash

This commit is contained in:
debris
2016-08-05 09:30:01 +02:00
23 changed files with 344 additions and 155 deletions

View File

@@ -15,7 +15,6 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::collections::{HashSet, HashMap, VecDeque};
use std::ops::Deref;
use std::sync::{Arc, Weak};
use std::path::{Path};
use std::fmt;
@@ -35,7 +34,7 @@ use util::kvdb::*;
// other
use views::{BlockView, HeaderView, BodyView};
use error::{ImportError, ExecutionError, ReplayError, BlockError, ImportResult};
use error::{ImportError, ExecutionError, CallError, BlockError, ImportResult};
use header::BlockNumber;
use state::State;
use spec::Spec;
@@ -272,7 +271,7 @@ impl Client {
}
fn check_and_close_block(&self, block: &PreverifiedBlock) -> Result<LockedBlock, ()> {
let engine = self.engine.deref().deref();
let engine = &**self.engine;
let header = &block.header;
// Check the block isn't so old we won't be able to enact it.
@@ -283,7 +282,7 @@ impl Client {
}
// Verify Block Family
let verify_family_result = self.verifier.verify_block_family(header, &block.bytes, engine, self.chain.deref());
let verify_family_result = self.verifier.verify_block_family(header, &block.bytes, engine, &*self.chain);
if let Err(e) = verify_family_result {
warn!(target: "client", "Stage 3 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e);
return Err(());
@@ -639,8 +638,8 @@ impl Client {
}
impl BlockChainClient for Client {
fn call(&self, t: &SignedTransaction, analytics: CallAnalytics) -> Result<Executed, ExecutionError> {
let header = self.block_header(BlockID::Latest).unwrap();
fn call(&self, t: &SignedTransaction, block: BlockID, analytics: CallAnalytics) -> Result<Executed, CallError> {
let header = try!(self.block_header(block).ok_or(CallError::StatePruned));
let view = HeaderView::new(&header);
let last_hashes = self.build_last_hashes(view.hash());
let env_info = EnvInfo {
@@ -653,7 +652,9 @@ impl BlockChainClient for Client {
gas_limit: U256::max_value(),
};
// that's just a copy of the state.
let mut state = self.state();
let mut state = try!(self.state_at(block).ok_or(CallError::StatePruned));
let original_state = if analytics.state_diffing { Some(state.clone()) } else { None };
let sender = try!(t.sender().map_err(|e| {
let message = format!("Transaction malformed: {:?}", e);
ExecutionError::TransactionMalformed(message)
@@ -665,26 +666,23 @@ impl BlockChainClient for Client {
state.add_balance(&sender, &(needed_balance - balance));
}
let options = TransactOptions { tracing: analytics.transaction_tracing, vm_tracing: analytics.vm_tracing, check_nonce: false };
let mut ret = Executive::new(&mut state, &env_info, self.engine.deref().deref(), &self.vm_factory).transact(t, options);
let mut ret = try!(Executive::new(&mut state, &env_info, &**self.engine, &self.vm_factory).transact(t, options));
// TODO gav move this into Executive.
if analytics.state_diffing {
if let Ok(ref mut x) = ret {
x.state_diff = Some(state.diff_from(self.state()));
}
}
ret
ret.state_diff = original_state.map(|original| state.diff_from(original));
Ok(ret)
}
fn replay(&self, id: TransactionID, analytics: CallAnalytics) -> Result<Executed, ReplayError> {
let address = try!(self.transaction_address(id).ok_or(ReplayError::TransactionNotFound));
let header_data = try!(self.block_header(BlockID::Hash(address.block_hash)).ok_or(ReplayError::StatePruned));
let body_data = try!(self.block_body(BlockID::Hash(address.block_hash)).ok_or(ReplayError::StatePruned));
let mut state = try!(self.state_at_beginning(BlockID::Hash(address.block_hash)).ok_or(ReplayError::StatePruned));
fn replay(&self, id: TransactionID, analytics: CallAnalytics) -> Result<Executed, CallError> {
let address = try!(self.transaction_address(id).ok_or(CallError::TransactionNotFound));
let header_data = try!(self.block_header(BlockID::Hash(address.block_hash)).ok_or(CallError::StatePruned));
let body_data = try!(self.block_body(BlockID::Hash(address.block_hash)).ok_or(CallError::StatePruned));
let mut state = try!(self.state_at_beginning(BlockID::Hash(address.block_hash)).ok_or(CallError::StatePruned));
let txs = BodyView::new(&body_data).transactions();
if address.index >= txs.len() {
return Err(ReplayError::TransactionNotFound);
return Err(CallError::TransactionNotFound);
}
let options = TransactOptions { tracing: analytics.transaction_tracing, vm_tracing: analytics.vm_tracing, check_nonce: false };
@@ -700,20 +698,18 @@ impl BlockChainClient for Client {
gas_limit: view.gas_limit(),
};
for t in txs.iter().take(address.index) {
match Executive::new(&mut state, &env_info, self.engine.deref().deref(), &self.vm_factory).transact(t, Default::default()) {
match Executive::new(&mut state, &env_info, &**self.engine, &self.vm_factory).transact(t, Default::default()) {
Ok(x) => { env_info.gas_used = env_info.gas_used + x.gas_used; }
Err(ee) => { return Err(ReplayError::Execution(ee)) }
Err(ee) => { return Err(CallError::Execution(ee)) }
}
}
let t = &txs[address.index];
let orig = state.clone();
let mut ret = Executive::new(&mut state, &env_info, self.engine.deref().deref(), &self.vm_factory).transact(t, options);
if analytics.state_diffing {
if let Ok(ref mut x) = ret {
x.state_diff = Some(state.diff_from(orig));
}
}
ret.map_err(ReplayError::Execution)
let original_state = if analytics.state_diffing { Some(state.clone()) } else { None };
let mut ret = try!(Executive::new(&mut state, &env_info, &**self.engine, &self.vm_factory).transact(t, options));
ret.state_diff = original_state.map(|original| state.diff_from(original));
Ok(ret)
}
fn keep_alive(&self) {
@@ -1002,7 +998,7 @@ impl BlockChainClient for Client {
impl MiningBlockChainClient for Client {
fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes) -> OpenBlock {
let engine = self.engine.deref().deref();
let engine = &**self.engine;
let h = self.chain.best_block_hash();
let mut open_block = OpenBlock::new(

View File

@@ -37,7 +37,7 @@ use spec::Spec;
use block_queue::BlockQueueInfo;
use block::{OpenBlock, SealedBlock};
use executive::Executed;
use error::{ExecutionError, ReplayError};
use error::CallError;
use trace::LocalizedTrace;
/// Test client.
@@ -61,7 +61,7 @@ pub struct TestBlockChainClient {
/// Code.
pub code: RwLock<HashMap<Address, Bytes>>,
/// Execution result.
pub execution_result: RwLock<Option<Executed>>,
pub execution_result: RwLock<Option<Result<Executed, CallError>>>,
/// Transaction receipts.
pub receipts: RwLock<HashMap<TransactionID, LocalizedReceipt>>,
/// Block queue size.
@@ -125,7 +125,7 @@ impl TestBlockChainClient {
}
/// Set the execution result.
pub fn set_execution_result(&self, result: Executed) {
pub fn set_execution_result(&self, result: Result<Executed, CallError>) {
*self.execution_result.write() = Some(result);
}
@@ -292,12 +292,12 @@ impl MiningBlockChainClient for TestBlockChainClient {
}
impl BlockChainClient for TestBlockChainClient {
fn call(&self, _t: &SignedTransaction, _analytics: CallAnalytics) -> Result<Executed, ExecutionError> {
Ok(self.execution_result.read().clone().unwrap())
fn call(&self, _t: &SignedTransaction, _block: BlockID, _analytics: CallAnalytics) -> Result<Executed, CallError> {
self.execution_result.read().clone().unwrap()
}
fn replay(&self, _id: TransactionID, _analytics: CallAnalytics) -> Result<Executed, ReplayError> {
Ok(self.execution_result.read().clone().unwrap())
fn replay(&self, _id: TransactionID, _analytics: CallAnalytics) -> Result<Executed, CallError> {
self.execution_result.read().clone().unwrap()
}
fn block_total_difficulty(&self, _id: BlockID) -> Option<U256> {
@@ -310,7 +310,7 @@ impl BlockChainClient for TestBlockChainClient {
fn nonce(&self, address: &Address, id: BlockID) -> Option<U256> {
match id {
BlockID::Latest => Some(self.nonces.read().get(address).cloned().unwrap_or_else(U256::zero)),
BlockID::Latest => Some(self.nonces.read().get(address).cloned().unwrap_or(self.spec.params.account_start_nonce)),
_ => None,
}
}

View File

@@ -23,7 +23,7 @@ use transaction::{LocalizedTransaction, SignedTransaction};
use log_entry::LocalizedLogEntry;
use filter::Filter;
use views::{BlockView};
use error::{ImportResult, ExecutionError, ReplayError};
use error::{ImportResult, CallError};
use receipt::LocalizedReceipt;
use trace::LocalizedTrace;
use evm::Factory as EvmFactory;
@@ -151,11 +151,10 @@ pub trait BlockChainClient : Sync + Send {
fn logs(&self, filter: Filter) -> Vec<LocalizedLogEntry>;
/// Makes a non-persistent transaction call.
// TODO: should be able to accept blockchain location for call.
fn call(&self, t: &SignedTransaction, analytics: CallAnalytics) -> Result<Executed, ExecutionError>;
fn call(&self, t: &SignedTransaction, block: BlockID, analytics: CallAnalytics) -> Result<Executed, CallError>;
/// Replays a given transaction for inspection.
fn replay(&self, t: TransactionID, analytics: CallAnalytics) -> Result<Executed, ReplayError>;
fn replay(&self, t: TransactionID, analytics: CallAnalytics) -> Result<Executed, CallError>;
/// Returns traces matching given filter.
fn filter_traces(&self, filter: TraceFilter) -> Option<Vec<LocalizedTrace>>;