#![forbid(unsafe_code)]
use crate::{ExecutedTrees, StateComputeResult};
use diem_crypto::{hash::EventAccumulatorHasher, HashValue};
use diem_types::{
account_address::AccountAddress,
account_state_blob::AccountStateBlob,
block_info::PivotBlockDecision,
contract_event::ContractEvent,
epoch_state::EpochState,
proof::accumulator::InMemoryAccumulator,
term_state::PosState,
transaction::{TransactionStatus, Version},
};
use std::{collections::HashMap, sync::Arc};
#[derive(Clone, Debug)]
pub struct TransactionData {
account_blobs: HashMap<AccountAddress, AccountStateBlob>,
events: Vec<ContractEvent>,
status: TransactionStatus,
state_root_hash: HashValue,
event_tree: Arc<InMemoryAccumulator<EventAccumulatorHasher>>,
gas_used: u64,
txn_info_hash: Option<HashValue>,
}
impl TransactionData {
pub fn new(
account_blobs: HashMap<AccountAddress, AccountStateBlob>,
events: Vec<ContractEvent>, status: TransactionStatus,
state_root_hash: HashValue,
event_tree: Arc<InMemoryAccumulator<EventAccumulatorHasher>>,
gas_used: u64, txn_info_hash: Option<HashValue>,
) -> Self {
TransactionData {
account_blobs,
events,
status,
state_root_hash,
event_tree,
gas_used,
txn_info_hash,
}
}
pub fn account_blobs(&self) -> &HashMap<AccountAddress, AccountStateBlob> {
&self.account_blobs
}
pub fn events(&self) -> &[ContractEvent] { &self.events }
pub fn status(&self) -> &TransactionStatus { &self.status }
pub fn state_root_hash(&self) -> HashValue { self.state_root_hash }
pub fn event_root_hash(&self) -> HashValue { self.event_tree.root_hash() }
pub fn gas_used(&self) -> u64 { self.gas_used }
pub fn txn_info_hash(&self) -> Option<HashValue> { self.txn_info_hash }
}
#[derive(Debug, Clone)]
pub struct ProcessedVMOutput {
transaction_data: Vec<TransactionData>,
executed_trees: ExecutedTrees,
epoch_state: Option<EpochState>,
pivot_block: Option<PivotBlockDecision>,
}
impl ProcessedVMOutput {
pub fn new(
transaction_data: Vec<TransactionData>, executed_trees: ExecutedTrees,
epoch_state: Option<EpochState>,
pivot_block: Option<PivotBlockDecision>,
) -> Self {
ProcessedVMOutput {
transaction_data,
executed_trees,
epoch_state,
pivot_block,
}
}
pub fn transaction_data(&self) -> &[TransactionData] {
&self.transaction_data
}
pub fn executed_trees(&self) -> &ExecutedTrees { &self.executed_trees }
pub fn accu_root(&self) -> HashValue { self.executed_trees().state_id() }
pub fn version(&self) -> Option<Version> { self.executed_trees().version() }
pub fn epoch_state(&self) -> &Option<EpochState> { &self.epoch_state }
pub fn pivot_block(&self) -> &Option<PivotBlockDecision> {
&self.pivot_block
}
pub fn has_reconfiguration(&self) -> bool { self.epoch_state.is_some() }
pub fn compute_result(
&self, parent_frozen_subtree_roots: Vec<HashValue>,
parent_num_leaves: u64,
) -> StateComputeResult {
let txn_accu = self.executed_trees().txn_accumulator();
StateComputeResult::new(
if parent_num_leaves == 0 {
self.accu_root()
} else {
Default::default()
},
txn_accu.frozen_subtree_roots().clone(),
txn_accu.num_leaves(),
parent_frozen_subtree_roots,
parent_num_leaves,
self.epoch_state.clone(),
self.transaction_data()
.iter()
.map(|txn_data| txn_data.status())
.cloned()
.collect(),
self.transaction_data()
.iter()
.filter_map(|x| x.txn_info_hash())
.collect(),
self.pivot_block().clone(),
)
}
pub fn replace_pos_state(&mut self, new_pos_state: PosState) {
self.executed_trees.pos_state = new_pos_state;
}
pub fn set_pos_state_skipped(&mut self) {
self.executed_trees.set_pos_state_skipped(true);
}
}