From 9ebe52a0345e9cb17565285f92d62bd1eb10a1f0 Mon Sep 17 00:00:00 2001 From: clearloop <26088946+clearloop@users.noreply.github.com> Date: Wed, 27 Sep 2023 09:37:19 +0800 Subject: [PATCH 01/22] feat(gcli): introduce metadata exectuor --- Cargo.lock | 2 + gcli/Cargo.toml | 2 + gcli/src/meta/executor.rs | 115 ++++++++++++++++++++++++++++ gcli/src/meta/funcs.rs | 157 ++++++++++++++++++++++++++++++++++++++ gcli/src/meta/mod.rs | 29 +------ gcli/src/meta/tests.rs | 2 + 6 files changed, 282 insertions(+), 25 deletions(-) create mode 100644 gcli/src/meta/executor.rs create mode 100644 gcli/src/meta/funcs.rs diff --git a/Cargo.lock b/Cargo.lock index 2a1e220ef61..337b1f054e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3696,6 +3696,8 @@ dependencies = [ "thiserror", "tokio", "vara-runtime", + "wabt", + "wasmi 0.14.0", "which", "whoami", ] diff --git a/gcli/Cargo.toml b/gcli/Cargo.toml index e6e0a52ab4e..7158e1d961e 100644 --- a/gcli/Cargo.toml +++ b/gcli/Cargo.toml @@ -47,6 +47,7 @@ etc.workspace = true sp-io = { workspace = true, features = [ "std" ] } sp-core = { workspace = true, features = [ "std" ] } vara-runtime = { workspace = true, features = [ "std" ] } +wasmi.workspace = true [dev-dependencies] rand.workspace = true @@ -54,6 +55,7 @@ demo-messager.workspace = true demo-new-meta.workspace = true demo-waiter.workspace = true gsdk = { workspace = true, features = ["testing"] } +wabt.workspace = true [build-dependencies] which.workspace = true diff --git a/gcli/src/meta/executor.rs b/gcli/src/meta/executor.rs new file mode 100644 index 00000000000..7d549e6b8e8 --- /dev/null +++ b/gcli/src/meta/executor.rs @@ -0,0 +1,115 @@ +// This file is part of Gear. +// +// Copyright (C) 2021-2023 Gear Technologies Inc. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use super::funcs; +use anyhow::{anyhow, Result}; +use wasmi::{AsContextMut, Engine, Extern, Linker, Memory, MemoryType, Module, Store}; + +const PAGE_STORAGE_PREFIX: [u8; 32] = *b"gcligcligcligcligcligcligcligcli"; + +/// HostState for the WASM executor +pub struct HostState { + pub msg: Vec, + pub timestamp: u64, + pub height: u64, +} + +impl Default for HostState { + fn default() -> Self { + Self { + msg: Vec::with_capacity(256), + timestamp: 0, + height: 0, + } + } +} + +/// Executes the WASM code. +pub fn execute(wasm: &[u8], method: &str) -> Result> { + assert!(gear_lazy_pages_interface::try_to_enable_lazy_pages( + PAGE_STORAGE_PREFIX + )); + + let engine = Engine::default(); + let module = Module::new(&engine, &wasm[..]).unwrap(); + + let mut store = Store::new(&engine, HostState::default()); + let mut linker = >::new(); + + // Execution environment + // + // (import "env" "memory" (memory (;0;) 17)) + // (import "env" "gr_read" (func (;0;) (type 5))) + // (import "env" "alloc" (func (;1;) (type 6))) + // (import "env" "free" (func (;2;) (type 6))) + // (import "env" "gr_size" (func (;3;) (type 4))) + // (import "env" "gr_reply" (func (;4;) (type 5))) + // (import "env" "gr_panic" (func (;5;) (type 0))) + // (import "env" "gr_oom_panic" (func (;6;) (type 7))) + { + let memory = Memory::new(store.as_context_mut(), MemoryType::new(256, None)).unwrap(); + linker + .define("env", "memory", Extern::Memory(memory)) + .unwrap(); + + linker + .define("env", "gr_read", funcs::gr_read(&mut store, memory.clone())) + .unwrap(); + + linker + .define("env", "alloc", funcs::alloc(&mut store, memory.clone())) + .unwrap(); + + linker + .define("env", "free", funcs::free(&mut store)) + .unwrap(); + + linker + .define("env", "gr_size", funcs::gr_size(&mut store, memory)) + .unwrap(); + + linker + .define("env", "gr_reply", funcs::gr_reply(&mut store)) + .unwrap(); + + linker + .define("env", "gr_panic", funcs::gr_panic(&mut store, memory)) + .unwrap(); + + linker + .define("env", "gr_oom_panic", funcs::gr_oom_panic(&mut store)) + .unwrap(); + } + + let instance = linker + .instantiate(&mut store, &module) + .unwrap() + .start(&mut store) + .unwrap(); + + let metadata = instance + .get_export(&store, method) + .and_then(Extern::into_func) + .ok_or_else(|| anyhow!("could not find function \"metadata\"")) + .unwrap() + .typed::<(), (), _>(&mut store) + .unwrap(); + + metadata.call(&mut store, ()).unwrap(); + Ok(store.state().msg.clone()) +} diff --git a/gcli/src/meta/funcs.rs b/gcli/src/meta/funcs.rs new file mode 100644 index 00000000000..d8d744a7b48 --- /dev/null +++ b/gcli/src/meta/funcs.rs @@ -0,0 +1,157 @@ +// This file is part of Gear. +// +// Copyright (C) 2021-2023 Gear Technologies Inc. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use super::executor::HostState; +use wasmi::{ + core::memory_units::Pages, AsContext, AsContextMut, Caller, Extern, Func, Memory, Store, +}; + +pub fn alloc(store: &mut Store, memory: Memory) -> Extern { + Extern::Func(Func::wrap( + store, + move |mut caller: Caller<'_, HostState>, pages: i32| { + memory + .clone() + .grow(caller.as_context_mut(), Pages(pages as usize)) + .map_or_else( + |err| { + log::error!("{err:?}"); + u32::MAX as i32 + }, + |pages| pages.0 as i32, + ) + }, + )) +} + +pub fn free(ctx: impl AsContextMut) -> Extern { + Extern::Func(Func::wrap(ctx, |_: i32| 0)) +} + +pub fn gr_panic(ctx: &mut Store, memory: Memory) -> Extern { + Extern::Func(Func::wrap( + ctx, + move |mut caller: Caller<'_, HostState>, ptr: u32, len: i32| { + // let (ptr, len) = (ptr as usize, len as usize); + // + // let mut msg = vec![0; len]; + // memory + // .clone() + // .read(store, ptr, &mut msg) + // .map_err(|e| { + // log::error!("{:?}", e); + // // Trap::i32_exit(1) + // }) + // .unwrap(); + // + // log::error!("panic occurred: {:?}", String::from_utf8_lossy(&msg)); + Ok(()) + }, + )) +} + +pub fn gr_oom_panic(ctx: impl AsContextMut) -> Extern { + Extern::Func(Func::wrap(ctx, || { + log::error!("OOM panic occurred"); + Ok(()) + })) +} + +pub fn gr_read(ctx: &mut Store, memory: Memory) -> Extern { + Extern::Func(Func::wrap( + ctx, + move |mut caller: Caller<'_, HostState>, at: u32, len: i32, buff: i32, err: i32| { + // let (at, len, buff, err) = (at as _, len as _, buff as _, err as _); + // + // let msg = &caller.data().msg; + // let mut payload = vec![0; len]; + // if at + len <= msg.len() { + // payload.copy_from_slice(&msg[at..(at + len)]); + // } else { + // log::error!("overflow"); + // // return Err(Trap::i32_exit(1)); + // return; + // } + // + // let len: u32 = memory + // .clone() + // .write(caller.as_context_mut(), buff, &payload) + // .map_err(|e| log::error!("{:?}", e)) + // .is_err() + // .into(); + // + // memory + // .clone() + // .write(caller.as_context_mut(), err, &len.to_le_bytes()) + // .map_err(|e| { + // log::error!("{:?}", e); + // // Trap::i32_exit(1) + // })?; + // + // Ok(()) + }, + )) +} + +/// # NOTE +/// +/// Just for the compatibility with the program metadata +pub fn gr_reply(ctx: &mut Store) -> Extern { + Extern::Func(Func::wrap( + ctx, + move |mut _caller: Caller<'_, HostState>, + _ptr: u32, + _len: i32, + _val: i32, + _delay: i32, + _msg: i32| Ok(()), + )) +} + +/// # NOTE +/// +/// Just for the compatible with the program metadata +pub fn gr_error(ctx: &mut Store) -> Extern { + Extern::Func(Func::wrap( + ctx, + move |mut _caller: Caller<'_, HostState>, _ptr: u32, _err_ptr: u32| Ok(()), + )) +} + +pub fn gr_size(ctx: &mut Store, memory: Memory) -> Extern { + Extern::Func(Func::wrap( + ctx, + move |mut caller: Caller<'_, HostState>, size_ptr: u32| { + // let size = caller.data().msg.len() as u32; + // + // memory + // .clone() + // .write( + // caller.as_context_mut(), + // size_ptr as usize, + // &size.to_le_bytes(), + // ) + // .map_err(|e| { + // log::error!("{:?}", e); + // // Trap::i32_exit(1) + // })?; + // + // Ok(()) + }, + )) +} diff --git a/gcli/src/meta/mod.rs b/gcli/src/meta/mod.rs index 4028cccb4a1..5bd90e2f8d8 100644 --- a/gcli/src/meta/mod.rs +++ b/gcli/src/meta/mod.rs @@ -17,13 +17,14 @@ // along with this program. If not, see . //! Program metadata parser +mod executor; +mod funcs; mod registry; #[cfg(test)] mod tests; use crate::result::{Error, Result}; -use core_processor::configs::BlockInfo; -use gear_core::code::{Code, CodeAndId, InstrumentedCode, InstrumentedCodeAndId, TryNewCodeConfig}; +use gear_core::code::{Code, CodeAndId, InstrumentedCodeAndId, TryNewCodeConfig}; use gmeta::{MetadataRepr, MetawasmData, TypesRepr}; use registry::LocalRegistry as _; use scale_info::{scale::Decode, PortableRegistry}; @@ -73,8 +74,6 @@ pub enum Meta { } impl Meta { - const PAGE_STORAGE_PREFIX: [u8; 32] = *b"gcligcligcligcligcligcligcligcli"; - fn format_metadata(meta: &MetadataRepr, fmt: &mut fmt::Formatter) -> fmt::Result { let registry = PortableRegistry::decode(&mut meta.registry.as_ref()).map_err(|_| fmt::Error)?; @@ -107,26 +106,6 @@ impl Meta { display.finish() } - /// Execute meta method. - fn execute(wasm: InstrumentedCode, method: &str) -> Result> { - assert!(gear_lazy_pages_interface::try_to_enable_lazy_pages( - Self::PAGE_STORAGE_PREFIX - )); - - sp_io::TestExternalities::default().execute_with(|| { - core_processor::informational::execute_for_reply::( - method.into(), - wasm, - None, - None, - Default::default(), - u64::MAX, - BlockInfo::default(), - ) - .map_err(Error::WasmExecution) - }) - } - /// Decode metawasm from wasm binary. pub fn decode_wasm(wasm: &[u8]) -> Result { let code = Code::try_new_mock_const_or_no_rules( @@ -137,7 +116,7 @@ impl Meta { let (code, _) = InstrumentedCodeAndId::from(CodeAndId::new(code)).into_parts(); Ok(Self::Wasm(MetawasmData::decode( - &mut Self::execute(code, "metadata")?.as_ref(), + &mut executor::execute(code.code(), "metadata")?.as_ref(), )?)) } diff --git a/gcli/src/meta/tests.rs b/gcli/src/meta/tests.rs index 51373147ae8..be9f13f4794 100644 --- a/gcli/src/meta/tests.rs +++ b/gcli/src/meta/tests.rs @@ -123,6 +123,8 @@ fn test_parse_metadata_works() { #[test] fn test_parse_metawasm_data_1_works() { use demo_new_meta::META_WASM_V1; + let www = wabt::wasm2wat(META_WASM_V1).unwrap(); + println!("{}", www); let meta = Meta::decode_wasm(META_WASM_V1).unwrap(); assert_eq!(format!("{:#}", meta), META_WASM_V1_OUTPUT.trim()); } From bd06a1a076e420f4637f5f827abffbef1b992abf Mon Sep 17 00:00:00 2001 From: clearloop <26088946+clearloop@users.noreply.github.com> Date: Wed, 27 Sep 2023 09:46:44 +0800 Subject: [PATCH 02/22] feat(gcli): introduce host functions for the metadata executor --- gcli/src/meta/funcs.rs | 109 ++++++++++++++++++----------------------- 1 file changed, 49 insertions(+), 60 deletions(-) diff --git a/gcli/src/meta/funcs.rs b/gcli/src/meta/funcs.rs index d8d744a7b48..136d8a55638 100644 --- a/gcli/src/meta/funcs.rs +++ b/gcli/src/meta/funcs.rs @@ -17,9 +17,7 @@ // along with this program. If not, see . use super::executor::HostState; -use wasmi::{ - core::memory_units::Pages, AsContext, AsContextMut, Caller, Extern, Func, Memory, Store, -}; +use wasmi::{core::memory_units::Pages, AsContextMut, Caller, Extern, Func, Memory, Store}; pub fn alloc(store: &mut Store, memory: Memory) -> Extern { Extern::Func(Func::wrap( @@ -43,16 +41,16 @@ pub fn free(ctx: impl AsContextMut) -> Extern { Extern::Func(Func::wrap(ctx, |_: i32| 0)) } -pub fn gr_panic(ctx: &mut Store, memory: Memory) -> Extern { +pub fn gr_panic(ctx: &mut Store, _memory: Memory) -> Extern { Extern::Func(Func::wrap( ctx, - move |mut caller: Caller<'_, HostState>, ptr: u32, len: i32| { + move |mut _caller: Caller<'_, HostState>, _ptr: u32, _len: i32| { // let (ptr, len) = (ptr as usize, len as usize); // // let mut msg = vec![0; len]; // memory // .clone() - // .read(store, ptr, &mut msg) + // .read(ctx.as_context(), ptr, &mut msg) // .map_err(|e| { // log::error!("{:?}", e); // // Trap::i32_exit(1) @@ -60,7 +58,7 @@ pub fn gr_panic(ctx: &mut Store, memory: Memory) -> Extern { // .unwrap(); // // log::error!("panic occurred: {:?}", String::from_utf8_lossy(&msg)); - Ok(()) + // Ok(()) }, )) } @@ -76,34 +74,35 @@ pub fn gr_read(ctx: &mut Store, memory: Memory) -> Extern { Extern::Func(Func::wrap( ctx, move |mut caller: Caller<'_, HostState>, at: u32, len: i32, buff: i32, err: i32| { - // let (at, len, buff, err) = (at as _, len as _, buff as _, err as _); - // - // let msg = &caller.data().msg; - // let mut payload = vec![0; len]; - // if at + len <= msg.len() { - // payload.copy_from_slice(&msg[at..(at + len)]); - // } else { - // log::error!("overflow"); - // // return Err(Trap::i32_exit(1)); - // return; - // } - // - // let len: u32 = memory - // .clone() - // .write(caller.as_context_mut(), buff, &payload) - // .map_err(|e| log::error!("{:?}", e)) - // .is_err() - // .into(); - // - // memory - // .clone() - // .write(caller.as_context_mut(), err, &len.to_le_bytes()) - // .map_err(|e| { - // log::error!("{:?}", e); - // // Trap::i32_exit(1) - // })?; - // - // Ok(()) + let (at, len, buff, err) = (at as _, len as _, buff as _, err as _); + + let msg = &caller.host_data().msg; + let mut payload = vec![0; len]; + if at + len <= msg.len() { + payload.copy_from_slice(&msg[at..(at + len)]); + } else { + log::error!("overflow"); + // return Err(Trap::i32_exit(1)); + return Ok(()); + } + + let len: u32 = memory + .clone() + .write(caller.as_context_mut(), buff, &payload) + .map_err(|e| log::error!("{:?}", e)) + .is_err() + .into(); + + memory + .clone() + .write(caller.as_context_mut(), err, &len.to_le_bytes()) + .map_err(|e| { + log::error!("{:?}", e); + // Trap::i32_exit(1) + }) + .unwrap(); + + Ok(()) }, )) } @@ -123,35 +122,25 @@ pub fn gr_reply(ctx: &mut Store) -> Extern { )) } -/// # NOTE -/// -/// Just for the compatible with the program metadata -pub fn gr_error(ctx: &mut Store) -> Extern { - Extern::Func(Func::wrap( - ctx, - move |mut _caller: Caller<'_, HostState>, _ptr: u32, _err_ptr: u32| Ok(()), - )) -} - pub fn gr_size(ctx: &mut Store, memory: Memory) -> Extern { Extern::Func(Func::wrap( ctx, move |mut caller: Caller<'_, HostState>, size_ptr: u32| { - // let size = caller.data().msg.len() as u32; - // - // memory - // .clone() - // .write( - // caller.as_context_mut(), - // size_ptr as usize, - // &size.to_le_bytes(), - // ) - // .map_err(|e| { - // log::error!("{:?}", e); - // // Trap::i32_exit(1) - // })?; - // - // Ok(()) + let size = caller.host_data().msg.len() as u32; + + memory + .clone() + .write( + caller.as_context_mut(), + size_ptr as usize, + &size.to_le_bytes(), + ) + .map_err(|e| { + log::error!("{:?}", e); + }) + .unwrap(); + + Ok(()) }, )) } From d20b210cb7e9d25164ed8909d16192d54ba9c251 Mon Sep 17 00:00:00 2001 From: clearloop <26088946+clearloop@users.noreply.github.com> Date: Wed, 27 Sep 2023 10:25:48 +0800 Subject: [PATCH 03/22] chore(gcli): use wasmi with std --- Cargo.lock | 1 - gcli/Cargo.toml | 3 +-- gcli/src/meta/executor.rs | 15 +++++---------- gcli/src/meta/funcs.rs | 18 ++++++++++++------ gcli/src/meta/mod.rs | 8 +++++--- gcli/src/meta/tests.rs | 2 -- 6 files changed, 23 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 337b1f054e5..c395373e414 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3696,7 +3696,6 @@ dependencies = [ "thiserror", "tokio", "vara-runtime", - "wabt", "wasmi 0.14.0", "which", "whoami", diff --git a/gcli/Cargo.toml b/gcli/Cargo.toml index 7158e1d961e..2295f60ee31 100644 --- a/gcli/Cargo.toml +++ b/gcli/Cargo.toml @@ -47,7 +47,7 @@ etc.workspace = true sp-io = { workspace = true, features = [ "std" ] } sp-core = { workspace = true, features = [ "std" ] } vara-runtime = { workspace = true, features = [ "std" ] } -wasmi.workspace = true +wasmi = { workspace = true, features = ["std"] } [dev-dependencies] rand.workspace = true @@ -55,7 +55,6 @@ demo-messager.workspace = true demo-new-meta.workspace = true demo-waiter.workspace = true gsdk = { workspace = true, features = ["testing"] } -wabt.workspace = true [build-dependencies] which.workspace = true diff --git a/gcli/src/meta/executor.rs b/gcli/src/meta/executor.rs index 7d549e6b8e8..b35e88695a0 100644 --- a/gcli/src/meta/executor.rs +++ b/gcli/src/meta/executor.rs @@ -23,22 +23,13 @@ use wasmi::{AsContextMut, Engine, Extern, Linker, Memory, MemoryType, Module, St const PAGE_STORAGE_PREFIX: [u8; 32] = *b"gcligcligcligcligcligcligcligcli"; /// HostState for the WASM executor +#[derive(Default)] pub struct HostState { pub msg: Vec, pub timestamp: u64, pub height: u64, } -impl Default for HostState { - fn default() -> Self { - Self { - msg: Vec::with_capacity(256), - timestamp: 0, - height: 0, - } - } -} - /// Executes the WASM code. pub fn execute(wasm: &[u8], method: &str) -> Result> { assert!(gear_lazy_pages_interface::try_to_enable_lazy_pages( @@ -94,6 +85,10 @@ pub fn execute(wasm: &[u8], method: &str) -> Result> { linker .define("env", "gr_oom_panic", funcs::gr_oom_panic(&mut store)) .unwrap(); + + linker + .define("env", "gr_out_of_gas", funcs::gr_out_of_gas(&mut store)) + .unwrap(); } let instance = linker diff --git a/gcli/src/meta/funcs.rs b/gcli/src/meta/funcs.rs index 136d8a55638..eb51a3c2dff 100644 --- a/gcli/src/meta/funcs.rs +++ b/gcli/src/meta/funcs.rs @@ -113,12 +113,11 @@ pub fn gr_read(ctx: &mut Store, memory: Memory) -> Extern { pub fn gr_reply(ctx: &mut Store) -> Extern { Extern::Func(Func::wrap( ctx, - move |mut _caller: Caller<'_, HostState>, - _ptr: u32, - _len: i32, - _val: i32, - _delay: i32, - _msg: i32| Ok(()), + move |mut _caller: Caller<'_, HostState>, _gas: u32, _ptr: i32, _len: i32, _value: i32| { + // TODO: process payload from here. + + Ok(()) + }, )) } @@ -144,3 +143,10 @@ pub fn gr_size(ctx: &mut Store, memory: Memory) -> Extern { }, )) } + +pub fn gr_out_of_gas(ctx: &mut Store) -> Extern { + Extern::Func(Func::wrap( + ctx, + move |_caller: Caller<'_, HostState>| Ok(()), + )) +} diff --git a/gcli/src/meta/mod.rs b/gcli/src/meta/mod.rs index 5bd90e2f8d8..f5b698c58f6 100644 --- a/gcli/src/meta/mod.rs +++ b/gcli/src/meta/mod.rs @@ -115,9 +115,11 @@ impl Meta { )?; let (code, _) = InstrumentedCodeAndId::from(CodeAndId::new(code)).into_parts(); - Ok(Self::Wasm(MetawasmData::decode( - &mut executor::execute(code.code(), "metadata")?.as_ref(), - )?)) + let result = executor::execute(code.code(), "metadata")?; + + println!("result: {:?}", result); + + Ok(Self::Wasm(MetawasmData::decode(&mut result.as_ref())?)) } /// Decode metadata from hex bytes. diff --git a/gcli/src/meta/tests.rs b/gcli/src/meta/tests.rs index be9f13f4794..51373147ae8 100644 --- a/gcli/src/meta/tests.rs +++ b/gcli/src/meta/tests.rs @@ -123,8 +123,6 @@ fn test_parse_metadata_works() { #[test] fn test_parse_metawasm_data_1_works() { use demo_new_meta::META_WASM_V1; - let www = wabt::wasm2wat(META_WASM_V1).unwrap(); - println!("{}", www); let meta = Meta::decode_wasm(META_WASM_V1).unwrap(); assert_eq!(format!("{:#}", meta), META_WASM_V1_OUTPUT.trim()); } From 94dbdd69d53597905adc968f37c0128138542210 Mon Sep 17 00:00:00 2001 From: clearloop <26088946+clearloop@users.noreply.github.com> Date: Wed, 27 Sep 2023 11:05:36 +0800 Subject: [PATCH 04/22] feat(gcli): implement gr_reply in metadata executor --- gcli/src/meta/executor.rs | 2 +- gcli/src/meta/funcs.rs | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/gcli/src/meta/executor.rs b/gcli/src/meta/executor.rs index b35e88695a0..bee4b836e15 100644 --- a/gcli/src/meta/executor.rs +++ b/gcli/src/meta/executor.rs @@ -75,7 +75,7 @@ pub fn execute(wasm: &[u8], method: &str) -> Result> { .unwrap(); linker - .define("env", "gr_reply", funcs::gr_reply(&mut store)) + .define("env", "gr_reply", funcs::gr_reply(&mut store, memory)) .unwrap(); linker diff --git a/gcli/src/meta/funcs.rs b/gcli/src/meta/funcs.rs index eb51a3c2dff..3cdd9569e87 100644 --- a/gcli/src/meta/funcs.rs +++ b/gcli/src/meta/funcs.rs @@ -17,7 +17,9 @@ // along with this program. If not, see . use super::executor::HostState; -use wasmi::{core::memory_units::Pages, AsContextMut, Caller, Extern, Func, Memory, Store}; +use wasmi::{ + core::memory_units::Pages, AsContext, AsContextMut, Caller, Extern, Func, Memory, Store, +}; pub fn alloc(store: &mut Store, memory: Memory) -> Extern { Extern::Func(Func::wrap( @@ -110,12 +112,18 @@ pub fn gr_read(ctx: &mut Store, memory: Memory) -> Extern { /// # NOTE /// /// Just for the compatibility with the program metadata -pub fn gr_reply(ctx: &mut Store) -> Extern { +pub fn gr_reply(ctx: &mut Store, memory: Memory) -> Extern { Extern::Func(Func::wrap( ctx, - move |mut _caller: Caller<'_, HostState>, _gas: u32, _ptr: i32, _len: i32, _value: i32| { + move |mut caller: Caller<'_, HostState>, ptr: u32, len: i32, _value: i32, _err: i32| { // TODO: process payload from here. + let len = len as usize; + let mut result = vec![0; len]; + memory + .read(caller.as_context(), ptr as usize, &mut result) + .unwrap(); + caller.host_data_mut().msg = result; Ok(()) }, )) From 6adf16d42623847af614b57e57a7632d70badeba Mon Sep 17 00:00:00 2001 From: clearloop <26088946+clearloop@users.noreply.github.com> Date: Wed, 27 Sep 2023 15:18:15 +0800 Subject: [PATCH 05/22] chore(gcli): make clippy happy --- gcli/src/meta/executor.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gcli/src/meta/executor.rs b/gcli/src/meta/executor.rs index bee4b836e15..ea32bbe8bf4 100644 --- a/gcli/src/meta/executor.rs +++ b/gcli/src/meta/executor.rs @@ -37,7 +37,7 @@ pub fn execute(wasm: &[u8], method: &str) -> Result> { )); let engine = Engine::default(); - let module = Module::new(&engine, &wasm[..]).unwrap(); + let module = Module::new(&engine, wasm).unwrap(); let mut store = Store::new(&engine, HostState::default()); let mut linker = >::new(); @@ -59,11 +59,11 @@ pub fn execute(wasm: &[u8], method: &str) -> Result> { .unwrap(); linker - .define("env", "gr_read", funcs::gr_read(&mut store, memory.clone())) + .define("env", "gr_read", funcs::gr_read(&mut store, memory)) .unwrap(); linker - .define("env", "alloc", funcs::alloc(&mut store, memory.clone())) + .define("env", "alloc", funcs::alloc(&mut store, memory)) .unwrap(); linker From be3de931f81862453f37376e6916308ac06a469e Mon Sep 17 00:00:00 2001 From: clearloop <26088946+clearloop@users.noreply.github.com> Date: Thu, 28 Sep 2023 02:46:51 +0800 Subject: [PATCH 06/22] feat(gcli): clean unwraps --- gcli/executor.rs | 1 + gcli/src/meta/executor.rs | 64 ++++++++------------------------------- gcli/src/meta/funcs.rs | 48 +++++++++-------------------- gcli/src/result.rs | 2 ++ 4 files changed, 31 insertions(+), 84 deletions(-) create mode 100644 gcli/executor.rs diff --git a/gcli/executor.rs b/gcli/executor.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/gcli/executor.rs @@ -0,0 +1 @@ + diff --git a/gcli/src/meta/executor.rs b/gcli/src/meta/executor.rs index ea32bbe8bf4..68464e0f22a 100644 --- a/gcli/src/meta/executor.rs +++ b/gcli/src/meta/executor.rs @@ -43,68 +43,30 @@ pub fn execute(wasm: &[u8], method: &str) -> Result> { let mut linker = >::new(); // Execution environment - // - // (import "env" "memory" (memory (;0;) 17)) - // (import "env" "gr_read" (func (;0;) (type 5))) - // (import "env" "alloc" (func (;1;) (type 6))) - // (import "env" "free" (func (;2;) (type 6))) - // (import "env" "gr_size" (func (;3;) (type 4))) - // (import "env" "gr_reply" (func (;4;) (type 5))) - // (import "env" "gr_panic" (func (;5;) (type 0))) - // (import "env" "gr_oom_panic" (func (;6;) (type 7))) { let memory = Memory::new(store.as_context_mut(), MemoryType::new(256, None)).unwrap(); - linker - .define("env", "memory", Extern::Memory(memory)) - .unwrap(); - - linker - .define("env", "gr_read", funcs::gr_read(&mut store, memory)) - .unwrap(); - - linker - .define("env", "alloc", funcs::alloc(&mut store, memory)) - .unwrap(); - - linker - .define("env", "free", funcs::free(&mut store)) - .unwrap(); - - linker - .define("env", "gr_size", funcs::gr_size(&mut store, memory)) - .unwrap(); - - linker - .define("env", "gr_reply", funcs::gr_reply(&mut store, memory)) - .unwrap(); - - linker - .define("env", "gr_panic", funcs::gr_panic(&mut store, memory)) - .unwrap(); - - linker - .define("env", "gr_oom_panic", funcs::gr_oom_panic(&mut store)) - .unwrap(); - - linker - .define("env", "gr_out_of_gas", funcs::gr_out_of_gas(&mut store)) - .unwrap(); + linker.define("env", "memory", Extern::Memory(memory))?; + linker.define("env", "gr_read", funcs::gr_read(&mut store, memory))?; + linker.define("env", "alloc", funcs::alloc(&mut store, memory))?; + linker.define("env", "free", funcs::free(&mut store))?; + linker.define("env", "gr_size", funcs::gr_size(&mut store, memory))?; + linker.define("env", "gr_reply", funcs::gr_reply(&mut store, memory))?; + linker.define("env", "gr_panic", funcs::gr_panic(&mut store, memory))?; + linker.define("env", "gr_oom_panic", funcs::gr_oom_panic(&mut store))?; + linker.define("env", "gr_out_of_gas", funcs::gr_out_of_gas(&mut store))?; } let instance = linker .instantiate(&mut store, &module) .unwrap() - .start(&mut store) - .unwrap(); + .start(&mut store)?; let metadata = instance .get_export(&store, method) .and_then(Extern::into_func) - .ok_or_else(|| anyhow!("could not find function \"metadata\"")) - .unwrap() - .typed::<(), (), _>(&mut store) - .unwrap(); + .ok_or_else(|| anyhow!("could not find function \"metadata\""))? + .typed::<(), (), _>(&mut store)?; - metadata.call(&mut store, ()).unwrap(); + metadata.call(&mut store, ())?; Ok(store.state().msg.clone()) } diff --git a/gcli/src/meta/funcs.rs b/gcli/src/meta/funcs.rs index 3cdd9569e87..5cbdf26d981 100644 --- a/gcli/src/meta/funcs.rs +++ b/gcli/src/meta/funcs.rs @@ -18,7 +18,8 @@ use super::executor::HostState; use wasmi::{ - core::memory_units::Pages, AsContext, AsContextMut, Caller, Extern, Func, Memory, Store, + core::{memory_units::Pages, Trap, TrapCode}, + AsContext, AsContextMut, Caller, Extern, Func, Memory, Store, }; pub fn alloc(store: &mut Store, memory: Memory) -> Extern { @@ -46,22 +47,7 @@ pub fn free(ctx: impl AsContextMut) -> Extern { pub fn gr_panic(ctx: &mut Store, _memory: Memory) -> Extern { Extern::Func(Func::wrap( ctx, - move |mut _caller: Caller<'_, HostState>, _ptr: u32, _len: i32| { - // let (ptr, len) = (ptr as usize, len as usize); - // - // let mut msg = vec![0; len]; - // memory - // .clone() - // .read(ctx.as_context(), ptr, &mut msg) - // .map_err(|e| { - // log::error!("{:?}", e); - // // Trap::i32_exit(1) - // }) - // .unwrap(); - // - // log::error!("panic occurred: {:?}", String::from_utf8_lossy(&msg)); - // Ok(()) - }, + move |mut _caller: Caller<'_, HostState>, _ptr: u32, _len: i32| {}, )) } @@ -83,9 +69,7 @@ pub fn gr_read(ctx: &mut Store, memory: Memory) -> Extern { if at + len <= msg.len() { payload.copy_from_slice(&msg[at..(at + len)]); } else { - log::error!("overflow"); - // return Err(Trap::i32_exit(1)); - return Ok(()); + return Err(Trap::Code(TrapCode::MemoryAccessOutOfBounds)); } let len: u32 = memory @@ -100,30 +84,28 @@ pub fn gr_read(ctx: &mut Store, memory: Memory) -> Extern { .write(caller.as_context_mut(), err, &len.to_le_bytes()) .map_err(|e| { log::error!("{:?}", e); - // Trap::i32_exit(1) - }) - .unwrap(); + Trap::Code(TrapCode::MemoryAccessOutOfBounds) + })?; Ok(()) }, )) } -/// # NOTE -/// -/// Just for the compatibility with the program metadata pub fn gr_reply(ctx: &mut Store, memory: Memory) -> Extern { Extern::Func(Func::wrap( ctx, move |mut caller: Caller<'_, HostState>, ptr: u32, len: i32, _value: i32, _err: i32| { - // TODO: process payload from here. - let len = len as usize; - let mut result = vec![0; len]; + let mut result = vec![0; len as usize]; + memory .read(caller.as_context(), ptr as usize, &mut result) - .unwrap(); - + .map_err(|e| { + log::error!("{:?}", e); + Trap::Code(TrapCode::MemoryAccessOutOfBounds) + })?; caller.host_data_mut().msg = result; + Ok(()) }, )) @@ -144,8 +126,8 @@ pub fn gr_size(ctx: &mut Store, memory: Memory) -> Extern { ) .map_err(|e| { log::error!("{:?}", e); - }) - .unwrap(); + Trap::Code(TrapCode::MemoryAccessOutOfBounds) + })?; Ok(()) }, diff --git a/gcli/src/result.rs b/gcli/src/result.rs index 8b6e2546509..621cd7e41ef 100644 --- a/gcli/src/result.rs +++ b/gcli/src/result.rs @@ -65,6 +65,8 @@ pub enum Error { InvalidWasm, #[error("Wasm execution error {0}")] WasmExecution(String), + #[error("Wasmi execution error {0}")] + Wasmi(wasmi::Error), #[error(transparent)] Etc(#[from] etc::Error), #[error("Metadata parsing error {0:?}")] From 78928559c7998ae57ac17a5794fd5513ef1d38d8 Mon Sep 17 00:00:00 2001 From: clearloop <26088946+clearloop@users.noreply.github.com> Date: Thu, 28 Sep 2023 03:00:51 +0800 Subject: [PATCH 07/22] chore(gcli): clean stdouts --- gcli/src/meta/mod.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/gcli/src/meta/mod.rs b/gcli/src/meta/mod.rs index f5b698c58f6..c361ca4a3c1 100644 --- a/gcli/src/meta/mod.rs +++ b/gcli/src/meta/mod.rs @@ -114,11 +114,8 @@ impl Meta { TryNewCodeConfig::new_no_exports_check(), )?; let (code, _) = InstrumentedCodeAndId::from(CodeAndId::new(code)).into_parts(); - let result = executor::execute(code.code(), "metadata")?; - println!("result: {:?}", result); - Ok(Self::Wasm(MetawasmData::decode(&mut result.as_ref())?)) } From a33afeec44e15757a36663f43792818b7c0b57f6 Mon Sep 17 00:00:00 2001 From: clearloop <26088946+clearloop@users.noreply.github.com> Date: Fri, 29 Sep 2023 00:37:05 +0800 Subject: [PATCH 08/22] chore(gcli): introduce gr_block_height in metadata executor --- gcli/src/meta/executor.rs | 6 ++++++ gcli/src/meta/funcs.rs | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/gcli/src/meta/executor.rs b/gcli/src/meta/executor.rs index 68464e0f22a..013b686d6b1 100644 --- a/gcli/src/meta/executor.rs +++ b/gcli/src/meta/executor.rs @@ -54,6 +54,12 @@ pub fn execute(wasm: &[u8], method: &str) -> Result> { linker.define("env", "gr_panic", funcs::gr_panic(&mut store, memory))?; linker.define("env", "gr_oom_panic", funcs::gr_oom_panic(&mut store))?; linker.define("env", "gr_out_of_gas", funcs::gr_out_of_gas(&mut store))?; + linker.define("env", "gr_block_height", funcs::gr_block_height(&mut store))?; + linker.define( + "env", + "gr_block_timestamp", + funcs::gr_block_timestamp(&mut store), + )?; } let instance = linker diff --git a/gcli/src/meta/funcs.rs b/gcli/src/meta/funcs.rs index 5cbdf26d981..2e2011b28bb 100644 --- a/gcli/src/meta/funcs.rs +++ b/gcli/src/meta/funcs.rs @@ -140,3 +140,17 @@ pub fn gr_out_of_gas(ctx: &mut Store) -> Extern { move |_caller: Caller<'_, HostState>| Ok(()), )) } + +pub fn gr_block_height(ctx: &mut Store) -> Extern { + Extern::Func(Func::wrap( + ctx, + move |_caller: Caller<'_, HostState>, _height: u32| Ok(()), + )) +} + +pub fn gr_block_timestamp(ctx: &mut Store) -> Extern { + Extern::Func(Func::wrap( + ctx, + move |_caller: Caller<'_, HostState>, _timestamp: u32| Ok(()), + )) +} From 4f9f357ca5ec7917cfa1a3c91ac39ed8c945c62f Mon Sep 17 00:00:00 2001 From: clearloop <26088946+clearloop@users.noreply.github.com> Date: Sat, 30 Sep 2023 11:31:22 +0800 Subject: [PATCH 09/22] chore(gcli): address comments --- gcli/executor.rs | 1 - gcli/src/meta/executor.rs | 144 ++++++++++++++++++++++++++++++++++- gcli/src/meta/funcs.rs | 156 -------------------------------------- gcli/src/meta/mod.rs | 1 - 4 files changed, 142 insertions(+), 160 deletions(-) delete mode 100644 gcli/executor.rs delete mode 100644 gcli/src/meta/funcs.rs diff --git a/gcli/executor.rs b/gcli/executor.rs deleted file mode 100644 index 8b137891791..00000000000 --- a/gcli/executor.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/gcli/src/meta/executor.rs b/gcli/src/meta/executor.rs index 013b686d6b1..713f1c5e70a 100644 --- a/gcli/src/meta/executor.rs +++ b/gcli/src/meta/executor.rs @@ -16,7 +16,6 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use super::funcs; use anyhow::{anyhow, Result}; use wasmi::{AsContextMut, Engine, Extern, Linker, Memory, MemoryType, Module, Store}; @@ -70,9 +69,150 @@ pub fn execute(wasm: &[u8], method: &str) -> Result> { let metadata = instance .get_export(&store, method) .and_then(Extern::into_func) - .ok_or_else(|| anyhow!("could not find function \"metadata\""))? + .ok_or_else(|| anyhow!("could not find function \"{}\"", method))? .typed::<(), (), _>(&mut store)?; metadata.call(&mut store, ())?; Ok(store.state().msg.clone()) } + +mod funcs { + use super::HostState; + use wasmi::{ + core::{memory_units::Pages, Trap, TrapCode}, + AsContext, AsContextMut, Caller, Extern, Func, Memory, Store, + }; + + pub fn alloc(store: &mut Store, memory: Memory) -> Extern { + Extern::Func(Func::wrap( + store, + move |mut caller: Caller<'_, HostState>, pages: i32| { + memory + .clone() + .grow(caller.as_context_mut(), Pages(pages as usize)) + .map_or_else( + |err| { + log::error!("{err:?}"); + u32::MAX as i32 + }, + |pages| pages.0 as i32, + ) + }, + )) + } + + pub fn free(ctx: impl AsContextMut) -> Extern { + Extern::Func(Func::wrap(ctx, |_: i32| 0)) + } + + pub fn gr_panic(ctx: &mut Store, _memory: Memory) -> Extern { + Extern::Func(Func::wrap( + ctx, + move |mut _caller: Caller<'_, HostState>, _ptr: u32, _len: i32| {}, + )) + } + + pub fn gr_oom_panic(ctx: impl AsContextMut) -> Extern { + Extern::Func(Func::wrap(ctx, || { + log::error!("OOM panic occurred"); + Ok(()) + })) + } + + pub fn gr_read(ctx: &mut Store, memory: Memory) -> Extern { + Extern::Func(Func::wrap( + ctx, + move |mut caller: Caller<'_, HostState>, at: u32, len: i32, buff: i32, err: i32| { + let (at, len, buff, err) = (at as _, len as _, buff as _, err as _); + + let msg = &caller.host_data().msg; + let mut payload = vec![0; len]; + if at + len <= msg.len() { + payload.copy_from_slice(&msg[at..(at + len)]); + } else { + return Err(Trap::Code(TrapCode::MemoryAccessOutOfBounds)); + } + + let len: u32 = memory + .clone() + .write(caller.as_context_mut(), buff, &payload) + .map_err(|e| log::error!("{:?}", e)) + .is_err() + .into(); + + memory + .clone() + .write(caller.as_context_mut(), err, &len.to_le_bytes()) + .map_err(|e| { + log::error!("{:?}", e); + Trap::Code(TrapCode::MemoryAccessOutOfBounds) + })?; + + Ok(()) + }, + )) + } + + pub fn gr_reply(ctx: &mut Store, memory: Memory) -> Extern { + Extern::Func(Func::wrap( + ctx, + move |mut caller: Caller<'_, HostState>, ptr: u32, len: i32, _value: i32, _err: i32| { + let mut result = vec![0; len as usize]; + + memory + .read(caller.as_context(), ptr as usize, &mut result) + .map_err(|e| { + log::error!("{:?}", e); + Trap::Code(TrapCode::MemoryAccessOutOfBounds) + })?; + caller.host_data_mut().msg = result; + + Ok(()) + }, + )) + } + + pub fn gr_size(ctx: &mut Store, memory: Memory) -> Extern { + Extern::Func(Func::wrap( + ctx, + move |mut caller: Caller<'_, HostState>, size_ptr: u32| { + let size = caller.host_data().msg.len() as u32; + + memory + .clone() + .write( + caller.as_context_mut(), + size_ptr as usize, + &size.to_le_bytes(), + ) + .map_err(|e| { + log::error!("{:?}", e); + Trap::Code(TrapCode::MemoryAccessOutOfBounds) + })?; + + Ok(()) + }, + )) + } + + pub fn gr_out_of_gas(ctx: &mut Store) -> Extern { + Extern::Func(Func::wrap( + ctx, + move |_caller: Caller<'_, HostState>| Ok(()), + )) + } + + pub fn gr_block_height(ctx: &mut Store) -> Extern { + Extern::Func(Func::wrap( + ctx, + move |_caller: Caller<'_, HostState>, _height: u32| Ok(()), + )) + } + + pub fn gr_block_timestamp(ctx: &mut Store) -> Extern { + Extern::Func(Func::wrap( + ctx, + move |_caller: Caller<'_, HostState>, _timestamp: u32| Ok(()), + )) + } +} diff --git a/gcli/src/meta/funcs.rs b/gcli/src/meta/funcs.rs deleted file mode 100644 index 2e2011b28bb..00000000000 --- a/gcli/src/meta/funcs.rs +++ /dev/null @@ -1,156 +0,0 @@ -// This file is part of Gear. -// -// Copyright (C) 2021-2023 Gear Technologies Inc. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -use super::executor::HostState; -use wasmi::{ - core::{memory_units::Pages, Trap, TrapCode}, - AsContext, AsContextMut, Caller, Extern, Func, Memory, Store, -}; - -pub fn alloc(store: &mut Store, memory: Memory) -> Extern { - Extern::Func(Func::wrap( - store, - move |mut caller: Caller<'_, HostState>, pages: i32| { - memory - .clone() - .grow(caller.as_context_mut(), Pages(pages as usize)) - .map_or_else( - |err| { - log::error!("{err:?}"); - u32::MAX as i32 - }, - |pages| pages.0 as i32, - ) - }, - )) -} - -pub fn free(ctx: impl AsContextMut) -> Extern { - Extern::Func(Func::wrap(ctx, |_: i32| 0)) -} - -pub fn gr_panic(ctx: &mut Store, _memory: Memory) -> Extern { - Extern::Func(Func::wrap( - ctx, - move |mut _caller: Caller<'_, HostState>, _ptr: u32, _len: i32| {}, - )) -} - -pub fn gr_oom_panic(ctx: impl AsContextMut) -> Extern { - Extern::Func(Func::wrap(ctx, || { - log::error!("OOM panic occurred"); - Ok(()) - })) -} - -pub fn gr_read(ctx: &mut Store, memory: Memory) -> Extern { - Extern::Func(Func::wrap( - ctx, - move |mut caller: Caller<'_, HostState>, at: u32, len: i32, buff: i32, err: i32| { - let (at, len, buff, err) = (at as _, len as _, buff as _, err as _); - - let msg = &caller.host_data().msg; - let mut payload = vec![0; len]; - if at + len <= msg.len() { - payload.copy_from_slice(&msg[at..(at + len)]); - } else { - return Err(Trap::Code(TrapCode::MemoryAccessOutOfBounds)); - } - - let len: u32 = memory - .clone() - .write(caller.as_context_mut(), buff, &payload) - .map_err(|e| log::error!("{:?}", e)) - .is_err() - .into(); - - memory - .clone() - .write(caller.as_context_mut(), err, &len.to_le_bytes()) - .map_err(|e| { - log::error!("{:?}", e); - Trap::Code(TrapCode::MemoryAccessOutOfBounds) - })?; - - Ok(()) - }, - )) -} - -pub fn gr_reply(ctx: &mut Store, memory: Memory) -> Extern { - Extern::Func(Func::wrap( - ctx, - move |mut caller: Caller<'_, HostState>, ptr: u32, len: i32, _value: i32, _err: i32| { - let mut result = vec![0; len as usize]; - - memory - .read(caller.as_context(), ptr as usize, &mut result) - .map_err(|e| { - log::error!("{:?}", e); - Trap::Code(TrapCode::MemoryAccessOutOfBounds) - })?; - caller.host_data_mut().msg = result; - - Ok(()) - }, - )) -} - -pub fn gr_size(ctx: &mut Store, memory: Memory) -> Extern { - Extern::Func(Func::wrap( - ctx, - move |mut caller: Caller<'_, HostState>, size_ptr: u32| { - let size = caller.host_data().msg.len() as u32; - - memory - .clone() - .write( - caller.as_context_mut(), - size_ptr as usize, - &size.to_le_bytes(), - ) - .map_err(|e| { - log::error!("{:?}", e); - Trap::Code(TrapCode::MemoryAccessOutOfBounds) - })?; - - Ok(()) - }, - )) -} - -pub fn gr_out_of_gas(ctx: &mut Store) -> Extern { - Extern::Func(Func::wrap( - ctx, - move |_caller: Caller<'_, HostState>| Ok(()), - )) -} - -pub fn gr_block_height(ctx: &mut Store) -> Extern { - Extern::Func(Func::wrap( - ctx, - move |_caller: Caller<'_, HostState>, _height: u32| Ok(()), - )) -} - -pub fn gr_block_timestamp(ctx: &mut Store) -> Extern { - Extern::Func(Func::wrap( - ctx, - move |_caller: Caller<'_, HostState>, _timestamp: u32| Ok(()), - )) -} diff --git a/gcli/src/meta/mod.rs b/gcli/src/meta/mod.rs index c361ca4a3c1..f914bd6d3dc 100644 --- a/gcli/src/meta/mod.rs +++ b/gcli/src/meta/mod.rs @@ -18,7 +18,6 @@ //! Program metadata parser mod executor; -mod funcs; mod registry; #[cfg(test)] mod tests; From 608b6bef5bb8cbe0a1b31d917299bc603c52770d Mon Sep 17 00:00:00 2001 From: clearloop <26088946+clearloop@users.noreply.github.com> Date: Fri, 6 Oct 2023 13:28:17 +0800 Subject: [PATCH 10/22] chore(gcli): address comments --- gcli/src/meta/executor.rs | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/gcli/src/meta/executor.rs b/gcli/src/meta/executor.rs index 713f1c5e70a..99d706b3152 100644 --- a/gcli/src/meta/executor.rs +++ b/gcli/src/meta/executor.rs @@ -25,7 +25,6 @@ const PAGE_STORAGE_PREFIX: [u8; 32] = *b"gcligcligcligcligcligcligcligcli"; #[derive(Default)] pub struct HostState { pub msg: Vec, - pub timestamp: u64, pub height: u64, } @@ -105,10 +104,18 @@ mod funcs { Extern::Func(Func::wrap(ctx, |_: i32| 0)) } - pub fn gr_panic(ctx: &mut Store, _memory: Memory) -> Extern { + pub fn gr_panic(ctx: &mut Store, memory: Memory) -> Extern { Extern::Func(Func::wrap( ctx, - move |mut _caller: Caller<'_, HostState>, _ptr: u32, _len: i32| {}, + move |caller: Caller<'_, HostState>, ptr: u32, len: i32| { + let mut buff = Vec::with_capacity(len as usize); + memory.read(caller, ptr as usize, &mut buff).map_err(|e| { + log::error!("{e:?}"); + Trap::Code(TrapCode::MemoryAccessOutOfBounds) + })?; + + Ok(()) + }, )) } @@ -123,15 +130,14 @@ mod funcs { Extern::Func(Func::wrap( ctx, move |mut caller: Caller<'_, HostState>, at: u32, len: i32, buff: i32, err: i32| { - let (at, len, buff, err) = (at as _, len as _, buff as _, err as _); + let (at, len, buff, err) = (at as _, len as usize, buff as _, err as _); let msg = &caller.host_data().msg; - let mut payload = vec![0; len]; - if at + len <= msg.len() { - payload.copy_from_slice(&msg[at..(at + len)]); + let payload = if at + len <= msg.len() { + msg[at..(at + len)].to_vec() } else { return Err(Trap::Code(TrapCode::MemoryAccessOutOfBounds)); - } + }; let len: u32 = memory .clone() From ed0edcbda9808de94764743a0b5f7e96eed3fd24 Mon Sep 17 00:00:00 2001 From: clearloop <26088946+clearloop@users.noreply.github.com> Date: Fri, 6 Oct 2023 20:26:39 +0800 Subject: [PATCH 11/22] chore(gcli): log panicking message --- gcli/src/meta/executor.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/gcli/src/meta/executor.rs b/gcli/src/meta/executor.rs index 99d706b3152..76e28b1d5df 100644 --- a/gcli/src/meta/executor.rs +++ b/gcli/src/meta/executor.rs @@ -114,6 +114,7 @@ mod funcs { Trap::Code(TrapCode::MemoryAccessOutOfBounds) })?; + log::error!("Panic: {}", String::from_utf8_lossy(&buff)); Ok(()) }, )) From 1d0a396dbbb2b8bc73cf45628d1d934fab26ae2b Mon Sep 17 00:00:00 2001 From: clearloop <26088946+clearloop@users.noreply.github.com> Date: Fri, 6 Oct 2023 20:50:42 +0800 Subject: [PATCH 12/22] docs(gcli): explain why some of the host functions are missing logics --- gcli/src/meta/executor.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/gcli/src/meta/executor.rs b/gcli/src/meta/executor.rs index 76e28b1d5df..f986538469c 100644 --- a/gcli/src/meta/executor.rs +++ b/gcli/src/meta/executor.rs @@ -16,6 +16,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +//! The WASM executor in this module is just for parsing the state types +//! of gear programs, some of the host functions are missing logics that +//! is because they are for the on-chain environment data. + use anyhow::{anyhow, Result}; use wasmi::{AsContextMut, Engine, Extern, Linker, Memory, MemoryType, Module, Store}; @@ -25,7 +29,6 @@ const PAGE_STORAGE_PREFIX: [u8; 32] = *b"gcligcligcligcligcligcligcligcli"; #[derive(Default)] pub struct HostState { pub msg: Vec, - pub height: u64, } /// Executes the WASM code. @@ -52,12 +55,6 @@ pub fn execute(wasm: &[u8], method: &str) -> Result> { linker.define("env", "gr_panic", funcs::gr_panic(&mut store, memory))?; linker.define("env", "gr_oom_panic", funcs::gr_oom_panic(&mut store))?; linker.define("env", "gr_out_of_gas", funcs::gr_out_of_gas(&mut store))?; - linker.define("env", "gr_block_height", funcs::gr_block_height(&mut store))?; - linker.define( - "env", - "gr_block_timestamp", - funcs::gr_block_timestamp(&mut store), - )?; } let instance = linker From 1329581bec207041093a276696f6ff34ad2dbe2b Mon Sep 17 00:00:00 2001 From: clearloop <26088946+clearloop@users.noreply.github.com> Date: Fri, 6 Oct 2023 21:41:50 +0800 Subject: [PATCH 13/22] chore(gcli): get back block_timestamp and block_height --- gcli/src/meta/executor.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/gcli/src/meta/executor.rs b/gcli/src/meta/executor.rs index f986538469c..b0eb205e5a6 100644 --- a/gcli/src/meta/executor.rs +++ b/gcli/src/meta/executor.rs @@ -55,6 +55,12 @@ pub fn execute(wasm: &[u8], method: &str) -> Result> { linker.define("env", "gr_panic", funcs::gr_panic(&mut store, memory))?; linker.define("env", "gr_oom_panic", funcs::gr_oom_panic(&mut store))?; linker.define("env", "gr_out_of_gas", funcs::gr_out_of_gas(&mut store))?; + linker.define("env", "gr_block_height", funcs::gr_block_height(&mut store))?; + linker.define( + "env", + "gr_block_timestamp", + funcs::gr_block_timestamp(&mut store), + )?; } let instance = linker From 3ebc93b0cb8b799fe7706318963fdc2cfc8d7046 Mon Sep 17 00:00:00 2001 From: clearloop <26088946+clearloop@users.noreply.github.com> Date: Tue, 17 Oct 2023 04:20:24 +0800 Subject: [PATCH 14/22] feat(gcli): introduce macro for declaring host functions --- Cargo.lock | 1 - gcli/Cargo.toml | 2 +- gcli/bin/gcli.rs | 2 +- gcli/src/meta/executor.rs | 86 ++++++++++++--------------------------- 4 files changed, 27 insertions(+), 64 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 84b0d6f0df6..dc8c6c37ec7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3837,7 +3837,6 @@ dependencies = [ "sp-io", "thiserror", "tokio", - "vara-runtime", "wasmi 0.14.0", "which", "whoami", diff --git a/gcli/Cargo.toml b/gcli/Cargo.toml index 829c03f6dc3..f8799be06d9 100644 --- a/gcli/Cargo.toml +++ b/gcli/Cargo.toml @@ -47,7 +47,7 @@ etc.workspace = true sp-io = { workspace = true, features = [ "std" ] } sp-core = { workspace = true, features = [ "std" ] } wasmi = { workspace = true, features = ["std"] } -vara-runtime = { workspace = true, features = [ "std", "dev" ] } +# vara-runtime = { workspace = true, features = [ "std", "dev" ] } [dev-dependencies] rand.workspace = true diff --git a/gcli/bin/gcli.rs b/gcli/bin/gcli.rs index 02fa6f9385c..51795641661 100644 --- a/gcli/bin/gcli.rs +++ b/gcli/bin/gcli.rs @@ -23,7 +23,7 @@ use color_eyre::eyre::Result; async fn main() -> Result<()> { color_eyre::install()?; - sp_core::crypto::set_default_ss58_version(vara_runtime::SS58Prefix::get().try_into().unwrap()); + // sp_core::crypto::set_default_ss58_version(vara_runtime::SS58Prefix::get().try_into().unwrap()); if let Err(e) = gcli::cmd::Opt::run().await { log::error!("{}", e); diff --git a/gcli/src/meta/executor.rs b/gcli/src/meta/executor.rs index b0eb205e5a6..8dd8aac9919 100644 --- a/gcli/src/meta/executor.rs +++ b/gcli/src/meta/executor.rs @@ -21,16 +21,31 @@ //! is because they are for the on-chain environment data. use anyhow::{anyhow, Result}; -use wasmi::{AsContextMut, Engine, Extern, Linker, Memory, MemoryType, Module, Store}; +use wasmi::{ + AsContextMut, Caller, Engine, Extern, Func, Linker, Memory, MemoryType, Module, Store, +}; const PAGE_STORAGE_PREFIX: [u8; 32] = *b"gcligcligcligcligcligcligcligcli"; /// HostState for the WASM executor #[derive(Default)] pub struct HostState { + /// Message buffer in host state. pub msg: Vec, } +macro_rules! func { + ($store:tt) => { + func!($store,) + }; + ($store:tt, $($ty:tt),* ) => { + Func::wrap( + &mut $store, + move |_caller: Caller<'_, HostState>, $(_: $ty),*| { Ok(()) }, + ) + }; +} + /// Executes the WASM code. pub fn execute(wasm: &[u8], method: &str) -> Result> { assert!(gear_lazy_pages_interface::try_to_enable_lazy_pages( @@ -47,20 +62,17 @@ pub fn execute(wasm: &[u8], method: &str) -> Result> { { let memory = Memory::new(store.as_context_mut(), MemoryType::new(256, None)).unwrap(); linker.define("env", "memory", Extern::Memory(memory))?; - linker.define("env", "gr_read", funcs::gr_read(&mut store, memory))?; linker.define("env", "alloc", funcs::alloc(&mut store, memory))?; - linker.define("env", "free", funcs::free(&mut store))?; - linker.define("env", "gr_size", funcs::gr_size(&mut store, memory))?; + linker.define("env", "gr_read", funcs::gr_read(&mut store, memory))?; linker.define("env", "gr_reply", funcs::gr_reply(&mut store, memory))?; - linker.define("env", "gr_panic", funcs::gr_panic(&mut store, memory))?; - linker.define("env", "gr_oom_panic", funcs::gr_oom_panic(&mut store))?; - linker.define("env", "gr_out_of_gas", funcs::gr_out_of_gas(&mut store))?; - linker.define("env", "gr_block_height", funcs::gr_block_height(&mut store))?; - linker.define( - "env", - "gr_block_timestamp", - funcs::gr_block_timestamp(&mut store), - )?; + linker.define("env", "gr_size", funcs::gr_size(&mut store, memory))?; + // methods may be used by programs but not required by metadata. + linker.define("env", "free", func!(store, i32))?; + linker.define("env", "gr_panic", func!(store, u32, i32))?; + linker.define("env", "gr_oom_panic", func!(store))?; + linker.define("env", "gr_out_of_gas", func!(store))?; + linker.define("env", "gr_block_height", func!(store, u32))?; + linker.define("env", "gr_block_timestamp", func!(store, u32))?; } let instance = linker @@ -103,33 +115,6 @@ mod funcs { )) } - pub fn free(ctx: impl AsContextMut) -> Extern { - Extern::Func(Func::wrap(ctx, |_: i32| 0)) - } - - pub fn gr_panic(ctx: &mut Store, memory: Memory) -> Extern { - Extern::Func(Func::wrap( - ctx, - move |caller: Caller<'_, HostState>, ptr: u32, len: i32| { - let mut buff = Vec::with_capacity(len as usize); - memory.read(caller, ptr as usize, &mut buff).map_err(|e| { - log::error!("{e:?}"); - Trap::Code(TrapCode::MemoryAccessOutOfBounds) - })?; - - log::error!("Panic: {}", String::from_utf8_lossy(&buff)); - Ok(()) - }, - )) - } - - pub fn gr_oom_panic(ctx: impl AsContextMut) -> Extern { - Extern::Func(Func::wrap(ctx, || { - log::error!("OOM panic occurred"); - Ok(()) - })) - } - pub fn gr_read(ctx: &mut Store, memory: Memory) -> Extern { Extern::Func(Func::wrap( ctx, @@ -204,25 +189,4 @@ mod funcs { }, )) } - - pub fn gr_out_of_gas(ctx: &mut Store) -> Extern { - Extern::Func(Func::wrap( - ctx, - move |_caller: Caller<'_, HostState>| Ok(()), - )) - } - - pub fn gr_block_height(ctx: &mut Store) -> Extern { - Extern::Func(Func::wrap( - ctx, - move |_caller: Caller<'_, HostState>, _height: u32| Ok(()), - )) - } - - pub fn gr_block_timestamp(ctx: &mut Store) -> Extern { - Extern::Func(Func::wrap( - ctx, - move |_caller: Caller<'_, HostState>, _timestamp: u32| Ok(()), - )) - } } From 18cdf6bb414348bf9cdf3708b16567e1e8597c19 Mon Sep 17 00:00:00 2001 From: clearloop <26088946+clearloop@users.noreply.github.com> Date: Thu, 19 Oct 2023 03:12:42 +0800 Subject: [PATCH 15/22] feat(gcli): complete all imports --- gcli/src/meta/executor.rs | 122 +++++++++++++++++++++++++++++++++++++- 1 file changed, 119 insertions(+), 3 deletions(-) diff --git a/gcli/src/meta/executor.rs b/gcli/src/meta/executor.rs index 8dd8aac9919..3636a6b58a4 100644 --- a/gcli/src/meta/executor.rs +++ b/gcli/src/meta/executor.rs @@ -59,20 +59,113 @@ pub fn execute(wasm: &[u8], method: &str) -> Result> { let mut linker = >::new(); // Execution environment + // + // TODO: refactor this after #3416. { let memory = Memory::new(store.as_context_mut(), MemoryType::new(256, None)).unwrap(); linker.define("env", "memory", Extern::Memory(memory))?; linker.define("env", "alloc", funcs::alloc(&mut store, memory))?; + linker.define("env", "gr_oom_panic", funcs::gr_oom_panic(&mut store))?; linker.define("env", "gr_read", funcs::gr_read(&mut store, memory))?; linker.define("env", "gr_reply", funcs::gr_reply(&mut store, memory))?; + linker.define("env", "gr_panic", funcs::gr_panic(&mut store, memory))?; linker.define("env", "gr_size", funcs::gr_size(&mut store, memory))?; // methods may be used by programs but not required by metadata. linker.define("env", "free", func!(store, i32))?; - linker.define("env", "gr_panic", func!(store, u32, i32))?; - linker.define("env", "gr_oom_panic", func!(store))?; - linker.define("env", "gr_out_of_gas", func!(store))?; linker.define("env", "gr_block_height", func!(store, u32))?; linker.define("env", "gr_block_timestamp", func!(store, u32))?; + linker.define( + "env", + "gr_create_program_wgas", + func!(store, i32, i32, u32, i32, u32, u64, u32, i32), + )?; + linker.define( + "env", + "gr_create_program", + func!(store, i32, i32, u32, i32, u32, u64, i32), + )?; + linker.define("env", "gr_debug", func!(store, i32, u32))?; + linker.define("env", "gr_exit", func!(store, i32))?; + linker.define("env", "gr_gas_available", func!(store, i32))?; + linker.define("env", "gr_leave", func!(store))?; + linker.define("env", "gr_message_id", func!(store, i32))?; + linker.define("env", "gr_out_of_gas", func!(store))?; + linker.define("env", "gr_pay_program_rent", func!(store, i32, i32))?; + linker.define("env", "gr_program_id", func!(store, i32))?; + linker.define("env", "gr_random", func!(store, i32, i32))?; + linker.define("env", "gr_reply", func!(store, i32, u32, i32, i32))?; + linker.define("env", "gr_reply_code", func!(store, i32))?; + linker.define("env", "gr_reply_commit", func!(store, i32, i32))?; + linker.define("env", "gr_reply_deposit", func!(store, i32, u64, i32))?; + linker.define("env", "gr_reply_input", func!(store, u32, u32, i32, i32))?; + linker.define("env", "gr_reply_push", func!(store, i32, u32, i32))?; + linker.define("env", "gr_reply_push_input", func!(store, u32, u32, i32))?; + linker.define( + "env", + "gr_reply_push_input_wgas", + func!(store, u32, u32, u64, i32, i32), + )?; + linker.define("env", "gr_reply_to", func!(store, i32))?; + linker.define( + "env", + "gr_reply_wgas", + func!(store, i32, u32, u64, i32, i32), + )?; + linker.define( + "env", + "gr_reservation_reply", + func!(store, i32, i32, u32, i32), + )?; + linker.define( + "env", + "gr_reservation_send_commit", + func!(store, u32, i32, u32, i32), + )?; + linker.define( + "env", + "gr_reservation_send", + func!(store, i32, i32, u32, u32, i32), + )?; + linker.define("env", "gr_reserve_gas", func!(store, u64, u32, i32))?; + linker.define("env", "gr_send", func!(store, i32, i32, u32, u32, i32))?; + linker.define("env", "gr_send_commit", func!(store, u32, i32, u32, i32))?; + linker.define( + "env", + "gr_send_commit_wgas", + func!(store, u32, i32, u64, u32, i32), + )?; + linker.define("env", "gr_send_init", func!(store, i32))?; + linker.define( + "env", + "gr_send_input", + func!(store, i32, u32, u32, u32, i32), + )?; + linker.define( + "env", + "gr_send_input_wgas", + func!(store, i32, u32, u32, u64, u32, i32), + )?; + linker.define("env", "gr_send_push", func!(store, u32, i32, u32, i32))?; + linker.define( + "env", + "gr_send_push_input", + func!(store, u32, u32, u32, i32), + )?; + linker.define( + "env", + "gr_send_wgas", + func!(store, i32, i32, u32, u64, u32, i32), + )?; + linker.define("env", "gr_signal_code", func!(store, i32))?; + linker.define("env", "gr_signal_from", func!(store, i32))?; + linker.define("env", "gr_source", func!(store, i32))?; + linker.define("env", "gr_system_reserve_gas", func!(store, u64, i32))?; + linker.define("env", "gr_unreserve_gas", func!(store, i32, i32))?; + linker.define("env", "gr_value", func!(store, i32))?; + linker.define("env", "gr_wait", func!(store, u32))?; + linker.define("env", "gr_wait_for", func!(store, u32))?; + linker.define("env", "gr_wait_up_to", func!(store, u32))?; + linker.define("env", "gr_wake", func!(store, i32, u32, i32))?; } let instance = linker @@ -189,4 +282,27 @@ mod funcs { }, )) } + + pub fn gr_panic(ctx: &mut Store, memory: Memory) -> Extern { + Extern::Func(Func::wrap( + ctx, + move |caller: Caller<'_, HostState>, ptr: u32, len: i32| { + let mut buff = Vec::with_capacity(len as usize); + memory.read(caller, ptr as usize, &mut buff).map_err(|e| { + log::error!("{e:?}"); + Trap::Code(TrapCode::MemoryAccessOutOfBounds) + })?; + + log::error!("Panic: {}", String::from_utf8_lossy(&buff)); + Ok(()) + }, + )) + } + + pub fn gr_oom_panic(ctx: impl AsContextMut) -> Extern { + Extern::Func(Func::wrap(ctx, || { + log::error!("OOM panic occurred"); + Ok(()) + })) + } } From b5f15efa734800a974ec5c670fc6030cad4089c6 Mon Sep 17 00:00:00 2001 From: clearloop <26088946+clearloop@users.noreply.github.com> Date: Thu, 19 Oct 2023 11:52:35 +0800 Subject: [PATCH 16/22] chore(gcli): wrap results for method free --- gcli/src/meta/executor.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/gcli/src/meta/executor.rs b/gcli/src/meta/executor.rs index 3636a6b58a4..84f8c87c5c4 100644 --- a/gcli/src/meta/executor.rs +++ b/gcli/src/meta/executor.rs @@ -44,6 +44,12 @@ macro_rules! func { move |_caller: Caller<'_, HostState>, $(_: $ty),*| { Ok(()) }, ) }; + (@result $store:tt, $($ty:tt),* ) => { + Func::wrap( + &mut $store, + move |_caller: Caller<'_, HostState>, $(_: $ty),*| { 0 }, + ) + }; } /// Executes the WASM code. @@ -71,7 +77,7 @@ pub fn execute(wasm: &[u8], method: &str) -> Result> { linker.define("env", "gr_panic", funcs::gr_panic(&mut store, memory))?; linker.define("env", "gr_size", funcs::gr_size(&mut store, memory))?; // methods may be used by programs but not required by metadata. - linker.define("env", "free", func!(store, i32))?; + linker.define("env", "free", func!(@result store, i32))?; linker.define("env", "gr_block_height", func!(store, u32))?; linker.define("env", "gr_block_timestamp", func!(store, u32))?; linker.define( @@ -93,7 +99,6 @@ pub fn execute(wasm: &[u8], method: &str) -> Result> { linker.define("env", "gr_pay_program_rent", func!(store, i32, i32))?; linker.define("env", "gr_program_id", func!(store, i32))?; linker.define("env", "gr_random", func!(store, i32, i32))?; - linker.define("env", "gr_reply", func!(store, i32, u32, i32, i32))?; linker.define("env", "gr_reply_code", func!(store, i32))?; linker.define("env", "gr_reply_commit", func!(store, i32, i32))?; linker.define("env", "gr_reply_deposit", func!(store, i32, u64, i32))?; From ad94391ea95f1886ef5a0e563afb0e38455c6f62 Mon Sep 17 00:00:00 2001 From: clearloop <26088946+clearloop@users.noreply.github.com> Date: Thu, 19 Oct 2023 12:04:33 +0800 Subject: [PATCH 17/22] chore(gcli): wrap method call_metadata --- gcli/src/meta/executor.rs | 7 ++++++- gcli/src/meta/mod.rs | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/gcli/src/meta/executor.rs b/gcli/src/meta/executor.rs index 84f8c87c5c4..404d5accb76 100644 --- a/gcli/src/meta/executor.rs +++ b/gcli/src/meta/executor.rs @@ -52,8 +52,13 @@ macro_rules! func { }; } +/// Call `metadata` method in the WASM code. +pub fn call_metadata(wasm: &[u8]) -> Result> { + execute(wasm, "metadata") +} + /// Executes the WASM code. -pub fn execute(wasm: &[u8], method: &str) -> Result> { +fn execute(wasm: &[u8], method: &str) -> Result> { assert!(gear_lazy_pages_interface::try_to_enable_lazy_pages( PAGE_STORAGE_PREFIX )); diff --git a/gcli/src/meta/mod.rs b/gcli/src/meta/mod.rs index f914bd6d3dc..1a34dd2af0d 100644 --- a/gcli/src/meta/mod.rs +++ b/gcli/src/meta/mod.rs @@ -113,7 +113,7 @@ impl Meta { TryNewCodeConfig::new_no_exports_check(), )?; let (code, _) = InstrumentedCodeAndId::from(CodeAndId::new(code)).into_parts(); - let result = executor::execute(code.code(), "metadata")?; + let result = executor::call_metadata(code.code())?; Ok(Self::Wasm(MetawasmData::decode(&mut result.as_ref())?)) } From 6d9ab5a67bd539407aeb65beffc67456749e5e80 Mon Sep 17 00:00:00 2001 From: clearloop <26088946+clearloop@users.noreply.github.com> Date: Thu, 19 Oct 2023 14:44:52 +0800 Subject: [PATCH 18/22] chore(gcli): parse metadata from local node --- gcli/tests/cmd/program.rs | 12 ++++++++---- gcli/tests/cmd/send.rs | 1 + gcli/tests/common/mod.rs | 7 ++++--- gcli/tests/common/node.rs | 1 - gcli/tests/common/result.rs | 2 ++ gsdk/src/signer/utils.rs | 1 + 6 files changed, 16 insertions(+), 8 deletions(-) delete mode 100644 gcli/tests/common/node.rs diff --git a/gcli/tests/cmd/program.rs b/gcli/tests/cmd/program.rs index 46c83bbfb22..d1e1594afa1 100644 --- a/gcli/tests/cmd/program.rs +++ b/gcli/tests/cmd/program.rs @@ -97,9 +97,10 @@ Metadata { #[test] fn test_command_program_metadata_works() -> Result<()> { + let node = common::dev()?; let meta = env::wasm_bin("demo_new_meta.meta.txt"); let args = Args::new("program").action("meta").meta(meta); - let result = common::gcli(Vec::::from(args)).expect("run gcli failed"); + let result = node.run(args)?; let stdout = result.stdout.convert(); assert_eq!( @@ -113,13 +114,14 @@ fn test_command_program_metadata_works() -> Result<()> { #[test] fn test_command_program_metadata_derive_works() -> Result<()> { let meta = env::wasm_bin("demo_new_meta.meta.txt"); + let node = common::dev()?; let args = Args::new("program") .action("meta") .meta(meta) .flag("--derive") .derive("Person"); - let result = common::gcli(Vec::::from(args)).expect("run gcli failed"); + let result = node.run(args)?; let stdout = result.stdout.convert(); let expected = "Person { surname: String, name: String }"; @@ -153,9 +155,10 @@ Exports { #[test] fn test_command_program_metawasm_works() -> Result<()> { + let node = common::dev()?; let meta = env::wasm_bin("demo_meta_state_v1.meta.wasm"); let args = Args::new("program").action("meta").meta(meta); - let result = common::gcli(Vec::::from(args)).expect("run gcli failed"); + let result = node.run(args)?; let stdout = result.stdout.convert(); assert_eq!( @@ -168,6 +171,7 @@ fn test_command_program_metawasm_works() -> Result<()> { #[test] fn test_command_program_metawasm_derive_works() -> Result<()> { + let node = common::dev()?; let meta = env::wasm_bin("demo_meta_state_v1.meta.wasm"); let args = Args::new("program") .action("meta") @@ -175,7 +179,7 @@ fn test_command_program_metawasm_derive_works() -> Result<()> { .flag("--derive") .derive("Person"); - let result = common::gcli(Vec::::from(args)).expect("run gcli failed"); + let result = node.run(args)?; let stdout = result.stdout.convert(); let expected = "Person { surname: String, name: String }"; diff --git a/gcli/tests/cmd/send.rs b/gcli/tests/cmd/send.rs index a1933576f03..83d8fb2020c 100644 --- a/gcli/tests/cmd/send.rs +++ b/gcli/tests/cmd/send.rs @@ -36,6 +36,7 @@ async fn test_command_send_works() -> Result<()> { // Send message to messager let dest = hex::encode(mailbox[0].0.source.0); let _ = node.run(Args::new("send").destination(dest).gas_limit("2000000000"))?; + let mailbox = signer .api() .mailbox(Some(common::alice_account_id()), 10) diff --git a/gcli/tests/common/mod.rs b/gcli/tests/common/mod.rs index dbbafc92d1c..78494bb3d1b 100644 --- a/gcli/tests/common/mod.rs +++ b/gcli/tests/common/mod.rs @@ -20,7 +20,7 @@ pub use self::{ args::Args, result::{Error, Result}, - traits::NodeExec, + traits::{Convert, NodeExec}, }; use gear_core::ids::{CodeId, ProgramId}; use gsdk::{ @@ -60,13 +60,14 @@ impl NodeExec for Node { /// Run binary `gcli` pub fn gcli(args: impl IntoIterator) -> Result { - Ok(Command::new(env::bin("gcli")) + Command::new(env::bin("gcli")) .args( args.into_iter() .map(|v| v.to_string()) .collect::>(), ) - .output()?) + .output() + .map_err(Into::into) } /// Run the dev node diff --git a/gcli/tests/common/node.rs b/gcli/tests/common/node.rs deleted file mode 100644 index 8b137891791..00000000000 --- a/gcli/tests/common/node.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/gcli/tests/common/result.rs b/gcli/tests/common/result.rs index ca23e82a260..aa2a5ab642e 100644 --- a/gcli/tests/common/result.rs +++ b/gcli/tests/common/result.rs @@ -18,6 +18,8 @@ #[derive(Debug, thiserror::Error)] pub enum Error { + #[error(transparent)] + Anyhow(#[from] anyhow::Error), #[error(transparent)] GCli(#[from] gcli::result::Error), #[error(transparent)] diff --git a/gsdk/src/signer/utils.rs b/gsdk/src/signer/utils.rs index 759d2477c63..84a568ef556 100644 --- a/gsdk/src/signer/utils.rs +++ b/gsdk/src/signer/utils.rs @@ -196,6 +196,7 @@ impl Inner { call: Call, fields: impl Into>, ) -> Result { + log::info!("Run tx: {}::{}", Call::PALLET, call.call_name()); let tx = subxt::dynamic::tx(Call::PALLET, call.call_name(), fields.into()); self.process(tx).await From c44843b30fea8625fe52ec7e9f7ad36a7edb3e2a Mon Sep 17 00:00:00 2001 From: clearloop <26088946+clearloop@users.noreply.github.com> Date: Fri, 20 Oct 2023 09:31:06 +0800 Subject: [PATCH 19/22] feat(gcli): add back vara-runtime --- gcli/Cargo.toml | 2 +- gcli/bin/gcli.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gcli/Cargo.toml b/gcli/Cargo.toml index dd9d131569f..296e382b2a0 100644 --- a/gcli/Cargo.toml +++ b/gcli/Cargo.toml @@ -47,7 +47,7 @@ etc.workspace = true sp-io = { workspace = true, features = [ "std" ] } sp-core = { workspace = true, features = [ "std" ] } wasmi = { workspace = true, features = ["std"] } -# vara-runtime = { workspace = true, features = [ "std", "dev" ] } +vara-runtime = { workspace = true, features = [ "std", "dev" ] } [dev-dependencies] rand.workspace = true diff --git a/gcli/bin/gcli.rs b/gcli/bin/gcli.rs index 51795641661..02fa6f9385c 100644 --- a/gcli/bin/gcli.rs +++ b/gcli/bin/gcli.rs @@ -23,7 +23,7 @@ use color_eyre::eyre::Result; async fn main() -> Result<()> { color_eyre::install()?; - // sp_core::crypto::set_default_ss58_version(vara_runtime::SS58Prefix::get().try_into().unwrap()); + sp_core::crypto::set_default_ss58_version(vara_runtime::SS58Prefix::get().try_into().unwrap()); if let Err(e) = gcli::cmd::Opt::run().await { log::error!("{}", e); From e152f6571beeb12d6bfcfeb2bf272518714a769a Mon Sep 17 00:00:00 2001 From: clearloop <26088946+clearloop@users.noreply.github.com> Date: Fri, 20 Oct 2023 09:42:22 +0800 Subject: [PATCH 20/22] chore(check): update Cargo.lock --- Cargo.lock | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.lock b/Cargo.lock index 3490e79f064..7701f3e4313 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3837,6 +3837,7 @@ dependencies = [ "sp-io", "thiserror", "tokio", + "vara-runtime", "wasmi 0.14.0", "which", "whoami", From e123edbfc119be77b0fe986bc64fd0230cf44f93 Mon Sep 17 00:00:00 2001 From: clearloop <26088946+clearloop@users.noreply.github.com> Date: Tue, 24 Oct 2023 12:57:07 +0800 Subject: [PATCH 21/22] feat(gcli): introduce function iterator for metadata executor --- Cargo.lock | 2 +- gcli/Cargo.toml | 3 +- gcli/src/meta/executor.rs | 288 +++++++++++++++++++------------------- 3 files changed, 144 insertions(+), 149 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7701f3e4313..4cb7705b394 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3838,7 +3838,7 @@ dependencies = [ "thiserror", "tokio", "vara-runtime", - "wasmi 0.14.0", + "wasmi 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)", "which", "whoami", ] diff --git a/gcli/Cargo.toml b/gcli/Cargo.toml index 296e382b2a0..a8e87b77c43 100644 --- a/gcli/Cargo.toml +++ b/gcli/Cargo.toml @@ -46,7 +46,8 @@ reqwest = { workspace = true, default-features = false, features = [ "json", "ru etc.workspace = true sp-io = { workspace = true, features = [ "std" ] } sp-core = { workspace = true, features = [ "std" ] } -wasmi = { workspace = true, features = ["std"] } +# TODO: use wasmi from workspace (#3214) +wasmi = { version = "0.30.0", features = ["std"] } vara-runtime = { workspace = true, features = [ "std", "dev" ] } [dev-dependencies] diff --git a/gcli/src/meta/executor.rs b/gcli/src/meta/executor.rs index 404d5accb76..f5854378120 100644 --- a/gcli/src/meta/executor.rs +++ b/gcli/src/meta/executor.rs @@ -21,9 +21,7 @@ //! is because they are for the on-chain environment data. use anyhow::{anyhow, Result}; -use wasmi::{ - AsContextMut, Caller, Engine, Extern, Func, Linker, Memory, MemoryType, Module, Store, -}; +use wasmi::{AsContextMut, Engine, Extern, Linker, Memory, MemoryType, Module, Store}; const PAGE_STORAGE_PREFIX: [u8; 32] = *b"gcligcligcligcligcligcligcligcli"; @@ -34,24 +32,6 @@ pub struct HostState { pub msg: Vec, } -macro_rules! func { - ($store:tt) => { - func!($store,) - }; - ($store:tt, $($ty:tt),* ) => { - Func::wrap( - &mut $store, - move |_caller: Caller<'_, HostState>, $(_: $ty),*| { Ok(()) }, - ) - }; - (@result $store:tt, $($ty:tt),* ) => { - Func::wrap( - &mut $store, - move |_caller: Caller<'_, HostState>, $(_: $ty),*| { 0 }, - ) - }; -} - /// Call `metadata` method in the WASM code. pub fn call_metadata(wasm: &[u8]) -> Result> { execute(wasm, "metadata") @@ -67,115 +47,26 @@ fn execute(wasm: &[u8], method: &str) -> Result> { let module = Module::new(&engine, wasm).unwrap(); let mut store = Store::new(&engine, HostState::default()); - let mut linker = >::new(); + let mut linker = >::new(&engine); + let memory = Memory::new( + store.as_context_mut(), + MemoryType::new(256, None).map_err(|_| anyhow!("failed to create memory type"))?, + ) + .map_err(|_| anyhow!("failed to create memory"))?; // Execution environment // // TODO: refactor this after #3416. { - let memory = Memory::new(store.as_context_mut(), MemoryType::new(256, None)).unwrap(); - linker.define("env", "memory", Extern::Memory(memory))?; - linker.define("env", "alloc", funcs::alloc(&mut store, memory))?; - linker.define("env", "gr_oom_panic", funcs::gr_oom_panic(&mut store))?; - linker.define("env", "gr_read", funcs::gr_read(&mut store, memory))?; - linker.define("env", "gr_reply", funcs::gr_reply(&mut store, memory))?; - linker.define("env", "gr_panic", funcs::gr_panic(&mut store, memory))?; - linker.define("env", "gr_size", funcs::gr_size(&mut store, memory))?; - // methods may be used by programs but not required by metadata. - linker.define("env", "free", func!(@result store, i32))?; - linker.define("env", "gr_block_height", func!(store, u32))?; - linker.define("env", "gr_block_timestamp", func!(store, u32))?; - linker.define( - "env", - "gr_create_program_wgas", - func!(store, i32, i32, u32, i32, u32, u64, u32, i32), - )?; - linker.define( - "env", - "gr_create_program", - func!(store, i32, i32, u32, i32, u32, u64, i32), - )?; - linker.define("env", "gr_debug", func!(store, i32, u32))?; - linker.define("env", "gr_exit", func!(store, i32))?; - linker.define("env", "gr_gas_available", func!(store, i32))?; - linker.define("env", "gr_leave", func!(store))?; - linker.define("env", "gr_message_id", func!(store, i32))?; - linker.define("env", "gr_out_of_gas", func!(store))?; - linker.define("env", "gr_pay_program_rent", func!(store, i32, i32))?; - linker.define("env", "gr_program_id", func!(store, i32))?; - linker.define("env", "gr_random", func!(store, i32, i32))?; - linker.define("env", "gr_reply_code", func!(store, i32))?; - linker.define("env", "gr_reply_commit", func!(store, i32, i32))?; - linker.define("env", "gr_reply_deposit", func!(store, i32, u64, i32))?; - linker.define("env", "gr_reply_input", func!(store, u32, u32, i32, i32))?; - linker.define("env", "gr_reply_push", func!(store, i32, u32, i32))?; - linker.define("env", "gr_reply_push_input", func!(store, u32, u32, i32))?; - linker.define( - "env", - "gr_reply_push_input_wgas", - func!(store, u32, u32, u64, i32, i32), - )?; - linker.define("env", "gr_reply_to", func!(store, i32))?; - linker.define( - "env", - "gr_reply_wgas", - func!(store, i32, u32, u64, i32, i32), - )?; - linker.define( - "env", - "gr_reservation_reply", - func!(store, i32, i32, u32, i32), - )?; - linker.define( - "env", - "gr_reservation_send_commit", - func!(store, u32, i32, u32, i32), - )?; - linker.define( - "env", - "gr_reservation_send", - func!(store, i32, i32, u32, u32, i32), - )?; - linker.define("env", "gr_reserve_gas", func!(store, u64, u32, i32))?; - linker.define("env", "gr_send", func!(store, i32, i32, u32, u32, i32))?; - linker.define("env", "gr_send_commit", func!(store, u32, i32, u32, i32))?; - linker.define( - "env", - "gr_send_commit_wgas", - func!(store, u32, i32, u64, u32, i32), - )?; - linker.define("env", "gr_send_init", func!(store, i32))?; - linker.define( - "env", - "gr_send_input", - func!(store, i32, u32, u32, u32, i32), - )?; - linker.define( - "env", - "gr_send_input_wgas", - func!(store, i32, u32, u32, u64, u32, i32), - )?; - linker.define("env", "gr_send_push", func!(store, u32, i32, u32, i32))?; - linker.define( - "env", - "gr_send_push_input", - func!(store, u32, u32, u32, i32), - )?; - linker.define( - "env", - "gr_send_wgas", - func!(store, i32, i32, u32, u64, u32, i32), - )?; - linker.define("env", "gr_signal_code", func!(store, i32))?; - linker.define("env", "gr_signal_from", func!(store, i32))?; - linker.define("env", "gr_source", func!(store, i32))?; - linker.define("env", "gr_system_reserve_gas", func!(store, u64, i32))?; - linker.define("env", "gr_unreserve_gas", func!(store, i32, i32))?; - linker.define("env", "gr_value", func!(store, i32))?; - linker.define("env", "gr_wait", func!(store, u32))?; - linker.define("env", "gr_wait_for", func!(store, u32))?; - linker.define("env", "gr_wait_up_to", func!(store, u32))?; - linker.define("env", "gr_wake", func!(store, i32, u32, i32))?; + let mut env = env::Env { + linker: &mut linker, + store: &mut store, + memory, + }; + + for import in module.imports() { + env.define(import.module(), import.name())?; + } } let instance = linker @@ -187,48 +78,151 @@ fn execute(wasm: &[u8], method: &str) -> Result> { .get_export(&store, method) .and_then(Extern::into_func) .ok_or_else(|| anyhow!("could not find function \"{}\"", method))? - .typed::<(), (), _>(&mut store)?; + .typed::<(), ()>(&mut store)?; metadata.call(&mut store, ())?; - Ok(store.state().msg.clone()) + Ok(store.data().msg.clone()) } -mod funcs { +mod env { use super::HostState; + use anyhow::{anyhow, Result}; use wasmi::{ - core::{memory_units::Pages, Trap, TrapCode}, - AsContext, AsContextMut, Caller, Extern, Func, Memory, Store, + core::{Pages, Trap, TrapCode}, + AsContext, AsContextMut, Caller, Extern, Func, Linker, Memory, Store, }; - pub fn alloc(store: &mut Store, memory: Memory) -> Extern { + /// Environment for the wasm execution. + pub struct Env<'e> { + pub linker: &'e mut Linker, + pub store: &'e mut Store, + pub memory: Memory, + } + + macro_rules! func { + ($store:tt) => { + func!($store,) + }; + ($store:tt, $($ty:tt),* ) => { + Extern::Func(Func::wrap( + $store, + move |_caller: Caller<'_, HostState>, $(_: $ty),*| { Ok(()) }, + )) + }; + (@result $store:tt, $($ty:tt),* ) => { + Extern::Func(Func::wrap( + $store, + move |_caller: Caller<'_, HostState>, $(_: $ty),*| { 0 }, + )) + }; + } + + impl Env<'_> { + /// Define function in the environment. + pub fn define(&mut self, module: &str, name: &str) -> Result<()> { + if module != "env" { + return Err(anyhow!("module \"{}\" not found", module)); + } + + let memory = self.memory.clone(); + let store = &mut self.store; + + let external = match name { + "memory" => Extern::Memory(memory), + "alloc" => alloc(self.store, memory), + "gr_oom_panic" => gr_oom_panic(store), + "gr_read" => gr_read(store, memory), + "gr_reply" => gr_reply(store, memory), + "gr_panic" => gr_panic(store, memory), + "gr_size" => gr_size(store, memory), + // methods may be used by programs but not required by metadata. + "free" => func!(@result store, i32), + "gr_block_height" => func!(store, u32), + "gr_block_timestamp" => func!(store, u32), + "gr_create_program_wgas" => func!(store, i32, i32, u32, i32, u32, u64, u32, i32), + "gr_create_program" => func!(store, i32, i32, u32, i32, u32, u64, i32), + "gr_debug" => func!(store, i32, u32), + "gr_exit" => func!(store, i32), + "gr_gas_available" => func!(store, i32), + "gr_leave" => func!(store), + "gr_message_id" => func!(store, i32), + "gr_out_of_gas" => func!(store), + "gr_pay_program_rent" => func!(store, i32, i32), + "gr_program_id" => func!(store, i32), + "gr_random" => func!(store, i32, i32), + "gr_reply_code" => func!(store, i32), + "gr_reply_commit" => func!(store, i32, i32), + "gr_reply_deposit" => func!(store, i32, u64, i32), + "gr_reply_input" => func!(store, u32, u32, i32, i32), + "gr_reply_push" => func!(store, i32, u32, i32), + "gr_reply_push_input" => func!(store, u32, u32, i32), + "gr_reply_push_input_wgas" => func!(store, u32, u32, u64, i32, i32), + "gr_reply_to" => func!(store, i32), + "gr_reply_wgas" => func!(store, i32, u32, u64, i32, i32), + "gr_reservation_reply" => func!(store, i32, i32, u32, i32), + "gr_reservation_send_commit" => func!(store, u32, i32, u32, i32), + "gr_reservation_send" => func!(store, i32, i32, u32, u32, i32), + "gr_reserve_gas" => func!(store, u64, u32, i32), + "gr_send" => func!(store, i32, i32, u32, u32, i32), + "gr_send_commit" => func!(store, u32, i32, u32, i32), + "gr_send_commit_wgas" => func!(store, u32, i32, u64, u32, i32), + "gr_send_init" => func!(store, i32), + "gr_send_input" => func!(store, i32, u32, u32, u32, i32), + "gr_send_input_wgas" => func!(store, i32, u32, u32, u64, u32, i32), + "gr_send_push" => func!(store, u32, i32, u32, i32), + "gr_send_push_input" => func!(store, u32, u32, u32, i32), + "gr_send_wgas" => func!(store, i32, i32, u32, u64, u32, i32), + "gr_signal_code" => func!(store, i32), + "gr_signal_from" => func!(store, i32), + "gr_source" => func!(store, i32), + "gr_system_reserve_gas" => func!(store, u64, i32), + "gr_unreserve_gas" => func!(store, i32, i32), + "gr_value" => func!(store, i32), + "gr_wait" => func!(store, u32), + "gr_wait_for" => func!(store, u32), + "gr_wait_up_to" => func!(store, u32), + "gr_wake" => func!(store, i32, u32, i32), + _ => return Err(anyhow!("export \"{}\" not found in env", name,)), + }; + + self.linker.define(module, name, external)?; + + Ok(()) + } + } + + fn alloc(store: &mut Store, memory: Memory) -> Extern { Extern::Func(Func::wrap( store, - move |mut caller: Caller<'_, HostState>, pages: i32| { + move |mut caller: Caller<'_, HostState>, pages: u32| { memory .clone() - .grow(caller.as_context_mut(), Pages(pages as usize)) + .grow( + caller.as_context_mut(), + Pages::new(pages).unwrap_or_default(), + ) .map_or_else( |err| { log::error!("{err:?}"); u32::MAX as i32 }, - |pages| pages.0 as i32, + |pages| pages.to_bytes().unwrap_or_default() as i32, ) }, )) } - pub fn gr_read(ctx: &mut Store, memory: Memory) -> Extern { + fn gr_read(ctx: &mut Store, memory: Memory) -> Extern { Extern::Func(Func::wrap( ctx, move |mut caller: Caller<'_, HostState>, at: u32, len: i32, buff: i32, err: i32| { let (at, len, buff, err) = (at as _, len as usize, buff as _, err as _); - let msg = &caller.host_data().msg; + let msg = &caller.data().msg; let payload = if at + len <= msg.len() { msg[at..(at + len)].to_vec() } else { - return Err(Trap::Code(TrapCode::MemoryAccessOutOfBounds)); + return Err(Trap::new(TrapCode::MemoryOutOfBounds.trap_message())); }; let len: u32 = memory @@ -243,7 +237,7 @@ mod funcs { .write(caller.as_context_mut(), err, &len.to_le_bytes()) .map_err(|e| { log::error!("{:?}", e); - Trap::Code(TrapCode::MemoryAccessOutOfBounds) + Trap::new(TrapCode::MemoryOutOfBounds.trap_message()) })?; Ok(()) @@ -251,7 +245,7 @@ mod funcs { )) } - pub fn gr_reply(ctx: &mut Store, memory: Memory) -> Extern { + fn gr_reply(ctx: &mut Store, memory: Memory) -> Extern { Extern::Func(Func::wrap( ctx, move |mut caller: Caller<'_, HostState>, ptr: u32, len: i32, _value: i32, _err: i32| { @@ -261,20 +255,20 @@ mod funcs { .read(caller.as_context(), ptr as usize, &mut result) .map_err(|e| { log::error!("{:?}", e); - Trap::Code(TrapCode::MemoryAccessOutOfBounds) + Trap::new(TrapCode::MemoryOutOfBounds.trap_message()) })?; - caller.host_data_mut().msg = result; + caller.data_mut().msg = result; Ok(()) }, )) } - pub fn gr_size(ctx: &mut Store, memory: Memory) -> Extern { + fn gr_size(ctx: &mut Store, memory: Memory) -> Extern { Extern::Func(Func::wrap( ctx, move |mut caller: Caller<'_, HostState>, size_ptr: u32| { - let size = caller.host_data().msg.len() as u32; + let size = caller.data().msg.len() as u32; memory .clone() @@ -285,7 +279,7 @@ mod funcs { ) .map_err(|e| { log::error!("{:?}", e); - Trap::Code(TrapCode::MemoryAccessOutOfBounds) + Trap::new(TrapCode::MemoryOutOfBounds.trap_message()) })?; Ok(()) @@ -293,14 +287,14 @@ mod funcs { )) } - pub fn gr_panic(ctx: &mut Store, memory: Memory) -> Extern { + fn gr_panic(ctx: &mut Store, memory: Memory) -> Extern { Extern::Func(Func::wrap( ctx, move |caller: Caller<'_, HostState>, ptr: u32, len: i32| { let mut buff = Vec::with_capacity(len as usize); memory.read(caller, ptr as usize, &mut buff).map_err(|e| { log::error!("{e:?}"); - Trap::Code(TrapCode::MemoryAccessOutOfBounds) + Trap::new(TrapCode::MemoryOutOfBounds.trap_message()) })?; log::error!("Panic: {}", String::from_utf8_lossy(&buff)); @@ -309,7 +303,7 @@ mod funcs { )) } - pub fn gr_oom_panic(ctx: impl AsContextMut) -> Extern { + fn gr_oom_panic(ctx: impl AsContextMut) -> Extern { Extern::Func(Func::wrap(ctx, || { log::error!("OOM panic occurred"); Ok(()) From b07464d91488b644da0298e9d7176ec81ae71a42 Mon Sep 17 00:00:00 2001 From: clearloop <26088946+clearloop@users.noreply.github.com> Date: Tue, 24 Oct 2023 14:32:33 +0800 Subject: [PATCH 22/22] ci(clippy): make clippy happy --- gcli/src/meta/executor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcli/src/meta/executor.rs b/gcli/src/meta/executor.rs index f5854378120..be76fd537c4 100644 --- a/gcli/src/meta/executor.rs +++ b/gcli/src/meta/executor.rs @@ -124,7 +124,7 @@ mod env { return Err(anyhow!("module \"{}\" not found", module)); } - let memory = self.memory.clone(); + let memory = self.memory; let store = &mut self.store; let external = match name {