mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 15:51:12 +00:00
Add get_global for Sandbox (#4756)
* Add `get_global` for `Sandbox` This pr adds `get_global` to retrieve a `global` variable from an instantiated sandbox wasm blob. * Bump `spec_version` * Update primitives/wasm-interface/src/lib.rs Co-Authored-By: Sergei Pepyakin <sergei@parity.io> * `get_global` -> `get_global_val` Co-authored-by: Sergei Pepyakin <s.pepyakin@gmail.com> Co-authored-by: Gavin Wood <github@gavwood.com>
This commit is contained in:
@@ -224,7 +224,8 @@ fn trap(msg: &'static str) -> Trap {
|
||||
}
|
||||
|
||||
fn deserialize_result(serialized_result: &[u8]) -> std::result::Result<Option<RuntimeValue>, Trap> {
|
||||
use self::sandbox_primitives::{HostError, ReturnValue};
|
||||
use self::sandbox_primitives::HostError;
|
||||
use sp_wasm_interface::ReturnValue;
|
||||
let result_val = std::result::Result::<ReturnValue, HostError>::decode(&mut &serialized_result[..])
|
||||
.map_err(|_| trap("Decoding Result<ReturnValue, HostError> failed!"))?;
|
||||
|
||||
@@ -260,7 +261,7 @@ impl<'a, FE: SandboxCapabilities + 'a> Externals for GuestExternals<'a, FE> {
|
||||
let invoke_args_data: Vec<u8> = args.as_ref()
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(sandbox_primitives::TypedValue::from)
|
||||
.map(sp_wasm_interface::Value::from)
|
||||
.collect::<Vec<_>>()
|
||||
.encode();
|
||||
|
||||
@@ -362,6 +363,18 @@ impl<FR> SandboxInstance<FR> {
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// Get the value from a global with the given `name`.
|
||||
///
|
||||
/// Returns `Some(_)` if the global could be found.
|
||||
pub fn get_global_val(&self, name: &str) -> Option<sp_wasm_interface::Value> {
|
||||
let global = self.instance
|
||||
.export_by_name(name)?
|
||||
.as_global()?
|
||||
.get();
|
||||
|
||||
Some(global.into())
|
||||
}
|
||||
}
|
||||
|
||||
/// Error occurred during instantiation of a sandboxed module.
|
||||
|
||||
@@ -17,6 +17,8 @@ use sp_io::{
|
||||
use sp_runtime::{print, traits::{BlakeTwo256, Hash}};
|
||||
#[cfg(not(feature = "std"))]
|
||||
use sp_core::{ed25519, sr25519};
|
||||
#[cfg(not(feature = "std"))]
|
||||
use sp_sandbox::Value;
|
||||
|
||||
extern "C" {
|
||||
#[allow(dead_code)]
|
||||
@@ -133,8 +135,8 @@ sp_core::wasm_export_functions! {
|
||||
execute_sandboxed(
|
||||
&code,
|
||||
&[
|
||||
sp_sandbox::TypedValue::I32(0x12345678),
|
||||
sp_sandbox::TypedValue::I64(0x1234567887654321),
|
||||
Value::I32(0x12345678),
|
||||
Value::I64(0x1234567887654321),
|
||||
],
|
||||
).is_ok()
|
||||
}
|
||||
@@ -143,10 +145,10 @@ sp_core::wasm_export_functions! {
|
||||
let ok = match execute_sandboxed(
|
||||
&code,
|
||||
&[
|
||||
sp_sandbox::TypedValue::I32(0x1336),
|
||||
Value::I32(0x1336),
|
||||
]
|
||||
) {
|
||||
Ok(sp_sandbox::ReturnValue::Value(sp_sandbox::TypedValue::I32(0x1337))) => true,
|
||||
Ok(sp_sandbox::ReturnValue::Value(Value::I32(0x1337))) => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
@@ -165,6 +167,22 @@ sp_core::wasm_export_functions! {
|
||||
code
|
||||
}
|
||||
|
||||
|
||||
fn test_sandbox_get_global_val(code: Vec<u8>) -> i64 {
|
||||
let env_builder = sp_sandbox::EnvironmentDefinitionBuilder::new();
|
||||
let instance = if let Ok(i) = sp_sandbox::Instance::new(&code, &env_builder, &mut ()) {
|
||||
i
|
||||
} else {
|
||||
return 20;
|
||||
};
|
||||
|
||||
match instance.get_global_val("test_global") {
|
||||
Some(sp_sandbox::Value::I64(val)) => val,
|
||||
None => 30,
|
||||
val => 40,
|
||||
}
|
||||
}
|
||||
|
||||
fn test_offchain_local_storage() -> bool {
|
||||
let kind = sp_core::offchain::StorageKind::PERSISTENT;
|
||||
assert_eq!(sp_io::offchain::local_storage_get(kind, b"test"), None);
|
||||
@@ -262,7 +280,7 @@ sp_core::wasm_export_functions! {
|
||||
#[cfg(not(feature = "std"))]
|
||||
fn execute_sandboxed(
|
||||
code: &[u8],
|
||||
args: &[sp_sandbox::TypedValue],
|
||||
args: &[Value],
|
||||
) -> Result<sp_sandbox::ReturnValue, sp_sandbox::HostError> {
|
||||
struct State {
|
||||
counter: u32,
|
||||
@@ -270,7 +288,7 @@ fn execute_sandboxed(
|
||||
|
||||
fn env_assert(
|
||||
_e: &mut State,
|
||||
args: &[sp_sandbox::TypedValue],
|
||||
args: &[Value],
|
||||
) -> Result<sp_sandbox::ReturnValue, sp_sandbox::HostError> {
|
||||
if args.len() != 1 {
|
||||
return Err(sp_sandbox::HostError);
|
||||
@@ -284,14 +302,14 @@ fn execute_sandboxed(
|
||||
}
|
||||
fn env_inc_counter(
|
||||
e: &mut State,
|
||||
args: &[sp_sandbox::TypedValue],
|
||||
args: &[Value],
|
||||
) -> Result<sp_sandbox::ReturnValue, sp_sandbox::HostError> {
|
||||
if args.len() != 1 {
|
||||
return Err(sp_sandbox::HostError);
|
||||
}
|
||||
let inc_by = args[0].as_i32().ok_or_else(|| sp_sandbox::HostError)?;
|
||||
e.counter += inc_by as u32;
|
||||
Ok(sp_sandbox::ReturnValue::Value(sp_sandbox::TypedValue::I32(e.counter as i32)))
|
||||
Ok(sp_sandbox::ReturnValue::Value(Value::I32(e.counter as i32)))
|
||||
}
|
||||
|
||||
let mut state = State { counter: 0 };
|
||||
|
||||
@@ -88,7 +88,7 @@ fn call_not_existing_function(wasm_method: WasmExecutionMethod) {
|
||||
#[cfg(feature = "wasmtime")]
|
||||
WasmExecutionMethod::Compiled => assert_eq!(
|
||||
&format!("{:?}", e),
|
||||
"Other(\"call to undefined external function with index 67\")"
|
||||
"Other(\"call to undefined external function with index 68\")"
|
||||
),
|
||||
}
|
||||
}
|
||||
@@ -117,7 +117,7 @@ fn call_yet_another_not_existing_function(wasm_method: WasmExecutionMethod) {
|
||||
#[cfg(feature = "wasmtime")]
|
||||
WasmExecutionMethod::Compiled => assert_eq!(
|
||||
&format!("{:?}", e),
|
||||
"Other(\"call to undefined external function with index 68\")"
|
||||
"Other(\"call to undefined external function with index 69\")"
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,3 +302,26 @@ fn start_fn_traps(wasm_method: WasmExecutionMethod) {
|
||||
2u8.encode(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test_case(WasmExecutionMethod::Interpreted)]
|
||||
#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))]
|
||||
fn get_global_val_works(wasm_method: WasmExecutionMethod) {
|
||||
let mut ext = TestExternalities::default();
|
||||
let mut ext = ext.ext();
|
||||
|
||||
let code = wabt::wat2wasm(r#"
|
||||
(module
|
||||
(global (export "test_global") i64 (i64.const 500))
|
||||
)
|
||||
"#).unwrap().encode();
|
||||
|
||||
assert_eq!(
|
||||
call_in_wasm(
|
||||
"test_sandbox_get_global_val",
|
||||
&code,
|
||||
wasm_method,
|
||||
&mut ext,
|
||||
).unwrap(),
|
||||
500i64.encode(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -213,7 +213,7 @@ impl<'a> Sandbox for FunctionExecutor<'a> {
|
||||
trace!(target: "sp-sandbox", "invoke, instance_idx={}", instance_id);
|
||||
|
||||
// Deserialize arguments and convert them into wasmi types.
|
||||
let args = Vec::<sandbox_primitives::TypedValue>::decode(&mut &args[..])
|
||||
let args = Vec::<sp_wasm_interface::Value>::decode(&mut &args[..])
|
||||
.map_err(|_| "Can't decode serialized arguments for the invocation")?
|
||||
.into_iter()
|
||||
.map(Into::into)
|
||||
@@ -226,7 +226,7 @@ impl<'a> Sandbox for FunctionExecutor<'a> {
|
||||
Ok(None) => Ok(sandbox_primitives::ERR_OK),
|
||||
Ok(Some(val)) => {
|
||||
// Serialize return value and write it back into the memory.
|
||||
sandbox_primitives::ReturnValue::Value(val.into()).using_encoded(|val| {
|
||||
sp_wasm_interface::ReturnValue::Value(val.into()).using_encoded(|val| {
|
||||
if val.len() > return_val_len as usize {
|
||||
Err("Return value buffer is too small")?;
|
||||
}
|
||||
@@ -269,6 +269,17 @@ impl<'a> Sandbox for FunctionExecutor<'a> {
|
||||
|
||||
Ok(instance_idx_or_err_code as u32)
|
||||
}
|
||||
|
||||
fn get_global_val(
|
||||
&self,
|
||||
instance_idx: u32,
|
||||
name: &str,
|
||||
) -> WResult<Option<sp_wasm_interface::Value>> {
|
||||
self.sandbox_store
|
||||
.instance(instance_idx)
|
||||
.map(|i| i.get_global_val(name))
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
/// Will be used on initialization of a module to resolve function and memory imports.
|
||||
|
||||
@@ -286,7 +286,7 @@ impl<'a> Sandbox for FunctionExecutor<'a> {
|
||||
trace!(target: "sp-sandbox", "invoke, instance_idx={}", instance_id);
|
||||
|
||||
// Deserialize arguments and convert them into wasmi types.
|
||||
let args = Vec::<sandbox_primitives::TypedValue>::decode(&mut &args[..])
|
||||
let args = Vec::<sp_wasm_interface::Value>::decode(&mut &args[..])
|
||||
.map_err(|_| "Can't decode serialized arguments for the invocation")?
|
||||
.into_iter()
|
||||
.map(Into::into)
|
||||
@@ -299,7 +299,7 @@ impl<'a> Sandbox for FunctionExecutor<'a> {
|
||||
Ok(None) => Ok(sandbox_primitives::ERR_OK),
|
||||
Ok(Some(val)) => {
|
||||
// Serialize return value and write it back into the memory.
|
||||
sandbox_primitives::ReturnValue::Value(val.into()).using_encoded(|val| {
|
||||
sp_wasm_interface::ReturnValue::Value(val.into()).using_encoded(|val| {
|
||||
if val.len() > return_val_len as usize {
|
||||
Err("Return value buffer is too small")?;
|
||||
}
|
||||
@@ -337,6 +337,17 @@ impl<'a> Sandbox for FunctionExecutor<'a> {
|
||||
|
||||
Ok(instance_idx_or_err_code as u32)
|
||||
}
|
||||
|
||||
fn get_global_val(
|
||||
&self,
|
||||
instance_idx: u32,
|
||||
name: &str,
|
||||
) -> WResult<Option<sp_wasm_interface::Value>> {
|
||||
self.sandbox_store
|
||||
.instance(instance_idx)
|
||||
.map(|i| i.get_global_val(name))
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
// The storage for a Wasmtime invocation argument.
|
||||
|
||||
Reference in New Issue
Block a user