1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#![cfg_attr(not(feature = "std"), no_std)]
use self::ext::Ext;
use ceres_executor::{derive::SealCall, Error, Memory, Result};
use ceres_std::{vec, Rc, Vec};
use ceres_support::{
    convert,
    traits::{self, Frame},
    types::Metadata,
};
use core::cell::RefCell;
use parity_scale_codec::Encode;
use parity_wasm::elements::Module;

/// Custom storage key
pub type StorageKey = [u8; 32];

mod chain;
mod contract;
mod ext;
mod instantiate;
mod memory;
mod restore;
mod ri;
mod schedule;
mod storage;
mod termination;
mod transfer;
mod tx;
mod util;

pub use self::{ri::RuntimeInterfaces, tx::Transaction};

/// The runtime of ink! machine
pub struct Sandbox {
    pub input: Option<Vec<u8>>,
    pub ret: Option<Vec<u8>>,
    pub ext: Ext,
    pub tx: tx::Transaction,
    pub cache: Rc<RefCell<dyn Frame<Memory>>>,
    pub events: Vec<(Vec<[u8; 32]>, Vec<u8>)>,
    pub ri: Vec<SealCall<Self>>,
}

impl Sandbox {
    /// New sandbox
    pub fn new(
        cache: Rc<RefCell<impl Frame<Memory> + 'static>>,
        ri: Vec<SealCall<Self>>,
    ) -> Sandbox {
        Sandbox {
            input: None,
            ret: None,
            ext: Default::default(),
            events: vec![],
            tx: Default::default(),
            cache,
            ri,
        }
    }

    /// Preare a new frame
    pub fn prepare(&mut self, code_hash: [u8; 32]) -> Result<()> {
        let mut cache_mut = self.cache.borrow_mut();
        if cache_mut.switch(code_hash).is_none() {
            let contract = cache_mut.get(&code_hash).ok_or(Error::CodeNotFound)?;
            let limit = ceres_executor::scan_imports(&Module::from_bytes(&contract)?)?;
            let memory = Memory::new(limit.0, limit.1)?;
            cache_mut.push(code_hash, memory);
        }
        drop(cache_mut);

        Ok(())
    }

    /// Load metadata to cache
    pub fn load_metadata(&mut self, meta: &Metadata) -> Result<[u8; 32]> {
        let code_hash =
            convert::parse_code_hash(&meta.source.hash).ok_or(Error::DecodeContractFailed)?;
        self.cache.borrow_mut().set(
            code_hash.to_vec(),
            Metadata::wasm(&meta.encode()).ok_or(Error::DecodeContractFailed)?,
        );
        Ok(code_hash)
    }
}

impl traits::Ext<Memory, Vec<SealCall<Self>>> for Sandbox {
    fn code(&self, hash: [u8; 32]) -> Option<Vec<u8>> {
        self.cache.borrow().get(&hash).map(|v| v.to_vec())
    }

    fn memory(&self) -> Option<Memory> {
        self.cache.borrow().memory()
    }

    fn seal_call(&self) -> Vec<SealCall<Self>> {
        self.ri.clone()
    }
}