Merge branch 'master' into warn-blacklisted
This commit is contained in:
@@ -523,8 +523,8 @@ impl AccountProvider {
|
||||
}
|
||||
|
||||
/// Returns each hardware account along with name and meta.
|
||||
pub fn is_hardware_address(&self, address: Address) -> bool {
|
||||
self.hardware_store.as_ref().and_then(|s| s.wallet_info(&address)).is_some()
|
||||
pub fn is_hardware_address(&self, address: &Address) -> bool {
|
||||
self.hardware_store.as_ref().and_then(|s| s.wallet_info(address)).is_some()
|
||||
}
|
||||
|
||||
/// Returns each account along with name and meta.
|
||||
@@ -596,7 +596,7 @@ impl AccountProvider {
|
||||
}
|
||||
}
|
||||
|
||||
if self.unlock_keep_secret && unlock != Unlock::OneTime {
|
||||
if self.unlock_keep_secret && unlock == Unlock::Perm {
|
||||
// verify password and get the secret
|
||||
let secret = self.sstore.raw_secret(&account, &password)?;
|
||||
self.unlocked_secrets.write().insert(account.clone(), secret);
|
||||
@@ -646,14 +646,22 @@ impl AccountProvider {
|
||||
}
|
||||
|
||||
/// Checks if given account is unlocked
|
||||
pub fn is_unlocked(&self, address: Address) -> bool {
|
||||
pub fn is_unlocked(&self, address: &Address) -> bool {
|
||||
let unlocked = self.unlocked.read();
|
||||
let unlocked_secrets = self.unlocked_secrets.read();
|
||||
self.sstore.account_ref(&address)
|
||||
self.sstore.account_ref(address)
|
||||
.map(|r| unlocked.get(&r).is_some() || unlocked_secrets.get(&r).is_some())
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Checks if given account is unlocked permanently
|
||||
pub fn is_unlocked_permanently(&self, address: &Address) -> bool {
|
||||
let unlocked = self.unlocked.read();
|
||||
self.sstore.account_ref(address)
|
||||
.map(|r| unlocked.get(&r).map_or(false, |account| account.unlock == Unlock::Perm))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Signs the message. If password is not provided the account must be unlocked.
|
||||
pub fn sign(&self, address: Address, password: Option<String>, message: Message) -> Result<Signature, SignError> {
|
||||
let account = self.sstore.account_ref(&address)?;
|
||||
|
||||
@@ -1142,7 +1142,7 @@ impl Client {
|
||||
state_diff: bool,
|
||||
transaction: &SignedTransaction,
|
||||
options: TransactOptions<T, V>,
|
||||
) -> Result<Executed, CallError> where
|
||||
) -> Result<Executed<T::Output, V::Output>, CallError> where
|
||||
T: trace::Tracer,
|
||||
V: trace::VMTracer,
|
||||
{
|
||||
@@ -1242,7 +1242,7 @@ impl BlockChainClient for Client {
|
||||
// that's just a copy of the state.
|
||||
let original_state = self.state_at(block).ok_or(CallError::StatePruned)?;
|
||||
let sender = t.sender();
|
||||
let options = || TransactOptions::with_tracing();
|
||||
let options = || TransactOptions::with_tracing().dont_check_nonce();
|
||||
|
||||
let cond = |gas| {
|
||||
let mut tx = t.as_unsigned().clone();
|
||||
|
||||
@@ -197,7 +197,7 @@ impl<'a> EvmTestClient<'a> {
|
||||
env_info: &client::EnvInfo,
|
||||
transaction: transaction::SignedTransaction,
|
||||
vm_tracer: T,
|
||||
) -> TransactResult {
|
||||
) -> TransactResult<T::Output> {
|
||||
let initial_gas = transaction.gas;
|
||||
// Verify transaction
|
||||
let is_ok = transaction.verify_basic(true, None, env_info.number >= self.spec.engine.params().eip86_transition);
|
||||
@@ -218,7 +218,8 @@ impl<'a> EvmTestClient<'a> {
|
||||
TransactResult::Ok {
|
||||
state_root: *self.state.root(),
|
||||
gas_left: initial_gas - result.receipt.gas_used,
|
||||
output: result.output
|
||||
output: result.output,
|
||||
vm_trace: result.vm_trace,
|
||||
}
|
||||
},
|
||||
Err(error) => TransactResult::Err {
|
||||
@@ -230,7 +231,7 @@ impl<'a> EvmTestClient<'a> {
|
||||
}
|
||||
|
||||
/// A result of applying transaction to the state.
|
||||
pub enum TransactResult {
|
||||
pub enum TransactResult<T> {
|
||||
/// Successful execution
|
||||
Ok {
|
||||
/// State root
|
||||
@@ -239,6 +240,8 @@ pub enum TransactResult {
|
||||
gas_left: U256,
|
||||
/// Output
|
||||
output: Vec<u8>,
|
||||
/// VM Traces
|
||||
vm_trace: Option<T>,
|
||||
},
|
||||
/// Transaction failed to run
|
||||
Err {
|
||||
|
||||
@@ -29,7 +29,7 @@ use std::fmt;
|
||||
|
||||
/// Transaction execution receipt.
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct Executed {
|
||||
pub struct Executed<T = FlatTrace, V = VMTrace> {
|
||||
/// True if the outer call/create resulted in an exceptional exit.
|
||||
pub exception: Option<vm::Error>,
|
||||
|
||||
@@ -63,9 +63,9 @@ pub struct Executed {
|
||||
/// Transaction output.
|
||||
pub output: Bytes,
|
||||
/// The trace of this transaction.
|
||||
pub trace: Vec<FlatTrace>,
|
||||
pub trace: Vec<T>,
|
||||
/// The VM trace of this transaction.
|
||||
pub vm_trace: Option<VMTrace>,
|
||||
pub vm_trace: Option<V>,
|
||||
/// The state diff, if we traced it.
|
||||
pub state_diff: Option<StateDiff>,
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ use evm::{CallType, Factory, Finalize, FinalizationResult};
|
||||
use vm::{self, Ext, CreateContractAddress, ReturnData, CleanDustMode, ActionParams, ActionValue};
|
||||
use wasm;
|
||||
use externalities::*;
|
||||
use trace::{self, FlatTrace, VMTrace, Tracer, VMTracer};
|
||||
use trace::{self, Tracer, VMTracer};
|
||||
use transaction::{Action, SignedTransaction};
|
||||
use crossbeam;
|
||||
pub use executed::{Executed, ExecutionResult};
|
||||
@@ -214,7 +214,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
|
||||
/// This function should be used to execute transaction.
|
||||
pub fn transact<T, V>(&'a mut self, t: &SignedTransaction, options: TransactOptions<T, V>)
|
||||
-> Result<Executed, ExecutionError> where T: Tracer, V: VMTracer,
|
||||
-> Result<Executed<T::Output, V::Output>, ExecutionError> where T: Tracer, V: VMTracer,
|
||||
{
|
||||
self.transact_with_tracer(t, options.check_nonce, options.output_from_init_contract, options.tracer, options.vm_tracer)
|
||||
}
|
||||
@@ -223,7 +223,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
/// This will ensure the caller has enough balance to execute the desired transaction.
|
||||
/// Used for extra-block executions for things like consensus contracts and RPCs
|
||||
pub fn transact_virtual<T, V>(&'a mut self, t: &SignedTransaction, options: TransactOptions<T, V>)
|
||||
-> Result<Executed, ExecutionError> where T: Tracer, V: VMTracer,
|
||||
-> Result<Executed<T::Output, V::Output>, ExecutionError> where T: Tracer, V: VMTracer,
|
||||
{
|
||||
let sender = t.sender();
|
||||
let balance = self.state.balance(&sender)?;
|
||||
@@ -244,7 +244,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
output_from_create: bool,
|
||||
mut tracer: T,
|
||||
mut vm_tracer: V
|
||||
) -> Result<Executed, ExecutionError> where T: Tracer, V: VMTracer {
|
||||
) -> Result<Executed<T::Output, V::Output>, ExecutionError> where T: Tracer, V: VMTracer {
|
||||
let sender = t.sender();
|
||||
let nonce = self.state.nonce(&sender)?;
|
||||
|
||||
@@ -309,6 +309,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
code: Some(Arc::new(t.data.clone())),
|
||||
data: None,
|
||||
call_type: CallType::None,
|
||||
params_type: vm::ParamsType::Embedded,
|
||||
};
|
||||
let mut out = if output_from_create { Some(vec![]) } else { None };
|
||||
(self.create(params, &mut substate, &mut out, &mut tracer, &mut vm_tracer), out.unwrap_or_else(Vec::new))
|
||||
@@ -326,6 +327,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
code_hash: Some(self.state.code_hash(address)?),
|
||||
data: Some(t.data.clone()),
|
||||
call_type: CallType::Call,
|
||||
params_type: vm::ParamsType::Separate,
|
||||
};
|
||||
let mut out = vec![];
|
||||
(self.call(params, &mut substate, BytesRef::Flexible(&mut out), &mut tracer, &mut vm_tracer), out)
|
||||
@@ -587,15 +589,15 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
}
|
||||
|
||||
/// Finalizes the transaction (does refunds and suicides).
|
||||
fn finalize(
|
||||
fn finalize<T, V>(
|
||||
&mut self,
|
||||
t: &SignedTransaction,
|
||||
mut substate: Substate,
|
||||
result: vm::Result<FinalizationResult>,
|
||||
output: Bytes,
|
||||
trace: Vec<FlatTrace>,
|
||||
vm_trace: Option<VMTrace>
|
||||
) -> ExecutionResult {
|
||||
trace: Vec<T>,
|
||||
vm_trace: Option<V>
|
||||
) -> Result<Executed<T, V>, ExecutionError> {
|
||||
let schedule = self.machine.schedule(self.info.number);
|
||||
|
||||
// refunds from SSTORE nonzero -> zero
|
||||
|
||||
@@ -171,6 +171,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
||||
code_hash: Some(code_hash),
|
||||
data: Some(H256::from(number).to_vec()),
|
||||
call_type: CallType::Call,
|
||||
params_type: vm::ParamsType::Separate,
|
||||
};
|
||||
|
||||
let mut output = H256::new();
|
||||
@@ -219,6 +220,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
||||
code_hash: code_hash,
|
||||
data: None,
|
||||
call_type: CallType::None,
|
||||
params_type: vm::ParamsType::Embedded,
|
||||
};
|
||||
|
||||
if !self.static_flag {
|
||||
@@ -240,7 +242,6 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
||||
Ok(FinalizationResult{ gas_left, apply_state: false, return_data }) => {
|
||||
ContractCreateResult::Reverted(gas_left, return_data)
|
||||
},
|
||||
Err(vm::Error::MutableCallInStaticContext) => ContractCreateResult::FailedInStaticCall,
|
||||
_ => ContractCreateResult::Failed,
|
||||
}
|
||||
}
|
||||
@@ -277,6 +278,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
||||
code_hash: Some(code_hash),
|
||||
data: Some(data.to_vec()),
|
||||
call_type: call_type,
|
||||
params_type: vm::ParamsType::Separate,
|
||||
};
|
||||
|
||||
if let Some(value) = value {
|
||||
|
||||
@@ -162,6 +162,12 @@ impl Header {
|
||||
pub fn difficulty(&self) -> &U256 { &self.difficulty }
|
||||
/// Get the seal field of the header.
|
||||
pub fn seal(&self) -> &[Bytes] { &self.seal }
|
||||
/// Get the seal field with RLP-decoded values as bytes.
|
||||
pub fn decode_seal<'a, T: ::std::iter::FromIterator<&'a [u8]>>(&'a self) -> Result<T, DecoderError> {
|
||||
self.seal.iter().map(|rlp| {
|
||||
UntrustedRlp::new(rlp).data()
|
||||
}).collect()
|
||||
}
|
||||
|
||||
// TODO: seal_at, set_seal_at &c.
|
||||
|
||||
@@ -340,13 +346,20 @@ mod tests {
|
||||
// that's rlp of block header created with ethash engine.
|
||||
let header_rlp = "f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23".from_hex().unwrap();
|
||||
let mix_hash = "a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd".from_hex().unwrap();
|
||||
let mix_hash_decoded = "a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd".from_hex().unwrap();
|
||||
let nonce = "88ab4e252a7e8c2a23".from_hex().unwrap();
|
||||
let nonce_decoded = "ab4e252a7e8c2a23".from_hex().unwrap();
|
||||
|
||||
let header: Header = rlp::decode(&header_rlp);
|
||||
let seal_fields = header.seal;
|
||||
let seal_fields = header.seal.clone();
|
||||
assert_eq!(seal_fields.len(), 2);
|
||||
assert_eq!(seal_fields[0], mix_hash);
|
||||
assert_eq!(seal_fields[1], nonce);
|
||||
|
||||
let decoded_seal = header.decode_seal::<Vec<_>>().unwrap();
|
||||
assert_eq!(decoded_seal.len(), 2);
|
||||
assert_eq!(decoded_seal[0], &*mix_hash_decoded);
|
||||
assert_eq!(decoded_seal[1], &*nonce_decoded);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -35,7 +35,7 @@ use tx_filter::TransactionFilter;
|
||||
use bigint::prelude::U256;
|
||||
use bytes::BytesRef;
|
||||
use util::Address;
|
||||
use vm::{CallType, ActionParams, ActionValue};
|
||||
use vm::{CallType, ActionParams, ActionValue, ParamsType};
|
||||
use vm::{EnvInfo, Schedule, CreateContractAddress};
|
||||
|
||||
/// Parity tries to round block.gas_limit to multiple of this constant
|
||||
@@ -149,6 +149,7 @@ impl EthereumMachine {
|
||||
code_hash: Some(state.code_hash(&contract_address)?),
|
||||
data: data,
|
||||
call_type: CallType::Call,
|
||||
params_type: ParamsType::Separate,
|
||||
};
|
||||
let mut ex = Executive::new(&mut state, &env_info, self);
|
||||
let mut substate = Substate::new();
|
||||
|
||||
@@ -123,6 +123,10 @@ pub struct MinerOptions {
|
||||
pub tx_queue_banning: Banning,
|
||||
/// Do we refuse to accept service transactions even if sender is certified.
|
||||
pub refuse_service_transactions: bool,
|
||||
/// Create a pending block with maximal possible gas limit.
|
||||
/// NOTE: Such block will contain all pending transactions but
|
||||
/// will be invalid if mined.
|
||||
pub infinite_pending_block: bool,
|
||||
}
|
||||
|
||||
impl Default for MinerOptions {
|
||||
@@ -145,6 +149,7 @@ impl Default for MinerOptions {
|
||||
enable_resubmission: true,
|
||||
tx_queue_banning: Banning::Disabled,
|
||||
refuse_service_transactions: false,
|
||||
infinite_pending_block: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -374,15 +379,14 @@ impl Miner {
|
||||
let mut sealing_work = self.sealing_work.lock();
|
||||
let last_work_hash = sealing_work.queue.peek_last_ref().map(|pb| pb.block().fields().header.hash());
|
||||
let best_hash = chain_info.best_block_hash;
|
||||
/*
|
||||
|
||||
// check to see if last ClosedBlock in would_seals is actually same parent block.
|
||||
// if so
|
||||
// duplicate, re-open and push any new transactions.
|
||||
// if at least one was pushed successfully, close and enqueue new ClosedBlock;
|
||||
// otherwise, leave everything alone.
|
||||
// otherwise, author a fresh block.
|
||||
*/
|
||||
let open_block = match sealing_work.queue.pop_if(|b| b.block().fields().header.parent_hash() == &best_hash) {
|
||||
let mut open_block = match sealing_work.queue.pop_if(|b| b.block().fields().header.parent_hash() == &best_hash) {
|
||||
Some(old_block) => {
|
||||
trace!(target: "miner", "prepare_block: Already have previous work; updating and returning");
|
||||
// add transactions to old_block
|
||||
@@ -398,6 +402,11 @@ impl Miner {
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
if self.options.infinite_pending_block {
|
||||
open_block.set_gas_limit(!U256::zero());
|
||||
}
|
||||
|
||||
(transactions, open_block, last_work_hash)
|
||||
};
|
||||
|
||||
@@ -1301,6 +1310,7 @@ mod tests {
|
||||
enable_resubmission: true,
|
||||
tx_queue_banning: Banning::Disabled,
|
||||
refuse_service_transactions: false,
|
||||
infinite_pending_block: false,
|
||||
},
|
||||
GasPricer::new_fixed(0u64.into()),
|
||||
&Spec::new_test(),
|
||||
|
||||
@@ -515,10 +515,6 @@ pub struct AccountDetails {
|
||||
/// `new_gas_price > old_gas_price + old_gas_price >> SHIFT`
|
||||
const GAS_PRICE_BUMP_SHIFT: usize = 3; // 2 = 25%, 3 = 12.5%, 4 = 6.25%
|
||||
|
||||
/// Future queue limits are lower from current queue limits:
|
||||
/// `future_limit = current_limit >> SHIFT`
|
||||
const FUTURE_QUEUE_LIMITS_SHIFT: usize = 3; // 2 = 25%, 3 = 12.5%, 4 = 6.25%
|
||||
|
||||
/// Describes the strategy used to prioritize transactions in the queue.
|
||||
#[cfg_attr(feature="dev", allow(enum_variant_names))]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
@@ -626,9 +622,9 @@ impl TransactionQueue {
|
||||
by_priority: BTreeSet::new(),
|
||||
by_address: Table::new(),
|
||||
by_gas_price: Default::default(),
|
||||
total_gas_limit: total_gas_limit >> FUTURE_QUEUE_LIMITS_SHIFT,
|
||||
limit: limit >> FUTURE_QUEUE_LIMITS_SHIFT,
|
||||
memory_limit: memory_limit >> FUTURE_QUEUE_LIMITS_SHIFT,
|
||||
total_gas_limit,
|
||||
limit,
|
||||
memory_limit,
|
||||
};
|
||||
|
||||
TransactionQueue {
|
||||
@@ -649,7 +645,7 @@ impl TransactionQueue {
|
||||
/// Set the new limit for `current` and `future` queue.
|
||||
pub fn set_limit(&mut self, limit: usize) {
|
||||
self.current.set_limit(limit);
|
||||
self.future.set_limit(limit >> FUTURE_QUEUE_LIMITS_SHIFT);
|
||||
self.future.set_limit(limit);
|
||||
// And ensure the limits
|
||||
self.current.enforce_limit(&mut self.by_hash, &mut self.local_transactions);
|
||||
self.future.enforce_limit(&mut self.by_hash, &mut self.local_transactions);
|
||||
@@ -686,7 +682,7 @@ impl TransactionQueue {
|
||||
/// Sets new total gas limit.
|
||||
pub fn set_total_gas_limit(&mut self, total_gas_limit: U256) {
|
||||
self.current.total_gas_limit = total_gas_limit;
|
||||
self.future.total_gas_limit = total_gas_limit >> FUTURE_QUEUE_LIMITS_SHIFT;
|
||||
self.future.total_gas_limit = total_gas_limit;
|
||||
self.future.enforce_limit(&mut self.by_hash, &mut self.local_transactions);
|
||||
}
|
||||
|
||||
@@ -2412,7 +2408,7 @@ pub mod test {
|
||||
fn should_limit_future_transactions() {
|
||||
let mut txq = TransactionQueue::with_limits(
|
||||
PrioritizationStrategy::GasPriceOnly,
|
||||
1 << FUTURE_QUEUE_LIMITS_SHIFT,
|
||||
1,
|
||||
usize::max_value(),
|
||||
!U256::zero(),
|
||||
!U256::zero(),
|
||||
@@ -2736,7 +2732,7 @@ pub mod test {
|
||||
// given
|
||||
let mut txq = TransactionQueue::with_limits(
|
||||
PrioritizationStrategy::GasPriceOnly,
|
||||
1 << FUTURE_QUEUE_LIMITS_SHIFT,
|
||||
1,
|
||||
usize::max_value(),
|
||||
!U256::zero(),
|
||||
!U256::zero()
|
||||
|
||||
@@ -30,7 +30,7 @@ use parking_lot::RwLock;
|
||||
use rlp::{Rlp, RlpStream};
|
||||
use rustc_hex::FromHex;
|
||||
use util::*;
|
||||
use vm::{EnvInfo, CallType, ActionValue, ActionParams};
|
||||
use vm::{EnvInfo, CallType, ActionValue, ActionParams, ParamsType};
|
||||
|
||||
use super::genesis::Genesis;
|
||||
use super::seal::Generic as GenericSeal;
|
||||
@@ -504,6 +504,7 @@ impl Spec {
|
||||
code: Some(Arc::new(constructor.clone())),
|
||||
data: None,
|
||||
call_type: CallType::None,
|
||||
params_type: ParamsType::Embedded,
|
||||
};
|
||||
|
||||
let mut substate = Substate::new();
|
||||
|
||||
@@ -62,19 +62,19 @@ pub use self::backend::Backend;
|
||||
pub use self::substate::Substate;
|
||||
|
||||
/// Used to return information about an `State::apply` operation.
|
||||
pub struct ApplyOutcome {
|
||||
pub struct ApplyOutcome<T, V> {
|
||||
/// The receipt for the applied transaction.
|
||||
pub receipt: Receipt,
|
||||
/// The output of the applied transaction.
|
||||
pub output: Bytes,
|
||||
/// The trace for the applied transaction, empty if tracing was not produced.
|
||||
pub trace: Vec<FlatTrace>,
|
||||
pub trace: Vec<T>,
|
||||
/// The VM trace for the applied transaction, None if tracing was not produced.
|
||||
pub vm_trace: Option<VMTrace>
|
||||
pub vm_trace: Option<V>
|
||||
}
|
||||
|
||||
/// Result type for the execution ("application") of a transaction.
|
||||
pub type ApplyResult = Result<ApplyOutcome, Error>;
|
||||
pub type ApplyResult<T, V> = Result<ApplyOutcome<T, V>, Error>;
|
||||
|
||||
/// Return type of proof validity check.
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -668,7 +668,7 @@ impl<B: Backend> State<B> {
|
||||
|
||||
/// 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, machine: &Machine, t: &SignedTransaction, tracing: bool) -> ApplyResult {
|
||||
pub fn apply(&mut self, env_info: &EnvInfo, machine: &Machine, t: &SignedTransaction, tracing: bool) -> ApplyResult<FlatTrace, VMTrace> {
|
||||
if tracing {
|
||||
let options = TransactOptions::with_tracing();
|
||||
self.apply_with_tracing(env_info, machine, t, options.tracer, options.vm_tracer)
|
||||
@@ -687,7 +687,7 @@ impl<B: Backend> State<B> {
|
||||
t: &SignedTransaction,
|
||||
tracer: T,
|
||||
vm_tracer: V,
|
||||
) -> ApplyResult where
|
||||
) -> ApplyResult<T::Output, V::Output> where
|
||||
T: trace::Tracer,
|
||||
V: trace::VMTracer,
|
||||
{
|
||||
@@ -728,7 +728,7 @@ impl<B: Backend> State<B> {
|
||||
// `virt` signals that we are executing outside of a block set and restrictions like
|
||||
// gas limits and gas costs should be lifted.
|
||||
fn execute<T, V>(&mut self, env_info: &EnvInfo, machine: &Machine, t: &SignedTransaction, options: TransactOptions<T, V>, virt: bool)
|
||||
-> Result<Executed, ExecutionError> where T: trace::Tracer, V: trace::VMTracer,
|
||||
-> Result<Executed<T::Output, V::Output>, ExecutionError> where T: trace::Tracer, V: trace::VMTracer,
|
||||
{
|
||||
let mut e = Executive::new(self, env_info, machine);
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
use std::sync::Arc;
|
||||
use hash::keccak;
|
||||
use vm::{EnvInfo, ActionParams, ActionValue, CallType};
|
||||
use vm::{EnvInfo, ActionParams, ActionValue, CallType, ParamsType};
|
||||
use evm::{Factory, VMType};
|
||||
use executive::Executive;
|
||||
use state::Substate;
|
||||
@@ -45,6 +45,7 @@ fn test_blockhash_eip210(factory: Factory) {
|
||||
code_hash: Some(blockhash_contract_code_hash),
|
||||
data: Some(H256::from(i - 1).to_vec()),
|
||||
call_type: CallType::Call,
|
||||
params_type: ParamsType::Separate,
|
||||
};
|
||||
let mut ex = Executive::new(&mut state, &env_info, &machine);
|
||||
let mut substate = Substate::new();
|
||||
@@ -67,6 +68,7 @@ fn test_blockhash_eip210(factory: Factory) {
|
||||
code_hash: Some(get_prev_hash_code_hash),
|
||||
data: None,
|
||||
call_type: CallType::Call,
|
||||
params_type: ParamsType::Separate,
|
||||
};
|
||||
let mut ex = Executive::new(&mut state, &env_info, &machine);
|
||||
let mut substate = Substate::new();
|
||||
|
||||
@@ -83,6 +83,8 @@ fn should_prefix_address_properly() {
|
||||
}
|
||||
|
||||
impl Tracer for ExecutiveTracer {
|
||||
type Output = FlatTrace;
|
||||
|
||||
fn prepare_trace_call(&self, params: &ActionParams) -> Option<Call> {
|
||||
Some(Call::from(params.clone()))
|
||||
}
|
||||
@@ -201,6 +203,8 @@ impl ExecutiveVMTracer {
|
||||
}
|
||||
|
||||
impl VMTracer for ExecutiveVMTracer {
|
||||
type Output = VMTrace;
|
||||
|
||||
fn trace_next_instruction(&mut self, _pc: usize, _instruction: u8) -> bool { true }
|
||||
|
||||
fn trace_prepare_execute(&mut self, pc: usize, instruction: u8, gas_cost: U256) {
|
||||
|
||||
@@ -48,6 +48,9 @@ use header::BlockNumber;
|
||||
|
||||
/// This trait is used by executive to build traces.
|
||||
pub trait Tracer: Send {
|
||||
/// Data returned when draining the Tracer.
|
||||
type Output;
|
||||
|
||||
/// Prepares call trace for given params. Noop tracer should return None.
|
||||
fn prepare_trace_call(&self, params: &ActionParams) -> Option<Call>;
|
||||
|
||||
@@ -63,7 +66,7 @@ pub trait Tracer: Send {
|
||||
call: Option<Call>,
|
||||
gas_used: U256,
|
||||
output: Option<Bytes>,
|
||||
subs: Vec<FlatTrace>,
|
||||
subs: Vec<Self::Output>,
|
||||
);
|
||||
|
||||
/// Stores trace create info.
|
||||
@@ -73,14 +76,14 @@ pub trait Tracer: Send {
|
||||
gas_used: U256,
|
||||
code: Option<Bytes>,
|
||||
address: Address,
|
||||
subs: Vec<FlatTrace>
|
||||
subs: Vec<Self::Output>
|
||||
);
|
||||
|
||||
/// Stores failed call trace.
|
||||
fn trace_failed_call(&mut self, call: Option<Call>, subs: Vec<FlatTrace>, error: TraceError);
|
||||
fn trace_failed_call(&mut self, call: Option<Call>, subs: Vec<Self::Output>, error: TraceError);
|
||||
|
||||
/// Stores failed create trace.
|
||||
fn trace_failed_create(&mut self, create: Option<Create>, subs: Vec<FlatTrace>, error: TraceError);
|
||||
fn trace_failed_create(&mut self, create: Option<Create>, subs: Vec<Self::Output>, error: TraceError);
|
||||
|
||||
/// Stores suicide info.
|
||||
fn trace_suicide(&mut self, address: Address, balance: U256, refund_address: Address);
|
||||
@@ -92,12 +95,15 @@ pub trait Tracer: Send {
|
||||
fn subtracer(&self) -> Self where Self: Sized;
|
||||
|
||||
/// Consumes self and returns all traces.
|
||||
fn drain(self) -> Vec<FlatTrace>;
|
||||
fn drain(self) -> Vec<Self::Output>;
|
||||
}
|
||||
|
||||
/// Used by executive to build VM traces.
|
||||
pub trait VMTracer: Send {
|
||||
|
||||
/// Data returned when draining the VMTracer.
|
||||
type Output;
|
||||
|
||||
/// Trace the progression of interpreter to next instruction.
|
||||
/// If tracer returns `false` it won't be called again.
|
||||
/// @returns true if `trace_prepare_execute` and `trace_executed` should be called.
|
||||
@@ -116,7 +122,7 @@ pub trait VMTracer: Send {
|
||||
fn done_subtrace(&mut self, sub: Self) where Self: Sized;
|
||||
|
||||
/// Consumes self and returns the VM trace.
|
||||
fn drain(self) -> Option<VMTrace>;
|
||||
fn drain(self) -> Option<Self::Output>;
|
||||
}
|
||||
|
||||
/// `DbExtras` provides an interface to query extra data which is not stored in tracesdb,
|
||||
|
||||
@@ -27,6 +27,8 @@ use trace::trace::{Call, Create, VMTrace, RewardType};
|
||||
pub struct NoopTracer;
|
||||
|
||||
impl Tracer for NoopTracer {
|
||||
type Output = FlatTrace;
|
||||
|
||||
fn prepare_trace_call(&self, _: &ActionParams) -> Option<Call> {
|
||||
None
|
||||
}
|
||||
@@ -76,6 +78,8 @@ impl Tracer for NoopTracer {
|
||||
pub struct NoopVMTracer;
|
||||
|
||||
impl VMTracer for NoopVMTracer {
|
||||
type Output = VMTrace;
|
||||
|
||||
fn trace_next_instruction(&mut self, _pc: usize, _instruction: u8) -> bool { false }
|
||||
|
||||
fn trace_prepare_execute(&mut self, _pc: usize, _instruction: u8, _gas_cost: U256) {}
|
||||
|
||||
@@ -469,6 +469,11 @@ impl SignedTransaction {
|
||||
pub fn is_unsigned(&self) -> bool {
|
||||
self.transaction.is_unsigned()
|
||||
}
|
||||
|
||||
/// Deconstructs this transaction back into `UnverifiedTransaction`
|
||||
pub fn deconstruct(self) -> (UnverifiedTransaction, Address, Option<Public>) {
|
||||
(self.transaction, self.sender, self.public)
|
||||
}
|
||||
}
|
||||
|
||||
/// Signed Transaction that is a part of canon blockchain.
|
||||
|
||||
@@ -21,7 +21,7 @@ use bigint::prelude::U256;
|
||||
use bigint::hash::{H256, H2048};
|
||||
use util::Address;
|
||||
use bytes::Bytes;
|
||||
use rlp::Rlp;
|
||||
use rlp::{self, Rlp};
|
||||
use header::BlockNumber;
|
||||
|
||||
/// View onto block header rlp.
|
||||
@@ -99,6 +99,14 @@ impl<'a> HeaderView<'a> {
|
||||
}
|
||||
seal
|
||||
}
|
||||
|
||||
/// Returns a vector of seal fields (RLP-decoded).
|
||||
pub fn decode_seal(&self) -> Result<Vec<Bytes>, rlp::DecoderError> {
|
||||
let seal = self.seal();
|
||||
seal.into_iter()
|
||||
.map(|s| rlp::UntrustedRlp::new(&s).data().map(|x| x.to_vec()))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Reference in New Issue
Block a user