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

@@ -226,7 +226,7 @@ impl BlockQueue {
};
let block_hash = block.header.hash();
match verify_block_unordered(block.header, block.bytes, engine.deref().deref()) {
match verify_block_unordered(block.header, block.bytes, &**engine) {
Ok(verified) => {
let mut verifying = verification.verifying.lock();
for e in verifying.iter_mut() {
@@ -319,7 +319,7 @@ impl BlockQueue {
}
}
match verify_block_basic(&header, &bytes, self.engine.deref().deref()) {
match verify_block_basic(&header, &bytes, &**self.engine) {
Ok(()) => {
self.processing.write().insert(h.clone());
self.verification.unverified.lock().push_back(UnverifiedBlock { header: header, bytes: bytes });

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>>;

View File

@@ -22,7 +22,7 @@ use basic_types::LogBloom;
use client::Error as ClientError;
use ipc::binary::{BinaryConvertError, BinaryConvertable};
use types::block_import_error::BlockImportError;
pub use types::executed::{ExecutionError, ReplayError};
pub use types::executed::{ExecutionError, CallError};
#[derive(Debug, PartialEq, Clone)]
/// Errors concerning transaction processing.

View File

@@ -171,7 +171,7 @@ pub struct Miner {
// for sealing...
options: MinerOptions,
next_allowed_reseal: Mutex<Instant>,
sealing_block_last_request: Mutex<u64>,
gas_range_target: RwLock<(U256, U256)>,
@@ -420,7 +420,7 @@ impl Miner {
*sealing_block_last_request = best_number;
}
// Return if we restarted
// Return if we restarted
prepare_new
}
@@ -464,7 +464,7 @@ impl MinerService for Miner {
}
}
fn call(&self, chain: &MiningBlockChainClient, t: &SignedTransaction, analytics: CallAnalytics) -> Result<Executed, ExecutionError> {
fn call(&self, chain: &MiningBlockChainClient, t: &SignedTransaction, analytics: CallAnalytics) -> Result<Executed, CallError> {
let sealing_work = self.sealing_work.lock();
match sealing_work.queue.peek_last_ref() {
Some(work) => {
@@ -484,6 +484,8 @@ impl MinerService for Miner {
};
// that's just a copy of the state.
let mut state = block.state().clone();
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)
@@ -495,18 +497,15 @@ impl MinerService for Miner {
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(), chain.vm_factory()).transact(t, options);
let mut ret = try!(Executive::new(&mut state, &env_info, self.engine(), chain.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(block.state().clone()));
}
}
ret
ret.state_diff = original_state.map(|original| state.diff_from(original));
Ok(ret)
},
None => {
chain.call(t, analytics)
chain.call(t, BlockID::Latest, analytics)
}
}
}
@@ -770,7 +769,7 @@ impl MinerService for Miner {
false
}
};
if requires_reseal {
// --------------------------------------------------------------------------
// | NOTE Code below requires transaction_queue and sealing_work locks. |

View File

@@ -58,7 +58,7 @@ use util::{H256, U256, Address, Bytes};
use client::{MiningBlockChainClient, Executed, CallAnalytics};
use block::ClosedBlock;
use receipt::Receipt;
use error::{Error, ExecutionError};
use error::{Error, CallError};
use transaction::SignedTransaction;
/// Miner client API
@@ -163,7 +163,7 @@ pub trait MinerService : Send + Sync {
fn balance(&self, chain: &MiningBlockChainClient, address: &Address) -> U256;
/// Call into contract code using pending state.
fn call(&self, chain: &MiningBlockChainClient, t: &SignedTransaction, analytics: CallAnalytics) -> Result<Executed, ExecutionError>;
fn call(&self, chain: &MiningBlockChainClient, t: &SignedTransaction, analytics: CallAnalytics) -> Result<Executed, CallError>;
/// Get storage value in pending state.
fn storage_at(&self, chain: &MiningBlockChainClient, address: &Address, position: &H256) -> H256;

View File

@@ -175,7 +175,7 @@ impl State {
/// Get the nonce of account `a`.
pub fn nonce(&self, a: &Address) -> U256 {
self.ensure_cached(a, false,
|a| a.as_ref().map_or(U256::zero(), |account| *account.nonce()))
|a| a.as_ref().map_or(self.account_start_nonce, |account| *account.nonce()))
}
/// Mutate storage of account `address` so that it is `value` for `key`.

View File

@@ -104,7 +104,7 @@ pub struct Executed {
}
/// Result of executing the transaction.
#[derive(PartialEq, Debug, Binary)]
#[derive(PartialEq, Debug, Clone, Binary)]
pub enum ExecutionError {
/// Returned when there gas paid for transaction execution is
/// lower than base gas required.
@@ -171,19 +171,25 @@ impl fmt::Display for ExecutionError {
}
/// Result of executing the transaction.
#[derive(PartialEq, Debug, Binary)]
pub enum ReplayError {
#[derive(PartialEq, Debug, Clone, Binary)]
pub enum CallError {
/// Couldn't find the transaction in the chain.
TransactionNotFound,
/// Couldn't find the transaction block's state in the chain.
/// Couldn't find requested block's state in the chain.
StatePruned,
/// Error executing.
Execution(ExecutionError),
}
impl fmt::Display for ReplayError {
impl From<ExecutionError> for CallError {
fn from(error: ExecutionError) -> Self {
CallError::Execution(error)
}
}
impl fmt::Display for CallError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::ReplayError::*;
use self::CallError::*;
let msg = match *self {
TransactionNotFound => "Transaction couldn't be found in the chain".into(),
@@ -191,7 +197,7 @@ impl fmt::Display for ReplayError {
Execution(ref e) => format!("{}", e),
};
f.write_fmt(format_args!("Transaction replay error ({}).", msg))
f.write_fmt(format_args!("Transaction execution error ({}).", msg))
}
}

View File

@@ -23,7 +23,7 @@ use std::mem;
use std::collections::VecDeque;
/// Uniquely identifies block.
#[derive(Debug, PartialEq, Clone, Hash, Eq, Binary)]
#[derive(Debug, PartialEq, Copy, Clone, Hash, Eq, Binary)]
pub enum BlockID {
/// Block's sha3.
/// Querying by hash is always faster.