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}