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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
use crate::{Error, Result};
use ceres_std::Vec;
use parity_wasm::elements::{External, Module};
const IMPORT_MODULE_MEMORY: &str = "env";
#[allow(clippy::needless_range_loop)]
pub fn parse_args(selector: &str, args: &[&str], tys: Vec<u32>) -> Result<Vec<u8>> {
if args.len() != tys.len() {
return Err(Error::InvalidArgumentLength);
}
let mut res = hex::decode(&selector[2..])
.map_err(|_| Error::DecodeSelectorFailed)?
.to_vec();
for i in 0..args.len() {
match args[i] {
"true" => res.push(1),
"false" => res.push(0),
hex if hex.starts_with("0x") => {
if let Some(stripped) = hex.strip_prefix("0x") {
res.append(&mut hex::decode(stripped).map_err(|_| Error::ParseArgumentFailed)?)
} else {
return Err(Error::DecodeSelectorFailed);
}
}
patt => res.append(&mut hex::decode(&patt).map_err(|_| Error::ParseArgumentFailed)?),
}
}
Ok(res)
}
pub fn step_hex(h: &str) -> Result<Vec<u8>> {
if let Some(stripped) = h.strip_prefix("0x") {
hex::decode(stripped)
} else {
hex::decode(&h)
}
.map_err(|_| Error::DecodeSelectorFailed)
}
pub fn parse_code_hash(h: &str) -> Result<[u8; 32]> {
let hash = step_hex(h)?;
let mut res = [0; 32];
if hash.len() != 32 {
Err(Error::InvalidCodeHash)
} else {
res.copy_from_slice(&hash);
Ok(res)
}
}
pub fn scan_imports(module: &Module) -> core::result::Result<(u32, Option<u32>), &'static str> {
let import_entries = module
.import_section()
.map(|is| is.entries())
.unwrap_or(&[]);
let mut range = None;
for import in import_entries {
match import.external() {
External::Table(_) => return Err("Cannot import tables"),
External::Global(_) => return Err("Cannot import globals"),
External::Function(ref type_idx) => type_idx,
External::Memory(ref memory_type) => {
if import.module() != IMPORT_MODULE_MEMORY {
return Err("Invalid module for imported memory");
}
if import.field() != "memory" {
return Err("Memory import must have the field name 'memory'");
}
if range.is_some() {
return Err("Multiple memory imports defined");
}
let limits = memory_type.limits();
range = Some((limits.initial() as u32, limits.maximum().map(|v| v as u32)));
continue;
}
};
}
if let Some(limit) = range {
Ok(limit)
} else {
Ok((0, None))
}
}