From b369ce903e866b6d93c48b412dfa68419a7b33de Mon Sep 17 00:00:00 2001 From: fro Date: Thu, 26 Oct 2017 15:49:55 +0300 Subject: [PATCH] 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()); },