From 85b7d2f43045ec7f7cbffdb623ed956dd7093a3a Mon Sep 17 00:00:00 2001 From: fro Date: Wed, 25 Oct 2017 20:36:05 +0300 Subject: [PATCH 1/7] wip build contract constructor --- build/src/main.rs | 37 +++++++++++++--- pack/.gitignore | 2 - pack/Cargo.toml | 9 ---- pack/src/main.rs | 32 -------------- src/pack.rs | 108 +++++++++++++++++++++++++++++++++------------- 5 files changed, 110 insertions(+), 78 deletions(-) delete mode 100644 pack/.gitignore delete mode 100644 pack/Cargo.toml delete mode 100644 pack/src/main.rs diff --git a/build/src/main.rs b/build/src/main.rs index 71b23b9..681f45f 100644 --- a/build/src/main.rs +++ b/build/src/main.rs @@ -6,9 +6,11 @@ extern crate clap; extern crate parity_wasm; use std::{fs, io}; +use std::io::Write; use std::path::PathBuf; use clap::{App, Arg}; +use parity_wasm::elements; #[derive(Debug)] pub enum Error { @@ -58,6 +60,14 @@ pub fn process_output(target_dir: &str, bin_name: &str) -> Result<(), Error> { Ok(()) } +fn has_ctor(module: &elements::Module) -> bool { + if let Some(ref section) = module.export_section() { + section.entries().iter().find(|e| "_create" == e.field()).is_some() + } else { + false + } +} + fn main() { wasm_utils::init_log(); @@ -102,10 +112,6 @@ fn main() { ); } - if !matches.is_present("skip_optimization") { - wasm_utils::optimize(&mut module, vec!["_call", "setTempRet0"]).expect("Optimizer to finish without errors"); - } - if let Some(runtime_type) = matches.value_of("runtime_type") { let runtime_type: &[u8] = runtime_type.as_bytes(); if runtime_type.len() != 4 { @@ -116,5 +122,26 @@ fn main() { module = wasm_utils::inject_runtime_type(module, &runtime_type, runtime_version); } - parity_wasm::serialize_to_file(&path, module).unwrap(); + let mut ctor_module = module.clone(); + + if !matches.is_present("skip_optimization") { + wasm_utils::optimize(&mut module, vec!["_call", "setTempRet0"]).expect("Optimizer to finish without errors"); + } + + let raw_module = parity_wasm::serialize(module).expect("Failed to serialize module"); + + let mut file = fs::File::create(&path).expect("Failed to create file");; + file.write_all(&raw_module).expect("Failed to write module to file"); + + // will pack into constructor + if has_ctor(&ctor_module) { + if !matches.is_present("skip_optimization") { + wasm_utils::optimize(&mut ctor_module, vec!["_create", "setTempRet0"]).expect("Optimizer to finish without errors"); + } + wasm_utils::pack_instance(raw_module, &mut ctor_module); + + let ctor_path = wasm_path(target_dir, &format!("{}_ctor", wasm_binary)); + parity_wasm::serialize_to_file(ctor_path, ctor_module); + } + } diff --git a/pack/.gitignore b/pack/.gitignore deleted file mode 100644 index f2f9e58..0000000 --- a/pack/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -target -Cargo.lock \ No newline at end of file diff --git a/pack/Cargo.toml b/pack/Cargo.toml deleted file mode 100644 index 71b99c0..0000000 --- a/pack/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "wasm-pack" -version = "0.1.0" -authors = ["NikVolf "] - -[dependencies] -parity-wasm = "0.12" -wasm-utils = { path = "../" } -clap = "2.24" diff --git a/pack/src/main.rs b/pack/src/main.rs deleted file mode 100644 index b8b1e09..0000000 --- a/pack/src/main.rs +++ /dev/null @@ -1,32 +0,0 @@ -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/pack.rs b/src/pack.rs index fd2062a..04c8fe4 100644 --- a/src/pack.rs +++ b/src/pack.rs @@ -1,35 +1,83 @@ -use parity_wasm::{elements, builder}; - -pub fn pack_instance(raw_module: Vec) -> elements::Module { +use parity_wasm::{serialize,elements, builder, deserialize_buffer}; +use self::elements::{ External, Section, ResizableLimits, Opcode, DataSegment, InitExpr, Internal }; +/// TODO: desc +pub fn pack_instance(raw_module: Vec, ctor_module: &mut 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(); + // Func + let create_func_id = { + let export_section = ctor_module.export_section().expect("No export section found"); + let found_entry = export_section.entries().iter() + .find(|entry| "_create" == entry.field()).expect("No export with name _create found"); - module -} \ No newline at end of file + let function_index: usize = match found_entry.internal() { + &Internal::Function(index) => index as usize, + _ => panic!("_create export is not a function"), + }; + + let import_section_len: usize = match ctor_module.import_section() { + Some(import) => + import.entries().iter().filter(|entry| match entry.external() { + &External::Function(_) => true, + _ => false, + }).count(), + None => 0, + }; + + // Calculates a function index within module's function section + function_index - import_section_len + }; + + let mut code_data_address = 0i32; + for section in ctor_module.sections_mut() { + match section { + &mut Section::Data(ref mut data_section) => { + let (index, offset) = if let Some(ref entry) = data_section.entries().iter().last() { + if let Opcode::I32Const(offst) = entry.offset().code()[0] { + let len = entry.value().len() as i32; + let offst = offst as i32; + (entry.index(), offst + len + len % 32) + } else { + (0, 0) + } + } else { + (0, 0) + }; + let code_data = DataSegment::new(index, InitExpr::new(vec![Opcode::I32Const(offset),Opcode::End]), raw_module.clone()); + data_section.entries_mut().push(code_data); + code_data_address = offset; + }, + _ => {;} + } + } + + for section in ctor_module.sections_mut() { + match section { + &mut Section::Export(ref mut export_section) => { + for entry in export_section.entries_mut().iter_mut() { + if "_create" == entry.field() { + // change _create export name into default _call + *entry.field_mut() = "_call".to_owned(); + } + } + } + + &mut Section::Code(ref mut code_section) => { + let code = code_section.bodies_mut()[create_func_id].code_mut().elements_mut(); + code.pop(); + code.extend([ + Opcode::GetLocal(0), + Opcode::I32Const(code_data_address), + Opcode::I32Store(0, 8), + Opcode::GetLocal(0), + Opcode::I32Const(raw_len as i32), + Opcode::I32Store(0, 12), + Opcode::End].iter().cloned()); + }, + + _ => {;}, + } + }; +} From b369ce903e866b6d93c48b412dfa68419a7b33de Mon Sep 17 00:00:00 2001 From: fro Date: Thu, 26 Oct 2017 15:49:55 +0300 Subject: [PATCH 2/7] fix grumbles + added constructor logic --- build/src/main.rs | 25 ++++++++++++++----------- src/lib.rs | 4 ++++ src/pack.rs | 36 ++++++++++++++++++++++-------------- 3 files changed, 40 insertions(+), 25 deletions(-) diff --git a/build/src/main.rs b/build/src/main.rs index 681f45f..faaf2ff 100644 --- a/build/src/main.rs +++ b/build/src/main.rs @@ -12,6 +12,9 @@ use std::path::PathBuf; use clap::{App, Arg}; use parity_wasm::elements; +use wasm_utils::CREATE_SYMBOL; +use wasm_utils::CALL_SYMBOL; + #[derive(Debug)] pub enum Error { Io(io::Error), @@ -62,7 +65,7 @@ pub fn process_output(target_dir: &str, bin_name: &str) -> Result<(), Error> { fn has_ctor(module: &elements::Module) -> bool { if let Some(ref section) = module.export_section() { - section.entries().iter().find(|e| "_create" == e.field()).is_some() + section.entries().iter().any(|e| CALL_SYMBOL == e.field()) } else { false } @@ -125,23 +128,23 @@ fn main() { let mut ctor_module = module.clone(); if !matches.is_present("skip_optimization") { - wasm_utils::optimize(&mut module, vec!["_call", "setTempRet0"]).expect("Optimizer to finish without errors"); + wasm_utils::optimize(&mut module, vec![CALL_SYMBOL, "setTempRet0"]).expect("Optimizer to finish without errors"); } let raw_module = parity_wasm::serialize(module).expect("Failed to serialize module"); - let mut file = fs::File::create(&path).expect("Failed to create file");; - file.write_all(&raw_module).expect("Failed to write module to file"); - - // will pack into constructor - if has_ctor(&ctor_module) { + // If module has an exported function with name=CREATE_SYMBOL + // build will pack the module (raw_module) into this funciton and export as CALL_SYMBOL. + // Otherwise it will just save an optimised raw_module + if !has_ctor(&ctor_module) { if !matches.is_present("skip_optimization") { - wasm_utils::optimize(&mut ctor_module, vec!["_create", "setTempRet0"]).expect("Optimizer to finish without errors"); + wasm_utils::optimize(&mut ctor_module, vec![CREATE_SYMBOL, "setTempRet0"]).expect("Optimizer to finish without errors"); } wasm_utils::pack_instance(raw_module, &mut ctor_module); - - let ctor_path = wasm_path(target_dir, &format!("{}_ctor", wasm_binary)); - parity_wasm::serialize_to_file(ctor_path, ctor_module); + parity_wasm::serialize_to_file(path, ctor_module).expect("Failed to serialize to file"); + } else { + let mut file = fs::File::create(&path).expect("Failed to create file"); + file.write_all(&raw_module).expect("Failed to write module to file"); } } diff --git a/src/lib.rs b/src/lib.rs index 12d0a9f..fb32da2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,9 @@ extern crate byteorder; #[macro_use] extern crate log; #[macro_use] extern crate lazy_static; +pub static CREATE_SYMBOL: &'static str = "_create"; +pub static CALL_SYMBOL: &'static str = "_call"; + pub mod rules; mod optimizer; @@ -22,3 +25,4 @@ pub use ext::externalize; pub use pack::pack_instance; pub use nondeterminism_check::is_deterministic; pub use runtime_type::inject_runtime_type; + diff --git a/src/pack.rs b/src/pack.rs index 04c8fe4..dbc9f16 100644 --- a/src/pack.rs +++ b/src/pack.rs @@ -1,20 +1,23 @@ use parity_wasm::{serialize,elements, builder, deserialize_buffer}; use self::elements::{ External, Section, ResizableLimits, Opcode, DataSegment, InitExpr, Internal }; -/// TODO: desc -pub fn pack_instance(raw_module: Vec, ctor_module: &mut elements::Module) { - let raw_len = raw_module.len(); - let mem_required = (raw_len / (64 * 1024) + 1) as u32; +use super::CREATE_SYMBOL; +use super::CALL_SYMBOL; - // Func +/// If module has an exported "_create" function we want to pack it into "constructor". +/// `raw_module` is the actual contract code +/// `ctor_module` is the constructor which should return `raw_module` +pub fn pack_instance(raw_module: Vec, ctor_module: &mut elements::Module) { + + // We need to find an internal ID of function witch is exported as "_create" + // in order to find it in the Code section of the module let create_func_id = { - let export_section = ctor_module.export_section().expect("No export section found"); - let found_entry = export_section.entries().iter() - .find(|entry| "_create" == entry.field()).expect("No export with name _create found"); + let found_entry = ctor_module.export_section().expect("No export section found").entries().iter() + .find(|entry| CREATE_SYMBOL == entry.field()).expect("No export with name _create found"); let function_index: usize = match found_entry.internal() { &Internal::Function(index) => index as usize, - _ => panic!("_create export is not a function"), + _ => panic!("export is not a function"), }; let import_section_len: usize = match ctor_module.import_section() { @@ -30,6 +33,7 @@ pub fn pack_instance(raw_module: Vec, ctor_module: &mut elements::Module) { function_index - import_section_len }; + // Code data address is an address where we put the contract's code (raw_module) let mut code_data_address = 0i32; for section in ctor_module.sections_mut() { match section { @@ -38,14 +42,18 @@ pub fn pack_instance(raw_module: Vec, ctor_module: &mut elements::Module) { if let Opcode::I32Const(offst) = entry.offset().code()[0] { let len = entry.value().len() as i32; let offst = offst as i32; - (entry.index(), offst + len + len % 32) + (entry.index(), offst + (len + 32) - len % 32) } else { (0, 0) } } else { (0, 0) }; - let code_data = DataSegment::new(index, InitExpr::new(vec![Opcode::I32Const(offset),Opcode::End]), raw_module.clone()); + let code_data = DataSegment::new( + index, + InitExpr::new(vec![Opcode::I32Const(offset),Opcode::End]), + raw_module.clone() + ); data_section.entries_mut().push(code_data); code_data_address = offset; }, @@ -57,9 +65,9 @@ pub fn pack_instance(raw_module: Vec, ctor_module: &mut elements::Module) { match section { &mut Section::Export(ref mut export_section) => { for entry in export_section.entries_mut().iter_mut() { - if "_create" == entry.field() { + if CREATE_SYMBOL == entry.field() { // change _create export name into default _call - *entry.field_mut() = "_call".to_owned(); + *entry.field_mut() = CALL_SYMBOL.to_owned(); } } } @@ -72,7 +80,7 @@ pub fn pack_instance(raw_module: Vec, ctor_module: &mut elements::Module) { Opcode::I32Const(code_data_address), Opcode::I32Store(0, 8), Opcode::GetLocal(0), - Opcode::I32Const(raw_len as i32), + Opcode::I32Const(raw_module.len() as i32), Opcode::I32Store(0, 12), Opcode::End].iter().cloned()); }, From 918c8485a449d5301b4020b5c49e96963cdb53a4 Mon Sep 17 00:00:00 2001 From: fro Date: Thu, 26 Oct 2017 19:24:40 +0300 Subject: [PATCH 3/7] fix logic + types --- build/src/main.rs | 4 ++-- src/pack.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build/src/main.rs b/build/src/main.rs index faaf2ff..401243c 100644 --- a/build/src/main.rs +++ b/build/src/main.rs @@ -136,12 +136,12 @@ fn main() { // If module has an exported function with name=CREATE_SYMBOL // build will pack the module (raw_module) into this funciton and export as CALL_SYMBOL. // Otherwise it will just save an optimised raw_module - if !has_ctor(&ctor_module) { + if has_ctor(&ctor_module) { if !matches.is_present("skip_optimization") { wasm_utils::optimize(&mut ctor_module, vec![CREATE_SYMBOL, "setTempRet0"]).expect("Optimizer to finish without errors"); } wasm_utils::pack_instance(raw_module, &mut ctor_module); - parity_wasm::serialize_to_file(path, ctor_module).expect("Failed to serialize to file"); + parity_wasm::serialize_to_file(&path, ctor_module).expect("Failed to serialize to file"); } else { let mut file = fs::File::create(&path).expect("Failed to create file"); file.write_all(&raw_module).expect("Failed to write module to file"); diff --git a/src/pack.rs b/src/pack.rs index dbc9f16..a5e7fa7 100644 --- a/src/pack.rs +++ b/src/pack.rs @@ -42,7 +42,7 @@ pub fn pack_instance(raw_module: Vec, ctor_module: &mut elements::Module) { if let Opcode::I32Const(offst) = entry.offset().code()[0] { let len = entry.value().len() as i32; let offst = offst as i32; - (entry.index(), offst + (len + 32) - len % 32) + (entry.index(), offst + (len + 4) - len % 4) } else { (0, 0) } From 4a70824a88f53f59efcd3475c7f38fd774981f33 Mon Sep 17 00:00:00 2001 From: fro Date: Fri, 27 Oct 2017 18:32:33 +0300 Subject: [PATCH 4/7] test for pack added --- Cargo.toml | 4 --- build/src/main.rs | 9 +++-- src/lib.rs | 1 + src/pack.rs | 85 +++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 88 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c5b07aa..cc225fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,10 +26,6 @@ path = "ext/src/main.rs" name = "wasm-gas" path = "gas/src/main.rs" -[[bin]] -name = "wasm-pack" -path = "pack/src/main.rs" - [[bin]] name = "wasm-build" path = "build/src/main.rs" diff --git a/build/src/main.rs b/build/src/main.rs index 401243c..3b0535f 100644 --- a/build/src/main.rs +++ b/build/src/main.rs @@ -12,8 +12,7 @@ use std::path::PathBuf; use clap::{App, Arg}; use parity_wasm::elements; -use wasm_utils::CREATE_SYMBOL; -use wasm_utils::CALL_SYMBOL; +use wasm_utils::{CREATE_SYMBOL, CALL_SYMBOL, SET_TEMP_RET_SYMBOL}; #[derive(Debug)] pub enum Error { @@ -65,7 +64,7 @@ pub fn process_output(target_dir: &str, bin_name: &str) -> Result<(), Error> { fn has_ctor(module: &elements::Module) -> bool { if let Some(ref section) = module.export_section() { - section.entries().iter().any(|e| CALL_SYMBOL == e.field()) + section.entries().iter().any(|e| CREATE_SYMBOL == e.field()) } else { false } @@ -128,7 +127,7 @@ fn main() { let mut ctor_module = module.clone(); if !matches.is_present("skip_optimization") { - wasm_utils::optimize(&mut module, vec![CALL_SYMBOL, "setTempRet0"]).expect("Optimizer to finish without errors"); + wasm_utils::optimize(&mut module, vec![CALL_SYMBOL, SET_TEMP_RET_SYMBOL]).expect("Optimizer to finish without errors"); } let raw_module = parity_wasm::serialize(module).expect("Failed to serialize module"); @@ -138,7 +137,7 @@ fn main() { // Otherwise it will just save an optimised raw_module if has_ctor(&ctor_module) { if !matches.is_present("skip_optimization") { - wasm_utils::optimize(&mut ctor_module, vec![CREATE_SYMBOL, "setTempRet0"]).expect("Optimizer to finish without errors"); + wasm_utils::optimize(&mut ctor_module, vec![CREATE_SYMBOL, SET_TEMP_RET_SYMBOL]).expect("Optimizer to finish without errors"); } wasm_utils::pack_instance(raw_module, &mut ctor_module); parity_wasm::serialize_to_file(&path, ctor_module).expect("Failed to serialize to file"); diff --git a/src/lib.rs b/src/lib.rs index fb32da2..96ab101 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,7 @@ extern crate byteorder; pub static CREATE_SYMBOL: &'static str = "_create"; pub static CALL_SYMBOL: &'static str = "_call"; +pub static SET_TEMP_RET_SYMBOL: &'static str = "setTempRet0"; pub mod rules; diff --git a/src/pack.rs b/src/pack.rs index a5e7fa7..9f2bfbb 100644 --- a/src/pack.rs +++ b/src/pack.rs @@ -1,8 +1,7 @@ use parity_wasm::{serialize,elements, builder, deserialize_buffer}; use self::elements::{ External, Section, ResizableLimits, Opcode, DataSegment, InitExpr, Internal }; -use super::CREATE_SYMBOL; -use super::CALL_SYMBOL; +use super::{CREATE_SYMBOL, CALL_SYMBOL}; /// If module has an exported "_create" function we want to pack it into "constructor". /// `raw_module` is the actual contract code @@ -35,8 +34,10 @@ pub fn pack_instance(raw_module: Vec, ctor_module: &mut elements::Module) { // Code data address is an address where we put the contract's code (raw_module) let mut code_data_address = 0i32; + for section in ctor_module.sections_mut() { match section { + // TODO: add data section is there no one &mut Section::Data(ref mut data_section) => { let (index, offset) = if let Some(ref entry) = data_section.entries().iter().last() { if let Opcode::I32Const(offst) = entry.offset().code()[0] { @@ -89,3 +90,83 @@ pub fn pack_instance(raw_module: Vec, ctor_module: &mut elements::Module) { } }; } + +#[cfg(test)] +mod test { + extern crate parity_wasm; + use parity_wasm::interpreter; + use parity_wasm::ModuleInstanceInterface; + use super::*; + use super::super::optimize; + use super::super::SET_TEMP_RET_SYMBOL; + + #[test] + fn call_returns_code() { + let mut module = builder::module() + .import() + .module("env") + .field("memory") + .external() + .memory(1 as u32, Some(1 as u32)) + .build() + .data() + .offset(elements::Opcode::I32Const(16)) + .value(vec![0u8]) + .build() + .function() + .signature().param().i32().build() + .body() + .with_opcodes(elements::Opcodes::new( + vec![ + elements::Opcode::End + ] + )) + .build() + .build() + .function() + .signature().param().i32().build() + .body() + .with_opcodes(elements::Opcodes::new( + vec![ + elements::Opcode::End + ] + )) + .build() + .build() + .export() + .field("_call") + .internal().func(0) + .build() + .export() + .field("_create") + .internal().func(1) + .build() + .build(); + let mut ctor_module = module.clone(); + optimize(&mut module, vec![CALL_SYMBOL, SET_TEMP_RET_SYMBOL]).expect("Optimizer to finish without errors"); + optimize(&mut ctor_module, vec![CREATE_SYMBOL, SET_TEMP_RET_SYMBOL]).expect("Optimizer to finish without errors"); + + let raw_module = parity_wasm::serialize(module).unwrap(); + let raw_module_len = raw_module.len(); + pack_instance(raw_module, &mut ctor_module); + + let program = parity_wasm::DefaultProgramInstance::new().expect("Program instance to load"); + let env_instance = program.module("env").expect("Wasm program to contain env module"); + let env_memory = env_instance.memory(interpreter::ItemIndex::Internal(0)).expect("Linear memory to exist in wasm runtime"); + + let execution_params = interpreter::ExecutionParams::default(); + let module = program.add_module("contract", ctor_module, None).expect("Failed to initialize module"); + + let _ = module.execute_export("_call", execution_params); + + let result_code = env_memory.get(20, raw_module_len).expect("Failed to get code"); + + let result_module: elements::Module = parity_wasm::deserialize_buffer(result_code).expect("Result module is not valid"); + + let program = parity_wasm::DefaultProgramInstance::new().expect("Program2 instance to load"); + let module = program.add_module("contract", result_module, None).expect("Failed to initialize module"); + let execution_params = interpreter::ExecutionParams::default(); + + let _ = module.execute_export("_call", execution_params); + } +} From 5f9460dbdf1b669835e90e76c25587145fa3d001 Mon Sep 17 00:00:00 2001 From: fro Date: Fri, 27 Oct 2017 19:25:57 +0300 Subject: [PATCH 5/7] write to pointer check --- src/pack.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/pack.rs b/src/pack.rs index 9f2bfbb..a2ade87 100644 --- a/src/pack.rs +++ b/src/pack.rs @@ -94,11 +94,15 @@ pub fn pack_instance(raw_module: Vec, ctor_module: &mut elements::Module) { #[cfg(test)] mod test { extern crate parity_wasm; + extern crate byteorder; + use parity_wasm::interpreter; + use parity_wasm::interpreter::RuntimeValue; use parity_wasm::ModuleInstanceInterface; use super::*; use super::super::optimize; use super::super::SET_TEMP_RET_SYMBOL; + use byteorder::{ByteOrder, LittleEndian}; #[test] fn call_returns_code() { @@ -142,24 +146,30 @@ mod test { .internal().func(1) .build() .build(); + let mut ctor_module = module.clone(); optimize(&mut module, vec![CALL_SYMBOL, SET_TEMP_RET_SYMBOL]).expect("Optimizer to finish without errors"); optimize(&mut ctor_module, vec![CREATE_SYMBOL, SET_TEMP_RET_SYMBOL]).expect("Optimizer to finish without errors"); let raw_module = parity_wasm::serialize(module).unwrap(); let raw_module_len = raw_module.len(); - pack_instance(raw_module, &mut ctor_module); + pack_instance(raw_module.clone(), &mut ctor_module); let program = parity_wasm::DefaultProgramInstance::new().expect("Program instance to load"); let env_instance = program.module("env").expect("Wasm program to contain env module"); let env_memory = env_instance.memory(interpreter::ItemIndex::Internal(0)).expect("Linear memory to exist in wasm runtime"); - let execution_params = interpreter::ExecutionParams::default(); + let mut execution_params = interpreter::ExecutionParams::default(); let module = program.add_module("contract", ctor_module, None).expect("Failed to initialize module"); - let _ = module.execute_export("_call", execution_params); + let _ = module.execute_export("_call", execution_params.add_argument(RuntimeValue::I32(1024))); - let result_code = env_memory.get(20, raw_module_len).expect("Failed to get code"); + let pointer = LittleEndian::read_u32(&env_memory.get(1024 + 8, 4).unwrap()); + let len = LittleEndian::read_u32(&env_memory.get(1024 + 12, 4).unwrap()); + + let result_code = env_memory.get(pointer, len as usize).expect("Failed to get code"); + + assert_eq!(raw_module, result_code); let result_module: elements::Module = parity_wasm::deserialize_buffer(result_code).expect("Result module is not valid"); From 092fb2034727f77e4f11555963afc223687e1494 Mon Sep 17 00:00:00 2001 From: fro Date: Fri, 27 Oct 2017 19:50:12 +0300 Subject: [PATCH 6/7] fix warnings --- src/pack.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/pack.rs b/src/pack.rs index a2ade87..22a24b6 100644 --- a/src/pack.rs +++ b/src/pack.rs @@ -1,5 +1,5 @@ -use parity_wasm::{serialize,elements, builder, deserialize_buffer}; -use self::elements::{ External, Section, ResizableLimits, Opcode, DataSegment, InitExpr, Internal }; +use parity_wasm::{elements}; +use self::elements::{ External, Section, Opcode, DataSegment, InitExpr, Internal }; use super::{CREATE_SYMBOL, CALL_SYMBOL}; @@ -96,6 +96,7 @@ mod test { extern crate parity_wasm; extern crate byteorder; + use parity_wasm::builder; use parity_wasm::interpreter; use parity_wasm::interpreter::RuntimeValue; use parity_wasm::ModuleInstanceInterface; @@ -152,17 +153,16 @@ mod test { optimize(&mut ctor_module, vec![CREATE_SYMBOL, SET_TEMP_RET_SYMBOL]).expect("Optimizer to finish without errors"); let raw_module = parity_wasm::serialize(module).unwrap(); - let raw_module_len = raw_module.len(); pack_instance(raw_module.clone(), &mut ctor_module); let program = parity_wasm::DefaultProgramInstance::new().expect("Program instance to load"); let env_instance = program.module("env").expect("Wasm program to contain env module"); let env_memory = env_instance.memory(interpreter::ItemIndex::Internal(0)).expect("Linear memory to exist in wasm runtime"); - let mut execution_params = interpreter::ExecutionParams::default(); + let execution_params = interpreter::ExecutionParams::default(); let module = program.add_module("contract", ctor_module, None).expect("Failed to initialize module"); - let _ = module.execute_export("_call", execution_params.add_argument(RuntimeValue::I32(1024))); + let _ = module.execute_export(CALL_SYMBOL, execution_params.add_argument(RuntimeValue::I32(1024))); let pointer = LittleEndian::read_u32(&env_memory.get(1024 + 8, 4).unwrap()); let len = LittleEndian::read_u32(&env_memory.get(1024 + 12, 4).unwrap()); @@ -177,6 +177,6 @@ mod test { let module = program.add_module("contract", result_module, None).expect("Failed to initialize module"); let execution_params = interpreter::ExecutionParams::default(); - let _ = module.execute_export("_call", execution_params); + let _ = module.execute_export(CALL_SYMBOL, execution_params); } } From d1f042cee8401dab72747d51e2c39b0ca1928f0f Mon Sep 17 00:00:00 2001 From: fro Date: Mon, 30 Oct 2017 18:35:20 +0300 Subject: [PATCH 7/7] grumbles fixed --- src/pack.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/pack.rs b/src/pack.rs index 22a24b6..4f8073d 100644 --- a/src/pack.rs +++ b/src/pack.rs @@ -52,7 +52,7 @@ pub fn pack_instance(raw_module: Vec, ctor_module: &mut elements::Module) { }; let code_data = DataSegment::new( index, - InitExpr::new(vec![Opcode::I32Const(offset),Opcode::End]), + InitExpr::new(vec![Opcode::I32Const(offset), Opcode::End]), raw_module.clone() ); data_section.entries_mut().push(code_data); @@ -76,14 +76,14 @@ pub fn pack_instance(raw_module: Vec, ctor_module: &mut elements::Module) { &mut Section::Code(ref mut code_section) => { let code = code_section.bodies_mut()[create_func_id].code_mut().elements_mut(); code.pop(); - code.extend([ + code.extend_from_slice(&[ Opcode::GetLocal(0), Opcode::I32Const(code_data_address), Opcode::I32Store(0, 8), Opcode::GetLocal(0), Opcode::I32Const(raw_module.len() as i32), Opcode::I32Store(0, 12), - Opcode::End].iter().cloned()); + Opcode::End]); }, _ => {;}, @@ -119,7 +119,7 @@ mod test { .value(vec![0u8]) .build() .function() - .signature().param().i32().build() + .signature().build() .body() .with_opcodes(elements::Opcodes::new( vec![ @@ -155,28 +155,28 @@ mod test { let raw_module = parity_wasm::serialize(module).unwrap(); pack_instance(raw_module.clone(), &mut ctor_module); - let program = parity_wasm::DefaultProgramInstance::new().expect("Program instance to load"); + let program = parity_wasm::DefaultProgramInstance::new().expect("Program instance failed to load"); let env_instance = program.module("env").expect("Wasm program to contain env module"); let env_memory = env_instance.memory(interpreter::ItemIndex::Internal(0)).expect("Linear memory to exist in wasm runtime"); let execution_params = interpreter::ExecutionParams::default(); - let module = program.add_module("contract", ctor_module, None).expect("Failed to initialize module"); + let constructor_module = program.add_module("contract", ctor_module, None).expect("Failed to initialize module"); - let _ = module.execute_export(CALL_SYMBOL, execution_params.add_argument(RuntimeValue::I32(1024))); + let _ = constructor_module.execute_export(CALL_SYMBOL, execution_params.add_argument(RuntimeValue::I32(1024))); let pointer = LittleEndian::read_u32(&env_memory.get(1024 + 8, 4).unwrap()); let len = LittleEndian::read_u32(&env_memory.get(1024 + 12, 4).unwrap()); - let result_code = env_memory.get(pointer, len as usize).expect("Failed to get code"); + let contract_code = env_memory.get(pointer, len as usize).expect("Failed to get code"); - assert_eq!(raw_module, result_code); + assert_eq!(raw_module, contract_code); - let result_module: elements::Module = parity_wasm::deserialize_buffer(result_code).expect("Result module is not valid"); + let contract_module: elements::Module = parity_wasm::deserialize_buffer(contract_code).expect("Constructed contract module is not valid"); - let program = parity_wasm::DefaultProgramInstance::new().expect("Program2 instance to load"); - let module = program.add_module("contract", result_module, None).expect("Failed to initialize module"); + let program = parity_wasm::DefaultProgramInstance::new().expect("Program2 instance failed to load"); + let contract_module_instance = program.add_module("contract", contract_module, None).expect("Failed to initialize constructed contract module"); let execution_params = interpreter::ExecutionParams::default(); - let _ = module.execute_export(CALL_SYMBOL, execution_params); + contract_module_instance.execute_export(CALL_SYMBOL, execution_params).expect("Constructed contract failed to execute"); } }