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}