1use parity_wasm::elements::{FunctionType, ValueType};
2
3use super::{ModuleError, ModulePreset};
4
5pub struct ImportList<'a>(Vec<ImportType<'a>>);
6
7#[derive(Clone)]
9pub enum ImportType<'a> {
10 Function(&'a str, &'a str, FunctionType),
11 Global(&'a str, &'a str),
12 Memory(&'a str, &'a str),
13 Table(&'a str, &'a str),
14}
15
16impl<'a> ImportType<'a> {
17 pub fn module(&self) -> &'a str {
18 match self {
20 ImportType::Function(module, _, _) => module,
21 ImportType::Global(module, _)
22 | ImportType::Memory(module, _)
23 | ImportType::Table(module, _) => module,
24 }
25 }
26
27 pub fn field(&self) -> &'a str {
28 match self {
30 ImportType::Function(_, field, _) => field,
31 ImportType::Global(_, field)
32 | ImportType::Memory(_, field)
33 | ImportType::Table(_, field) => field,
34 }
35 }
36
37 pub fn signature(&self) -> Result<&FunctionType, ()> {
38 match self {
39 ImportType::Function(_, _, sig) => Ok(&sig),
40 _ => Err(()),
41 }
42 }
43}
44
45impl<'a> ImportList<'a> {
46 pub fn new() -> Self {
47 ImportList(Vec::new())
48 }
49
50 pub fn entries(&'a self) -> &'a Vec<ImportType<'a>> {
51 &self.0
52 }
53
54 pub fn entries_mut(&'a mut self) -> &'a mut Vec<ImportType<'a>> {
55 &mut self.0
56 }
57
58 pub fn into_inner(self) -> Vec<ImportType<'a>> {
59 self.0
60 }
61
62 pub fn concatenate(&mut self, other: ImportList<'a>) {
63 let mut to_append = other.into_inner();
64 self.0.append(&mut to_append);
65 }
66
67 pub fn with_entries(entries: Vec<ImportType<'a>>) -> Self {
68 ImportList(entries)
69 }
70
71 pub fn lookup_by_field(&self, name: &str) -> Option<&ImportType> {
72 let entries = self.entries();
73
74 for import in entries {
75 if import.field() == name {
76 return Some(&import);
77 }
78 }
79 None
80 }
81}
82
83impl<'a> ModulePreset for ImportList<'a> {
84 fn with_preset(preset: &str) -> Result<Self, ModuleError>
85 where
86 Self: Sized,
87 {
88 match preset {
89 "ewasm" => Ok(ImportList(vec![
90 ImportType::Function(
91 "ethereum",
92 "useGas",
93 FunctionType::new(vec![ValueType::I64], None),
94 ),
95 ImportType::Function(
96 "ethereum",
97 "getGasLeft",
98 FunctionType::new(vec![], Some(ValueType::I64)),
99 ),
100 ImportType::Function(
101 "ethereum",
102 "getAddress",
103 FunctionType::new(vec![ValueType::I32], None),
104 ),
105 ImportType::Function(
106 "ethereum",
107 "getExternalBalance",
108 FunctionType::new(vec![ValueType::I32, ValueType::I32], None),
109 ),
110 ImportType::Function(
111 "ethereum",
112 "getBlockHash",
113 FunctionType::new(vec![ValueType::I64, ValueType::I32], Some(ValueType::I32)),
114 ),
115 ImportType::Function(
116 "ethereum",
117 "call",
118 FunctionType::new(
119 vec![
120 ValueType::I64,
121 ValueType::I32,
122 ValueType::I32,
123 ValueType::I32,
124 ValueType::I32,
125 ],
126 Some(ValueType::I32),
127 ),
128 ),
129 ImportType::Function(
130 "ethereum",
131 "callCode",
132 FunctionType::new(
133 vec![
134 ValueType::I64,
135 ValueType::I32,
136 ValueType::I32,
137 ValueType::I32,
138 ValueType::I32,
139 ],
140 Some(ValueType::I32),
141 ),
142 ),
143 ImportType::Function(
144 "ethereum",
145 "callDelegate",
146 FunctionType::new(
147 vec![
148 ValueType::I64,
149 ValueType::I32,
150 ValueType::I32,
151 ValueType::I32,
152 ],
153 Some(ValueType::I32),
154 ),
155 ),
156 ImportType::Function(
157 "ethereum",
158 "callStatic",
159 FunctionType::new(
160 vec![
161 ValueType::I64,
162 ValueType::I32,
163 ValueType::I32,
164 ValueType::I32,
165 ],
166 Some(ValueType::I32),
167 ),
168 ),
169 ImportType::Function(
170 "ethereum",
171 "create",
172 FunctionType::new(
173 vec![
174 ValueType::I64,
175 ValueType::I32,
176 ValueType::I32,
177 ValueType::I32,
178 ],
179 Some(ValueType::I32),
180 ),
181 ),
182 ImportType::Function(
183 "ethereum",
184 "callDataCopy",
185 FunctionType::new(vec![ValueType::I32, ValueType::I32, ValueType::I32], None),
186 ),
187 ImportType::Function(
188 "ethereum",
189 "getCallDataSize",
190 FunctionType::new(vec![], Some(ValueType::I32)),
191 ),
192 ImportType::Function(
193 "ethereum",
194 "getCodeSize",
195 FunctionType::new(vec![], Some(ValueType::I32)),
196 ),
197 ImportType::Function(
198 "ethereum",
199 "getExternalCodeSize",
200 FunctionType::new(vec![ValueType::I32], Some(ValueType::I32)),
201 ),
202 ImportType::Function(
203 "ethereum",
204 "externalCodeCopy",
205 FunctionType::new(
206 vec![
207 ValueType::I32,
208 ValueType::I32,
209 ValueType::I32,
210 ValueType::I32,
211 ],
212 None,
213 ),
214 ),
215 ImportType::Function(
216 "ethereum",
217 "codeCopy",
218 FunctionType::new(vec![ValueType::I32, ValueType::I32, ValueType::I32], None),
219 ),
220 ImportType::Function(
221 "ethereum",
222 "getCaller",
223 FunctionType::new(vec![ValueType::I32], None),
224 ),
225 ImportType::Function(
226 "ethereum",
227 "getCallValue",
228 FunctionType::new(vec![ValueType::I32], None),
229 ),
230 ImportType::Function(
231 "ethereum",
232 "getBlockDifficulty",
233 FunctionType::new(vec![ValueType::I32], None),
234 ),
235 ImportType::Function(
236 "ethereum",
237 "getBlockCoinbase",
238 FunctionType::new(vec![ValueType::I32], None),
239 ),
240 ImportType::Function(
241 "ethereum",
242 "getBlockNumber",
243 FunctionType::new(vec![], Some(ValueType::I64)),
244 ),
245 ImportType::Function(
246 "ethereum",
247 "getBlockGasLimit",
248 FunctionType::new(vec![], Some(ValueType::I64)),
249 ),
250 ImportType::Function(
251 "ethereum",
252 "getBlockTimestamp",
253 FunctionType::new(vec![], Some(ValueType::I64)),
254 ),
255 ImportType::Function(
256 "ethereum",
257 "getTxGasPrice",
258 FunctionType::new(vec![ValueType::I32], None),
259 ),
260 ImportType::Function(
261 "ethereum",
262 "getTxOrigin",
263 FunctionType::new(vec![ValueType::I32], None),
264 ),
265 ImportType::Function(
266 "ethereum",
267 "storageStore",
268 FunctionType::new(vec![ValueType::I32, ValueType::I32], None),
269 ),
270 ImportType::Function(
271 "ethereum",
272 "storageLoad",
273 FunctionType::new(vec![ValueType::I32, ValueType::I32], None),
274 ),
275 ImportType::Function(
276 "ethereum",
277 "log",
278 FunctionType::new(
279 vec![
280 ValueType::I32,
281 ValueType::I32,
282 ValueType::I32,
283 ValueType::I32,
284 ValueType::I32,
285 ValueType::I32,
286 ValueType::I32,
287 ],
288 None,
289 ),
290 ),
291 ImportType::Function(
292 "ethereum",
293 "getReturnDataSize",
294 FunctionType::new(vec![], Some(ValueType::I32)),
295 ),
296 ImportType::Function(
297 "ethereum",
298 "returnDataCopy",
299 FunctionType::new(vec![ValueType::I32, ValueType::I32, ValueType::I32], None),
300 ),
301 ImportType::Function(
302 "ethereum",
303 "finish",
304 FunctionType::new(vec![ValueType::I32, ValueType::I32], None),
305 ),
306 ImportType::Function(
307 "ethereum",
308 "revert",
309 FunctionType::new(vec![ValueType::I32, ValueType::I32], None),
310 ),
311 ImportType::Function(
312 "ethereum",
313 "selfDestruct",
314 FunctionType::new(vec![ValueType::I32], None),
315 ),
316 ])),
317 "eth2" => Ok(ImportList(vec![
318 ImportType::Function(
319 "eth2",
320 "loadPreStateRoot",
321 FunctionType::new(vec![ValueType::I32], None),
322 ),
323 ImportType::Function(
324 "eth2",
325 "blockDataSize",
326 FunctionType::new(vec![], Some(ValueType::I32)),
327 ),
328 ImportType::Function(
329 "eth2",
330 "blockDataCopy",
331 FunctionType::new(vec![ValueType::I32, ValueType::I32, ValueType::I32], None),
332 ),
333 ImportType::Function(
334 "eth2",
335 "savePostStateRoot",
336 FunctionType::new(vec![ValueType::I32], None),
337 ),
338 ImportType::Function(
339 "eth2",
340 "pushNewDeposit",
341 FunctionType::new(vec![ValueType::I32, ValueType::I32], None),
342 ),
343 ])),
344 "debug" => Ok(ImportList(vec![
345 ImportType::Function(
346 "debug",
347 "print32",
348 FunctionType::new(vec![ValueType::I32], None),
349 ),
350 ImportType::Function(
351 "debug",
352 "print64",
353 FunctionType::new(vec![ValueType::I64], None),
354 ),
355 ImportType::Function(
356 "debug",
357 "printMem",
358 FunctionType::new(vec![ValueType::I32, ValueType::I32], None),
359 ),
360 ImportType::Function(
361 "debug",
362 "printMemHex",
363 FunctionType::new(vec![ValueType::I32, ValueType::I32], None),
364 ),
365 ImportType::Function(
366 "debug",
367 "printStorage",
368 FunctionType::new(vec![ValueType::I32], None),
369 ),
370 ImportType::Function(
371 "debug",
372 "printStorageHex",
373 FunctionType::new(vec![ValueType::I32], None),
374 ),
375 ])),
376 "bignum" => Ok(ImportList(vec![
377 ImportType::Function(
378 "bignum",
379 "mul256",
380 FunctionType::new(vec![ValueType::I32, ValueType::I32, ValueType::I32], None),
381 ),
382 ImportType::Function(
383 "bignum",
384 "umulmod256",
385 FunctionType::new(
386 vec![
387 ValueType::I32,
388 ValueType::I32,
389 ValueType::I32,
390 ValueType::I32,
391 ],
392 None,
393 ),
394 ),
395 ])),
396 _ => Err(ModuleError::NotSupported),
397 }
398 }
399}
400
401#[cfg(test)]
402mod tests {
403 use super::*;
404
405 #[test]
406 fn lookup_by_field_ewasm_good() {
407 let list = ImportList::with_preset("ewasm").unwrap();
408 assert!(list.lookup_by_field("useGas").is_some());
409 }
410
411 #[test]
412 fn lookup_by_field_ewasm_not_found() {
413 let list = ImportList::with_preset("ewasm").unwrap();
414 assert!(list.lookup_by_field("foo").is_none());
415 }
416}