Merge branch 'master' into keccak_fn
This commit is contained in:
@@ -20,7 +20,8 @@ use std::collections::{HashMap, VecDeque};
|
||||
use std::sync::Arc;
|
||||
use bloomchain::{Number, Config as BloomConfig};
|
||||
use bloomchain::group::{BloomGroupDatabase, BloomGroupChain, GroupPosition, BloomGroup};
|
||||
use util::{H256, H264, KeyValueDB, DBTransaction, RwLock, HeapSizeOf};
|
||||
use heapsize::HeapSizeOf;
|
||||
use util::{H256, H264, KeyValueDB, DBTransaction, RwLock};
|
||||
use header::BlockNumber;
|
||||
use trace::{LocalizedTrace, Config, Filter, Database as TraceDatabase, ImportRequest, DatabaseExtras};
|
||||
use db::{self, Key, Writable, Readable, CacheUpdatePolicy};
|
||||
@@ -215,8 +216,11 @@ impl<T> TraceDB<T> where T: DatabaseExtras {
|
||||
block_number: BlockNumber,
|
||||
tx_number: usize
|
||||
) -> Vec<LocalizedTrace> {
|
||||
let tx_hash = self.extras.transaction_hash(block_number, tx_number)
|
||||
.expect("Expected to find transaction hash. Database is probably corrupted");
|
||||
let (trace_tx_number, trace_tx_hash) = match self.extras.transaction_hash(block_number, tx_number) {
|
||||
Some(hash) => (Some(tx_number), Some(hash.clone())),
|
||||
//None means trace without transaction (reward)
|
||||
None => (None, None),
|
||||
};
|
||||
|
||||
let flat_traces: Vec<FlatTrace> = traces.into();
|
||||
flat_traces.into_iter()
|
||||
@@ -227,8 +231,8 @@ impl<T> TraceDB<T> where T: DatabaseExtras {
|
||||
result: trace.result,
|
||||
subtraces: trace.subtraces,
|
||||
trace_address: trace.trace_address.into_iter().collect(),
|
||||
transaction_number: tx_number,
|
||||
transaction_hash: tx_hash.clone(),
|
||||
transaction_number: trace_tx_number,
|
||||
transaction_hash: trace_tx_hash,
|
||||
block_number: block_number,
|
||||
block_hash: block_hash
|
||||
}),
|
||||
@@ -321,8 +325,8 @@ impl<T> TraceDatabase for TraceDB<T> where T: DatabaseExtras {
|
||||
result: trace.result,
|
||||
subtraces: trace.subtraces,
|
||||
trace_address: trace.trace_address.into_iter().collect(),
|
||||
transaction_number: tx_position,
|
||||
transaction_hash: tx_hash,
|
||||
transaction_number: Some(tx_position),
|
||||
transaction_hash: Some(tx_hash),
|
||||
block_number: block_number,
|
||||
block_hash: block_hash,
|
||||
}
|
||||
@@ -345,8 +349,8 @@ impl<T> TraceDatabase for TraceDB<T> where T: DatabaseExtras {
|
||||
result: trace.result,
|
||||
subtraces: trace.subtraces,
|
||||
trace_address: trace.trace_address.into_iter().collect(),
|
||||
transaction_number: tx_position,
|
||||
transaction_hash: tx_hash.clone(),
|
||||
transaction_number: Some(tx_position),
|
||||
transaction_hash: Some(tx_hash.clone()),
|
||||
block_number: block_number,
|
||||
block_hash: block_hash
|
||||
})
|
||||
@@ -363,8 +367,11 @@ impl<T> TraceDatabase for TraceDB<T> where T: DatabaseExtras {
|
||||
.map(Into::<Vec<FlatTrace>>::into)
|
||||
.enumerate()
|
||||
.flat_map(|(tx_position, traces)| {
|
||||
let tx_hash = self.extras.transaction_hash(block_number, tx_position)
|
||||
.expect("Expected to find transaction hash. Database is probably corrupted");
|
||||
let (trace_tx_number, trace_tx_hash) = match self.extras.transaction_hash(block_number, tx_position) {
|
||||
Some(hash) => (Some(tx_position), Some(hash.clone())),
|
||||
//None means trace without transaction (reward)
|
||||
None => (None, None),
|
||||
};
|
||||
|
||||
traces.into_iter()
|
||||
.map(|trace| LocalizedTrace {
|
||||
@@ -372,8 +379,8 @@ impl<T> TraceDatabase for TraceDB<T> where T: DatabaseExtras {
|
||||
result: trace.result,
|
||||
subtraces: trace.subtraces,
|
||||
trace_address: trace.trace_address.into_iter().collect(),
|
||||
transaction_number: tx_position,
|
||||
transaction_hash: tx_hash.clone(),
|
||||
transaction_number: trace_tx_number,
|
||||
transaction_hash: trace_tx_hash,
|
||||
block_number: block_number,
|
||||
block_hash: block_hash,
|
||||
})
|
||||
@@ -543,8 +550,8 @@ mod tests {
|
||||
result: Res::FailedCall(TraceError::OutOfGas),
|
||||
trace_address: vec![],
|
||||
subtraces: 0,
|
||||
transaction_number: 0,
|
||||
transaction_hash: tx_hash,
|
||||
transaction_number: Some(0),
|
||||
transaction_hash: Some(tx_hash),
|
||||
block_number: block_number,
|
||||
block_hash: block_hash,
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
use util::{Bytes, Address, U256};
|
||||
use vm::ActionParams;
|
||||
use trace::trace::{Call, Create, Action, Res, CreateResult, CallResult, VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, Suicide};
|
||||
use trace::trace::{Call, Create, Action, Res, CreateResult, CallResult, VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, Suicide, Reward, RewardType};
|
||||
use trace::{Tracer, VMTracer, FlatTrace, TraceError};
|
||||
|
||||
/// Simple executive tracer. Traces all calls and creates. Ignores delegatecalls.
|
||||
@@ -151,15 +151,22 @@ impl Tracer for ExecutiveTracer {
|
||||
fn trace_suicide(&mut self, address: Address, balance: U256, refund_address: Address) {
|
||||
let trace = FlatTrace {
|
||||
subtraces: 0,
|
||||
action: Action::Suicide(Suicide {
|
||||
address: address,
|
||||
refund_address: refund_address,
|
||||
balance: balance,
|
||||
}),
|
||||
action: Action::Suicide(Suicide { address, refund_address, balance } ),
|
||||
result: Res::None,
|
||||
trace_address: Default::default(),
|
||||
};
|
||||
debug!(target: "trace", "Traced failed suicide {:?}", trace);
|
||||
debug!(target: "trace", "Traced suicide {:?}", trace);
|
||||
self.traces.push(trace);
|
||||
}
|
||||
|
||||
fn trace_reward(&mut self, author: Address, value: U256, reward_type: RewardType) {
|
||||
let trace = FlatTrace {
|
||||
subtraces: 0,
|
||||
action: Action::Reward(Reward { author, value, reward_type } ),
|
||||
result: Res::None,
|
||||
trace_address: Default::default(),
|
||||
};
|
||||
debug!(target: "trace", "Traced reward {:?}", trace);
|
||||
self.traces.push(trace);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ pub use self::localized::LocalizedTrace;
|
||||
|
||||
pub use self::types::{filter, flat, localized, trace};
|
||||
pub use self::types::error::Error as TraceError;
|
||||
pub use self::types::trace::{VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff};
|
||||
pub use self::types::trace::{VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, RewardType};
|
||||
pub use self::types::flat::{FlatTrace, FlatTransactionTraces, FlatBlockTraces};
|
||||
pub use self::types::filter::{Filter, AddressesFilter};
|
||||
|
||||
@@ -81,6 +81,9 @@ pub trait Tracer: Send {
|
||||
/// Stores suicide info.
|
||||
fn trace_suicide(&mut self, address: Address, balance: U256, refund_address: Address);
|
||||
|
||||
/// Stores reward info.
|
||||
fn trace_reward(&mut self, author: Address, value: U256, reward_type: RewardType);
|
||||
|
||||
/// Spawn subtracer which will be used to trace deeper levels of execution.
|
||||
fn subtracer(&self) -> Self where Self: Sized;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
use util::{Bytes, Address, U256};
|
||||
use vm::ActionParams;
|
||||
use trace::{Tracer, VMTracer, FlatTrace, TraceError};
|
||||
use trace::trace::{Call, Create, VMTrace};
|
||||
use trace::trace::{Call, Create, VMTrace, RewardType};
|
||||
|
||||
/// Nonoperative tracer. Does not trace anything.
|
||||
pub struct NoopTracer;
|
||||
@@ -58,6 +58,9 @@ impl Tracer for NoopTracer {
|
||||
fn trace_suicide(&mut self, _address: Address, _balance: U256, _refund_address: Address) {
|
||||
}
|
||||
|
||||
fn trace_reward(&mut self, _: Address, _: U256, _: RewardType) {
|
||||
}
|
||||
|
||||
fn subtracer(&self) -> Self {
|
||||
NoopTracer
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ impl Filter {
|
||||
let from_matches = self.from_address.matches(&call.from);
|
||||
let to_matches = self.to_address.matches(&call.to);
|
||||
from_matches && to_matches
|
||||
}
|
||||
},
|
||||
Action::Create(ref create) => {
|
||||
let from_matches = self.from_address.matches(&create.from);
|
||||
|
||||
@@ -128,7 +128,10 @@ impl Filter {
|
||||
let from_matches = self.from_address.matches(&suicide.address);
|
||||
let to_matches = self.to_address.matches(&suicide.refund_address);
|
||||
from_matches && to_matches
|
||||
}
|
||||
},
|
||||
Action::Reward(ref reward) => {
|
||||
self.to_address.matches(&reward.author)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -138,9 +141,9 @@ mod tests {
|
||||
use util::Address;
|
||||
use hash::keccak;
|
||||
use bloomable::Bloomable;
|
||||
use trace::trace::{Action, Call, Res, Create, CreateResult, Suicide};
|
||||
use trace::trace::{Action, Call, Res, Create, CreateResult, Suicide, Reward};
|
||||
use trace::flat::FlatTrace;
|
||||
use trace::{Filter, AddressesFilter, TraceError};
|
||||
use trace::{Filter, AddressesFilter, TraceError, RewardType};
|
||||
use evm::CallType;
|
||||
|
||||
#[test]
|
||||
@@ -341,5 +344,24 @@ mod tests {
|
||||
assert!(f4.matches(&trace));
|
||||
assert!(f5.matches(&trace));
|
||||
assert!(!f6.matches(&trace));
|
||||
|
||||
let trace = FlatTrace {
|
||||
action: Action::Reward(Reward {
|
||||
author: 2.into(),
|
||||
value: 100.into(),
|
||||
reward_type: RewardType::Block,
|
||||
}),
|
||||
result: Res::None,
|
||||
trace_address: vec![].into_iter().collect(),
|
||||
subtraces: 0
|
||||
};
|
||||
|
||||
assert!(f0.matches(&trace));
|
||||
assert!(f1.matches(&trace));
|
||||
assert!(f2.matches(&trace));
|
||||
assert!(f3.matches(&trace));
|
||||
assert!(f4.matches(&trace));
|
||||
assert!(f5.matches(&trace));
|
||||
assert!(!f6.matches(&trace));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
use std::collections::VecDeque;
|
||||
use rlp::*;
|
||||
use util::HeapSizeOf;
|
||||
use heapsize::HeapSizeOf;
|
||||
use basic_types::LogBloom;
|
||||
use super::trace::{Action, Res};
|
||||
|
||||
@@ -138,8 +138,9 @@ impl Into<Vec<FlatTransactionTraces>> for FlatBlockTraces {
|
||||
mod tests {
|
||||
use rlp::*;
|
||||
use super::{FlatBlockTraces, FlatTransactionTraces, FlatTrace};
|
||||
use trace::trace::{Action, Res, CallResult, Call, Suicide};
|
||||
use trace::trace::{Action, Res, CallResult, Call, Suicide, Reward};
|
||||
use evm::CallType;
|
||||
use trace::RewardType;
|
||||
|
||||
#[test]
|
||||
fn encode_flat_transaction_traces() {
|
||||
@@ -214,9 +215,32 @@ mod tests {
|
||||
subtraces: 0,
|
||||
};
|
||||
|
||||
let flat_trace3 = FlatTrace {
|
||||
action: Action::Reward(Reward {
|
||||
author: "412fda7643b37d436cb40628f6dbbb80a07267ed".parse().unwrap(),
|
||||
value: 10.into(),
|
||||
reward_type: RewardType::Uncle,
|
||||
}),
|
||||
result: Res::None,
|
||||
trace_address: vec![0].into_iter().collect(),
|
||||
subtraces: 0,
|
||||
};
|
||||
|
||||
let flat_trace4 = FlatTrace {
|
||||
action: Action::Reward(Reward {
|
||||
author: "412fda7643b37d436cb40628f6dbbb80a07267ed".parse().unwrap(),
|
||||
value: 10.into(),
|
||||
reward_type: RewardType::Block,
|
||||
}),
|
||||
result: Res::None,
|
||||
trace_address: vec![0].into_iter().collect(),
|
||||
subtraces: 0,
|
||||
};
|
||||
|
||||
let block_traces = FlatBlockTraces(vec![
|
||||
FlatTransactionTraces(vec![flat_trace]),
|
||||
FlatTransactionTraces(vec![flat_trace1, flat_trace2])
|
||||
FlatTransactionTraces(vec![flat_trace1, flat_trace2]),
|
||||
FlatTransactionTraces(vec![flat_trace3, flat_trace4])
|
||||
]);
|
||||
|
||||
let encoded = ::rlp::encode(&block_traces);
|
||||
|
||||
@@ -34,9 +34,9 @@ pub struct LocalizedTrace {
|
||||
/// [index in root, index in first CALL, index in second CALL, ...]
|
||||
pub trace_address: Vec<usize>,
|
||||
/// Transaction number within the block.
|
||||
pub transaction_number: usize,
|
||||
pub transaction_number: Option<usize>,
|
||||
/// Signed transaction hash.
|
||||
pub transaction_hash: H256,
|
||||
pub transaction_hash: Option<H256>,
|
||||
/// Block number.
|
||||
pub block_number: BlockNumber,
|
||||
/// Block hash.
|
||||
|
||||
@@ -128,6 +128,77 @@ impl Create {
|
||||
}
|
||||
}
|
||||
|
||||
/// Reward type.
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
#[cfg_attr(feature = "ipc", binary)]
|
||||
pub enum RewardType {
|
||||
/// Block
|
||||
Block,
|
||||
/// Uncle
|
||||
Uncle,
|
||||
}
|
||||
|
||||
impl Encodable for RewardType {
|
||||
fn rlp_append(&self, s: &mut RlpStream) {
|
||||
let v = match *self {
|
||||
RewardType::Block => 0u32,
|
||||
RewardType::Uncle => 1,
|
||||
};
|
||||
Encodable::rlp_append(&v, s);
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for RewardType {
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
rlp.as_val().and_then(|v| Ok(match v {
|
||||
0u32 => RewardType::Block,
|
||||
1 => RewardType::Uncle,
|
||||
_ => return Err(DecoderError::Custom("Invalid value of RewardType item")),
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
/// Reward action
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[cfg_attr(feature = "ipc", binary)]
|
||||
pub struct Reward {
|
||||
/// Author's address.
|
||||
pub author: Address,
|
||||
/// Reward amount.
|
||||
pub value: U256,
|
||||
/// Reward type.
|
||||
pub reward_type: RewardType,
|
||||
}
|
||||
|
||||
impl Reward {
|
||||
/// Return reward action bloom.
|
||||
pub fn bloom(&self) -> LogBloom {
|
||||
LogBloom::from_bloomed(&keccak(&self.author))
|
||||
}
|
||||
}
|
||||
|
||||
impl Encodable for Reward {
|
||||
fn rlp_append(&self, s: &mut RlpStream) {
|
||||
s.begin_list(3);
|
||||
s.append(&self.author);
|
||||
s.append(&self.value);
|
||||
s.append(&self.reward_type);
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for Reward {
|
||||
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
|
||||
let res = Reward {
|
||||
author: rlp.val_at(0)?,
|
||||
value: rlp.val_at(1)?,
|
||||
reward_type: rlp.val_at(2)?,
|
||||
};
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Suicide action.
|
||||
#[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)]
|
||||
#[cfg_attr(feature = "ipc", binary)]
|
||||
@@ -158,6 +229,8 @@ pub enum Action {
|
||||
Create(Create),
|
||||
/// Suicide.
|
||||
Suicide(Suicide),
|
||||
/// Reward
|
||||
Reward(Reward),
|
||||
}
|
||||
|
||||
impl Encodable for Action {
|
||||
@@ -175,7 +248,12 @@ impl Encodable for Action {
|
||||
Action::Suicide(ref suicide) => {
|
||||
s.append(&2u8);
|
||||
s.append(suicide);
|
||||
},
|
||||
Action::Reward(ref reward) => {
|
||||
s.append(&3u8);
|
||||
s.append(reward);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -187,6 +265,7 @@ impl Decodable for Action {
|
||||
0 => rlp.val_at(1).map(Action::Call),
|
||||
1 => rlp.val_at(1).map(Action::Create),
|
||||
2 => rlp.val_at(1).map(Action::Suicide),
|
||||
3 => rlp.val_at(1).map(Action::Reward),
|
||||
_ => Err(DecoderError::Custom("Invalid action type.")),
|
||||
}
|
||||
}
|
||||
@@ -199,6 +278,7 @@ impl Action {
|
||||
Action::Call(ref call) => call.bloom(),
|
||||
Action::Create(ref create) => create.bloom(),
|
||||
Action::Suicide(ref suicide) => suicide.bloom(),
|
||||
Action::Reward(ref reward) => reward.bloom(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user