core_processor/
context.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 contains context-structures for processing.
20
21use crate::common::{ExecutableActorData, Program};
22use gear_core::{
23    code::InstrumentedCode,
24    gas::{GasAllowanceCounter, GasCounter},
25    ids::ProgramId,
26    message::IncomingDispatch,
27    pages::WasmPagesAmount,
28    program::MemoryInfix,
29    reservation::GasReserver,
30};
31
32/// Struct with dispatch and counters charged for program data.
33#[derive(Debug)]
34pub struct ContextChargedForProgram {
35    pub(crate) dispatch: IncomingDispatch,
36    pub(crate) destination_id: ProgramId,
37    pub(crate) gas_counter: GasCounter,
38    pub(crate) gas_allowance_counter: GasAllowanceCounter,
39}
40
41impl ContextChargedForProgram {
42    /// Unwraps into inner data.
43    #[cfg(feature = "gtest")]
44    pub fn into_inner(self) -> (IncomingDispatch, ProgramId, GasCounter) {
45        (self.dispatch, self.destination_id, self.gas_counter)
46    }
47}
48
49pub struct ContextChargedForAllocations(pub(crate) ContextChargedForProgram);
50
51pub(crate) struct ContextData {
52    pub(crate) gas_counter: GasCounter,
53    pub(crate) gas_allowance_counter: GasAllowanceCounter,
54    pub(crate) dispatch: IncomingDispatch,
55    pub(crate) destination_id: ProgramId,
56    pub(crate) actor_data: ExecutableActorData,
57}
58
59pub struct ContextChargedForCodeLength {
60    pub(crate) data: ContextData,
61}
62
63impl ContextChargedForCodeLength {
64    /// Returns reference to the ExecutableActorData.
65    pub fn actor_data(&self) -> &ExecutableActorData {
66        &self.data.actor_data
67    }
68}
69
70/// The instance returned by `precharge_for_code`.
71/// Existence of the instance means that corresponding counters were
72/// successfully charged for fetching the binary code from storage.
73pub struct ContextChargedForCode {
74    pub(crate) data: ContextData,
75}
76
77impl From<ContextChargedForCodeLength> for ContextChargedForCode {
78    fn from(context: ContextChargedForCodeLength) -> Self {
79        Self { data: context.data }
80    }
81}
82
83/// The instance returned by `precharge_for_instrumentation`.
84/// Existence of the instance means that corresponding counters were
85/// successfully charged for reinstrumentation of the code.
86pub struct ContextChargedForInstrumentation {
87    pub(crate) data: ContextData,
88}
89
90impl From<ContextChargedForCode> for ContextChargedForInstrumentation {
91    fn from(context: ContextChargedForCode) -> Self {
92        Self { data: context.data }
93    }
94}
95
96pub struct ContextChargedForMemory {
97    pub(crate) data: ContextData,
98    pub(crate) max_reservations: u64,
99    pub(crate) memory_size: WasmPagesAmount,
100}
101
102impl ContextChargedForMemory {
103    /// Returns reference to the ExecutableActorData.
104    pub fn actor_data(&self) -> &ExecutableActorData {
105        &self.data.actor_data
106    }
107
108    /// Returns reference to the GasCounter.
109    pub fn gas_counter(&self) -> &GasCounter {
110        &self.data.gas_counter
111    }
112}
113
114/// Checked parameters for message execution across processing runs.
115pub struct ProcessExecutionContext {
116    pub(crate) gas_counter: GasCounter,
117    pub(crate) gas_allowance_counter: GasAllowanceCounter,
118    pub(crate) gas_reserver: GasReserver,
119    pub(crate) dispatch: IncomingDispatch,
120    pub(crate) balance: u128,
121    pub(crate) program: Program,
122    pub(crate) memory_size: WasmPagesAmount,
123}
124
125impl ProcessExecutionContext {
126    /// Returns program id.
127    pub fn program_id(&self) -> ProgramId {
128        self.program.id
129    }
130
131    /// Returns memory infix.
132    pub fn memory_infix(&self) -> MemoryInfix {
133        self.program.memory_infix
134    }
135}
136
137impl From<(ContextChargedForMemory, InstrumentedCode, u128)> for ProcessExecutionContext {
138    fn from(args: (ContextChargedForMemory, InstrumentedCode, u128)) -> Self {
139        let (context, code, balance) = args;
140
141        let ContextChargedForMemory {
142            data:
143                ContextData {
144                    gas_counter,
145                    gas_allowance_counter,
146                    dispatch,
147                    destination_id,
148                    actor_data,
149                },
150            max_reservations,
151            memory_size,
152        } = context;
153
154        let program = Program {
155            id: destination_id,
156            memory_infix: actor_data.memory_infix,
157            code,
158            allocations: actor_data.allocations,
159        };
160
161        // Must be created once per taken from the queue dispatch by program.
162        let gas_reserver =
163            GasReserver::new(&dispatch, actor_data.gas_reservation_map, max_reservations);
164
165        Self {
166            gas_counter,
167            gas_allowance_counter,
168            gas_reserver,
169            dispatch,
170            balance,
171            program,
172            memory_size,
173        }
174    }
175}
176
177/// System reservation context.
178#[derive(Debug, Default)]
179pub struct SystemReservationContext {
180    /// Reservation created in current execution.
181    pub current_reservation: Option<u64>,
182    /// Reservation from `ContextStore`.
183    pub previous_reservation: Option<u64>,
184}
185
186impl SystemReservationContext {
187    /// Extracts reservation context from dispatch.
188    pub fn from_dispatch(dispatch: &IncomingDispatch) -> Self {
189        Self {
190            current_reservation: None,
191            previous_reservation: dispatch
192                .context()
193                .as_ref()
194                .and_then(|ctx| ctx.system_reservation()),
195        }
196    }
197
198    /// Checks if there are any reservations.
199    pub fn has_any(&self) -> bool {
200        self.current_reservation.is_some() || self.previous_reservation.is_some()
201    }
202}