Skip to main content

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