Skip to content

Commit

Permalink
add helper crate for writing wasm smartcontracts
Browse files Browse the repository at this point in the history
Signed-off-by: Marin Veršić <[email protected]>
  • Loading branch information
mversic committed Jan 14, 2022
1 parent 62541b4 commit b516ee2
Show file tree
Hide file tree
Showing 11 changed files with 352 additions and 1,320 deletions.
4 changes: 1 addition & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ members = [
"telemetry",
"version",
"version/derive",
"wasm",
"wasm/derive",
]

exclude = ["wasm_test"]
exclude = ["wasm_test", "wasm", "wasm/derive"]
2 changes: 1 addition & 1 deletion core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ crossbeam-queue = "0.3"
warp = "0.3"
thiserror = "1.0.28"
pin-project = "1"
wasmtime = "0.29.0"
wasmtime = "0.33.0"

# transitive dependencies
anyhow = ">= 1.0"
Expand Down
45 changes: 37 additions & 8 deletions core/src/smartcontracts/wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ use crate::{
wsv::{WorldStateView, WorldTrait},
};

const WASM_ALLOC_FN: &str = "alloc";
const WASM_ALLOC_FN: &str = "_iroha_wasm_alloc";
const WASM_MEMORY_NAME: &str = "memory";
const WASM_MAIN_FN_NAME: &str = "main";
const EXECUTE_ISI_FN_NAME: &str = "execute_isi";
const WASM_MAIN_FN_NAME: &str = "_iroha_wasm_main";
const EXECUTE_ISI_FN_NAME: &str = "execute_instruction";
const EXECUTE_QUERY_FN_NAME: &str = "execute_query";

/// `WebAssembly` execution error type
Expand All @@ -32,7 +32,7 @@ pub enum Error {
ExportNotFound(#[source] anyhow::Error),
/// Call to function exported from module failed
#[error("Exported function call failed")]
ExportFnCall(#[source] Trap),
ExportFnCall(#[from] Trap),
/// Some other error happened
#[error(transparent)]
Other(eyre::Error),
Expand Down Expand Up @@ -81,6 +81,11 @@ impl<'a, W: WorldTrait> Runtime<'a, W> {
/// Host defined function which executes query. When calling this function, module
/// serializes query to linear memory and provides offset and length as parameters
///
/// # Warning
///
/// This function doesn't take ownership of the provided allocation
/// but it does transfer ownership of the result to the caller
///
/// # Errors
///
/// If decoding or execution of the query fails
Expand Down Expand Up @@ -125,10 +130,19 @@ impl<'a, W: WorldTrait> Runtime<'a, W> {
/// Host defined function which executes ISI. When calling this function, module
/// serializes ISI to linear memory and provides offset and length as parameters
///
/// # Warning
///
/// This function doesn't take ownership of the provided allocation
/// but it does tranasfer ownership of the result to the caller
///
/// # Errors
///
/// If decoding or execution of the ISI fails
fn execute_isi(mut caller: Caller<State<W>>, offset: u32, len: u32) -> Result<(), Trap> {
fn execute_instruction(
mut caller: Caller<State<W>>,
offset: u32,
len: u32,
) -> Result<(), Trap> {
let memory = Self::get_memory(&mut caller)?;

// Accessing memory as a byte slice to avoid the use of unsafe
Expand All @@ -150,7 +164,7 @@ impl<'a, W: WorldTrait> Runtime<'a, W> {
let mut linker = Linker::new(engine);

linker
.func_wrap("iroha", EXECUTE_ISI_FN_NAME, Self::execute_isi)
.func_wrap("iroha", EXECUTE_ISI_FN_NAME, Self::execute_instruction)
.map_err(Error::Initialization)?;

linker
Expand Down Expand Up @@ -246,11 +260,13 @@ impl<'a, W: WorldTrait> Runtime<'a, W> {
acc_offset
};

let main = instance
let main_fn = instance
.get_typed_func::<(u32, u32), (), _>(&mut store, WASM_MAIN_FN_NAME)
.map_err(Error::ExportNotFound)?;

main.call(&mut store, (account_offset, account_bytes_len))
// NOTE: This function takes ownership of the pointer
main_fn
.call(&mut store, (account_offset, account_bytes_len))
.map_err(Error::ExportFnCall)?;

Ok(())
Expand Down Expand Up @@ -396,4 +412,17 @@ mod tests {

Ok(())
}

#[test]
fn execute_wasm_test() -> Result<(), Error> {
let account_id = AccountId::test("alice", "wonderland");
let wsv = WorldStateView::new(world_with_test_account(account_id.clone()));

let wat = std::fs::read("/home/emarin/Documents/soramitsu/iroha/wasm_test.wasm").unwrap();

let mut runtime = Runtime::new()?;
runtime.execute(&wsv, account_id, wat)?;

Ok(())
}
}
Loading

0 comments on commit b516ee2

Please sign in to comment.