1use std::cell::RefCell;
2use std::collections::HashMap;
3use std::rc::Rc;
4use sha3::Digest;
5use fvm_std::prelude::{Vec, Address, H256};
6use fvm_std::types::LogLevel;
7
8
9#[derive(Default)]
11pub struct Runtime {
12 pub inner: Rc<RefCell<RuntimeInner>>,
13}
14
15#[derive(Default)]
16pub struct RuntimeInner {
17 pub storage: HashMap<Vec<u8>, Vec<u8>>,
18 pub block_time: u64,
19 pub block_height: u64,
20 pub caller_addr: Address,
21 pub origin_addr: Address,
22 pub self_addr: Address,
23 pub block_hash: H256,
24 pub tx_hash: H256,
25 pub log: Vec<Vec<u8>>,
26 pub call_return: Vec<Vec<u8>>,
27 pub debug: HashMap<u32, Vec<Vec<u8>>>,
28 pub input: Vec<u8>,
29 pub ret: Vec<u8>,
30 pub hyper_counter: HashMap<Vec<u8>, i64>,
31 pub hyper_list: HashMap<Vec<u8>, Vec<i64>>,
32}
33
34impl RuntimeInner {
35 fn call_contract(&mut self) -> u32 {
36 self.call_return.last().expect("cross call set is not enough.").len() as u32
37 }
38}
39
40impl Runtime {
41 fn storage_write(&self, key: &[u8], prefix: &[u8], val: &[u8]) {
42 let mut p = prefix.to_vec();
43 let mut s = key.to_vec();
44 p.append(&mut s);
45 self.inner.borrow_mut().storage.insert(p, val.to_vec());
46 }
47
48 fn storage_read(&self, key: &[u8], prefix: &[u8]) -> Option<Vec<u8>> {
49 let mut p = prefix.to_vec();
50 let mut s = key.to_vec();
51 p.append(&mut s);
52 self.inner.borrow().storage.get(&p).map(|val| val.to_vec())
53 }
54
55 fn storage_delete(&self, key: &[u8], prefix: &[u8]) {
56 let mut p = prefix.to_vec();
57 let mut s = key.to_vec();
58 p.append(&mut s);
59 self.inner.borrow_mut().storage.remove(&p);
60 }
61
62 fn block_time(&self) -> u64 {
63 self.inner.borrow().block_time
64 }
65
66 fn block_height(&self) -> u64 {
67 self.inner.borrow().block_height
68 }
69
70 fn self_address(&self) -> Address {
71 self.inner.borrow().self_addr.clone()
72 }
73
74 fn caller_address(&self) -> Address {
75 self.inner.borrow().caller_addr.clone()
76 }
77
78 fn origin_address(&self) -> Address {
79 self.inner.borrow().origin_addr.clone()
80 }
81
82 fn tx_hash(&self) -> H256 {
83 self.inner.borrow().tx_hash.clone()
84 }
85
86 fn event(&self, msg: &[u8]) {
87 self.inner.borrow_mut().log.push(msg.to_vec());
88 }
89
90 fn sha256(&self, data: &[u8]) -> H256 {
91 let mut hasher = sha3::Keccak256::new();
92 hasher.update(data);
93 let hash = hasher.finalize();
94 H256::from_slice(hash.as_slice())
95 }
96
97 fn call_contract(&self, _: &Address, _: &[u8]) -> u32 {
98 self.inner.borrow_mut().call_contract()
99 }
100
101 fn cns_call_contract(&self, _: &[u8], _: &[u8]) -> u32 {
102 self.inner.borrow_mut().call_contract()
103 }
104
105 fn call_return(&self) -> Vec<u8> {
106 self.inner.borrow_mut().call_return.pop().expect("cross call set is not enough.")
107 }
108
109 fn ret(&self, _data: &[u8]) {
110 self.inner.borrow_mut().ret = _data.to_vec()
111 }
112
113 fn debug(&self, class_name: &[u8], data: &[u8], level: LogLevel) {
114 let mut c = String::from("[");
115 c.push_str(String::from_utf8(class_name.to_vec()).unwrap().as_str());
116 c.push_str("]: ");
117 c.push_str(String::from_utf8(data.to_vec()).unwrap().as_str());
118 if self.inner.borrow_mut().debug.contains_key(&level.to_int()) {
119 self.inner.borrow_mut().debug.get_mut(&level.to_int()).unwrap().push(c.into_bytes());
120 } else {
121 let mut temp = Vec::new();
122 temp.push(c.into_bytes());
123 self.inner.borrow_mut().debug.entry(level.to_int()).or_insert(temp);
124 }
125 }
126
127 pub fn revert(&self, _msg: &str) -> ! {
128 panic!("{}", _msg)
129 }
130
131 pub fn input(&self) -> Vec<u8> {
132 self.inner.borrow_mut().input.to_vec()
133 }
134
135 pub fn input_length(&self) -> u32 {
136 self.inner.borrow().input.len() as u32
137 }
138
139 pub fn add_list_key(&self, list_name: &[u8], index: u32) -> Option<i64> {
140 let list_name = list_name.to_vec();
141 let inner = &mut self.inner.borrow_mut();
143 let key =
145 match inner.hyper_counter.get(&list_name) {
146 None => {
147 inner.hyper_counter.insert(list_name.clone(), 0);
148 0
149 }
150 Some(v) => v.clone()
151 };
152
153 match inner.hyper_list.get_mut(&list_name) {
155 None => {
156 if index == 0 {
157 let mut new_vec = Vec::<i64>::new();
158 new_vec.insert(index as usize, key);
159 inner.hyper_list.insert(list_name.clone(), new_vec);
160 } else {
161 panic!("invalid index when add");
162 }
163 inner.hyper_counter.insert(list_name, key + 1);
164 Some(key)
165 }
166 Some(v) => {
167 if index as usize > v.len() {
169 return None;
170 }
171 v.insert(index as usize, key);
173 inner.hyper_counter.insert(list_name, key + 1);
175 Some(key)
176 }
177 }
178 }
179
180 pub fn get_list_key(&self, list_name: &[u8], index: u32) -> Option<i64> {
181 let list_name = list_name.to_vec();
182 let hyper_list = &self.inner.borrow().hyper_list;
184 let list = match hyper_list.get(&list_name) {
185 None => {
186 panic!("no list according to list_name when try to get key");
187 }
188 Some(v) => v
189 };
190 if index as usize >= list.len() {
192 None
193 } else {
194 Some(list[index as usize])
195 }
196 }
197
198 pub fn remove_list_key(&self, list_name: &[u8], index: u32) -> Option<i64> {
199 let list_name = list_name.to_vec();
200 let hyper_list = &mut self.inner.borrow_mut().hyper_list;
202 let list = match hyper_list.get_mut(&list_name) {
203 None => {
204 panic!("no list according to list_name when try to remove key");
205 }
206 Some(v) => v
207 };
208 if index as usize >= list.len() {
210 None
211 } else {
212 Some(list.remove(index as usize))
213 }
214 }
215
216 pub fn write_list_keys_back(&mut self, old_list_name: &[u8], list_name: &[u8], size: u32) {
217 let old_list_name = old_list_name.to_vec();
218 let new_list_name = list_name.to_vec();
219 let list_name = if old_list_name.len() > 0 {
220 old_list_name.clone()
221 } else {
222 new_list_name.clone()
223 };
224 let inner = &mut self.inner.borrow_mut();
226 let is_contain = inner.hyper_list.contains_key(&list_name);
227 match is_contain {
228 false => {
229 if size == 0 {
230 inner.hyper_counter.insert(new_list_name.clone(), 0);
232 let new_list = Vec::<i64>::new();
233 inner.hyper_list.insert(new_list_name.clone(), new_list);
234 } else {
235 panic!("size is not 0 but no list when writing keys back");
237 }
238 }
239 true => {
240 if old_list_name.len() > 0 {
242 let counter = inner.hyper_counter.remove(&old_list_name).unwrap();
243 let list = inner.hyper_list.remove(&old_list_name).unwrap();
244 inner.hyper_counter.insert(new_list_name.clone(), counter);
245 inner.hyper_list.insert(new_list_name.clone(), list);
246 }
247 let list = inner.hyper_list.get(&list_name).unwrap();
248 if list.len() != size as usize {
249 panic!("size not equal when writing keys back");
250 }
251 }
252 };
253 inner.storage.insert(["@HyperList".as_bytes(), new_list_name.as_slice()].concat().to_vec(), vec![0; 28]);
254 }
256}
257
258thread_local!(static RUNTIME: RefCell<Runtime> = RefCell::new(Runtime::default()));
259
260pub fn setup_runtime(runtime: Runtime) {
261 RUNTIME.with(|r| *r.borrow_mut() = runtime);
262}
263
264mod env {
265 use super::*;
266 use std::cmp;
267 use std::ptr;
268 use std::slice;
269 use std::u32;
270 use fvm_std::types::Address;
271 use fvm_std::prelude::H256;
272
273 #[no_mangle]
274 pub unsafe extern "C" fn fvm_block_time() -> u64 {
275 RUNTIME.with(|r| r.borrow().block_time())
276 }
277
278 #[no_mangle]
279 pub unsafe extern "C" fn fvm_block_height() -> u64 {
280 RUNTIME.with(|r| r.borrow().block_height())
281 }
282
283 #[no_mangle]
284 pub unsafe extern "C" fn fvm_self_address(dest: *mut u8) {
285 RUNTIME.with(|r| {
286 let addr = r.borrow().self_address();
287 ptr::copy(addr.as_ptr(), dest, Address::len_bytes());
288 })
289 }
290
291 #[no_mangle]
292 pub unsafe extern "C" fn fvm_caller_address(dest: *mut u8) {
293 RUNTIME.with(|r| {
294 let caller = r.borrow().caller_address();
295 ptr::copy(caller.as_ptr(), dest, Address::len_bytes());
296 })
297 }
298
299 #[no_mangle]
300 pub unsafe extern "C" fn fvm_origin_address(dest: *mut u8) {
301 RUNTIME.with(|r| {
302 let origin = r.borrow().origin_address();
303 ptr::copy(origin.as_ptr(), dest, Address::len_bytes());
304 })
305 }
306
307
308 #[no_mangle]
309 pub unsafe extern "C" fn fvm_tx_hash(dest: *const u8) {
310 RUNTIME.with(|r| {
311 let tx_hash = r.borrow().tx_hash();
312 ptr::copy(tx_hash.as_ptr(), dest as *mut u8, H256::len_bytes());
313 })
314 }
315
316 #[no_mangle]
317 pub unsafe extern "C" fn fvm_storage_read(
318 key_ptr: *const u8, key_len: u32, prefix_ptr: *const u8, prefix_len: u32,
319 val: *mut u8, vlen: u32, offset: u32,
320 ) -> u32 {
321 let key = core::slice::from_raw_parts(key_ptr, key_len as usize);
322 let prefix = core::slice::from_raw_parts(prefix_ptr, prefix_len as usize);
323 let offset = offset as usize;
324
325 let v = RUNTIME.with(|r| r.borrow().storage_read(key, prefix));
326 match v {
327 None => 0,
328 Some(v) => {
329 ptr::copy(
330 v.as_slice()[offset..].as_ptr(),
331 val,
332 cmp::min(vlen as usize, v.len() - offset),
333 );
334 v.len() as u32
335 }
336 }
337 }
338
339 #[no_mangle]
340 pub unsafe extern "C" fn fvm_storage_write(
341 key_ptr: *const u8, key_len: u32, prefix_ptr: *const u8, prefix_len: u32, val: *const u8, vlen: u32,
342 ) {
343 let key = core::slice::from_raw_parts(key_ptr, key_len as usize);
344 let prefix = core::slice::from_raw_parts(prefix_ptr, prefix_len as usize);
345 let val = core::slice::from_raw_parts(val, vlen as usize);
346 RUNTIME.with(|r| r.borrow().storage_write(key, prefix, val));
347 }
348
349 #[no_mangle]
350 pub unsafe extern "C" fn fvm_storage_delete(key_ptr: *const u8, key_len: u32, prefix_ptr: *const u8, prefix_len: u32) {
351 let key = core::slice::from_raw_parts(key_ptr, key_len as usize);
352 let prefix = core::slice::from_raw_parts(prefix_ptr, prefix_len as usize);
353 RUNTIME.with(|r| r.borrow().storage_delete(key, prefix));
354 }
355
356 #[no_mangle]
357 pub unsafe extern "C" fn fvm_log(ptr: *const u8, len: u32) {
358 let data = core::slice::from_raw_parts(ptr, len as usize);
359 RUNTIME.with(|r| r.borrow().event(data));
360 }
361
362 #[no_mangle]
363 pub unsafe extern "C" fn fvm_sha256(data_ptr: *const u8, len: u32, val: *mut u8) {
364 let data = core::slice::from_raw_parts(data_ptr, len as usize);
365 RUNTIME.with(|r| {
366 let mut hash = r.borrow_mut().sha256(data);
367 ptr::copy(hash.as_mut_ptr(), val, 32);
368 });
369 }
370
371 #[no_mangle]
372 pub unsafe extern "C" fn fvm_call_contract(
373 addr: *const u8, input_ptr: *const u8, input_len: u32,
374 ) -> u32 {
375 let input = core::slice::from_raw_parts(input_ptr, input_len as usize);
376 let addr = Address::from_slice(slice::from_raw_parts(addr, 20));
377 RUNTIME.with(|r| r.borrow().call_contract(&addr, input))
378 }
379
380 #[no_mangle]
381 pub unsafe extern "C" fn fvm_cns_call_contract(
382 cns: *const u8, cns_len: u32, input_ptr: *const u8, input_len: u32,
383 ) -> u32 {
384 let input = core::slice::from_raw_parts(input_ptr, input_len as usize);
385 let addr = core::slice::from_raw_parts(cns, cns_len as usize);
386 RUNTIME.with(|r| r.borrow().cns_call_contract(&addr, input))
387 }
388
389
390 #[no_mangle]
391 pub unsafe extern "C" fn fvm_revert(ptr: *const u8, len: u32) -> ! {
392 let temp = core::slice::from_raw_parts(ptr, len as usize);
393 RUNTIME.with(|r| r.borrow().revert(std::str::from_utf8(temp).unwrap()))
394 }
395
396 #[no_mangle]
397 pub unsafe extern "C" fn fvm_call_return(dst: *mut u8) {
398 let output = RUNTIME.with(|r| r.borrow().call_return());
399 std::ptr::copy(output.as_ptr(), dst, output.len());
400 }
401
402 #[no_mangle]
403 pub unsafe extern "C" fn fvm_input_length() -> u32 {
404 RUNTIME.with(|r| r.borrow().input_length())
405 }
406
407 #[no_mangle]
408 pub unsafe extern "C" fn fvm_fetch_input(_dst: *mut u8) {
409 let output = RUNTIME.with(|r| r.borrow().input());
410 ptr::copy(output.as_ptr(), _dst, output.len())
411 }
412
413 #[no_mangle]
414 pub unsafe extern "C" fn fvm_return(ptr: *const u8, len: u32) {
415 let ret = core::slice::from_raw_parts(ptr, len as usize);
416 RUNTIME.with(|r| r.borrow().ret(ret))
417 }
418
419 #[no_mangle]
420 pub unsafe fn fvm_debug(class_prt: *const u8, class_len: u32, ptr: *const u8, len: u32, level: u32) {
421 let class_name = core::slice::from_raw_parts(class_prt, class_len as usize);
422 let data = core::slice::from_raw_parts(ptr, len as usize);
423 let l = match level {
424 0 => LogLevel::CRITICAL,
425 1 => LogLevel::ERROR,
426 2 => LogLevel::WARNING,
427 3 => LogLevel::NOTICE,
428 4 => LogLevel::INFO,
429 5 => LogLevel::DEBUG,
430 _ => panic!("invalid log level type")
431 };
432 RUNTIME.with(|r| r.borrow_mut().debug(class_name, data, l))
433 }
434
435 #[no_mangle]
436 pub unsafe fn fvm_add_list_key(key_ptr: *const u8, key_len: u32, index: u32) -> i64 {
437 let list_name = core::slice::from_raw_parts(key_ptr, key_len as usize);
438 let v = RUNTIME.with(|r| r.borrow_mut().add_list_key(list_name, index));
439 match v {
440 None => {
441 -1
442 }
443 Some(v) => v
444 }
445 }
446
447 #[no_mangle]
448 pub unsafe fn fvm_get_list_key(key_ptr: *const u8, key_len: u32, index: u32) -> i64 {
449 let list_name = core::slice::from_raw_parts(key_ptr, key_len as usize);
450 let v = RUNTIME.with(|r| r.borrow().get_list_key(list_name, index));
451 match v {
452 None => -1,
453 Some(v) => v
454 }
455 }
456
457 #[no_mangle]
458 pub fn fvm_remove_list_key(key_ptr: *const u8, key_len: u32, index: u32) -> i64 {
459 unsafe {
460 let list_name = core::slice::from_raw_parts(key_ptr, key_len as usize);
461 let v = RUNTIME.with(|r| r.borrow().remove_list_key(list_name, index));
462 match v {
463 None => -1,
464 Some(v) => v
465 }
466 }
467 }
468
469 #[no_mangle]
470 pub fn fvm_write_list_keys(old_list_name_ptr: *const u8, old_list_name_len: u32, new_list_name_ptr: *const u8, new_list_name_len: u32, size: u32) {
471 unsafe {
472 let old_list_name = core::slice::from_raw_parts(old_list_name_ptr, old_list_name_len as usize);
473 let list_name = core::slice::from_raw_parts(new_list_name_ptr, new_list_name_len as usize);
474 RUNTIME.with(|r| r.borrow_mut().write_list_keys_back(old_list_name, list_name, size))
475 }
476 }
477}