fuel_vm/
state.rs

1//! Runtime state representation for the VM
2
3use alloc::vec::Vec;
4use fuel_tx::Receipt;
5use fuel_types::{
6    Bytes32,
7    Word,
8};
9
10mod debug;
11
12mod debugger;
13
14pub use debug::{
15    Breakpoint,
16    DebugEval,
17};
18
19pub use debugger::Debugger;
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
22/// Resulting state of an instruction set execution.
23pub enum ExecuteState {
24    /// The VM should proceed normally with the execution.
25    Proceed,
26    /// The current context returned a [`Word`].
27    Return(Word),
28    /// The current context returned some data represented as its digest.
29    ReturnData(Bytes32),
30    /// The set execution resulted in a `RVRT` instruction.
31    Revert(Word),
32
33    /// A debug event was reached.
34    DebugEvent(DebugEval),
35}
36
37impl ExecuteState {
38    /// Return true if the VM execution should continue.
39    pub const fn should_continue(&self) -> bool {
40        matches!(self, Self::Proceed | Self::DebugEvent(DebugEval::Continue))
41    }
42}
43
44impl Default for ExecuteState {
45    fn default() -> Self {
46        Self::Proceed
47    }
48}
49
50impl From<DebugEval> for ExecuteState {
51    fn from(d: DebugEval) -> Self {
52        Self::DebugEvent(d)
53    }
54}
55
56#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
57#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
58/// Resulting state of a transaction/program execution.
59pub enum ProgramState {
60    /// The transaction returned a [`Word`].
61    Return(Word),
62    /// The transaction returned some data represented as its digest.
63    ReturnData(Bytes32),
64    /// The transaction execution resulted in a `RVRT` instruction.
65    Revert(Word),
66
67    /// A debug event was reached for the transaction. The VM is suspended.
68    RunProgram(DebugEval),
69
70    /// A debug event was reached for a predicate verification. The VM is
71    /// suspended.
72    VerifyPredicate(DebugEval),
73}
74
75impl PartialEq<Breakpoint> for ProgramState {
76    fn eq(&self, other: &Breakpoint) -> bool {
77        match self.debug_ref() {
78            Some(&DebugEval::Breakpoint(b)) => &b == other,
79            _ => false,
80        }
81    }
82}
83
84impl ProgramState {
85    /// Debug event representation.
86    ///
87    /// Will return `None` if no debug event was reached.
88    pub const fn debug_ref(&self) -> Option<&DebugEval> {
89        match self {
90            Self::RunProgram(d) | Self::VerifyPredicate(d) => Some(d),
91            _ => None,
92        }
93    }
94
95    /// Return `true` if a debug event was reached.
96    pub const fn is_debug(&self) -> bool {
97        self.debug_ref().is_some()
98    }
99}
100
101#[derive(Debug, Clone, PartialEq, Eq)]
102/// Representation of the result of a transaction execution.
103pub struct StateTransition<Tx, Verifier> {
104    state: ProgramState,
105    tx: Tx,
106    receipts: Vec<Receipt>,
107    verifier: Verifier,
108}
109
110impl<Tx, Verifier> StateTransition<Tx, Verifier> {
111    /// Create a new state transition representation.
112    pub fn new(
113        state: ProgramState,
114        tx: Tx,
115        receipts: Vec<Receipt>,
116        verifier: Verifier,
117    ) -> Self {
118        Self {
119            state,
120            tx,
121            receipts,
122            verifier,
123        }
124    }
125
126    /// Program state representation.
127    pub const fn state(&self) -> &ProgramState {
128        &self.state
129    }
130
131    /// Resulting mutated transaction after VM execution.
132    pub const fn tx(&self) -> &Tx {
133        &self.tx
134    }
135
136    /// Flag whether the client should revert after execution.
137    pub fn should_revert(&self) -> bool {
138        self.receipts
139            .iter()
140            .any(|r| matches!(r, Receipt::Revert { .. } | Receipt::Panic { .. }))
141    }
142
143    /// Transaction receipts representing the state transition.
144    pub fn receipts(&self) -> &[Receipt] {
145        self.receipts.as_slice()
146    }
147
148    /// Verifier used during the transaction execution.
149    pub const fn verifier(&self) -> &Verifier {
150        &self.verifier
151    }
152
153    /// Convert this instance into its internal attributes.
154    pub fn into_inner(self) -> (ProgramState, Tx, Vec<Receipt>, Verifier) {
155        (self.state, self.tx, self.receipts, self.verifier)
156    }
157}
158
159impl<Tx, Verifier> From<StateTransition<Tx, Verifier>> for ProgramState {
160    fn from(t: StateTransition<Tx, Verifier>) -> ProgramState {
161        t.state
162    }
163}
164
165#[derive(Debug, Clone, Copy, PartialEq, Eq)]
166/// Zero-copy Representation of the result of a transaction execution bound to
167/// the lifetime of the VM.
168pub struct StateTransitionRef<'a, Tx, Verifier> {
169    state: ProgramState,
170    tx: &'a Tx,
171    receipts: &'a [Receipt],
172    verifier: &'a Verifier,
173}
174
175impl<'a, Tx, Verifier> StateTransitionRef<'a, Tx, Verifier> {
176    /// Create a new by reference state transition representation.
177    pub const fn new(
178        state: ProgramState,
179        tx: &'a Tx,
180        receipts: &'a [Receipt],
181        verifier: &'a Verifier,
182    ) -> Self {
183        Self {
184            state,
185            tx,
186            receipts,
187            verifier,
188        }
189    }
190
191    /// Program state representation.
192    pub const fn state(&self) -> &ProgramState {
193        &self.state
194    }
195
196    /// Resulting mutated transaction after VM execution.
197    pub const fn tx(&self) -> &Tx {
198        self.tx
199    }
200
201    /// Transaction receipts representing the state transition.
202    pub const fn receipts(&self) -> &[Receipt] {
203        self.receipts
204    }
205
206    /// Verifier used during the transaction execution.
207    pub const fn verifier(&self) -> &Verifier {
208        self.verifier
209    }
210
211    /// Flag whether the client should revert after execution.
212    pub fn should_revert(&self) -> bool {
213        self.receipts
214            .iter()
215            .any(|r| matches!(r, Receipt::Revert { .. } | Receipt::Panic { .. }))
216    }
217}
218
219impl<'a, Tx, Verifier> From<&'a StateTransition<Tx, Verifier>>
220    for StateTransitionRef<'a, Tx, Verifier>
221{
222    fn from(
223        t: &'a StateTransition<Tx, Verifier>,
224    ) -> StateTransitionRef<'a, Tx, Verifier> {
225        Self {
226            state: *t.state(),
227            tx: t.tx(),
228            receipts: t.receipts(),
229            verifier: t.verifier(),
230        }
231    }
232}
233
234impl<Tx, Verifier> From<StateTransitionRef<'_, Tx, Verifier>>
235    for StateTransition<Tx, Verifier>
236where
237    Tx: Clone,
238    Verifier: Clone,
239{
240    fn from(t: StateTransitionRef<Tx, Verifier>) -> StateTransition<Tx, Verifier> {
241        StateTransition {
242            state: *t.state(),
243            tx: t.tx().clone(),
244            receipts: t.receipts().to_vec(),
245            verifier: t.verifier.clone(),
246        }
247    }
248}
249
250impl<'a, Tx, Verifier> From<StateTransitionRef<'a, Tx, Verifier>> for ProgramState {
251    fn from(t: StateTransitionRef<'a, Tx, Verifier>) -> ProgramState {
252        t.state
253    }
254}