Merge branch 'master' into warn-blacklisted

This commit is contained in:
Robert Habermeier
2017-11-07 16:56:57 +01:00
112 changed files with 6872 additions and 4986 deletions

View File

@@ -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)?;

View File

@@ -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();

View File

@@ -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 {

View File

@@ -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>,
}

View File

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

View File

@@ -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 {

View File

@@ -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]

View File

@@ -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();

View File

@@ -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(),

View File

@@ -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()

View File

@@ -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();

View File

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

View File

@@ -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();

View File

@@ -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) {

View File

@@ -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,

View File

@@ -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) {}

View File

@@ -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.

View File

@@ -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)]