Move to the new sdk (#8)

This commit is contained in:
vms 2020-07-11 23:04:55 +03:00 committed by GitHub
parent 37ce9dafb3
commit e9ef12b6b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 311 additions and 631 deletions

3
.gitignore vendored
View File

@ -2,6 +2,9 @@ target/
**/*.rs.bk
.idea
# MacOS misc file
*.DS_Store
# Wasm files
*.wasm
*.wat

73
Cargo.lock generated
View File

@ -11,9 +11,9 @@ dependencies = [
[[package]]
name = "adler"
version = "0.2.2"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccc9a9dd069569f212bc4330af9f17c4afb5e8ce185e83dbb14f1349dda18b10"
checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
[[package]]
name = "ansi_term"
@ -91,9 +91,9 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "blake3"
version = "0.3.4"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "423897d97e11b810c9da22458400b28ec866991c711409073662eb34dc44bfff"
checksum = "59f88a20f7dc23e3896bcbd85add056543c87215de721468b90e0c85d5a9f365"
dependencies = [
"arrayref",
"arrayvec",
@ -101,7 +101,7 @@ dependencies = [
"cfg-if",
"constant_time_eq",
"crypto-mac",
"digest",
"digest 0.9.0",
]
[[package]]
@ -268,11 +268,11 @@ dependencies = [
[[package]]
name = "crypto-mac"
version = "0.7.0"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5"
checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab"
dependencies = [
"generic-array",
"generic-array 0.14.2",
"subtle",
]
@ -292,7 +292,16 @@ version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
dependencies = [
"generic-array",
"generic-array 0.12.3",
]
[[package]]
name = "digest"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
dependencies = [
"generic-array 0.14.2",
]
[[package]]
@ -403,7 +412,7 @@ dependencies = [
[[package]]
name = "fluence"
version = "0.2.0"
source = "git+https://github.com/fluencelabs/rust-sdk#cc2b8249fc43d9667a4ec82a2e767f27df100c55"
source = "git+https://github.com/fluencelabs/rust-sdk#9775ca6144b67b96aa70ad8020336cd264063316"
dependencies = [
"fluence-sdk-macro",
"fluence-sdk-main",
@ -428,7 +437,7 @@ dependencies = [
[[package]]
name = "fluence-sdk-macro"
version = "0.2.0"
source = "git+https://github.com/fluencelabs/rust-sdk#cc2b8249fc43d9667a4ec82a2e767f27df100c55"
source = "git+https://github.com/fluencelabs/rust-sdk#9775ca6144b67b96aa70ad8020336cd264063316"
dependencies = [
"fluence-sdk-wit",
]
@ -436,7 +445,7 @@ dependencies = [
[[package]]
name = "fluence-sdk-main"
version = "0.2.0"
source = "git+https://github.com/fluencelabs/rust-sdk#cc2b8249fc43d9667a4ec82a2e767f27df100c55"
source = "git+https://github.com/fluencelabs/rust-sdk#9775ca6144b67b96aa70ad8020336cd264063316"
dependencies = [
"log",
]
@ -444,7 +453,7 @@ dependencies = [
[[package]]
name = "fluence-sdk-wit"
version = "0.2.0"
source = "git+https://github.com/fluencelabs/rust-sdk#cc2b8249fc43d9667a4ec82a2e767f27df100c55"
source = "git+https://github.com/fluencelabs/rust-sdk#9775ca6144b67b96aa70ad8020336cd264063316"
dependencies = [
"proc-macro2",
"quote",
@ -479,6 +488,16 @@ dependencies = [
"typenum",
]
[[package]]
name = "generic-array"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac746a5f3bbfdadd6106868134545e684693d54d9d44f6e9588a7d54af0bf980"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "getrandom"
version = "0.1.14"
@ -521,7 +540,8 @@ checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724"
name = "greeting"
version = "0.1.0"
dependencies = [
"fluence",
"anyhow",
"fluence-faas",
]
[[package]]
@ -898,9 +918,9 @@ dependencies = [
[[package]]
name = "redox_syscall"
version = "0.1.56"
version = "0.1.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
[[package]]
name = "rustc-demangle"
@ -1014,9 +1034,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "subtle"
version = "1.0.0"
version = "2.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee"
checksum = "502d53007c02d7605a05df1c1a73ee436952781653da5d0bf57ad608f66932c1"
[[package]]
name = "syn"
@ -1202,13 +1222,28 @@ version = "0.9.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
[[package]]
name = "wasm_greeting"
version = "0.1.0"
dependencies = [
"fluence",
]
[[package]]
name = "wasm_ipfs_node"
version = "0.1.0"
dependencies = [
"fluence",
"log",
]
[[package]]
name = "wasm_ipfs_rpc"
version = "0.1.0"
dependencies = [
"fluence",
"log",
]
[[package]]
name = "wasmer-clif-backend"
@ -1292,7 +1327,7 @@ dependencies = [
"bincode",
"blake3",
"cc",
"digest",
"digest 0.8.1",
"errno",
"hex",
"indexmap",

View File

@ -7,7 +7,8 @@ members = [
"examples/ipfs_node",
"examples/ipfs_node/wasm/ipfs_node",
"examples/ipfs_node/wasm/ipfs_rpc",
"examples/simple_greeting",
"examples/greeting",
"examples/greeting/wasm/",
"fluence-faas",
"tools/cli",
]

View File

@ -182,13 +182,13 @@ impl<'a> FCEWITInterfaces<'a> {
&self,
core_function_type: CoreFunctionType,
) -> Option<&Vec<AdapterFunctionType>> {
self.adapter_type_to_core.get_vec(&core_function_type)
self.core_type_to_adapter.get_vec(&core_function_type)
}
pub fn core_types_by_adapter_type(
&self,
adapter_function_type: AdapterFunctionType,
) -> Option<&Vec<CoreFunctionType>> {
self.core_type_to_adapter.get_vec(&adapter_function_type)
self.adapter_type_to_core.get_vec(&adapter_function_type)
}
}

View File

@ -61,14 +61,14 @@ impl WITGenerator for AstFunctionItem {
.signature
.input_types
.iter()
.rev()
.enumerate()
.map(|(id, input_type)| input_type.generate_instructions_for_input_type(id as _))
.flatten()
.collect();
let export_function_index = (interfaces.exports.len() - 1) as u32;
instructions.push(Instruction::CallCore {
function_index: export_idx,
function_index: export_function_index,
});
instructions.extend(match &self.signature.output_type {
@ -114,10 +114,10 @@ impl FnInstructionGenerator for ParsedType {
],
ParsedType::ByteVector => vec![
Instruction::ArgumentGet { index },
Instruction::StringSize,
Instruction::ByteArraySize,
Instruction::CallCore { function_index: ALLOCATE_FUNC.id },
Instruction::ArgumentGet { index },
Instruction::StringLowerMemory,
Instruction::ByteArrayLowerMemory,
],
_ => unimplemented!(),
}

View File

@ -24,6 +24,7 @@ use fluence_sdk_wit::AstExternModItem;
use fluence_sdk_wit::AstExternFnItem;
use fluence_sdk_wit::ParsedType;
use wasmer_wit::interpreter::Instruction;
use crate::instructions_generator::utils::wtype_to_itype;
impl WITGenerator for AstExternModItem {
fn generate_wit<'a>(&'a self, interfaces: &mut Interfaces<'a>) {
@ -52,35 +53,71 @@ fn generate_wit_for_import<'a>(
Some(ref output_type) => vec![ptype_to_itype(output_type)],
None => vec![],
};
interfaces.types.push(Type::Function {
inputs: inputs.clone(),
outputs: outputs.clone(),
});
// TODO: replace with Wasm types
interfaces.types.push(Type::Function { inputs, outputs });
let raw_inputs = import
.signature
.input_types
.iter()
.map(to_raw_input_types)
.flatten()
.map(|wt| wtype_to_itype(&wt))
.collect::<Vec<_>>();
let raw_outputs = match import.signature.output_type {
Some(ref output_type) => to_raw_output_type(output_type)
.iter()
.map(wtype_to_itype)
.collect(),
None => vec![],
};
interfaces.types.push(Type::Function {
inputs: raw_inputs.clone(),
outputs: raw_outputs.clone(),
});
interfaces.types.push(Type::Function {
inputs: raw_inputs,
outputs: raw_outputs,
});
let adapter_idx = (interfaces.types.len() - 2) as u32;
let import_idx = (interfaces.types.len() - 1) as u32;
let import_idx = (interfaces.types.len() - 3) as u32;
let raw_import_idx = (interfaces.types.len() - 1) as u32;
let link_name = match &import.link_name {
Some(link_name) => link_name,
None => &import.signature.name,
};
interfaces.imports.push(wasmer_wit::ast::Import {
namespace: &namespace,
name: &import.signature.name,
name: link_name,
function_type: import_idx,
});
interfaces.imports.push(wasmer_wit::ast::Import {
namespace: &namespace,
name: link_name,
function_type: raw_import_idx,
});
let mut instructions: Vec<Instruction> = import
.signature
.input_types
.iter()
.rev()
.enumerate()
.map(|(id, input_type)| input_type.generate_instructions_for_input_type(id as _))
.flatten()
.collect();
// TODO: refactor
let import_function_index =
(interfaces.exports.len() + interfaces.imports.len() / 2 - 1) as u32;
instructions.push(Instruction::CallCore {
function_index: import_idx,
function_index: import_function_index,
});
instructions.extend(match &import.signature.output_type {
@ -95,7 +132,7 @@ fn generate_wit_for_import<'a>(
interfaces.adapters.push(adapter);
let implementation = wasmer_wit::ast::Implementation {
core_function_type: import_idx,
core_function_type: raw_import_idx,
adapter_function_type: adapter_idx,
};
interfaces.implementations.push(implementation);
@ -163,3 +200,39 @@ impl ForeignModInstructionGenerator for ParsedType {
}
}
}
use fluence_sdk_wit::WasmType;
pub fn to_raw_input_types(ty: &ParsedType) -> Vec<WasmType> {
match ty {
ParsedType::Boolean
| ParsedType::I8
| ParsedType::I16
| ParsedType::I32
| ParsedType::U8
| ParsedType::U16
| ParsedType::U32 => vec![WasmType::I32],
ParsedType::I64 | ParsedType::U64 => vec![WasmType::I64],
ParsedType::F32 => vec![WasmType::F32],
ParsedType::F64 => vec![WasmType::F64],
ParsedType::Utf8String | ParsedType::ByteVector | ParsedType::Record(_) => {
vec![WasmType::I32, WasmType::I32]
}
}
}
pub fn to_raw_output_type(ty: &ParsedType) -> Vec<WasmType> {
match ty {
ParsedType::Boolean
| ParsedType::I8
| ParsedType::I16
| ParsedType::I32
| ParsedType::U8
| ParsedType::U16
| ParsedType::U32 => vec![WasmType::I32],
ParsedType::I64 | ParsedType::U64 => vec![WasmType::I64],
ParsedType::F32 => vec![WasmType::F32],
ParsedType::F64 => vec![WasmType::F64],
ParsedType::Utf8String | ParsedType::ByteVector | ParsedType::Record(_) => vec![],
}
}

View File

@ -16,6 +16,7 @@
use super::IType;
use fluence_sdk_wit::ParsedType;
use fluence_sdk_wit::WasmType;
pub(crate) fn ptype_to_itype(pty: &ParsedType) -> IType {
match pty {
@ -35,3 +36,12 @@ pub(crate) fn ptype_to_itype(pty: &ParsedType) -> IType {
ParsedType::Record(_) => unimplemented!(),
}
}
pub(crate) fn wtype_to_itype(pty: &WasmType) -> IType {
match pty {
WasmType::I32 => IType::I32,
WasmType::I64 => IType::I64,
WasmType::F32 => IType::F32,
WasmType::F64 => IType::F64,
}
}

View File

@ -31,7 +31,9 @@ pub fn embed_wit(path: std::path::PathBuf) -> Result<()> {
let ast_set = wasm_ast_extractor(&wasm_module)?;
let interfaces = generate_interfaces(&ast_set);
let wasm_module = wit_parser::delete_wit_section(wasm_module);
let mut wasm_module = wit_parser::embed_wit(wasm_module, &interfaces);
wasm_module.emit_wasm_file(path).map_err(|e| {
WITGeneratorError::IOError(format!("resulted Wasm fule can't be emitted: {:?}", e))
})
@ -68,10 +70,11 @@ fn generate_interfaces(ast_set: &[FCEAst]) -> Interfaces<'_> {
}
fn generate_default_export_api(interfaces: &mut Interfaces) {
// TODO: the order is matter
ALLOCATE_FUNC.update_interfaces(interfaces);
DEALLOCATE_FUNC.update_interfaces(interfaces);
SET_RESULT_SIZE_FUNC.update_interfaces(interfaces);
SET_RESULT_PTR_FUNC.update_interfaces(interfaces);
GET_RESULT_SIZE_FUNC.update_interfaces(interfaces);
GET_RESULT_PTR_FUNC.update_interfaces(interfaces);
SET_RESULT_SIZE_FUNC.update_interfaces(interfaces);
SET_RESULT_PTR_FUNC.update_interfaces(interfaces);
}

View File

@ -51,7 +51,7 @@ impl FCE {
match self.modules.get_mut(module_name.as_ref()) {
// TODO: refactor errors
Some(module) => module.call(func_name.as_ref(), argument),
None => Err(FCEError::NoSuchModule),
None => Err(FCEError::NoSuchModule(module_name.as_ref().to_string())),
}
}
@ -82,7 +82,7 @@ impl FCE {
pub fn unload_module<S: AsRef<str>>(&mut self, module_name: S) -> Result<(), FCEError> {
match self.modules.remove(module_name.as_ref()) {
Some(_) => Ok(()),
None => Err(FCEError::NoSuchModule),
None => Err(FCEError::NoSuchModule(module_name.as_ref().to_string())),
}
}
@ -103,7 +103,7 @@ impl FCE {
) -> Result<Vec<FCEFunctionSignature<'_>>, FCEError> {
match self.modules.get(module_name.as_ref()) {
Some(module) => Ok(Self::get_module_function_signatures(module)),
None => Err(FCEError::NoSuchModule),
None => Err(FCEError::NoSuchModule(module_name.as_ref().to_string())),
}
}

View File

@ -48,7 +48,7 @@ pub enum FCEError {
NoSuchFunction(String),
/// Returns when there is no module with such name.
NoSuchModule,
NoSuchModule(String),
/// WIT section parse error.
WITParseError(WITParserError),
@ -73,7 +73,9 @@ impl std::fmt::Display for FCEError {
FCEError::NoSuchFunction(msg) => {
write!(f, "FCE doesn't have a function with such a name: {}", msg)
}
FCEError::NoSuchModule => write!(f, "FCE doesn't have a module with such a name"),
FCEError::NoSuchModule(module_name) => {
write!(f, "FCE doesn't have a module with name {}", module_name)
}
FCEError::WITParseError(err) => write!(f, "{}", err),
FCEError::IncorrectWIT(err_msg) => write!(f, "{}", err_msg),
}

View File

@ -16,6 +16,7 @@
use super::wit_prelude::*;
use super::{IType, IValue, WValue};
use crate::FCEModuleConfig;
use fce_wit_interfaces::FCEWITInterfaces;
use wasmer_wit::interpreter::Interpreter;
@ -28,7 +29,6 @@ use std::collections::HashMap;
use std::convert::TryInto;
use std::mem::MaybeUninit;
use std::sync::Arc;
use crate::FCEModuleConfig;
type WITInterpreter =
Interpreter<WITInstance, WITExport, WITFunction, WITMemory, WITMemoryView<'static>>;
@ -231,15 +231,20 @@ impl FCEModule {
use wasmer_core::vm::Ctx;
// returns function that will be called from imports of Wasmer module
fn dyn_func_from_raw_import<F>(inputs: Vec<IType>, raw_import: F) -> DynamicFunc<'static>
fn dyn_func_from_raw_import<F>(
inputs: Vec<IType>,
outputs: Vec<IType>,
raw_import: F,
) -> DynamicFunc<'static>
where
F: Fn(&mut Ctx, &[WValue]) -> Vec<WValue> + 'static,
{
use wasmer_core::types::FuncSig;
use super::type_converters::itype_to_wtype;
let signature = inputs.iter().map(itype_to_wtype).collect::<Vec<_>>();
DynamicFunc::new(Arc::new(FuncSig::new(signature, vec![])), raw_import)
let inputs = inputs.iter().map(itype_to_wtype).collect::<Vec<_>>();
let outputs = outputs.iter().map(itype_to_wtype).collect::<Vec<_>>();
DynamicFunc::new(Arc::new(FuncSig::new(inputs, outputs)), raw_import)
}
// creates a closure that is represent a WIT module import
@ -302,7 +307,7 @@ impl FCEModule {
let wit_type = wit.type_by_idx_r(adapter_function_type)?;
match wit_type {
WITAstType::Function { inputs, .. } => {
WITAstType::Function { inputs, outputs } => {
let interpreter: WITInterpreter = adapter_instructions.try_into()?;
let raw_import = create_raw_import(
@ -311,7 +316,8 @@ impl FCEModule {
import_namespace.to_string(),
import_name.to_string(),
);
let wit_import = dyn_func_from_raw_import(inputs.clone(), raw_import);
let wit_import =
dyn_func_from_raw_import(inputs.clone(), outputs.clone(), raw_import);
Ok((import_namespace.to_string(), (*import_name, wit_import)))
}

View File

@ -78,17 +78,16 @@ impl WITInstance {
start_index: usize,
) -> Result<HashMap<usize, WITFunction>, FCEError> {
wit.imports()
.filter(|import| {
.filter(|import|
// filter out imports that have implementations
matches!(wit.adapter_by_type(import.function_type), None)
})
matches!(wit.adapter_types_by_core_type(import.function_type), Some(_)))
.enumerate()
.map(|(idx, import)| match modules.get(import.namespace) {
Some(module) => {
let func = WITFunction::from_import(module, import.name)?;
Ok((start_index + idx as usize, func))
}
None => Err(FCEError::NoSuchModule),
None => Err(FCEError::NoSuchModule(import.namespace.to_string())),
})
.collect::<Result<HashMap<_, _>, _>>()
}

View File

@ -0,0 +1,9 @@
[package]
name = "greeting"
version = "0.1.0"
authors = ["Fluence Labs"]
edition = "2018"
[dependencies]
fluence-faas = { path = "../../fluence-faas" }
anyhow = "1.0.31"

View File

@ -0,0 +1,6 @@
core_modules_dir = "wasm/artifacts/"
[[core_module]]
name = "greeting.wasm"
mem_pages_count = 1
logger_enabled = false

View File

@ -0,0 +1,40 @@
/*
* Copyright 2020 Fluence Labs Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
use fluence_faas::FluenceFaaS;
use fluence_faas::IValue;
use std::path::PathBuf;
const GREETING_MODULE_CONFIG_PATH: &str = "Config.toml";
fn main() -> Result<(), anyhow::Error> {
let mut greeting_node = FluenceFaaS::new(PathBuf::from(GREETING_MODULE_CONFIG_PATH))?;
println!(
"greeting node interface is\n{}",
greeting_node.get_interface()
);
let result = greeting_node.call_module(
"greeting.wasm",
"greeting",
&[IValue::String("Fluence".to_string()), IValue::I32(1)],
)?;
println!("execution result {:?}", result);
Ok(())
}

View File

@ -1,5 +1,5 @@
[package]
name = "greeting"
name = "wasm_greeting"
version = "0.1.0"
authors = ["Fluence Labs"]
edition = "2018"
@ -10,4 +10,4 @@ path = "src/lib.rs"
crate-type = ["cdylib"]
[dependencies]
fluence = { git = "https://github.com/fluencelabs/rust-sdk" }
fluence = { git = "https://github.com/fluencelabs/rust-sdk", features = ["debug"] }

View File

@ -18,5 +18,5 @@ use fluence::fce;
#[fce]
pub fn greeting(name: String) -> String {
format!("Hi, {}\n", name)
format!("Hi, {}", name)
}

View File

@ -21,25 +21,24 @@ use std::path::PathBuf;
use anyhow::Context;
const IPFS_MODULES_CONFIG_PATH: &str = "Config.toml";
const IPFS_RPC: &str = "wasm/artifacts/wasm_ipfs_rpc_wit.wasi.wasm";
const IPFS_RPC: &str = "wasm/artifacts/ipfs_rpc.wasm";
fn main() -> Result<(), anyhow::Error> {
let ipfs_rpc = std::fs::read(IPFS_RPC).context(format!("{} wasn't found", IPFS_RPC))?;
let ipfs_rpc = std::fs::read(IPFS_RPC).with_context(|| format!("{} wasn't found", IPFS_RPC))?;
let mut ipfs_node = FluenceFaaS::new(PathBuf::from(IPFS_MODULES_CONFIG_PATH))?;
println!("ipfs node interface is\n{}", ipfs_node.get_interface());
let node_address = ipfs_node.call_module("ipfs_node.wasm", "get_address", &[])?;
println!("ipfs node address is:\n{:?}", node_address);
let result = ipfs_node.call_code(
&ipfs_rpc,
"put",
&[IValue::String("Hello, world".to_string())],
"get",
&[IValue::String(
"QmXdC36pX1B1sdHdbri859vMYctQjAhvTmkWyG9xzhShxb".to_string(),
)],
)?;
println!("execution result {:?}", result);
Ok(())

View File

@ -1,2 +0,0 @@
[build]
target = "wasm32-wasi"

View File

@ -5,5 +5,9 @@ authors = ["Fluence Labs"]
edition = "2018"
[[bin]]
name = "wasm_ipfs_node"
name = "ipfs_node"
path = "src/main.rs"
[dependencies]
fluence = { git = "https://github.com/fluencelabs/rust-sdk", features = ["debug"] }
log = "0.4.8"

View File

@ -14,63 +14,38 @@
* limitations under the License.
*/
#![allow(clippy::missing_safety_doc)]
mod mem;
mod result;
mod path;
use crate::result::{RESULT_PTR, RESULT_SIZE};
use crate::path::to_full_path;
use fluence::fce;
use fluence::WasmLogger;
const RESULT_FILE_PATH: &str = "/tmp/ipfs_rpc_file";
const IPFS_ADDR_ENV_NAME: &str = "IPFS_ADDR";
const TIMEOUT_ENV_NAME: &str = "timeout";
pub fn main() {
let msg = "ipfs_node.main: WASI initialization finished";
unsafe {
log_utf8_string(msg.as_ptr() as _, msg.len() as _);
}
WasmLogger::init_with_level(log::Level::Info).unwrap();
}
#[no_mangle]
pub unsafe fn put(file_path_ptr: *mut u8, file_path_size: usize) {
let file_path = String::from_raw_parts(file_path_ptr, file_path_size, file_path_size);
let msg = format!("ipfs_node.put: file path is {}\n", file_path);
log_utf8_string(msg.as_ptr() as _, msg.len() as _);
/// Put file from specified path to IPFS and return its hash.
#[fce]
pub fn put(file_path: String) -> String {
log::info!("put called with file path {}", file_path);
let file_path = to_full_path(file_path);
let timeout = std::env::var(TIMEOUT_ENV_NAME).unwrap_or_else(|_| "1s".to_string());
let cmd = format!("add --timeout {} -Q {}", timeout, file_path);
let result = ipfs(cmd.as_ptr() as _, cmd.len() as _);
let hash = if result == 0 {
String::from_raw_parts(
*RESULT_PTR.get_mut() as _,
*RESULT_SIZE.get_mut(),
*RESULT_SIZE.get_mut(),
)
} else {
"host ipfs call failed".to_string()
};
let msg = format!("ipfs_node.put: file add with hash is {} \n", hash);
log_utf8_string(msg.as_ptr() as _, msg.len() as _);
*RESULT_PTR.get_mut() = hash.as_ptr() as _;
*RESULT_SIZE.get_mut() = hash.len();
std::mem::forget(hash);
call_ipfs(cmd)
}
#[no_mangle]
pub unsafe fn get(hash_ptr: *mut u8, hash_size: usize) {
let hash = String::from_raw_parts(hash_ptr, hash_size, hash_size);
let msg = format!("ipfs_node.get: file hash is {}\n", hash);
log_utf8_string(msg.as_ptr() as _, msg.len() as _);
/// Get file by provided hash from IPFS, saves it to a temporary file and returns a path to it.
#[fce]
pub fn get(hash: String) -> String {
log::info!("get called with hash {}", hash);
let result_file_path = to_full_path(RESULT_FILE_PATH);
@ -79,51 +54,39 @@ pub unsafe fn get(hash_ptr: *mut u8, hash_size: usize) {
"get --timeout {} -o {} {}",
timeout, result_file_path, hash
);
let _result = ipfs(cmd.as_ptr() as _, cmd.len() as _);
let _output = String::from_raw_parts(
*RESULT_PTR.get_mut() as _,
*RESULT_SIZE.get_mut(),
*RESULT_SIZE.get_mut(),
);
call_ipfs(cmd);
// TODO: check output
let file_path = RESULT_FILE_PATH.to_string();
let msg = format!("ipfs_node.get: file path is {}", file_path);
log_utf8_string(msg.as_ptr() as _, msg.len() as _);
*RESULT_PTR.get_mut() = file_path.as_ptr() as _;
*RESULT_SIZE.get_mut() = file_path.len();
std::mem::forget(file_path);
RESULT_FILE_PATH.to_string()
}
#[no_mangle]
pub unsafe fn get_address() {
let msg = "ipfs_node.get_address".to_string();
log_utf8_string(msg.as_ptr() as _, msg.len() as _);
let ipfs_address = match std::env::var(IPFS_ADDR_ENV_NAME) {
#[fce]
pub fn get_address() -> String {
match std::env::var(IPFS_ADDR_ENV_NAME) {
Ok(addr) => addr,
Err(e) => format!(
"getting {} env variable failed with error {:?}",
IPFS_ADDR_ENV_NAME, e
),
};
}
}
let msg = format!("ipfs_node.get_address: node address is {} \n", ipfs_address);
log_utf8_string(msg.as_ptr() as _, msg.len() as _);
*RESULT_PTR.get_mut() = ipfs_address.as_ptr() as _;
*RESULT_SIZE.get_mut() = ipfs_address.len();
std::mem::forget(ipfs_address);
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(),
}
}
}
#[link(wasm_import_module = "host")]
extern "C" {
/// Writes a byte string of size bytes that starts from ptr to a logger.
fn log_utf8_string(ptr: i32, size: i32);
/// Put a file to ipfs, returns ipfs hash of the file.
fn ipfs(ptr: i32, size: i32) -> i32;
}

View File

@ -1,41 +0,0 @@
/*
* Copyright 2020 Fluence Labs Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
use crate::log_utf8_string;
use std::alloc::{alloc as global_alloc, dealloc as global_dealloc, Layout};
use std::ptr::NonNull;
/// Allocates memory area of specified size and returns its address.
#[no_mangle]
pub unsafe fn allocate(size: usize) -> NonNull<u8> {
let layout: Layout = Layout::from_size_align(size, std::mem::align_of::<u8>()).unwrap();
let msg = format!("ipfs_node.allocate: {}\n", size);
log_utf8_string(msg.as_ptr() as _, msg.len() as _);
NonNull::new_unchecked(global_alloc(layout))
}
/// Deallocates memory area for provided memory pointer and size.
#[no_mangle]
pub unsafe fn deallocate(ptr: NonNull<u8>, size: usize) {
let layout = Layout::from_size_align(size, std::mem::align_of::<u8>()).unwrap();
let msg = format!("ipfs_node.deallocate: {:?} {}\n", ptr, size);
log_utf8_string(msg.as_ptr() as _, msg.len() as _);
global_dealloc(ptr.as_ptr(), layout);
}

View File

@ -1,53 +0,0 @@
/*
* Copyright 2020 Fluence Labs Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
use crate::log_utf8_string;
use std::sync::atomic::AtomicUsize;
pub static mut RESULT_PTR: AtomicUsize = AtomicUsize::new(0);
pub static mut RESULT_SIZE: AtomicUsize = AtomicUsize::new(0);
#[no_mangle]
pub unsafe fn get_result_ptr() -> usize {
let msg = "ipfs_node.get_result_ptr\n";
log_utf8_string(msg.as_ptr() as _, msg.len() as _);
*RESULT_PTR.get_mut()
}
#[no_mangle]
pub unsafe fn get_result_size() -> usize {
let msg = "ipfs_node.get_result_size\n";
log_utf8_string(msg.as_ptr() as _, msg.len() as _);
*RESULT_SIZE.get_mut()
}
#[no_mangle]
pub unsafe fn set_result_ptr(ptr: usize) {
let msg = format!("ipfs_node.set_result_ptr: {}\n", ptr);
log_utf8_string(msg.as_ptr() as _, msg.len() as _);
*RESULT_PTR.get_mut() = ptr;
}
#[no_mangle]
pub unsafe fn set_result_size(size: usize) {
let msg = format!("ipfs_node.set_result_size: {}\n", size);
log_utf8_string(msg.as_ptr() as _, msg.len() as _);
*RESULT_SIZE.get_mut() = size;
}

View File

@ -1,91 +0,0 @@
;; allocate function type
(@interface type (func (param i32) (result i32))) ;; 0
;; deallocate function
(@interface type (func (param i32 i32))) ;; 1
;; invoke function
(@interface type (func (param string) (result string))) ;; 2
;; result extractor functions
(@interface type (func (result i32))) ;; 3
;; result setter functions
(@interface type (func (param string))) ;; 4
;; import ipfs put/get function
(@interface type (func (param i32 i32))) ;; 5
;; import ipfs put/get function
(@interface type (func (param string) (result string))) ;; 6
;; import ipfs put/get function
(@interface type (func (param string) (result string))) ;; 7
;; import ipfs put/get function
(@interface type (func (param string) (result string))) ;; 8
;; export ipfs.get_address function
(@interface type (func (result string))) ;; 9
;; export ipfs.get_address function
(@interface type (func )) ;; 10
(@interface export "allocate" (func 0)) ;; 0
(@interface export "deallocate" (func 1)) ;; 1
(@interface export "get_result_size" (func 3)) ;; 2
(@interface export "get_result_ptr" (func 3)) ;; 3
(@interface export "set_result_size" (func 4)) ;; 4
(@interface export "set_result_ptr" (func 4)) ;; 5
(@interface export "put" (func 5)) ;; 6
(@interface export "get" (func 6)) ;; 7
(@interface export "get_address" (func 10)) ;; 8
;; adapter for export function put
(@interface func (type 7)
arg.get 0
string.size
call-core 0 ;; call allocate
arg.get 0
string.lower_memory
call-core 6 ;; call self.put
call-core 3 ;; call get_result_ptr
call-core 2 ;; call get_result_size
string.lift_memory
call-core 3 ;; call get_result_ptr
call-core 2 ;; call get_result_size
call-core 1 ;; call deallocate
)
;; adapter for export function get
(@interface func (type 8)
arg.get 0
string.size
call-core 0 ;; call allocate
arg.get 0
string.lower_memory
call-core 7 ;; call self.get
call-core 3 ;; call get_result_ptr
call-core 2 ;; call get_result_size
string.lift_memory
call-core 3 ;; call get_result_ptr
call-core 2 ;; call get_result_size
call-core 1 ;; call deallocate
)
;; adapter for export function get_address
(@interface func (type 9)
call-core 8 ;; call self.get
call-core 3 ;; call get_result_ptr
call-core 2 ;; call get_result_size
string.lift_memory
call-core 3 ;; call get_result_ptr
call-core 2 ;; call get_result_size
call-core 1 ;; call deallocate
)
;; Implementations
(@interface implement (func 5) (func 7))
(@interface implement (func 6) (func 8))
(@interface implement (func 10) (func 9))

View File

@ -1,2 +0,0 @@
[build]
target = "wasm32-wasi"

View File

@ -5,5 +5,9 @@ authors = ["Fluence Labs"]
edition = "2018"
[[bin]]
name = "wasm_ipfs_rpc"
name = "ipfs_rpc"
path = "src/main.rs"
[dependencies]
fluence = { git = "https://github.com/fluencelabs/rust-sdk", features = ["debug"] }
log = "0.4.8"

View File

@ -13,107 +13,54 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#![allow(clippy::missing_safety_doc)]
mod mem;
mod result;
use fluence::fce;
use fluence::WasmLogger;
use crate::result::{RESULT_PTR, RESULT_SIZE};
use std::fs;
use std::path::PathBuf;
const RPC_TMP_FILEPATH: &str = "/tmp/ipfs_rpc_file";
pub fn main() {
let msg = "ipfs_rpc.main: WASI initialization finished";
unsafe {
log_utf8_string(msg.as_ptr() as _, msg.len() as _);
}
WasmLogger::init_with_level(log::Level::Info).unwrap();
}
#[no_mangle]
pub unsafe fn invoke(_ptr: *mut u8, _size: usize) {
let msg = "ipfs_rpc.invoke: invoke called\n";
log_utf8_string(msg.as_ptr() as _, msg.len() as _);
let result = "IPFS_RPC wasm example, it allows to:\ninvoke\nput\nget".to_string();
*RESULT_PTR.get_mut() = result.as_ptr() as _;
*RESULT_SIZE.get_mut() = result.len();
std::mem::forget(result);
#[fce]
pub fn invoke() -> String {
"IPFS_RPC wasm example, it allows to:\ninvoke\nput\nget".to_string()
}
#[no_mangle]
pub unsafe fn put(file_content_ptr: *mut u8, file_content_size: usize) {
let file_content =
String::from_raw_parts(file_content_ptr, file_content_size, file_content_size);
let msg = format!("ipfs_rpc.put: file_content is {}\n", file_content);
log_utf8_string(msg.as_ptr() as _, msg.len() as _);
#[fce]
pub fn put(file_content: Vec<u8>) -> String {
log::info!("put called with {:?}", file_content);
let rpc_tmp_filepath = RPC_TMP_FILEPATH.to_string();
let r = fs::write(PathBuf::from(rpc_tmp_filepath.clone()), file_content);
if let Err(e) = r {
let msg: String = e.to_string();
log_utf8_string(msg.as_ptr() as _, msg.len() as _);
return format!("file can't be written: {}", e);
}
ipfs_put(rpc_tmp_filepath.as_ptr() as _, rpc_tmp_filepath.len() as _);
std::mem::forget(rpc_tmp_filepath);
let hash = String::from_raw_parts(
*RESULT_PTR.get_mut() as _,
*RESULT_SIZE.get_mut(),
*RESULT_SIZE.get_mut(),
);
let msg = format!("ipfs_rpc.put: file add with hash {}\n", hash);
log_utf8_string(msg.as_ptr() as _, msg.len() as _);
*RESULT_PTR.get_mut() = hash.as_ptr() as _;
*RESULT_SIZE.get_mut() = hash.len();
std::mem::forget(hash);
ipfs_put(rpc_tmp_filepath)
}
#[no_mangle]
pub unsafe fn get(hash_ptr: *mut u8, hash_size: usize) {
let hash = String::from_raw_parts(hash_ptr, hash_size, hash_size);
#[fce]
pub fn get(hash: String) -> Vec<u8> {
log::info!("get called with hash: {}", hash);
let msg = format!("ipfs_rpc.get: getting file with hash {}\n", hash);
log_utf8_string(msg.as_ptr() as _, msg.len() as _);
ipfs_get(hash.as_ptr() as _, hash.len() as _);
let file_path = String::from_raw_parts(
*RESULT_PTR.get_mut() as _,
*RESULT_SIZE.get_mut(),
*RESULT_SIZE.get_mut(),
);
let msg = format!("ipfs_rpc.get: reading file from {}\n", file_path);
log_utf8_string(msg.as_ptr() as _, msg.len() as _);
let file_content = fs::read(file_path).unwrap_or_else(|_| b"error while reading file".to_vec());
*RESULT_PTR.get_mut() = file_content.as_ptr() as _;
*RESULT_SIZE.get_mut() = file_content.len();
std::mem::forget(file_content);
}
#[link(wasm_import_module = "host")]
extern "C" {
/// Writes a byte string of size bytes that starts from ptr to a logger.
fn log_utf8_string(ptr: i32, size: i32);
let file_path = ipfs_get(hash);
fs::read(file_path).unwrap_or_else(|_| b"error while reading file".to_vec())
}
#[fce]
#[link(wasm_import_module = "ipfs_node.wasm")]
extern "C" {
/// Put a file to ipfs, returns ipfs hash of the file.
/// Put provided file to ipfs, return ipfs hash of the file.
#[link_name = "put"]
fn ipfs_put(ptr: i32, size: i32);
pub fn ipfs_put(file_path: String) -> String;
/// Get file from ipfs by hash.
#[link_name = "get"]
fn ipfs_get(ptr: i32, size: i32);
pub fn ipfs_get(hash: String) -> String;
}

View File

@ -1,41 +0,0 @@
/*
* Copyright 2020 Fluence Labs Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
use crate::log_utf8_string;
use std::alloc::{alloc as global_alloc, dealloc as global_dealloc, Layout};
use std::ptr::NonNull;
/// Allocates memory area of specified size and returns its address.
#[no_mangle]
pub unsafe fn allocate(size: usize) -> NonNull<u8> {
let layout: Layout = Layout::from_size_align(size, std::mem::align_of::<u8>()).unwrap();
let msg = format!("ipfs_rpc.allocate: {}\n", size);
log_utf8_string(msg.as_ptr() as _, msg.len() as _);
NonNull::new_unchecked(global_alloc(layout))
}
/// Deallocates memory area for provided memory pointer and size.
#[no_mangle]
pub unsafe fn deallocate(ptr: NonNull<u8>, size: usize) {
let layout = Layout::from_size_align(size, std::mem::align_of::<u8>()).unwrap();
let msg = format!("ipfs_rpc.deallocate: {:?} {}\n", ptr, size);
log_utf8_string(msg.as_ptr() as _, msg.len() as _);
global_dealloc(ptr.as_ptr(), layout);
}

View File

@ -1,53 +0,0 @@
/*
* Copyright 2020 Fluence Labs Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
use crate::log_utf8_string;
use std::sync::atomic::AtomicUsize;
pub static mut RESULT_PTR: AtomicUsize = AtomicUsize::new(0);
pub static mut RESULT_SIZE: AtomicUsize = AtomicUsize::new(0);
#[no_mangle]
pub unsafe fn get_result_ptr() -> usize {
let msg = "ipfs_rpc.get_result_ptr\n";
log_utf8_string(msg.as_ptr() as _, msg.len() as _);
*RESULT_PTR.get_mut()
}
#[no_mangle]
pub unsafe fn get_result_size() -> usize {
let msg = "ipfs_rpc.get_result_size\n";
log_utf8_string(msg.as_ptr() as _, msg.len() as _);
*RESULT_SIZE.get_mut()
}
#[no_mangle]
pub unsafe fn set_result_ptr(ptr: usize) {
let msg = format!("ipfs_rpc.set_result_ptr: {}\n", ptr);
log_utf8_string(msg.as_ptr() as _, msg.len() as _);
*RESULT_PTR.get_mut() = ptr;
}
#[no_mangle]
pub unsafe fn set_result_size(size: usize) {
let msg = format!("ipfs_rpc.set_result_size: {}\n", size);
log_utf8_string(msg.as_ptr() as _, msg.len() as _);
*RESULT_SIZE.get_mut() = size;
}

View File

@ -1,139 +0,0 @@
;; allocate function type
(@interface type (func (param i32) (result i32))) ;; 0
;; deallocate function
(@interface type (func (param i32 i32))) ;; 1
;; invoke function
(@interface type (func (param string) (result string))) ;; 2
;; result extractor functions
(@interface type (func (result i32))) ;; 3
;; result setter functions
(@interface type (func (param i32))) ;; 4
;; import ipfs put/get function
(@interface type (func (param i32 i32))) ;; 5
;; import ipfs put/get function
(@interface type (func (param i32 i32))) ;; 6
;; import ipfs put/get function
(@interface type (func (param string) (result string))) ;; 7
;; import ipfs put/get function
(@interface type (func (param string) (result string))) ;; 8
;; import ipfs put/get function
(@interface type (func (param i32 i32))) ;; 9
;; import ipfs put/get function
(@interface type (func (param i32 i32))) ;; 10
;; export ipfs put/get function
(@interface type (func (param string) (result string))) ;; 11
;; export ipfs put/get function
(@interface type (func (param string) (result string))) ;; 12
(@interface export "allocate" (func 0)) ;; 0
(@interface export "deallocate" (func 1)) ;; 1
(@interface export "invoke" (func 2)) ;; 2
(@interface export "get_result_size" (func 3)) ;; 3
(@interface export "get_result_ptr" (func 3)) ;; 4
(@interface export "set_result_size" (func 4)) ;; 5
(@interface export "set_result_ptr" (func 4)) ;; 6
(@interface export "put" (func 11)) ;; 7
(@interface export "get" (func 12)) ;; 8
(@interface import "ipfs_node.wasm" "get" (func (type 5)))
(@interface import "ipfs_node.wasm" "put" (func (type 6)))
(@interface import "ipfs_node.wasm" "get" (func (type 7))) ;; 9
(@interface import "ipfs_node.wasm" "put" (func (type 8))) ;; 10
;; adapter for export invoke function
(@interface func (type 2)
arg.get 0
string.size
call-core 0 ;; call allocate
arg.get 0
string.lower_memory
call-core 2 ;; call invoke
call-core 4 ;; call get_result_size
call-core 3 ;; call get_result_ptr
string.lift_memory
call-core 4 ;; call get_result_size
call-core 3 ;; call get_result_ptr
call-core 1 ;; call deallocate
)
;; adapter for export put function
(@interface func (type 11)
arg.get 0
string.size
call-core 0 ;; call allocate
arg.get 0
string.lower_memory
call-core 7 ;; call put
call-core 4 ;; call get_result_size
call-core 3 ;; call get_result_ptr
string.lift_memory
call-core 4 ;; call get_result_size
call-core 3 ;; call get_result_ptr
call-core 1 ;; call deallocate
)
;; adapter for export get function
(@interface func (type 12)
arg.get 0
string.size
call-core 0 ;; call allocate
arg.get 0
string.lower_memory
call-core 8 ;; call get
call-core 4 ;; call get_result_size
call-core 3 ;; call get_result_ptr
string.lift_memory
call-core 4 ;; call get_result_size
call-core 3 ;; call get_result_ptr
call-core 1 ;; call deallocate
)
;; adapter for import function ipfs.get
(@interface func (type 9)
arg.get 0
arg.get 1
string.lift_memory
call-core 9 ;; call ipfs_node.get that returns string
dup
string.size
call-core 0 ;; call allocate
swap2
string.lower_memory
call-core 5 ;; call set_result_size
call-core 6 ;; call set_result_ptr
)
;; adapter for import function ipfs.put
(@interface func (type 10)
arg.get 0
arg.get 1
string.lift_memory
call-core 10 ;; call ipfs_node.put that returns string
dup
string.size
call-core 0 ;; call allocate
swap2
string.lower_memory
call-core 5 ;; call set_result_size
call-core 6 ;; call set_result_ptr
)
;; Implementations
(@interface implement (func 2) (func 2))
(@interface implement (func 5) (func 9))
(@interface implement (func 6) (func 10))
(@interface implement (func 11) (func 11))
(@interface implement (func 12) (func 12))

View File

@ -1,2 +0,0 @@
[build]
target = "wasm32-unknown-unknown"