From 4a70824a88f53f59efcd3475c7f38fd774981f33 Mon Sep 17 00:00:00 2001 From: fro Date: Fri, 27 Oct 2017 18:32:33 +0300 Subject: [PATCH] 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); + } +}