gear_core/
program.rs

1// This file is part of Gear.
2
3// Copyright (C) 2021-2025 Gear Technologies Inc.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19//! Module for programs.
20
21use crate::{
22    ids::{ActorId, MessageId},
23    reservation::GasReservationMap,
24};
25use gprimitives::CodeId;
26use scale_info::{
27    TypeInfo,
28    scale::{Decode, Encode},
29};
30
31/// Program in different states in storage.
32#[derive(Clone, Debug, Decode, Encode, PartialEq, Eq, TypeInfo)]
33pub enum Program<BlockNumber: Copy> {
34    /// Program in active state.
35    Active(ActiveProgram<BlockNumber>),
36    /// Program has been exited (gr_exit was called)
37    Exited(ActorId),
38    /// Program has been terminated (`init` was failed)
39    Terminated(ActorId),
40}
41
42impl<BlockNumber: Copy> Program<BlockNumber> {
43    /// Returns whether the program is active.
44    pub fn is_active(&self) -> bool {
45        matches!(self, Program::Active(_))
46    }
47
48    /// Returns whether the program is exited.
49    pub fn is_exited(&self) -> bool {
50        matches!(self, Program::Exited(_))
51    }
52
53    /// Returns whether the program is terminated.
54    pub fn is_terminated(&self) -> bool {
55        matches!(self, Program::Terminated(_))
56    }
57
58    /// Returns whether the program is active and initialized.
59    pub fn is_initialized(&self) -> bool {
60        matches!(
61            self,
62            Program::Active(ActiveProgram {
63                state: ProgramState::Initialized,
64                ..
65            })
66        )
67    }
68}
69
70/// Program is not an active one.
71#[derive(Clone, Debug, derive_more::Display)]
72#[display("Program is not an active one")]
73pub struct InactiveProgramError;
74
75impl<BlockNumber: Copy> core::convert::TryFrom<Program<BlockNumber>>
76    for ActiveProgram<BlockNumber>
77{
78    type Error = InactiveProgramError;
79
80    fn try_from(prog_with_status: Program<BlockNumber>) -> Result<Self, Self::Error> {
81        match prog_with_status {
82            Program::Active(p) => Ok(p),
83            _ => Err(InactiveProgramError),
84        }
85    }
86}
87
88/// Active program in storage.
89#[derive(Clone, Debug, Decode, Encode, PartialEq, Eq, TypeInfo)]
90pub struct ActiveProgram<BlockNumber: Copy> {
91    /// Continuous intervals amount in program allocations.
92    pub allocations_tree_len: u32,
93    /// Infix of memory pages storage (is used for memory wake after pausing)
94    pub memory_infix: MemoryInfix,
95    /// Gas reservation map.
96    pub gas_reservation_map: GasReservationMap,
97    /// Code id of the program.
98    pub code_id: CodeId,
99    /// Initialization state of the program.
100    pub state: ProgramState,
101    /// Block number when the program will be expired.
102    pub expiration_block: BlockNumber,
103}
104
105/// Enumeration contains variants for program state.
106#[derive(Clone, Debug, Decode, Encode, PartialEq, Eq, TypeInfo)]
107pub enum ProgramState {
108    /// `init` method of a program has not yet finished its execution so
109    /// the program is not considered as initialized.
110    Uninitialized {
111        /// identifier of the initialization message.
112        message_id: MessageId,
113    },
114    /// Program has been successfully initialized and can process messages.
115    Initialized,
116}
117
118/// Struct defines infix of memory pages storage.
119#[derive(Clone, Copy, Debug, Default, Decode, Encode, PartialEq, Eq, Hash, TypeInfo)]
120#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
121pub struct MemoryInfix(u32);
122
123impl MemoryInfix {
124    /// Constructing function from u32 number.
125    pub const fn new(value: u32) -> Self {
126        Self(value)
127    }
128
129    /// Return inner u32 value.
130    pub fn inner(&self) -> u32 {
131        self.0
132    }
133}