Skip to main content

fuel_vm/
context.rs

1//! VM runtime context definitions
2
3use crate::predicate::RuntimePredicate;
4
5use fuel_asm::Word;
6use fuel_types::BlockHeight;
7
8#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10/// Runtime context description.
11pub enum Context {
12    /// Current context is a predicate estimation.
13    PredicateEstimation {
14        /// Predicate program to be executed
15        program: RuntimePredicate,
16    },
17    /// Current context is a predicate verification.
18    PredicateVerification {
19        /// Predicate program to be executed
20        program: RuntimePredicate,
21    },
22    /// Current context is a script execution.
23    Script {
24        /// Block height of the context
25        block_height: BlockHeight,
26    },
27    /// Current context is under a `CALL` scope
28    Call {
29        /// Block height of the context
30        block_height: BlockHeight,
31    },
32    /// No transaction initialized/invalid context.
33    #[default]
34    NotInitialized,
35}
36
37impl Context {
38    /// Check if the context is predicate
39    pub const fn is_predicate(&self) -> bool {
40        matches!(
41            self,
42            Self::PredicateEstimation { .. } | Self::PredicateVerification { .. }
43        )
44    }
45
46    /// Return `true` if the context is external; `false` otherwise.
47    pub const fn is_external(&self) -> bool {
48        matches!(
49            self,
50            Self::PredicateEstimation { .. }
51                | Self::PredicateVerification { .. }
52                | Self::Script { .. }
53        )
54    }
55
56    /// Return `true` if the context is internal; `false` otherwise.
57    pub const fn is_internal(&self) -> bool {
58        !self.is_external()
59    }
60
61    /// Return the program to be executed, if its a predicate
62    pub const fn predicate(&self) -> Option<&RuntimePredicate> {
63        match self {
64            Context::PredicateEstimation { program } => Some(program),
65            Context::PredicateVerification { program } => Some(program),
66            _ => None,
67        }
68    }
69
70    /// Return the block height from the context, if either script or call
71    pub const fn block_height(&self) -> Option<BlockHeight> {
72        match self {
73            Context::Script { block_height } | Context::Call { block_height } => {
74                Some(*block_height)
75            }
76            _ => None,
77        }
78    }
79
80    /// Update the context according to the provided frame pointer
81    pub fn update_from_frame_pointer(&mut self, fp: Word) {
82        match self {
83            Context::Script { block_height } if fp != 0 => {
84                *self = Self::Call {
85                    block_height: *block_height,
86                }
87            }
88
89            Context::Call { block_height } if fp == 0 => {
90                *self = Self::Script {
91                    block_height: *block_height,
92                }
93            }
94            _ => (),
95        }
96    }
97}