diff --git a/.circleci/config.yml b/.circleci/config.yml index 756e0e6f..bcf17f7e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -54,12 +54,12 @@ jobs: cd examples/ipfs_node/wasm/ipfs_node cargo fmt --all -- --check --color always cargo wasi build - cargo clippy -v + cargo clippy -v --target wasm32-wasi cd ../ipfs_rpc cargo fmt --all -- --check --color always cargo wasi build - cargo clippy -v + cargo clippy -v --target wasm32-wasi # cd ../../../../tools/wit_embedder # cargo fmt --all -- --check --color always diff --git a/crates/wit-generator/src/instructions_generator/foreign_mod_instructions.rs b/crates/wit-generator/src/instructions_generator/foreign_mod_instructions.rs index c532c3a3..010f5aee 100644 --- a/crates/wit-generator/src/instructions_generator/foreign_mod_instructions.rs +++ b/crates/wit-generator/src/instructions_generator/foreign_mod_instructions.rs @@ -26,8 +26,15 @@ use fluence_sdk_wit::ParsedType; use wasmer_wit::interpreter::Instruction; use crate::instructions_generator::utils::wtype_to_itype; +const HOST_NAMESPACE_NAME: &str = "host"; + impl WITGenerator for AstExternModItem { fn generate_wit<'a>(&'a self, interfaces: &mut Interfaces<'a>) { + // host imports should be left as is + if self.namespace == HOST_NAMESPACE_NAME { + return; + } + for import in &self.imports { generate_wit_for_import(import, &self.namespace, interfaces); } diff --git a/crates/wit-generator/src/instructions_generator/utils.rs b/crates/wit-generator/src/instructions_generator/utils.rs index d728cae6..e1583463 100644 --- a/crates/wit-generator/src/instructions_generator/utils.rs +++ b/crates/wit-generator/src/instructions_generator/utils.rs @@ -32,7 +32,7 @@ pub(crate) fn ptype_to_itype(pty: &ParsedType) -> IType { ParsedType::F64 => IType::F64, ParsedType::Boolean => IType::I32, ParsedType::Utf8String => IType::String, - ParsedType::ByteVector => IType::String, + ParsedType::ByteVector => IType::ByteArray, ParsedType::Record(_) => unimplemented!(), } } diff --git a/engine/src/engine.rs b/engine/src/engine.rs index e0f5d7a2..a41df11e 100644 --- a/engine/src/engine.rs +++ b/engine/src/engine.rs @@ -47,29 +47,44 @@ impl FCE { module_name: MN, func_name: FN, argument: &[IValue], - ) -> Result, FCEError> { - match self.modules.get_mut(module_name.as_ref()) { + ) -> Result> { + self.call_(module_name.as_ref(), func_name.as_ref(), argument) + } + + pub fn call_( + &mut self, + module_name: &str, + func_name: &str, + argument: &[IValue], + ) -> Result> { + match self.modules.get_mut(module_name) { // TODO: refactor errors Some(module) => module.call(func_name.as_ref(), argument), - None => Err(FCEError::NoSuchModule(module_name.as_ref().to_string())), + None => Err(FCEError::NoSuchModule(module_name.to_string())), } } /// Load a new module inside FCE. - pub fn load_module( + pub fn load_module>( &mut self, module_name: S, wasm_bytes: &[u8], config: FCEModuleConfig, - ) -> Result<(), FCEError> - where - S: Into, - { + ) -> Result<()> { + self.load_module_(module_name.into(), wasm_bytes, config) + } + + pub fn load_module_( + &mut self, + module_name: String, + wasm_bytes: &[u8], + config: FCEModuleConfig, + ) -> Result<()> { let _prepared_wasm_bytes = crate::misc::prepare_module(wasm_bytes, config.mem_pages_count)?; let module = FCEModule::new(&wasm_bytes, config, &self.modules)?; - match self.modules.entry(module_name.into()) { + match self.modules.entry(module_name) { Entry::Vacant(entry) => { entry.insert(module); Ok(()) @@ -79,10 +94,14 @@ impl FCE { } /// Unload previously loaded module. - pub fn unload_module>(&mut self, module_name: S) -> Result<(), FCEError> { - match self.modules.remove(module_name.as_ref()) { + pub fn unload_module>(&mut self, module_name: S) -> Result<()> { + self.unload_module_(module_name.as_ref()) + } + + pub fn unload_module_(&mut self, module_name: &str) -> Result<()> { + match self.modules.remove(module_name) { Some(_) => Ok(()), - None => Err(FCEError::NoSuchModule(module_name.as_ref().to_string())), + None => Err(FCEError::NoSuchModule(module_name.to_string())), } } @@ -100,7 +119,7 @@ impl FCE { pub fn module_interface>( &self, module_name: S, - ) -> Result>, FCEError> { + ) -> Result>> { match self.modules.get(module_name.as_ref()) { Some(module) => Ok(Self::get_module_function_signatures(module)), None => Err(FCEError::NoSuchModule(module_name.as_ref().to_string())), diff --git a/engine/src/lib.rs b/engine/src/lib.rs index b65afd77..b0dd5ec4 100644 --- a/engine/src/lib.rs +++ b/engine/src/lib.rs @@ -39,4 +39,7 @@ pub use engine::FCEFunctionSignature; pub use errors::FCEError; pub use module::IValue; pub use module::IType; -pub use module::{to_interface_value, from_interface_values}; +pub use module::from_interface_values; +pub use module::to_interface_value; + +pub(crate) type Result = std::result::Result; diff --git a/engine/src/misc/prepare.rs b/engine/src/misc/prepare.rs index a60b51b2..357860f8 100644 --- a/engine/src/misc/prepare.rs +++ b/engine/src/misc/prepare.rs @@ -18,7 +18,7 @@ // https://github.com/paritytech/substrate/blob/master/srml/contracts/src/wasm/prepare.rs // https://github.com/nearprotocol/nearcore/blob/master/runtime/near-vm-runner/src/prepare.rs -use crate::FCEError; +use crate::Result; use parity_wasm::{ builder, elements, @@ -30,7 +30,7 @@ struct ModuleBootstrapper { } impl<'a> ModuleBootstrapper { - fn init(module_code: &[u8]) -> Result { + fn init(module_code: &[u8]) -> Result { let module = elements::deserialize_buffer(module_code)?; Ok(Self { module }) @@ -66,14 +66,14 @@ impl<'a> ModuleBootstrapper { } } - fn into_wasm(self) -> Result, FCEError> { + fn into_wasm(self) -> Result> { elements::serialize(self.module).map_err(Into::into) } } /// Prepares a Wasm module: /// - set memory page count -pub(crate) fn prepare_module(module: &[u8], mem_pages_count: u32) -> Result, FCEError> { +pub(crate) fn prepare_module(module: &[u8], mem_pages_count: u32) -> Result> { ModuleBootstrapper::init(module)? .set_mem_pages_count(mem_pages_count) .into_wasm() diff --git a/engine/src/module/exports.rs b/engine/src/module/exports.rs index 322b1f86..b0d34e85 100644 --- a/engine/src/module/exports.rs +++ b/engine/src/module/exports.rs @@ -14,7 +14,8 @@ * limitations under the License. */ -use super::{IValue, IType}; +use super::IValue; +use super::IType; use wasmer_wit::interpreter::wasm; // In current implementation export simply does nothing, because there is no more diff --git a/engine/src/module/fce_module.rs b/engine/src/module/fce_module.rs index 1ce79d3a..eb5f3c2c 100644 --- a/engine/src/module/fce_module.rs +++ b/engine/src/module/fce_module.rs @@ -16,13 +16,15 @@ use super::wit_prelude::*; use super::{IType, IValue, WValue}; +use crate::Result; use crate::FCEModuleConfig; use fce_wit_interfaces::FCEWITInterfaces; -use wasmer_wit::interpreter::Interpreter; -use wasmer_runtime::{compile, ImportObject}; use wasmer_core::Instance as WasmerInstance; use wasmer_core::import::Namespace; +use wasmer_runtime::compile; +use wasmer_runtime::ImportObject; +use wasmer_wit::interpreter::Interpreter; use wit_parser::extract_wit; use std::collections::HashMap; @@ -47,7 +49,7 @@ pub(super) struct Callable { } impl Callable { - pub fn call(&mut self, args: &[IValue]) -> Result, FCEError> { + pub fn call(&mut self, args: &[IValue]) -> Result> { use wasmer_wit::interpreter::stack::Stackable; let result = self @@ -86,7 +88,7 @@ impl FCEModule { wasm_bytes: &[u8], fce_module_config: FCEModuleConfig, modules: &HashMap, - ) -> Result { + ) -> Result { let wasmer_module = compile(&wasm_bytes)?; let wit = extract_wit(&wasmer_module)?; let fce_wit = FCEWITInterfaces::new(wit); @@ -130,11 +132,7 @@ impl FCEModule { }) } - pub(crate) fn call( - &mut self, - function_name: &str, - args: &[IValue], - ) -> Result, FCEError> { + pub(crate) fn call(&mut self, function_name: &str, args: &[IValue]) -> Result> { match self.exports_funcs.get_mut(function_name) { Some(func) => Arc::make_mut(func).call(args), None => Err(FCEError::NoSuchFunction(format!( @@ -157,7 +155,7 @@ impl FCEModule { } // TODO: change the cloning Callable behaviour after changes of Wasmer API - pub(super) fn get_callable(&self, function_name: &str) -> Result, FCEError> { + pub(super) fn get_callable(&self, function_name: &str) -> Result> { match self.exports_funcs.get(function_name) { Some(func) => Ok(func.clone()), None => Err(FCEError::NoSuchFunction(format!( @@ -170,7 +168,7 @@ impl FCEModule { fn instantiate_wit_exports( wit_instance: Arc, wit: &FCEWITInterfaces<'_>, - ) -> Result>, FCEError> { + ) -> Result>> { use fce_wit_interfaces::WITAstType; wit.implementations() @@ -218,14 +216,14 @@ impl FCEModule { ))), } }) - .collect::>, FCEError>>() + .collect::>>>() } // this function deals only with import functions that have an adaptor implementation fn adjust_wit_imports( wit: &FCEWITInterfaces<'_>, wit_instance: Arc>, - ) -> Result { + ) -> Result { use fce_wit_interfaces::WITAstType; use wasmer_core::typed_func::DynamicFunc; use wasmer_core::vm::Ctx; @@ -327,7 +325,7 @@ impl FCEModule { ))), } }) - .collect::, FCEError>>()?; + .collect::>>()?; let mut import_object = ImportObject::new(); diff --git a/engine/src/module/mod.rs b/engine/src/module/mod.rs index 00505753..5c21504b 100644 --- a/engine/src/module/mod.rs +++ b/engine/src/module/mod.rs @@ -21,11 +21,12 @@ mod wit_instance; mod type_converters; mod fce_module; -pub(crate) use fce_module::FCEModule; - pub use wasmer_wit::types::InterfaceType as IType; pub use wasmer_wit::values::InterfaceValue as IValue; -pub use wasmer_wit::values::{to_interface_value, from_interface_values}; +pub use wasmer_wit::values::from_interface_values; +pub use wasmer_wit::values::to_interface_value; + +pub(crate) use fce_module::FCEModule; pub(self) use wasmer_core::types::Type as WType; pub(self) use wasmer_core::types::Value as WValue; diff --git a/engine/src/module/wit_function.rs b/engine/src/module/wit_function.rs index 27453ed5..ed80e83f 100644 --- a/engine/src/module/wit_function.rs +++ b/engine/src/module/wit_function.rs @@ -14,10 +14,10 @@ * limitations under the License. */ -use super::wit_prelude::FCEError; use super::fce_module::FCEModule; use super::{IType, IValue, WValue}; use super::fce_module::Callable; +use crate::Result; use wasmer_wit::interpreter::wasm; use wasmer_core::instance::DynFunc; @@ -45,7 +45,7 @@ pub(super) struct WITFunction { impl WITFunction { /// Creates functions from a "usual" (not WIT) module export. - pub(super) fn from_export(dyn_func: DynFunc<'static>) -> Result { + pub(super) fn from_export(dyn_func: DynFunc<'static>) -> Result { use super::type_converters::wtype_to_itype; let signature = dyn_func.signature(); @@ -70,10 +70,7 @@ impl WITFunction { } /// Creates function from a module import. - pub(super) fn from_import( - wit_module: &FCEModule, - function_name: &str, - ) -> Result { + pub(super) fn from_import(wit_module: &FCEModule, function_name: &str) -> Result { let callable = wit_module.get_callable(function_name)?; let inner = WITFunctionInner::Import { callable }; @@ -111,7 +108,7 @@ impl wasm::structures::LocalImport for WITFunction { } } - fn call(&self, arguments: &[IValue]) -> Result, ()> { + fn call(&self, arguments: &[IValue]) -> std::result::Result, ()> { use super::type_converters::{ival_to_wval, wval_to_ival}; match &self.inner { diff --git a/engine/src/module/wit_instance.rs b/engine/src/module/wit_instance.rs index 1a5f3257..372e2e4a 100644 --- a/engine/src/module/wit_instance.rs +++ b/engine/src/module/wit_instance.rs @@ -16,6 +16,7 @@ use super::wit_prelude::*; use super::fce_module::FCEModule; +use crate::Result; use fce_wit_interfaces::FCEWITInterfaces; use fce_wit_interfaces::WITAstType; @@ -37,7 +38,7 @@ impl WITInstance { wasmer_instance: &WasmerInstance, wit: &FCEWITInterfaces<'_>, modules: &HashMap, - ) -> Result { + ) -> Result { let mut exports = Self::extract_raw_exports(&wasmer_instance, wit)?; let imports = Self::extract_imports(modules, wit, exports.len())?; let memories = Self::extract_memories(&wasmer_instance); @@ -51,7 +52,7 @@ impl WITInstance { fn extract_raw_exports( wasmer_instance: &WasmerInstance, wit: &FCEWITInterfaces<'_>, - ) -> Result, FCEError> { + ) -> Result> { use wasmer_core::DynFunc; let module_exports = &wasmer_instance.exports; @@ -76,7 +77,7 @@ impl WITInstance { modules: &HashMap, wit: &FCEWITInterfaces<'_>, start_index: usize, - ) -> Result, FCEError> { + ) -> Result> { wit.imports() .filter(|import| // filter out imports that have implementations @@ -89,7 +90,7 @@ impl WITInstance { } None => Err(FCEError::NoSuchModule(import.namespace.to_string())), }) - .collect::, _>>() + .collect::>>() } fn extract_memories(wasmer_instance: &WasmerInstance) -> Vec { diff --git a/examples/ipfs_node/wasm/artifacts/ipfs_rpc.wasm b/examples/ipfs_node/wasm/artifacts/ipfs_rpc.wasm index 18e57ba3..5d85eaa2 100755 Binary files a/examples/ipfs_node/wasm/artifacts/ipfs_rpc.wasm and b/examples/ipfs_node/wasm/artifacts/ipfs_rpc.wasm differ diff --git a/examples/ipfs_node/wasm/artifacts/wasm_modules/ipfs_node.wasm b/examples/ipfs_node/wasm/artifacts/wasm_modules/ipfs_node.wasm index 63ee598e..8821a79b 100644 Binary files a/examples/ipfs_node/wasm/artifacts/wasm_modules/ipfs_node.wasm and b/examples/ipfs_node/wasm/artifacts/wasm_modules/ipfs_node.wasm differ diff --git a/examples/ipfs_node/wasm/ipfs_node/src/main.rs b/examples/ipfs_node/wasm/ipfs_node/src/main.rs index b4bc71bc..ad0c1a60 100644 --- a/examples/ipfs_node/wasm/ipfs_node/src/main.rs +++ b/examples/ipfs_node/wasm/ipfs_node/src/main.rs @@ -39,7 +39,7 @@ pub fn put(file_path: String) -> String { let timeout = std::env::var(TIMEOUT_ENV_NAME).unwrap_or_else(|_| "1s".to_string()); let cmd = format!("add --timeout {} -Q {}", timeout, file_path); - call_ipfs(cmd) + ipfs(cmd) } /// Get file by provided hash from IPFS, saves it to a temporary file and returns a path to it. @@ -55,7 +55,7 @@ pub fn get(hash: String) -> String { timeout, result_file_path, hash ); - call_ipfs(cmd); + ipfs(cmd); RESULT_FILE_PATH.to_string() } @@ -71,22 +71,9 @@ pub fn get_address() -> String { } } -fn call_ipfs(cmd: String) -> String { - unsafe { - // TODO: better error handling - match ipfs(cmd.as_ptr() as _, cmd.len() as _) { - 0 => String::from_raw_parts( - fluence::internal::get_result_ptr() as _, - fluence::internal::get_result_size(), - fluence::internal::get_result_size(), - ), - _ => "host ipfs call failed".to_string(), - } - } -} - +#[fce] #[link(wasm_import_module = "host")] extern "C" { - /// Put a file to ipfs, returns ipfs hash of the file. - fn ipfs(ptr: i32, size: i32) -> i32; + /// Execute provided cmd as a parameters of ipfs cli, return result. + pub fn ipfs(cmd: String) -> String; } diff --git a/fluence-faas/src/faas.rs b/fluence-faas/src/faas.rs index a3d6de08..607d598f 100644 --- a/fluence-faas/src/faas.rs +++ b/fluence-faas/src/faas.rs @@ -106,7 +106,16 @@ impl FluenceFaaS { } /// Executes provided Wasm code in the internal environment (with access to module exports). - pub fn call_code( + pub fn call_code>( + &mut self, + wasm: &[u8], + func_name: S, + args: &[IValue], + ) -> Result> { + self.call_code_(wasm, func_name.as_ref(), args) + } + + pub fn call_code_( &mut self, wasm: &[u8], func_name: &str, @@ -125,10 +134,10 @@ impl FluenceFaaS { } /// Call a specified function of loaded on a startup module by its name. - pub fn call_module( + pub fn call_module, FN: AsRef>( &mut self, - module_name: &str, - func_name: &str, + module_name: MN, + func_name: FN, args: &[IValue], ) -> Result> { self.fce diff --git a/fluence-faas/src/misc/imports.rs b/fluence-faas/src/misc/imports.rs index 2e0c94bd..c5813cca 100644 --- a/fluence-faas/src/misc/imports.rs +++ b/fluence-faas/src/misc/imports.rs @@ -93,7 +93,7 @@ where }; DynamicFunc::new( - std::sync::Arc::new(FuncSig::new(vec![Type::I32, Type::I32], vec![Type::I32])), + std::sync::Arc::new(FuncSig::new(vec![Type::I32, Type::I32], vec![])), func, ) } diff --git a/fluence-faas/src/misc/utils.rs b/fluence-faas/src/misc/utils.rs index bf03c36f..dc9680f3 100644 --- a/fluence-faas/src/misc/utils.rs +++ b/fluence-faas/src/misc/utils.rs @@ -14,20 +14,19 @@ * limitations under the License. */ -use wasmer_core::vm::Ctx; -use crate::FaaSError; use super::config::ModuleConfig; use fce::FCEModuleConfig; +use wasmer_core::backend::SigRegistry; +use wasmer_core::module::ExportIndex; +use wasmer_core::vm::Ctx; use wasmer_core::import::ImportObject; -use wasmer_runtime::func; use wasmer_core::typed_func::WasmTypeList; +use wasmer_runtime::func; use wasmer_runtime::Func; use wasmer_runtime::error::ResolveError; -use wasmer_core::backend::SigRegistry; use wasmer_runtime::types::LocalOrImport; -use wasmer_core::module::ExportIndex; use std::path::PathBuf; @@ -103,7 +102,7 @@ where } /// Make FCE config based on parsed raw config. -pub(crate) fn make_fce_config(config: Option) -> Result { +pub(crate) fn make_fce_config(config: Option) -> crate::Result { use super::imports::create_host_import_func; use super::imports::log_utf8_string; use wasmer_core::import::Namespace; diff --git a/tools/cli/src/args.rs b/tools/cli/src/args.rs index 36cca3aa..c8eaa5f6 100644 --- a/tools/cli/src/args.rs +++ b/tools/cli/src/args.rs @@ -25,15 +25,15 @@ pub const IN_WASM_PATH: &str = "in-wasm-path"; pub fn build<'a, 'b>() -> App<'a, 'b> { SubCommand::with_name("build") .about("build provided Rust project to Wasm") - .args(&[Arg::with_name(IN_WASM_PATH) - .takes_value(true) - .short("i") - .help("path to a Cargo.toml file")]) + .setting(clap::AppSettings::TrailingVarArg) + .setting(clap::AppSettings::AllowLeadingHyphen) + .arg(Arg::from_usage("[optional]... 'cargo build arguments'").multiple(true)) } pub fn show_wit<'a, 'b>() -> App<'a, 'b> { SubCommand::with_name("show") .about("show WIT in provided Wasm file") + .setting(clap::AppSettings::ArgRequiredElseHelp) .args(&[Arg::with_name(IN_WASM_PATH) .required(true) .takes_value(true) diff --git a/tools/cli/src/build.rs b/tools/cli/src/build.rs index 7300d4ba..9e1d4ee9 100644 --- a/tools/cli/src/build.rs +++ b/tools/cli/src/build.rs @@ -17,7 +17,6 @@ use crate::Result; use crate::errors::CLIError; -use std::path::PathBuf; use std::process::Command; #[derive(serde::Deserialize)] @@ -29,15 +28,13 @@ enum DiagnosticMessage { RunWithArgs, } -pub(crate) fn build(manifest_path: Option) -> Result<()> { +pub(crate) fn build(trailing_args: Vec<&str>) -> Result<()> { use std::io::Read; let mut cargo = Command::new("cargo"); cargo.arg("build").arg("--target").arg("wasm32-wasi"); cargo.arg("--message-format").arg("json-render-diagnostics"); - if let Some(wasm_path) = manifest_path { - cargo.arg("--manifest-path").arg(wasm_path); - } + cargo.args(trailing_args); let mut process = cargo.stdout(std::process::Stdio::piped()).spawn()?; diff --git a/tools/cli/src/main.rs b/tools/cli/src/main.rs index e77dc56b..1f4ec738 100644 --- a/tools/cli/src/main.rs +++ b/tools/cli/src/main.rs @@ -29,27 +29,22 @@ mod args; mod build; mod errors; -use clap::App; -use clap::AppSettings; - pub(crate) type Result = std::result::Result; pub fn main() -> Result<()> { - let app = App::new("CLI tool for embedding WIT to provided Wasm file") + let app = clap::App::new("CLI tool for embedding WIT to provided Wasm file") .version(args::VERSION) .author(args::AUTHORS) .about(args::DESCRIPTION) - .setting(AppSettings::ArgRequiredElseHelp) .subcommand(args::build()) .subcommand(args::show_wit()); + let arg_matches = app.get_matches(); - match app.get_matches().subcommand() { - ("build", Some(arg)) => { - let manifest_path = arg - .value_of(args::IN_WASM_PATH) - .map(std::path::PathBuf::from); + match arg_matches.subcommand() { + ("build", Some(args)) => { + let trailing_args: Vec<&str> = args.values_of("optional").unwrap_or_default().collect(); - crate::build::build(manifest_path) + crate::build::build(trailing_args) } ("show", Some(arg)) => { let wasm_path = arg.value_of(args::IN_WASM_PATH).unwrap();