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_decode::DecodeAsType;
27use scale_encode::EncodeAsType;
28use scale_info::{
29    TypeInfo,
30    scale::{Decode, Encode},
31};
32
33/// Program in different states in storage.
34#[derive(Clone, Debug, Decode, Encode, PartialEq, Eq, TypeInfo)]
35pub enum Program<BlockNumber: Copy> {
36    /// Program in active state.
37    Active(ActiveProgram<BlockNumber>),
38    /// Program has been exited (gr_exit was called)
39    Exited(ActorId),
40    /// Program has been terminated (`init` was failed)
41    Terminated(ActorId),
42}
43
44impl<BlockNumber: Copy> Program<BlockNumber> {
45    /// Returns whether the program is active.
46    pub fn is_active(&self) -> bool {
47        matches!(self, Program::Active(_))
48    }
49
50    /// Returns whether the program is exited.
51    pub fn is_exited(&self) -> bool {
52        matches!(self, Program::Exited(_))
53    }
54
55    /// Returns whether the program is terminated.
56    pub fn is_terminated(&self) -> bool {
57        matches!(self, Program::Terminated(_))
58    }
59
60    /// Returns whether the program is active and initialized.
61    pub fn is_initialized(&self) -> bool {
62        matches!(
63            self,
64            Program::Active(ActiveProgram {
65                state: ProgramState::Initialized,
66                ..
67            })
68        )
69    }
70}
71
72/// Program is not an active one.
73#[derive(Clone, Debug, derive_more::Display)]
74#[display("Program is not an active one")]
75pub struct InactiveProgramError;
76
77impl<BlockNumber: Copy> core::convert::TryFrom<Program<BlockNumber>>
78    for ActiveProgram<BlockNumber>
79{
80    type Error = InactiveProgramError;
81
82    fn try_from(prog_with_status: Program<BlockNumber>) -> Result<Self, Self::Error> {
83        match prog_with_status {
84            Program::Active(p) => Ok(p),
85            _ => Err(InactiveProgramError),
86        }
87    }
88}
89
90/// Active program in storage.
91#[derive(Clone, Debug, Decode, Encode, PartialEq, Eq, TypeInfo)]
92pub struct ActiveProgram<BlockNumber: Copy> {
93    /// Continuous intervals amount in program allocations.
94    pub allocations_tree_len: u32,
95    /// Infix of memory pages storage (is used for memory wake after pausing)
96    pub memory_infix: MemoryInfix,
97    /// Gas reservation map.
98    pub gas_reservation_map: GasReservationMap,
99    /// Code id of the program.
100    pub code_id: CodeId,
101    /// Initialization state of the program.
102    pub state: ProgramState,
103    /// Block number when the program will be expired.
104    pub expiration_block: BlockNumber,
105}
106
107/// Enumeration contains variants for program state.
108#[derive(Clone, Debug, Decode, DecodeAsType, Encode, EncodeAsType, PartialEq, Eq, TypeInfo)]
109pub enum ProgramState {
110    /// `init` method of a program has not yet finished its execution so
111    /// the program is not considered as initialized.
112    Uninitialized {
113        /// identifier of the initialization message.
114        message_id: MessageId,
115    },
116    /// Program has been successfully initialized and can process messages.
117    Initialized,
118}
119
120/// Struct defines infix of memory pages storage.
121#[derive(
122    Clone,
123    Copy,
124    Debug,
125    Default,
126    Decode,
127    DecodeAsType,
128    Encode,
129    EncodeAsType,
130    PartialEq,
131    Eq,
132    Hash,
133    TypeInfo,
134)]
135#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
136pub struct MemoryInfix(u32);
137
138impl MemoryInfix {
139    /// Constructing function from u32 number.
140    pub const fn new(value: u32) -> Self {
141        Self(value)
142    }
143
144    /// Return inner u32 value.
145    pub fn inner(&self) -> u32 {
146        self.0
147    }
148}