1use tetsy_vm;
20use wasm_utils::{self, rules};
21use tetsy_wasm::elements::{self, Deserialize};
22use tetsy_wasm::peek_size;
23
24fn gas_rules(wasm_costs: &tetsy_vm::WasmCosts) -> rules::Set {
25 rules::Set::new(
26 wasm_costs.regular,
27 {
28 let mut vals = ::std::collections::BTreeMap::new();
29 vals.insert(rules::InstructionType::Load, rules::Metering::Fixed(wasm_costs.mem as u32));
30 vals.insert(rules::InstructionType::Store, rules::Metering::Fixed(wasm_costs.mem as u32));
31 vals.insert(rules::InstructionType::Div, rules::Metering::Fixed(wasm_costs.div as u32));
32 vals.insert(rules::InstructionType::Mul, rules::Metering::Fixed(wasm_costs.mul as u32));
33 vals
34 })
35 .with_grow_cost(wasm_costs.grow_mem)
36 .with_forbidden_floats()
37}
38
39pub fn payload<'a>(params: &'a tetsy_vm::ActionParams, wasm_costs: &tetsy_vm::WasmCosts)
43 -> Result<(elements::Module, &'a [u8]), tetsy_vm::Error>
44{
45 let code = match params.code {
46 Some(ref code) => &code[..],
47 None => { return Err(tetsy_vm::Error::Wasm("Invalid wasm call".to_owned())); }
48 };
49
50 let (mut cursor, data_position) = match params.params_type {
51 tetsy_vm::ParamsType::Embedded => {
52 let module_size = peek_size(&*code);
53 (
54 ::std::io::Cursor::new(&code[..module_size]),
55 module_size
56 )
57 },
58 tetsy_vm::ParamsType::Separate => {
59 (::std::io::Cursor::new(&code[..]), 0)
60 },
61 };
62
63 let deserialized_module = elements::Module::deserialize(
64 &mut cursor
65 ).map_err(|err| {
66 tetsy_vm::Error::Wasm(format!("Error deserializing contract code ({:?})", err))
67 })?;
68
69 if deserialized_module.memory_section().map_or(false, |ms| ms.entries().len() > 0) {
70 return Err(tetsy_vm::Error::Wasm(format!("Malformed wasm module: internal memory")));
73 }
74
75 let contract_module = wasm_utils::inject_gas_counter(
76 deserialized_module,
77 &gas_rules(wasm_costs),
78 ).map_err(|_| tetsy_vm::Error::Wasm(format!("Wasm contract error: bytecode invalid")))?;
79
80 let contract_module = wasm_utils::stack_height::inject_limiter(
81 contract_module,
82 wasm_costs.max_stack_height,
83 ).map_err(|_| tetsy_vm::Error::Wasm(format!("Wasm contract error: stack limiter failure")))?;
84
85 let data = match params.params_type {
86 tetsy_vm::ParamsType::Embedded => {
87 if data_position < code.len() { &code[data_position..] } else { &[] }
88 },
89 tetsy_vm::ParamsType::Separate => {
90 match params.data {
91 Some(ref s) => &s[..],
92 None => &[]
93 }
94 }
95 };
96
97 Ok((contract_module, data))
98}