Merge branch 'master' of github.com:ethcore/parity into move_hash
This commit is contained in:
@@ -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 });
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>>;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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. |
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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`.
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user