use anyhow::Context;
use tycho_types::models::{AccountStatus, ComputePhase, TickTock, TickTockTxInfo};
use crate::error::{TxError, TxResult};
use crate::phase::{
ActionPhaseContext, ComputePhaseContext, ComputePhaseFull, StoragePhaseContext,
TransactionInput,
};
use crate::{ExecutorInspector, ExecutorState};
impl ExecutorState<'_> {
pub fn run_tick_tock_transaction(
&mut self,
kind: TickTock,
mut inspector: Option<&mut ExecutorInspector<'_>>,
) -> TxResult<TickTockTxInfo> {
if self.state.status() != AccountStatus::Active {
return Err(TxError::Skipped);
}
let storage_phase = self
.storage_phase(StoragePhaseContext {
adjust_msg_balance: false,
received_message: None,
inspector: inspector.as_deref_mut(),
})
.context("storage phase failed")?;
let ComputePhaseFull {
compute_phase,
original_balance,
new_state,
actions,
..
} = self
.compute_phase(ComputePhaseContext {
input: TransactionInput::TickTock(kind),
storage_fee: storage_phase.storage_fees_collected,
force_accept: false,
stop_on_accept: false,
inspector: inspector.as_deref_mut(),
})
.context("compute phase failed")?;
let mut aborted = true;
let mut destroyed = false;
let mut action_phase = None;
if let ComputePhase::Executed(compute_phase) = &compute_phase
&& compute_phase.success
{
let res = self
.action_phase(ActionPhaseContext {
received_message: None,
original_balance,
new_state,
actions,
compute_phase,
inspector,
})
.context("action phase failed")?;
aborted = !res.action_phase.success;
destroyed = self.end_status == AccountStatus::NotExists;
action_phase = Some(res.action_phase);
}
Ok(TickTockTxInfo {
kind,
storage_phase,
compute_phase,
action_phase,
aborted,
destroyed,
})
}
}