1use std::{collections::HashMap, println};
2
3use super::constants::PREIMAGE_HASH_SIZE;
4
5pub const MAX_MESSAGE_SIZE: usize = 4096;
6
7#[derive(Clone)]
8pub struct RawInput {
9 pub level: u32,
10 pub id: u32,
11 pub payload: Vec<u8>,
12}
13
14#[repr(C)]
15pub struct ReadInputMessageInfo {
16 pub level: i32,
17 pub id: i32,
18}
19
20#[link(wasm_import_module = "smart_rollup_core")]
21extern "C" {
22 pub fn write_debug(src: *const u8, num_bytes: usize);
24
25 pub fn read_input(
26 message_info: *mut ReadInputMessageInfo,
27 dst: *mut u8,
28 max_bytes: usize,
29 ) -> i32;
30
31 pub fn store_has(path: *const u8, path_len: usize) -> i32;
37
38 pub fn store_delete(path: *const u8, path_len: usize) -> i32;
40
41 pub fn store_read(
44 path: *const u8,
45 path_len: usize,
46 offset: usize,
47 dst: *mut u8,
48 num_bytes: usize,
49 ) -> i32;
50
51 pub fn store_write(
53 path: *const u8,
54 path_len: usize,
55 offset: usize,
56 src: *const u8,
57 num_bytes: usize,
58 ) -> i32;
59
60 pub fn reveal_preimage(
62 hash_addr: *const u8,
63 hash_size: u8,
64 dst: *mut u8,
65 max_bytes: usize,
66 ) -> i32;
67
68 pub fn store_move(
70 src_path: *const u8,
71 scr_path_len: usize,
72 dst_path: *const u8,
73 dst_path_len: usize,
74 ) -> i32;
75}
76
77pub trait Runtime: 'static {
78 fn write_debug(&mut self, msg: &str);
80
81 fn next_input(&mut self) -> Option<RawInput>;
83
84 fn store_is_present(&mut self, path: &str) -> bool;
86
87 fn store_delete(&mut self, path: &str) -> Result<(), ()>;
89
90 fn store_read(&mut self, path: &str, offset: usize, size: usize) -> Option<Vec<u8>>;
92
93 fn store_write(&mut self, path: &str, data: &[u8], at_offset: usize) -> Result<(), ()>;
98
99 fn reveal_preimage(&mut self, hash: &[u8; PREIMAGE_HASH_SIZE]) -> Result<Vec<u8>, ()>;
101
102 fn store_move(&mut self, from: &str, to: &str) -> Result<(), ()>;
104}
105
106#[derive(Default)]
107pub struct KernelRuntime {}
108
109impl Runtime for KernelRuntime {
110 fn write_debug(&mut self, msg: &str) {
111 unsafe {
112 write_debug(msg.as_ptr(), msg.len());
113 }
114 }
115
116 fn next_input(&mut self) -> Option<RawInput> {
117 let mut payload = Vec::with_capacity(MAX_MESSAGE_SIZE as usize);
118
119 let mut message_info = ReadInputMessageInfo { level: 0, id: 0 };
121
122 let size = unsafe { read_input(&mut message_info, payload.as_mut_ptr(), MAX_MESSAGE_SIZE) };
123
124 if size == 0 {
125 None
126 } else {
127 unsafe { payload.set_len(size as usize) };
128 Some(RawInput {
129 level: message_info.level as u32,
130 id: message_info.id as u32,
131 payload,
132 })
133 }
134 }
135
136 fn store_is_present(&mut self, path: &str) -> bool {
137 let ptr = path.as_ptr();
138 let res = unsafe { store_has(ptr, path.len()) };
139 match res {
140 0 => false, 1 => true, 2 => true, 3 => true, _ => false,
145 }
146 }
147
148 fn store_delete(&mut self, path: &str) -> Result<(), ()> {
149 let ptr = path.as_ptr();
150 let res = unsafe { store_delete(ptr, path.len()) };
151 match res {
152 0 => Ok(()),
153 _ => Err(()),
154 }
155 }
156
157 fn store_read(&mut self, path: &str, offset: usize, size: usize) -> Option<Vec<u8>> {
158 if !self.store_is_present(path) {
159 return None;
160 }
161
162 let ptr = path.as_ptr();
163 let path_len = path.len();
164 let mut buffer = Vec::with_capacity(size);
165 let dst = buffer.as_mut_ptr();
166 unsafe {
167 let _ = store_read(ptr, path_len, offset, dst, size);
168 buffer.set_len(size);
169 }
170
171 Some(buffer)
172 }
173
174 fn store_write(&mut self, path: &str, data: &[u8], at_offset: usize) -> Result<(), ()> {
175 let res = unsafe {
176 let path_len = path.len();
177 let path = path.as_ptr();
178 let num_bytes = data.len();
179 let src = data.as_ptr();
180 store_write(path, path_len, at_offset, src, num_bytes)
181 };
182 match res {
183 0 => Ok(()),
184 err => {
185 self.write_debug(&format!("error store_write_raw: {}\n", err));
186 Err(())
187 }
188 }
189 }
190 fn reveal_preimage(&mut self, hash: &[u8; PREIMAGE_HASH_SIZE]) -> Result<Vec<u8>, ()> {
191 let max_size = 4096;
192 let mut payload = Vec::with_capacity(MAX_MESSAGE_SIZE as usize);
193
194 let u8_size = u8::try_from(PREIMAGE_HASH_SIZE).unwrap();
195
196 unsafe {
197 let size = reveal_preimage(hash.as_ptr(), u8_size, payload.as_mut_ptr(), max_size);
198 if size < 0 {
199 Err(())
200 } else {
201 let size = usize::try_from(size).unwrap();
202 payload.set_len(size);
203 Ok(payload)
204 }
205 }
206 }
207
208 fn store_move(&mut self, from: &str, to: &str) -> Result<(), ()> {
209 let res = unsafe { store_move(from.as_ptr(), from.len(), to.as_ptr(), to.len()) };
210 match res {
211 0 => Ok(()),
212 _ => Err(()),
213 }
214 }
215}
216
217pub struct MockRuntime {
218 stdout: Vec<String>,
219 inputs: Vec<RawInput>,
220 storage: HashMap<String, Vec<u8>>,
221}
222
223impl Default for MockRuntime {
224 fn default() -> Self {
225 Self {
226 stdout: Vec::default(),
227 inputs: Vec::default(),
228 storage: HashMap::default(),
229 }
230 }
231}
232
233impl MockRuntime {
234 pub fn stdout(&self) -> Vec<&str> {
235 self.stdout
236 .iter()
237 .map(|str| str.as_str())
238 .collect::<Vec<&str>>()
239 }
240
241 pub fn add_input(&mut self, input: Vec<u8>) -> &mut Self {
242 let level = 0;
243 let id = self.inputs.len();
244 let msg = RawInput {
245 level,
246 id: u32::try_from(id).unwrap(),
247 payload: input,
248 };
249 self.inputs.push(msg);
250 self
251 }
252}
253
254impl Runtime for MockRuntime {
255 fn write_debug(&mut self, msg: &str) {
256 self.stdout.push(msg.to_string());
257 }
258
259 fn next_input(&mut self) -> Option<RawInput> {
260 self.inputs.pop()
261 }
262
263 fn store_is_present(&mut self, _path: &str) -> bool {
264 todo!()
265 }
266
267 fn store_delete(&mut self, _path: &str) -> Result<(), ()> {
268 todo!()
269 }
270
271 fn store_read(&mut self, path: &str, offset: usize, size: usize) -> Option<Vec<u8>> {
272 let bytes = self.storage.get(path).cloned()?;
273 if offset + size <= bytes.len() {
274 let data = &bytes[offset..offset + size].to_vec();
275 Some(data.clone())
276 } else {
277 todo!()
278 }
279 }
280
281 fn store_write(&mut self, path: &str, data: &[u8], offset: usize) -> Result<(), ()> {
282 let buffer = self.storage.get(path).cloned();
283 match buffer {
284 None => {
285 self.storage.insert(path.to_string(), data.to_vec());
286 println!("there");
287 Ok(())
288 }
289 Some(mut buffer) => {
290 if offset == buffer.len() {
291 println!("ici");
292 let mut data = data.to_vec();
293 buffer.append(&mut data);
294 println!("{:?}", &buffer);
295 self.storage.insert(path.to_string(), buffer.to_vec());
296 Ok(())
297 } else {
298 todo!()
299 }
300 }
301 }
302 }
303
304 fn reveal_preimage(&mut self, _hash: &[u8; PREIMAGE_HASH_SIZE]) -> Result<Vec<u8>, ()> {
305 todo!()
306 }
307
308 fn store_move(&mut self, _from: &str, _to: &str) -> Result<(), ()> {
309 todo!()
310 }
311}