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
14pub 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
34pub 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 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 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 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}