inkpad_browser/
ri.rs

1//! runtime interfaces
2use crate::result::err_check;
3use blake2_rfc::blake2b;
4use inkpad_executor::{derive::Value, Error, Result};
5use inkpad_sandbox::{RuntimeInterfaces, Sandbox};
6use getrandom::getrandom;
7use sha2::{Digest, Sha256};
8use tiny_keccak::{Hasher, Keccak};
9use wasm_bindgen::prelude::wasm_bindgen;
10
11#[wasm_bindgen]
12extern "C" {
13    // Use `js_namespace` here to bind `console.log(..)` instead of just
14    // `log(..)`
15    #[wasm_bindgen(js_namespace = console)]
16    pub fn log(s: &str);
17}
18
19/// Return type
20type Ret = Result<Option<Value>>;
21
22/// Browser interface
23pub struct Interface;
24
25impl RuntimeInterfaces for Interface {
26    /// Println
27    fn seal_println(sandbox: &mut Sandbox, args: &[Value]) -> Ret {
28        if args.len() != 2 {
29            return Err(Error::WrongArugmentLength);
30        }
31
32        let data = sandbox.read_sandbox_memory(args[0].into(), args[1].into())?;
33        if let Ok(utf8) = core::str::from_utf8(&data) {
34            log(utf8);
35        }
36
37        Ok(None)
38    }
39
40    /// Generate random value
41    fn seal_random(sandbox: &mut Sandbox, args: &[Value]) -> Ret {
42        if args.len() != 4 {
43            return Err(Error::WrongArugmentLength);
44        }
45        let subject_ptr = args[0].into();
46        let subject_len = args[1].into();
47        let output_ptr: u32 = args[2].into();
48        let output_len: u32 = args[2].into();
49
50        // random
51        let mut dest: [u8; 1] = [0];
52        err_check(getrandom(&mut dest));
53        let mut subject_buf = sandbox
54            .read_sandbox_memory(subject_ptr, subject_len)?
55            .to_vec();
56        subject_buf.push(dest[0]);
57
58        let output = blake2b::blake2b(32, &[], &subject_buf);
59        sandbox.write_sandbox_output(output_ptr, output_len, output.as_bytes())?;
60        Ok(None)
61    }
62
63    /// sha2 256
64    fn seal_hash_sha2_256(sandbox: &mut Sandbox, args: &[Value]) -> Ret {
65        if args.len() != 3 {
66            return Err(Error::WrongArugmentLength);
67        }
68        let input_ptr = args[0].into();
69        let input_len = args[1].into();
70        let output_ptr = args[2].into();
71
72        // hash
73        let mut dest: [u8; 32] = [0; 32];
74        let mut hasher = Sha256::new();
75        let input = sandbox.read_sandbox_memory(input_ptr, input_len)?;
76        hasher.update(&input);
77        dest.copy_from_slice(&hasher.finalize());
78        sandbox.write_sandbox_memory(output_ptr, dest.as_ref())?;
79
80        // result
81        Ok(None)
82    }
83
84    /// keccak 256
85    fn seal_hash_keccak_256(sandbox: &mut Sandbox, args: &[Value]) -> Ret {
86        if args.len() != 3 {
87            return Err(Error::WrongArugmentLength);
88        }
89        let input_ptr = args[0].into();
90        let input_len = args[1].into();
91        let output_ptr = args[2].into();
92
93        // hash
94        let mut dest: [u8; 32] = [0; 32];
95        let mut keccak = Keccak::v256();
96        let input = sandbox.read_sandbox_memory(input_ptr, input_len)?;
97        keccak.update(&input);
98        keccak.finalize(&mut dest);
99        sandbox.write_sandbox_memory(output_ptr, dest.as_ref())?;
100
101        // result
102        Ok(None)
103    }
104
105    /// blake2 256
106    fn seal_hash_blake2_256(sandbox: &mut Sandbox, args: &[Value]) -> Ret {
107        if args.len() != 3 {
108            return Err(Error::WrongArugmentLength);
109        }
110        let input_ptr = args[0].into();
111        let input_len = args[1].into();
112        let output_ptr = args[2].into();
113
114        // hash
115        let mut dest = [0; 32];
116        let input = sandbox.read_sandbox_memory(input_ptr, input_len)?;
117        dest.copy_from_slice(blake2b::blake2b(32, &[], &input).as_bytes());
118        sandbox.write_sandbox_memory(output_ptr, dest.as_ref())?;
119
120        // result
121        Ok(None)
122    }
123
124    /// blake2 128
125    fn seal_hash_blake2_128(sandbox: &mut Sandbox, args: &[Value]) -> Ret {
126        if args.len() != 3 {
127            return Err(Error::WrongArugmentLength);
128        }
129        let input_ptr = args[0].into();
130        let input_len = args[1].into();
131        let output_ptr = args[2].into();
132
133        // hash
134        let mut dest = [0; 16];
135        let input = sandbox.read_sandbox_memory(input_ptr, input_len)?;
136        dest.copy_from_slice(blake2b::blake2b(16, &[], &input).as_bytes());
137        sandbox.write_sandbox_memory(output_ptr, dest.as_ref())?;
138
139        // result
140        Ok(None)
141    }
142}