From bf1023fc04a3be726c802c01d2313aef238e2c15 Mon Sep 17 00:00:00 2001 From: Vadim Smirnov Date: Sat, 15 Jul 2023 11:47:14 +0300 Subject: [PATCH] get/set gas and allowance explicitly inside sandbox --- core-backend/sandbox/src/env.rs | 34 ++++++---- core-backend/sandbox/src/runtime.rs | 38 ++++++----- runtime-interface/src/gear_sandbox/detail.rs | 68 ++++++++++++++++++++ runtime-interface/src/gear_sandbox/mod.rs | 23 +++++++ sandbox/sandbox/src/embedded_executor.rs | 11 ++++ sandbox/sandbox/src/host_executor.rs | 23 +++++++ sandbox/sandbox/src/lib.rs | 4 ++ 7 files changed, 173 insertions(+), 28 deletions(-) diff --git a/core-backend/sandbox/src/env.rs b/core-backend/sandbox/src/env.rs index 57edda05fed..764ae5e15d2 100644 --- a/core-backend/sandbox/src/env.rs +++ b/core-backend/sandbox/src/env.rs @@ -374,14 +374,18 @@ where .get_global_i32(STACK_END_EXPORT_NAME) .map(|global| global as u32); + // runtime + // .globals + // .set_global_i64(GLOBAL_NAME_GAS, gas as i64) + // .map_err(|_| System(WrongInjectedGas))?; + + // runtime + // .globals + // .set_global_i64(GLOBAL_NAME_ALLOWANCE, allowance as i64) + // .map_err(|_| System(WrongInjectedAllowance))?; runtime .globals - .set_global_i64(GLOBAL_NAME_GAS, gas as i64) - .map_err(|_| System(WrongInjectedGas))?; - - runtime - .globals - .set_global_i64(GLOBAL_NAME_ALLOWANCE, allowance as i64) + .set_global_gas_and_allowance(gas as i64, allowance as i64) .map_err(|_| System(WrongInjectedAllowance))?; let globals_config = if cfg!(not(feature = "std")) { @@ -409,15 +413,19 @@ where .then(|| instance.invoke(entry_point.as_entry(), &[], &mut runtime)) .unwrap_or(Ok(ReturnValue::Unit)); - let gas = runtime - .globals - .get_global_i64(GLOBAL_NAME_GAS) - .ok_or(System(WrongInjectedGas))?; - - let allowance = runtime + let (gas, allowance) = runtime .globals - .get_global_i64(GLOBAL_NAME_ALLOWANCE) + .get_global_gas_and_allowance() .ok_or(System(WrongInjectedAllowance))?; + // let gas = runtime + // .globals + // .get_global_i64(GLOBAL_NAME_GAS) + // .ok_or(System(WrongInjectedGas))?; + + // let allowance = runtime + // .globals + // .get_global_i64(GLOBAL_NAME_ALLOWANCE) + // .ok_or(System(WrongInjectedAllowance))?; let (ext, memory_wrap, termination_reason) = runtime.terminate(res, gas, allowance); diff --git a/core-backend/sandbox/src/runtime.rs b/core-backend/sandbox/src/runtime.rs index 99956203a48..f38dbc8036c 100644 --- a/core-backend/sandbox/src/runtime.rs +++ b/core-backend/sandbox/src/runtime.rs @@ -96,16 +96,19 @@ impl Runtime { fn prepare_run(&mut self) { self.memory_manager = Default::default(); - let gas = self + // let gas = self + // .globals + // .get_global_i64(GLOBAL_NAME_GAS) + // .unwrap_or_else(|| unreachable!("Globals must be checked during env creation")); + + // let allowance = self + // .globals + // .get_global_i64(GLOBAL_NAME_ALLOWANCE) + // .unwrap_or_else(|| unreachable!("Globals must be checked during env creation")); + let (gas, allowance) = self .globals - .get_global_i64(GLOBAL_NAME_GAS) + .get_global_gas_and_allowance() .unwrap_or_else(|| unreachable!("Globals must be checked during env creation")); - - let allowance = self - .globals - .get_global_i64(GLOBAL_NAME_ALLOWANCE) - .unwrap_or_else(|| unreachable!("Globals must be checked during env creation")); - self.ext.set_gas_left((gas, allowance).into()); } @@ -113,14 +116,19 @@ impl Runtime { fn update_globals(&mut self) { let GasLeft { gas, allowance } = self.ext.gas_left(); + // self.globals + // .set_global_i64(GLOBAL_NAME_GAS, gas as i64) + // .unwrap_or_else(|e| { + // unreachable!("Globals must be checked during env creation: {:?}", e) + // }); + + // self.globals + // .set_global_i64(GLOBAL_NAME_ALLOWANCE, allowance as i64) + // .unwrap_or_else(|e| { + // unreachable!("Globals must be checked during env creation: {:?}", e) + // }); self.globals - .set_global_i64(GLOBAL_NAME_GAS, gas as i64) - .unwrap_or_else(|e| { - unreachable!("Globals must be checked during env creation: {:?}", e) - }); - - self.globals - .set_global_i64(GLOBAL_NAME_ALLOWANCE, allowance as i64) + .set_global_gas_and_allowance(gas as i64, allowance as i64) .unwrap_or_else(|e| { unreachable!("Globals must be checked during env creation: {:?}", e) }); diff --git a/runtime-interface/src/gear_sandbox/detail.rs b/runtime-interface/src/gear_sandbox/detail.rs index e6bb83b85ef..c9e91577c81 100644 --- a/runtime-interface/src/gear_sandbox/detail.rs +++ b/runtime-interface/src/gear_sandbox/detail.rs @@ -239,6 +239,35 @@ pub fn get_global_i64( method_result } +pub fn get_global_gas_and_allowance( + context: &mut dyn FunctionContext, + instance_idx: u32, +) -> (Option, Option) { + let mut method_result = (None::, None::); + + sp_wasm_interface::with_caller_mut(context, |caller| { + trace("get_global_val", caller); + + let data_ptr: *const _ = caller.data(); + method_result = SANDBOXES.with(|sandboxes| { + sandboxes + .borrow_mut() + .get(data_ptr as usize) + .instance(instance_idx) + .map(|i| { + ( + i.get_global_i64("gear_gas"), + i.get_global_i64("gear_allowance"), + ) + }) + .map_err(|e| e.to_string()) + .expect("Failed to get global from sandbox") + }); + }); + + method_result +} + pub fn get_instance_ptr(context: &mut dyn FunctionContext, instance_id: u32) -> HostPointer { let mut method_result: HostPointer = u32::MAX.into(); @@ -660,3 +689,42 @@ pub fn set_global_i64( method_result } + +pub fn set_global_gas_and_allowance( + context: &mut dyn FunctionContext, + instance_idx: u32, + gas: i64, + allowance: i64, +) -> u32 { + let mut method_result = u32::MAX; + + sp_wasm_interface::with_caller_mut(context, |caller| { + trace("set_global_val", caller); + + log::trace!("set_global_val, instance_idx={instance_idx}"); + + let data_ptr: *const _ = caller.data(); + let result = SANDBOXES.with(|sandboxes| { + let instance = sandboxes + .borrow_mut() + .get(data_ptr as usize) + .instance(instance_idx) + .map_err(|e| e.to_string()) + .expect("Failed to set global in sandbox"); + + instance.set_global_i64("gear_gas", gas); + instance.set_global_i64("gear_allowance", allowance) + }); + + log::trace!("set_global_val, name=gear_gas, value={gas:?}, result={result:?}",); + log::trace!("set_global_val, name=gear_allowance, value={allowance:?}, result={result:?}",); + + method_result = match result { + Ok(None) => sandbox_env::env::ERROR_GLOBALS_NOT_FOUND, + Ok(Some(_)) => sandbox_env::env::ERROR_GLOBALS_OK, + Err(_) => sandbox_env::env::ERROR_GLOBALS_OTHER, + }; + }); + + method_result +} diff --git a/runtime-interface/src/gear_sandbox/mod.rs b/runtime-interface/src/gear_sandbox/mod.rs index c038d7b043b..e3e823ca879 100644 --- a/runtime-interface/src/gear_sandbox/mod.rs +++ b/runtime-interface/src/gear_sandbox/mod.rs @@ -127,6 +127,23 @@ pub trait Sandbox { detail::get_global_i64(*self, instance_idx, name) } + /// Get the value from a global with the given `name`. The sandbox is determined by the given + /// `instance_idx`. + /// + /// Returns `Some(_)` when the requested global variable could be found. + fn get_global_gas_and_allowance(&mut self, instance_idx: u32) -> i128 { + if let (Some(gas), Some(allowance)) = + detail::get_global_gas_and_allowance(*self, instance_idx) + { + // let (h, l) = ((gas >> 64) as i64, allowance as i64); + (gas as i128) << 64 | (allowance as i128) + } else { + i128::MAX + } + // let gas = detail::get_global_i64(*self, instance_idx, "gear_gas"); + // let allowance = detail::get_global_i64(*self, instance_idx, "gear_allowance"); + } + /// Set the value of a global with the given `name`. The sandbox is determined by the given /// `instance_idx`. fn set_global_val( @@ -141,6 +158,12 @@ pub trait Sandbox { fn set_global_i64(&mut self, instance_idx: u32, name: &str, value: i64) -> u32 { detail::set_global_i64(*self, instance_idx, name, value) } + + fn set_global_gas_and_allowance(&mut self, instance_idx: u32, val: i128) -> u32 { + let (gas, allowance) = (((val >> 64) as i64, val as i64)); + detail::set_global_gas_and_allowance(*self, instance_idx, gas, allowance) + } + fn memory_grow(&mut self, memory_idx: u32, size: u32) -> u32 { detail::memory_grow(*self, memory_idx, size) } diff --git a/sandbox/sandbox/src/embedded_executor.rs b/sandbox/sandbox/src/embedded_executor.rs index 7504a1e0456..9e6a78844fc 100644 --- a/sandbox/sandbox/src/embedded_executor.rs +++ b/sandbox/sandbox/src/embedded_executor.rs @@ -298,6 +298,9 @@ impl super::InstanceGlobals for InstanceGlobals { fn get_global_i64(&self, _name: &str) -> Option { None } + fn get_global_gas_and_allowance(&self) -> Option<(i64, i64)> { + None + } fn set_global_val(&self, _name: &str, _value: Value) -> Result<(), super::GlobalsSetError> { Err(super::GlobalsSetError::NotFound) @@ -306,6 +309,14 @@ impl super::InstanceGlobals for InstanceGlobals { fn set_global_i64(&self, _name: &str, _value: i64) -> Result<(), super::GlobalsSetError> { Err(super::GlobalsSetError::NotFound) } + + fn set_global_gas_and_allowance( + &self, + gas: i64, + allowance: i64, + ) -> Result<(), super::GlobalsSetError> { + Err(super::GlobalsSetError::NotFound) + } } impl super::SandboxInstance for Instance { diff --git a/sandbox/sandbox/src/host_executor.rs b/sandbox/sandbox/src/host_executor.rs index d0e4f0f4b73..d610c1075ff 100644 --- a/sandbox/sandbox/src/host_executor.rs +++ b/sandbox/sandbox/src/host_executor.rs @@ -211,6 +211,13 @@ impl super::InstanceGlobals for InstanceGlobals { .and_then(|i| sandbox::get_global_i64(i, name)) } + fn get_global_gas_and_allowance(&self) -> Option<(i64, i64)> { + self.instance_idx.and_then(|i| { + let val = sandbox::get_global_gas_and_allowance(i); + Some(((val >> 64) as i64, val as i64)) + }) + } + fn set_global_val(&self, name: &str, value: Value) -> Result<(), super::GlobalsSetError> { match self.instance_idx { None => Err(super::GlobalsSetError::Other), @@ -232,6 +239,22 @@ impl super::InstanceGlobals for InstanceGlobals { }, } } + + fn set_global_gas_and_allowance( + &self, + gas: i64, + allowance: i64, + ) -> Result<(), super::GlobalsSetError> { + let val = (gas as i128) << 64 | (allowance as i128); + match self.instance_idx { + None => Err(super::GlobalsSetError::Other), + Some(i) => match sandbox::set_global_gas_and_allowance(i, val) { + env::ERROR_GLOBALS_OK => Ok(()), + env::ERROR_GLOBALS_NOT_FOUND => Err(super::GlobalsSetError::NotFound), + _ => Err(super::GlobalsSetError::Other), + }, + } + } } /// The primary responsibility of this thunk is to deserialize arguments and diff --git a/sandbox/sandbox/src/lib.rs b/sandbox/sandbox/src/lib.rs index d43f9400b21..c376243bf5b 100644 --- a/sandbox/sandbox/src/lib.rs +++ b/sandbox/sandbox/src/lib.rs @@ -247,9 +247,13 @@ pub trait InstanceGlobals: Sized + Clone { /// Returns `Some(_)` if the global could be found. fn get_global_i64(&self, name: &str) -> Option; + fn get_global_gas_and_allowance(&self) -> Option<(i64, i64)>; + /// Set the value of a global with the given `name`. fn set_global_val(&self, name: &str, value: Value) -> Result<(), GlobalsSetError>; /// Set the `i64` value of a global with the given `name`. fn set_global_i64(&self, name: &str, value: i64) -> Result<(), GlobalsSetError>; + fn set_global_gas_and_allowance(&self, gas: i64, allowance: i64) + -> Result<(), GlobalsSetError>; }