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