diff --git a/Cargo.toml b/Cargo.toml index e802fd6..046c53f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,4 +22,8 @@ path = "ext/src/main.rs" [[bin]] name = "wasm-gas" -path = "gas/src/main.rs" \ No newline at end of file +path = "gas/src/main.rs" + +[[bin]] +name = "wasm-pack" +path = "pack/src/main.rs" \ No newline at end of file diff --git a/pack/.gitignore b/pack/.gitignore new file mode 100644 index 0000000..f2f9e58 --- /dev/null +++ b/pack/.gitignore @@ -0,0 +1,2 @@ +target +Cargo.lock \ No newline at end of file diff --git a/pack/Cargo.toml b/pack/Cargo.toml new file mode 100644 index 0000000..8a69bbe --- /dev/null +++ b/pack/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "wasm-pack" +version = "0.1.0" +authors = ["NikVolf "] + +[dependencies] +parity-wasm = { git="https://github.com/nikvolf/parity-wasm" } +wasm-utils = { path = "../" } +clap = "2.24" diff --git a/pack/src/main.rs b/pack/src/main.rs new file mode 100644 index 0000000..b8b1e09 --- /dev/null +++ b/pack/src/main.rs @@ -0,0 +1,32 @@ +extern crate parity_wasm; +extern crate wasm_utils; +extern crate clap; + +use clap::{App, Arg}; + +fn main() { + wasm_utils::init_log(); + + let matches = App::new("wasm-opt") + .arg(Arg::with_name("input") + .index(1) + .required(true) + .help("Input WASM file")) + .arg(Arg::with_name("output") + .index(2) + .required(true) + .help("Output WASM file")) + .get_matches(); + + let input = matches.value_of("input").expect("is required; qed"); + let output = matches.value_of("output").expect("is required; qed"); + + // doing serialization roundtrip to make sure the input is a valid wasm module + let module = parity_wasm::deserialize_file(&input).expect("Failed to load wasm module from file"); + let bytes = parity_wasm::serialize(module).expect("Failed to serialize wasm module"); + + // Wrap contract code into the wasm module that returns it + let packed_module = wasm_utils::pack_instance(bytes); + + parity_wasm::serialize_to_file(&output, packed_module).unwrap(); +} diff --git a/src/gas.rs b/src/gas.rs index 2366c7c..3b469ec 100644 --- a/src/gas.rs +++ b/src/gas.rs @@ -1,6 +1,5 @@ use parity_wasm::{elements, builder}; - pub fn update_call_index(opcodes: &mut elements::Opcodes, inserted_index: u32) { use parity_wasm::elements::Opcode::*; for opcode in opcodes.elements_mut().iter_mut() { diff --git a/src/lib.rs b/src/lib.rs index a316b7e..4483999 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,8 +8,10 @@ mod gas; mod symbols; mod logger; mod ext; +mod pack; pub use optimizer::{optimize, Error as OptimizerError}; pub use gas::inject_gas_counter; pub use logger::init_log; -pub use ext::externalize; \ No newline at end of file +pub use ext::externalize; +pub use pack::pack_instance; \ No newline at end of file diff --git a/src/pack.rs b/src/pack.rs new file mode 100644 index 0000000..fd2062a --- /dev/null +++ b/src/pack.rs @@ -0,0 +1,35 @@ +use parity_wasm::{elements, builder}; + +pub fn pack_instance(raw_module: Vec) -> elements::Module { + + let raw_len = raw_module.len(); + let mem_required = (raw_len / (64 * 1024) + 1) as u32; + + let module = builder::module() + .import() + .module("env") + .field("memory") + .external() + .memory(mem_required as u32, Some(mem_required as u32)) + .build() + .data() + .offset(elements::Opcode::I32Const(0)) + .value(raw_module) + .build() + .function() + .signature().param().i32().build() + .body().with_opcodes(elements::Opcodes::new(vec![ + elements::Opcode::GetLocal(0), + elements::Opcode::I32Const(raw_len as i32), + elements::Opcode::I32Store(0, 12), + elements::Opcode::End, + ])).build() + .build() + .export() + .field("_call") + .internal().func(0) + .build() + .build(); + + module +} \ No newline at end of file