libchisel/
imports.rs

1use parity_wasm::elements::{FunctionType, ValueType};
2
3use super::{ModuleError, ModulePreset};
4
5pub struct ImportList<'a>(Vec<ImportType<'a>>);
6
7/// Enum internally representing a type of import.
8#[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        // FIXME: Is there a way to shorten this expression?
19        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        // FIXME: Is there a way to shorten this expression?
29        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}