use super::{action_types::Action, filter::TraceFilter};
use cfx_bytes::Bytes;
use cfx_internal_common::{DatabaseDecodable, DatabaseEncodable};
use cfx_types::{Bloom, Space, H256, U256, U64};
use malloc_size_of_derive::MallocSizeOf;
use rlp::{Decodable, DecoderError, Encodable, Rlp, RlpStream};
use rlp_derive::{RlpDecodable, RlpEncodable};
#[derive(Debug, PartialEq, Clone, MallocSizeOf)]
pub struct ExecTrace {
#[ignore_malloc_size_of = "ignored for performance reason"]
pub action: Action,
pub valid: bool,
}
impl ExecTrace {
pub fn bloom(&self) -> Bloom { self.action.bloom() }
}
impl Encodable for ExecTrace {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(2);
s.append(&self.action);
s.append(&self.valid);
}
}
impl Decodable for ExecTrace {
fn decode(d: &Rlp) -> Result<Self, DecoderError> {
match d.item_count()? {
1 => Ok(ExecTrace {
action: d.val_at(0)?,
valid: true,
}),
2 => Ok(ExecTrace {
action: d.val_at(0)?,
valid: d.val_at(1)?,
}),
_ => Err(DecoderError::RlpInvalidLength),
}
}
}
pub struct LocalizedTrace {
pub action: Action,
pub valid: bool,
pub epoch_hash: H256,
pub epoch_number: U256,
pub block_hash: H256,
pub transaction_position: U64,
pub transaction_hash: H256,
}
#[derive(Debug, PartialEq, Clone, RlpEncodable, RlpDecodable, MallocSizeOf)]
pub struct TransactionExecTraces(pub Vec<ExecTrace>);
impl From<Vec<ExecTrace>> for TransactionExecTraces {
fn from(v: Vec<ExecTrace>) -> Self { TransactionExecTraces(v) }
}
impl TransactionExecTraces {
pub fn bloom(&self) -> Bloom {
self.0
.iter()
.fold(Default::default(), |bloom, trace| bloom | trace.bloom())
}
pub fn filter_space(self, space: Space) -> Self {
Self(
TraceFilter::space_filter(space)
.filter_traces(self)
.unwrap_or(vec![]),
)
}
}
impl Into<Vec<ExecTrace>> for TransactionExecTraces {
fn into(self) -> Vec<ExecTrace> { self.0 }
}
#[derive(
Debug, PartialEq, Clone, Default, RlpEncodable, RlpDecodable, MallocSizeOf,
)]
pub struct BlockExecTraces(pub Vec<TransactionExecTraces>);
impl From<Vec<TransactionExecTraces>> for BlockExecTraces {
fn from(v: Vec<TransactionExecTraces>) -> Self { BlockExecTraces(v) }
}
impl BlockExecTraces {
pub fn bloom(&self) -> Bloom {
self.0.iter().fold(Default::default(), |bloom, tx_traces| {
bloom | tx_traces.bloom()
})
}
pub fn filter_space(self, space: Space) -> Self {
Self(
self.0
.into_iter()
.map(|tx_trace| tx_trace.filter_space(space))
.collect(),
)
}
}
impl Into<Vec<TransactionExecTraces>> for BlockExecTraces {
fn into(self) -> Vec<TransactionExecTraces> { self.0 }
}
impl DatabaseDecodable for BlockExecTraces {
fn db_decode(bytes: &[u8]) -> Result<Self, DecoderError> {
rlp::decode(bytes)
}
}
impl DatabaseEncodable for BlockExecTraces {
fn db_encode(&self) -> Bytes { rlp::encode(self) }
}