inkpad_sandbox/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2use self::ext::Ext;
3use inkpad_executor::{derive::SealCall, Error, Memory, Result};
4use inkpad_std::{vec, Rc, Vec};
5use inkpad_support::{
6    convert,
7    traits::{self, Frame},
8    types::Metadata,
9};
10use core::cell::RefCell;
11use parity_scale_codec::Encode;
12use parity_wasm::elements::Module;
13
14/// Custom storage key
15pub type StorageKey = [u8; 32];
16
17mod chain;
18mod contract;
19mod crypto;
20mod ext;
21mod instantiate;
22mod memory;
23mod restore;
24mod ri;
25mod schedule;
26mod storage;
27mod termination;
28mod transfer;
29mod tx;
30mod util;
31
32pub use self::{ri::RuntimeInterfaces, tx::Transaction};
33
34/// The runtime of ink! machine
35pub struct Sandbox {
36    pub input: Option<Vec<u8>>,
37    pub ret: Option<Vec<u8>>,
38    pub ext: Ext,
39    pub tx: tx::Transaction,
40    pub cache: Rc<RefCell<dyn Frame<Memory>>>,
41    pub events: Vec<(Vec<[u8; 32]>, Vec<u8>)>,
42    pub ri: Vec<SealCall<Self>>,
43}
44
45impl Sandbox {
46    /// New sandbox
47    pub fn new(
48        cache: Rc<RefCell<impl Frame<Memory> + 'static>>,
49        ri: Vec<SealCall<Self>>,
50    ) -> Sandbox {
51        Sandbox {
52            input: None,
53            ret: None,
54            ext: Default::default(),
55            events: vec![],
56            tx: Default::default(),
57            cache,
58            ri,
59        }
60    }
61
62    /// Preare a new frame
63    pub fn prepare(&mut self, code_hash: [u8; 32]) -> Result<()> {
64        let mut cache_mut = self.cache.borrow_mut();
65        if cache_mut.switch(code_hash).is_none() {
66            let contract = cache_mut.get(&code_hash).ok_or(Error::CodeNotFound)?;
67            let limit = inkpad_executor::scan_imports(&Module::from_bytes(&contract)?)?;
68            let memory = Memory::new(limit.0, limit.1)?;
69            cache_mut.push(code_hash, memory);
70        }
71        drop(cache_mut);
72
73        Ok(())
74    }
75
76    /// Load metadata to cache
77    pub fn load_metadata(&mut self, meta: &Metadata) -> Result<[u8; 32]> {
78        let code_hash =
79            convert::parse_code_hash(&meta.source.hash).ok_or(Error::DecodeContractFailed)?;
80        self.cache.borrow_mut().set(
81            code_hash.to_vec(),
82            Metadata::wasm(&meta.encode()).ok_or(Error::DecodeContractFailed)?,
83        );
84        Ok(code_hash)
85    }
86}
87
88impl traits::Ext<Memory, Vec<SealCall<Self>>> for Sandbox {
89    fn code(&self, hash: [u8; 32]) -> Option<Vec<u8>> {
90        self.cache.borrow().get(&hash).map(|v| v.to_vec())
91    }
92
93    fn memory(&self) -> Option<Memory> {
94        self.cache.borrow().memory()
95    }
96
97    fn seal_call(&self) -> Vec<SealCall<Self>> {
98        self.ri.clone()
99    }
100}