1use 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 #[wasm_bindgen(js_namespace = console)]
16 pub fn log(s: &str);
17}
18
19type Ret = Result<Option<Value>>;
21
22pub struct Interface;
24
25impl RuntimeInterfaces for Interface {
26 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 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 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 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 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 Ok(None)
82 }
83
84 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 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 Ok(None)
103 }
104
105 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 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 Ok(None)
122 }
123
124 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 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 Ok(None)
141 }
142}