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