use alloc::vec::Vec;
use fuel_tx::Receipt;
use fuel_types::{
Bytes32,
Word,
};
mod debug;
mod debugger;
pub use debug::{
Breakpoint,
DebugEval,
};
pub use debugger::Debugger;
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ExecuteState {
#[default]
Proceed,
Return(Word),
ReturnData(Bytes32),
Revert(Word),
DebugEvent(DebugEval),
}
impl ExecuteState {
pub const fn should_continue(&self) -> bool {
matches!(self, Self::Proceed | Self::DebugEvent(DebugEval::Continue))
}
}
impl From<DebugEval> for ExecuteState {
fn from(d: DebugEval) -> Self {
Self::DebugEvent(d)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum ProgramState {
Return(Word),
ReturnData(Bytes32),
Revert(Word),
RunProgram(DebugEval),
VerifyPredicate(DebugEval),
}
impl PartialEq<Breakpoint> for ProgramState {
fn eq(&self, other: &Breakpoint) -> bool {
match self.debug_ref() {
Some(&DebugEval::Breakpoint(b)) => &b == other,
_ => false,
}
}
}
impl ProgramState {
pub const fn debug_ref(&self) -> Option<&DebugEval> {
match self {
Self::RunProgram(d) | Self::VerifyPredicate(d) => Some(d),
_ => None,
}
}
pub const fn is_debug(&self) -> bool {
self.debug_ref().is_some()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StateTransition<Tx, Verifier> {
state: ProgramState,
tx: Tx,
receipts: Vec<Receipt>,
verifier: Verifier,
}
impl<Tx, Verifier> StateTransition<Tx, Verifier> {
pub fn new(
state: ProgramState,
tx: Tx,
receipts: Vec<Receipt>,
verifier: Verifier,
) -> Self {
Self {
state,
tx,
receipts,
verifier,
}
}
pub const fn state(&self) -> &ProgramState {
&self.state
}
pub const fn tx(&self) -> &Tx {
&self.tx
}
pub fn should_revert(&self) -> bool {
self.receipts
.iter()
.any(|r| matches!(r, Receipt::Revert { .. } | Receipt::Panic { .. }))
}
pub fn receipts(&self) -> &[Receipt] {
self.receipts.as_slice()
}
pub const fn verifier(&self) -> &Verifier {
&self.verifier
}
pub fn into_inner(self) -> (ProgramState, Tx, Vec<Receipt>, Verifier) {
(self.state, self.tx, self.receipts, self.verifier)
}
}
impl<Tx, Verifier> From<StateTransition<Tx, Verifier>> for ProgramState {
fn from(t: StateTransition<Tx, Verifier>) -> ProgramState {
t.state
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct StateTransitionRef<'a, Tx, Verifier> {
state: ProgramState,
tx: &'a Tx,
receipts: &'a [Receipt],
verifier: &'a Verifier,
}
impl<'a, Tx, Verifier> StateTransitionRef<'a, Tx, Verifier> {
pub const fn new(
state: ProgramState,
tx: &'a Tx,
receipts: &'a [Receipt],
verifier: &'a Verifier,
) -> Self {
Self {
state,
tx,
receipts,
verifier,
}
}
pub const fn state(&self) -> &ProgramState {
&self.state
}
pub const fn tx(&self) -> &Tx {
self.tx
}
pub const fn receipts(&self) -> &[Receipt] {
self.receipts
}
pub const fn verifier(&self) -> &Verifier {
self.verifier
}
pub fn should_revert(&self) -> bool {
self.receipts
.iter()
.any(|r| matches!(r, Receipt::Revert { .. } | Receipt::Panic { .. }))
}
}
impl<'a, Tx, Verifier> From<&'a StateTransition<Tx, Verifier>>
for StateTransitionRef<'a, Tx, Verifier>
{
fn from(
t: &'a StateTransition<Tx, Verifier>,
) -> StateTransitionRef<'a, Tx, Verifier> {
Self {
state: *t.state(),
tx: t.tx(),
receipts: t.receipts(),
verifier: t.verifier(),
}
}
}
impl<Tx, Verifier> From<StateTransitionRef<'_, Tx, Verifier>>
for StateTransition<Tx, Verifier>
where
Tx: Clone,
Verifier: Clone,
{
fn from(t: StateTransitionRef<Tx, Verifier>) -> StateTransition<Tx, Verifier> {
StateTransition {
state: *t.state(),
tx: t.tx().clone(),
receipts: t.receipts().to_vec(),
verifier: t.verifier.clone(),
}
}
}
impl<'a, Tx, Verifier> From<StateTransitionRef<'a, Tx, Verifier>> for ProgramState {
fn from(t: StateTransitionRef<'a, Tx, Verifier>) -> ProgramState {
t.state
}
}