1#![no_std]
22
23extern crate alloc;
24
25use alloc::{vec, vec::Vec};
26use core::{any::Any, fmt::Debug};
27use gear_core::{
28 costs::LazyPagesCosts,
29 ids::ActorId,
30 memory::{HostPointer, Memory, MemoryInterval},
31 pages::{GearPage, WasmPage, WasmPagesAmount},
32 program::MemoryInfix,
33 str::LimitedStr,
34};
35use num_enum::{IntoPrimitive, TryFromPrimitive};
36use parity_scale_codec::{Decode, Encode};
37
38const GLOBAL_NAME_GAS: &str = "gear_gas";
40
41#[derive(Debug, Copy, Clone, IntoPrimitive, TryFromPrimitive)]
44#[repr(u8)]
45pub enum ProcessAccessError {
46 OutOfBounds = 1,
47 GasLimitExceeded = 2,
48}
49
50#[derive(Debug, Clone, Copy, PartialEq, Eq, Encode, Decode)]
52pub enum GlobalsAccessMod {
53 WasmRuntime,
55 NativeRuntime,
57}
58
59#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)]
61pub struct GlobalsAccessConfig {
62 pub access_ptr: HostPointer,
64 pub access_mod: GlobalsAccessMod,
66}
67
68#[derive(Debug)]
70pub struct GlobalsAccessError;
71
72pub trait GlobalsAccessor {
74 fn get_i64(&mut self, name: &LimitedStr) -> Result<i64, GlobalsAccessError>;
76
77 fn set_i64(&mut self, name: &LimitedStr, value: i64) -> Result<(), GlobalsAccessError>;
79
80 fn get_i32(&self, _name: &LimitedStr) -> Result<i32, GlobalsAccessError> {
82 unimplemented!("Currently has no i32 system globals")
83 }
84
85 fn set_i32(&mut self, _name: &LimitedStr, _value: i32) -> Result<(), GlobalsAccessError> {
87 unimplemented!("Currently has no i32 system globals")
88 }
89
90 fn as_any_mut(&mut self) -> &mut dyn Any;
92}
93
94#[derive(Debug, Clone, Copy, Encode, Decode, PartialEq, Eq)]
104#[repr(i64)]
105pub enum Status {
108 Normal = 0_i64,
110 GasLimitExceeded,
112}
113
114impl Status {
115 pub fn is_normal(&self) -> bool {
117 *self == Self::Normal
118 }
119}
120
121#[derive(Debug, Clone)]
122pub struct LazyPagesInitContext {
123 pub page_sizes: Vec<u32>,
124 pub global_names: Vec<LimitedStr<'static>>,
125 pub pages_storage_prefix: Vec<u8>,
126}
127
128impl LazyPagesInitContext {
129 pub fn new(prefix: [u8; 32]) -> Self {
130 Self {
131 page_sizes: vec![WasmPage::SIZE, GearPage::SIZE],
132 global_names: vec![LimitedStr::from_small_str(GLOBAL_NAME_GAS)],
133 pages_storage_prefix: prefix.to_vec(),
134 }
135 }
136}
137
138pub trait LazyPagesInterface {
139 fn try_to_enable_lazy_pages(prefix: [u8; 32]) -> bool;
141
142 fn init_for_program<Context>(
144 ctx: &mut Context,
145 mem: &mut impl Memory<Context>,
146 program_id: ActorId,
147 memory_infix: MemoryInfix,
148 stack_end: Option<WasmPage>,
149 globals_config: GlobalsAccessConfig,
150 costs: LazyPagesCosts,
151 );
152
153 fn remove_lazy_pages_prot<Context>(ctx: &mut Context, mem: &mut impl Memory<Context>);
155
156 fn update_lazy_pages_and_protect_again<Context>(
159 ctx: &mut Context,
160 mem: &mut impl Memory<Context>,
161 old_mem_addr: Option<HostPointer>,
162 old_mem_size: WasmPagesAmount,
163 new_mem_addr: HostPointer,
164 );
165
166 fn get_write_accessed_pages() -> Vec<GearPage>;
168
169 fn get_status() -> Status;
171
172 fn pre_process_memory_accesses(
174 reads: &[MemoryInterval],
175 writes: &[MemoryInterval],
176 gas_counter: &mut u64,
177 ) -> Result<(), ProcessAccessError>;
178}
179
180impl LazyPagesInterface for () {
181 fn try_to_enable_lazy_pages(_prefix: [u8; 32]) -> bool {
182 unimplemented!()
183 }
184
185 fn init_for_program<Context>(
186 _ctx: &mut Context,
187 _mem: &mut impl Memory<Context>,
188 _program_id: ActorId,
189 _memory_infix: MemoryInfix,
190 _stack_end: Option<WasmPage>,
191 _globals_config: GlobalsAccessConfig,
192 _costs: LazyPagesCosts,
193 ) {
194 unimplemented!()
195 }
196
197 fn remove_lazy_pages_prot<Context>(_ctx: &mut Context, _mem: &mut impl Memory<Context>) {
198 unimplemented!()
199 }
200
201 fn update_lazy_pages_and_protect_again<Context>(
202 _ctx: &mut Context,
203 _mem: &mut impl Memory<Context>,
204 _old_mem_addr: Option<HostPointer>,
205 _old_mem_size: WasmPagesAmount,
206 _new_mem_addr: HostPointer,
207 ) {
208 unimplemented!()
209 }
210
211 fn get_write_accessed_pages() -> Vec<GearPage> {
212 unimplemented!()
213 }
214
215 fn get_status() -> Status {
216 unimplemented!()
217 }
218
219 fn pre_process_memory_accesses(
220 _reads: &[MemoryInterval],
221 _writes: &[MemoryInterval],
222 _gas_counter: &mut u64,
223 ) -> Result<(), ProcessAccessError> {
224 unimplemented!()
225 }
226}