gear_backend_common/
lazy_pages.rs

1// This file is part of Gear.
2
3// Copyright (C) 2022-2023 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//! Core logic for usage both in runtime and in lazy-pages native part.
20
21use core::fmt::Debug;
22
23use core::any::Any;
24use gear_core::{costs::CostPerPage, memory::HostPointer, pages::GearPage};
25use scale_info::scale::{self, Decode, Encode};
26
27use crate::utils::LimitedStr;
28
29/// Informs lazy-pages whether they work with native or WASM runtime.
30#[derive(Debug, Clone, Copy, PartialEq, Eq, Encode, Decode)]
31#[codec(crate = scale)]
32pub enum GlobalsAccessMod {
33    /// Is wasm runtime.
34    WasmRuntime,
35    /// Is native runtime.
36    NativeRuntime,
37}
38
39/// Lazy-pages cases weights.
40#[derive(Debug, Default, Clone, PartialEq, Eq, Encode, Decode)]
41#[codec(crate = scale)]
42pub struct LazyPagesWeights {
43    /// First read page access cost.
44    pub signal_read: CostPerPage<GearPage>,
45    /// First write page access cost.
46    pub signal_write: CostPerPage<GearPage>,
47    /// First write access cost for page, which has been already read accessed.
48    pub signal_write_after_read: CostPerPage<GearPage>,
49    /// First read page access cost from host function call.
50    pub host_func_read: CostPerPage<GearPage>,
51    /// First write page access cost from host function call.
52    pub host_func_write: CostPerPage<GearPage>,
53    /// First write page access cost from host function call.
54    pub host_func_write_after_read: CostPerPage<GearPage>,
55    /// Loading page data from storage cost.
56    pub load_page_storage_data: CostPerPage<GearPage>,
57}
58
59/// Globals ctx for lazy-pages initialization for program.
60#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)]
61#[codec(crate = scale)]
62pub struct GlobalsAccessConfig {
63    /// Raw pointer to the globals access provider.
64    pub access_ptr: HostPointer,
65    /// Access mod, currently two: native or WASM runtime.
66    pub access_mod: GlobalsAccessMod,
67}
68
69/// Globals access error.
70#[derive(Debug)]
71pub struct GlobalsAccessError;
72
73/// Globals access trait.
74pub trait GlobalsAccessor {
75    /// Returns global `name` value, if `name` is I64 global export.
76    fn get_i64(&self, name: &LimitedStr) -> Result<i64, GlobalsAccessError>;
77    /// Set global `name` == `value`, if `name` is I64 global export.
78    fn set_i64(&mut self, name: &LimitedStr, value: i64) -> Result<(), GlobalsAccessError>;
79    /// Returns global `name` value, if `name` is I32 global export.
80    fn get_i32(&self, _name: &LimitedStr) -> Result<i32, GlobalsAccessError> {
81        unimplemented!("Currently has no i32 system globals")
82    }
83    /// Set global `name` == `value`, if `name` is I32 global export.
84    fn set_i32(&mut self, _name: &LimitedStr, _value: i32) -> Result<(), GlobalsAccessError> {
85        unimplemented!("Currently has no i32 system globals")
86    }
87    /// Returns as `&mut dyn Any`.
88    fn as_any_mut(&mut self) -> &mut dyn Any;
89}
90
91/// Lazy-pages status.
92/// By default in program initialization status is set as `Normal`.
93/// If nothing bad happens in lazy-pages, then status remains to be `Normal`.
94/// If gas limit exceed, then status is set as `GasLimitExceeded`, and lazy-pages
95/// starts to skips all signals processing until the end of execution.
96/// The same is for gas allowance exceed, except it sets status as `GasAllowanceExceed`.
97/// In the end of execution this status is checked and if it's not `Normal` then
98/// termination reason sets as `gas limit exceeded` or `gas allowance exceeded`, depending on status.
99/// NOTE: `repr(i64)` is important to be able add additional fields, without old runtimes separate support logic.
100#[derive(Debug, Clone, Copy, Encode, Decode, PartialEq, Eq)]
101#[codec(crate = scale)]
102#[repr(i64)]
103// TODO: consider removal of two exceed options in favor of one global (issue #3018).
104// Will require bump of many RI func's versions.
105pub enum Status {
106    /// Lazy-pages works in normal mode.
107    Normal = 0_i64,
108    /// Skips signals processing until the end of execution, set termination reason as `gas limit exceeded`.
109    GasLimitExceeded,
110}
111
112impl Status {
113    /// Returns bool defining if status is `Normal`.
114    pub fn is_normal(&self) -> bool {
115        *self == Self::Normal
116    }
117}