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
use crate::Sandbox;
use ceres_executor::{Error, Result};
use ceres_std::{vec, Vec};
use ceres_support::traits::Ext;
use parity_scale_codec::{Decode, DecodeAll, Encode};

impl Sandbox {
    /// Read designated chunk from the sandbox memory.
    pub fn read_sandbox_memory(&self, ptr: u32, len: u32) -> Result<Vec<u8>> {
        let mut buf = vec![0u8; len as usize];
        self.read_sandbox_memory_into_buf(ptr, &mut buf)?;
        Ok(buf.to_vec())
    }

    /// Read designated chunk from the sandbox into the supplied buffer
    pub fn read_sandbox_memory_into_buf(&self, ptr: u32, buf: &mut [u8]) -> Result<()> {
        self.memory()
            .ok_or(Error::CodeNotFound)?
            .get(ptr, buf)
            .map_err(|_| Error::OutOfBounds)?;
        Ok(())
    }

    /// Read designated chunk from the sandbox memory and attempt to decode into the specified type.
    pub fn read_sandbox_memory_as<D: Decode>(&mut self, ptr: u32, len: u32) -> Result<D> {
        let buf = self.read_sandbox_memory(ptr, len)?;
        let decoded = D::decode_all(&buf[..]).map_err(|_| Error::DecodeRuntimeValueFailed)?;
        Ok(decoded)
    }

    /// Write the given buffer to the designated location in the sandbox memory.
    pub fn write_sandbox_memory(&mut self, ptr: u32, buf: &[u8]) -> Result<()> {
        self.memory()
            .ok_or(Error::CodeNotFound)?
            .set(ptr, buf)
            .map_err(|_| Error::OutOfBounds)
    }

    /// Write the given buffer and its length to the designated locations in sandbox memory
    ///
    /// buf -> memory
    pub fn write_sandbox_output(
        &mut self,
        out_ptr: u32,
        out_len_ptr: u32,
        buf: &[u8],
    ) -> Result<()> {
        let buf_len = buf.len() as u32;
        let len: u32 = self.read_sandbox_memory_as(out_len_ptr, 4)?;

        if len < buf_len {
            return Err(Error::OutputBufferTooSmall);
        }

        let memory = self.memory().ok_or(Error::CodeNotFound)?;
        memory
            .set(out_ptr, buf)
            .and_then(|_| memory.set(out_len_ptr, &buf_len.encode()))
            .map_err(|_| Error::OutOfBounds)?;

        Ok(())
    }
}