From 52302401391fdb07c489abde11e13f446c8e1532 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Fri, 13 Dec 2024 21:31:45 +0200 Subject: [PATCH 1/2] static api - initialization flags grouped into single bitfield --- framework/base/src/api/managed_types.rs | 2 + .../src/api/managed_types/static_var_api.rs | 18 ++++++- .../api/managed_types/static_var_api_flags.rs | 53 +++++++++++++++++++ .../uncallable/static_var_api_uncallable.rs | 10 +++- .../wrappers/call_value_wrapper.rs | 22 ++++---- .../src/api/local_api_vh/static_var_api_vh.rs | 12 ++++- .../src/debug_executor/tx_static_vars.rs | 7 ++- .../api/managed_types/static_var_api_node.rs | 13 ++++- 8 files changed, 119 insertions(+), 18 deletions(-) create mode 100644 framework/base/src/api/managed_types/static_var_api_flags.rs diff --git a/framework/base/src/api/managed_types.rs b/framework/base/src/api/managed_types.rs index 3562020b95..1322ede5ee 100644 --- a/framework/base/src/api/managed_types.rs +++ b/framework/base/src/api/managed_types.rs @@ -8,6 +8,7 @@ mod managed_map_api; mod managed_type_api; mod managed_type_api_impl; mod static_var_api; +mod static_var_api_flags; mod token_identifier_util; pub use big_float_api::*; @@ -19,3 +20,4 @@ pub use managed_map_api::*; pub use managed_type_api::*; pub use managed_type_api_impl::*; pub use static_var_api::*; +pub use static_var_api_flags::StaticVarApiFlags; diff --git a/framework/base/src/api/managed_types/static_var_api.rs b/framework/base/src/api/managed_types/static_var_api.rs index 8eaf474ef3..8fd007d648 100644 --- a/framework/base/src/api/managed_types/static_var_api.rs +++ b/framework/base/src/api/managed_types/static_var_api.rs @@ -1,6 +1,6 @@ use crate::types::LockableStaticBuffer; -use super::RawHandle; +use super::{RawHandle, StaticVarApiFlags}; pub trait StaticVarApi { type StaticVarApiImpl: StaticVarApiImpl; @@ -24,6 +24,22 @@ pub trait StaticVarApiImpl { fn get_num_arguments(&self) -> i32; + fn set_flags(&self, flags: StaticVarApiFlags); + + fn get_flags(&self) -> StaticVarApiFlags; + + /// Returns true if the flag is set, false if is default (false). + /// + /// If the flag is unset (false), will set it. + fn flag_is_set_or_update(&self, flag: StaticVarApiFlags) -> bool { + let mut current_flags = self.get_flags(); + let contains_flag = current_flags.check_and_set(flag); + if !contains_flag { + self.set_flags(current_flags); + } + contains_flag + } + fn set_call_value_egld_handle(&self, handle: RawHandle); fn get_call_value_egld_handle(&self) -> RawHandle; diff --git a/framework/base/src/api/managed_types/static_var_api_flags.rs b/framework/base/src/api/managed_types/static_var_api_flags.rs new file mode 100644 index 0000000000..1c9e153e69 --- /dev/null +++ b/framework/base/src/api/managed_types/static_var_api_flags.rs @@ -0,0 +1,53 @@ +use bitflags::bitflags; + +bitflags! { + #[derive(Clone, Copy, Debug, PartialEq, Eq)] + pub struct StaticVarApiFlags: u8 { + const NONE = 0b00000000; + const CALL_VALUE_EGLD_INITIALIZED = 0b00000001; + const CALL_VALUE_EGLD_MULTI_INITIALIZED = 0b00000010; + const CALL_VALUE_MULTI_ESDT_INITIALIZED = 0b00000100; + const CALL_VALUE_ALL_INITIALIZED = 0b00001000; + } +} + +impl StaticVarApiFlags { + pub fn check_and_set(&mut self, other: StaticVarApiFlags) -> bool { + let contains_flag = self.contains(other); + if !contains_flag { + *self |= other; + } + contains_flag + } +} + +#[cfg(test)] +pub mod tests { + use super::StaticVarApiFlags; + + #[test] + fn test_check_and_set() { + let mut current = StaticVarApiFlags::NONE; + + assert!(current.check_and_set(StaticVarApiFlags::NONE)); + assert_eq!(current, StaticVarApiFlags::NONE); + + assert!(!current.check_and_set(StaticVarApiFlags::CALL_VALUE_EGLD_INITIALIZED)); + assert_eq!(current, StaticVarApiFlags::CALL_VALUE_EGLD_INITIALIZED); + assert!(current.check_and_set(StaticVarApiFlags::CALL_VALUE_EGLD_INITIALIZED)); + assert_eq!(current, StaticVarApiFlags::CALL_VALUE_EGLD_INITIALIZED); + + assert!(!current.check_and_set(StaticVarApiFlags::CALL_VALUE_ALL_INITIALIZED)); + assert_eq!( + current, + StaticVarApiFlags::CALL_VALUE_EGLD_INITIALIZED + | StaticVarApiFlags::CALL_VALUE_ALL_INITIALIZED + ); + assert!(current.check_and_set(StaticVarApiFlags::CALL_VALUE_ALL_INITIALIZED)); + assert_eq!( + current, + StaticVarApiFlags::CALL_VALUE_EGLD_INITIALIZED + | StaticVarApiFlags::CALL_VALUE_ALL_INITIALIZED + ); + } +} diff --git a/framework/base/src/api/uncallable/static_var_api_uncallable.rs b/framework/base/src/api/uncallable/static_var_api_uncallable.rs index 1da3c772cf..db126b337d 100644 --- a/framework/base/src/api/uncallable/static_var_api_uncallable.rs +++ b/framework/base/src/api/uncallable/static_var_api_uncallable.rs @@ -1,5 +1,5 @@ use crate::{ - api::{RawHandle, StaticVarApi, StaticVarApiImpl}, + api::{RawHandle, StaticVarApi, StaticVarApiFlags, StaticVarApiImpl}, types::LockableStaticBuffer, }; @@ -41,6 +41,14 @@ impl StaticVarApiImpl for UncallableApi { unreachable!() } + fn set_flags(&self, _flags: StaticVarApiFlags) { + unreachable!() + } + + fn get_flags(&self) -> StaticVarApiFlags { + unreachable!() + } + fn set_call_value_egld_handle(&self, _handle: RawHandle) { unreachable!() } diff --git a/framework/base/src/contract_base/wrappers/call_value_wrapper.rs b/framework/base/src/contract_base/wrappers/call_value_wrapper.rs index 3fb85e1658..1edb635a9d 100644 --- a/framework/base/src/contract_base/wrappers/call_value_wrapper.rs +++ b/framework/base/src/contract_base/wrappers/call_value_wrapper.rs @@ -3,7 +3,7 @@ use core::marker::PhantomData; use crate::{ api::{ const_handles, use_raw_handle, CallValueApi, CallValueApiImpl, ErrorApi, ErrorApiImpl, - HandleConstraints, ManagedTypeApi, StaticVarApiImpl, + ManagedTypeApi, StaticVarApiFlags, StaticVarApiImpl, }, err_msg, types::{ @@ -34,11 +34,10 @@ where /// Retrieves the EGLD call value from the VM. /// Will return 0 in case of an ESDT transfer (cannot have both EGLD and ESDT transfer simultaneously). pub fn egld_value(&self) -> ManagedRef<'static, A, BigUint> { - let mut call_value_handle: A::BigIntHandle = - use_raw_handle(A::static_var_api_impl().get_call_value_egld_handle()); - if call_value_handle == const_handles::UNINITIALIZED_HANDLE { - call_value_handle = use_raw_handle(const_handles::CALL_VALUE_EGLD); - A::static_var_api_impl().set_call_value_egld_handle(call_value_handle.get_raw_handle()); + let call_value_handle: A::BigIntHandle = use_raw_handle(const_handles::CALL_VALUE_EGLD); + if !A::static_var_api_impl() + .flag_is_set_or_update(StaticVarApiFlags::CALL_VALUE_EGLD_INITIALIZED) + { A::call_value_api_impl().load_egld_value(call_value_handle.clone()); } unsafe { ManagedRef::wrap_handle(call_value_handle) } @@ -55,12 +54,11 @@ where /// Will return 0 results if nothing was transfered, or just EGLD. /// Fully managed underlying types, very efficient. pub fn all_esdt_transfers(&self) -> ManagedRef<'static, A, ManagedVec>> { - let mut call_value_handle: A::ManagedBufferHandle = - use_raw_handle(A::static_var_api_impl().get_call_value_multi_esdt_handle()); - if call_value_handle == const_handles::UNINITIALIZED_HANDLE { - call_value_handle = use_raw_handle(const_handles::CALL_VALUE_MULTI_ESDT); - A::static_var_api_impl() - .set_call_value_multi_esdt_handle(call_value_handle.get_raw_handle()); + let call_value_handle: A::ManagedBufferHandle = + use_raw_handle(const_handles::CALL_VALUE_MULTI_ESDT); + if !A::static_var_api_impl() + .flag_is_set_or_update(StaticVarApiFlags::CALL_VALUE_MULTI_ESDT_INITIALIZED) + { A::call_value_api_impl().load_all_esdt_transfers(call_value_handle.clone()); } unsafe { ManagedRef::wrap_handle(call_value_handle) } diff --git a/framework/scenario/src/api/local_api_vh/static_var_api_vh.rs b/framework/scenario/src/api/local_api_vh/static_var_api_vh.rs index e72ae45f74..07bef47bda 100644 --- a/framework/scenario/src/api/local_api_vh/static_var_api_vh.rs +++ b/framework/scenario/src/api/local_api_vh/static_var_api_vh.rs @@ -1,6 +1,6 @@ use crate::api::{VMHooksApi, VMHooksApiBackend}; use multiversx_sc::{ - api::{use_raw_handle, RawHandle, StaticVarApi, StaticVarApiImpl}, + api::{use_raw_handle, RawHandle, StaticVarApi, StaticVarApiFlags, StaticVarApiImpl}, types::LockableStaticBuffer, }; @@ -55,6 +55,16 @@ impl StaticVarApiImpl for VMHooksApi { self.with_static_data(|data| data.static_vars_cell.borrow().num_arguments) } + fn set_flags(&self, flags: StaticVarApiFlags) { + self.with_static_data(|data| { + data.static_vars_cell.borrow_mut().flags = flags; + }) + } + + fn get_flags(&self) -> StaticVarApiFlags { + self.with_static_data(|data| data.static_vars_cell.borrow().flags) + } + fn set_call_value_egld_handle(&self, handle: RawHandle) { self.with_static_data(|data| { data.static_vars_cell.borrow_mut().call_value_egld_handle = handle; diff --git a/framework/scenario/src/debug_executor/tx_static_vars.rs b/framework/scenario/src/debug_executor/tx_static_vars.rs index 88277694c4..bca543d8ba 100644 --- a/framework/scenario/src/debug_executor/tx_static_vars.rs +++ b/framework/scenario/src/debug_executor/tx_static_vars.rs @@ -1,13 +1,15 @@ -use multiversx_sc::api::{const_handles, RawHandle}; +use multiversx_sc::api::{const_handles, RawHandle, StaticVarApiFlags}; #[derive(Debug)] pub struct TxStaticVars { pub external_view_target_address_handle: RawHandle, pub next_handle: RawHandle, pub num_arguments: i32, + pub flags: StaticVarApiFlags, pub call_value_egld_handle: RawHandle, pub call_value_multi_esdt_handle: RawHandle, - //vec of true/false, true if bit from handle = scaling_start + index is not empty + + /// Vec of true/false, true if bit from handle = scaling_start + index is not empty pub scaling_factor_init: [bool; const_handles::SCALING_FACTOR_LENGTH], } @@ -20,6 +22,7 @@ impl Default for TxStaticVars { call_value_egld_handle: const_handles::UNINITIALIZED_HANDLE, call_value_multi_esdt_handle: const_handles::UNINITIALIZED_HANDLE, scaling_factor_init: [false; const_handles::SCALING_FACTOR_LENGTH], + flags: StaticVarApiFlags::NONE, } } } diff --git a/framework/wasm-adapter/src/api/managed_types/static_var_api_node.rs b/framework/wasm-adapter/src/api/managed_types/static_var_api_node.rs index 501d53d68f..b282449c94 100644 --- a/framework/wasm-adapter/src/api/managed_types/static_var_api_node.rs +++ b/framework/wasm-adapter/src/api/managed_types/static_var_api_node.rs @@ -1,5 +1,5 @@ use multiversx_sc::{ - api::{const_handles, RawHandle, StaticVarApi, StaticVarApiImpl}, + api::{const_handles, RawHandle, StaticVarApi, StaticVarApiFlags, StaticVarApiImpl}, types::LockableStaticBuffer, }; @@ -9,6 +9,7 @@ static mut STATIC_BUFFER: LockableStaticBuffer = LockableStaticBuffer::new(); static mut EXTERNAL_VIEW_TARGET_ADDRESS_HANDLE: i32 = 0; static mut NEXT_HANDLE: i32 = const_handles::NEW_HANDLE_START_FROM; static mut NUM_ARGUMENTS: i32 = 0; +static mut FLAGS: StaticVarApiFlags = StaticVarApiFlags::NONE; static mut CALL_VALUE_EGLD_HANDLE: i32 = const_handles::UNINITIALIZED_HANDLE; static mut CALL_VALUE_MULTI_ESDT_HANDLE: i32 = const_handles::UNINITIALIZED_HANDLE; static mut SCALING_FACTOR_INIT: [bool; const_handles::SCALING_FACTOR_LENGTH] = @@ -62,6 +63,16 @@ impl StaticVarApiImpl for VmApiImpl { unsafe { NUM_ARGUMENTS } } + fn set_flags(&self, flags: StaticVarApiFlags) { + unsafe { + FLAGS = flags; + } + } + + fn get_flags(&self) -> StaticVarApiFlags { + unsafe { FLAGS } + } + fn set_call_value_egld_handle(&self, handle: RawHandle) { unsafe { CALL_VALUE_EGLD_HANDLE = handle; From de2c6302d11ebe2c1cdd9dc25bf8bae863f3e964 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Sat, 14 Dec 2024 05:28:13 +0200 Subject: [PATCH 2/2] static api - removing old call value handle fields --- .../src/api/managed_types/static_var_api.rs | 8 ------ .../uncallable/static_var_api_uncallable.rs | 16 ----------- .../src/api/local_api_vh/static_var_api_vh.rs | 28 +------------------ .../src/debug_executor/tx_static_vars.rs | 4 --- .../api/managed_types/static_var_api_node.rs | 22 --------------- 5 files changed, 1 insertion(+), 77 deletions(-) diff --git a/framework/base/src/api/managed_types/static_var_api.rs b/framework/base/src/api/managed_types/static_var_api.rs index 8fd007d648..9044cd6b06 100644 --- a/framework/base/src/api/managed_types/static_var_api.rs +++ b/framework/base/src/api/managed_types/static_var_api.rs @@ -40,14 +40,6 @@ pub trait StaticVarApiImpl { contains_flag } - fn set_call_value_egld_handle(&self, handle: RawHandle); - - fn get_call_value_egld_handle(&self) -> RawHandle; - - fn set_call_value_multi_esdt_handle(&self, handle: RawHandle); - - fn get_call_value_multi_esdt_handle(&self) -> RawHandle; - fn is_scaling_factor_cached(&self, decimals: usize) -> bool; fn set_scaling_factor_cached(&self, decimals: usize); diff --git a/framework/base/src/api/uncallable/static_var_api_uncallable.rs b/framework/base/src/api/uncallable/static_var_api_uncallable.rs index db126b337d..005a302e53 100644 --- a/framework/base/src/api/uncallable/static_var_api_uncallable.rs +++ b/framework/base/src/api/uncallable/static_var_api_uncallable.rs @@ -49,22 +49,6 @@ impl StaticVarApiImpl for UncallableApi { unreachable!() } - fn set_call_value_egld_handle(&self, _handle: RawHandle) { - unreachable!() - } - - fn get_call_value_egld_handle(&self) -> RawHandle { - unreachable!() - } - - fn set_call_value_multi_esdt_handle(&self, _handle: RawHandle) { - unreachable!() - } - - fn get_call_value_multi_esdt_handle(&self) -> RawHandle { - unreachable!() - } - fn is_scaling_factor_cached(&self, _decimals: usize) -> bool { unreachable!() } diff --git a/framework/scenario/src/api/local_api_vh/static_var_api_vh.rs b/framework/scenario/src/api/local_api_vh/static_var_api_vh.rs index 07bef47bda..903094279e 100644 --- a/framework/scenario/src/api/local_api_vh/static_var_api_vh.rs +++ b/framework/scenario/src/api/local_api_vh/static_var_api_vh.rs @@ -1,6 +1,6 @@ use crate::api::{VMHooksApi, VMHooksApiBackend}; use multiversx_sc::{ - api::{use_raw_handle, RawHandle, StaticVarApi, StaticVarApiFlags, StaticVarApiImpl}, + api::{RawHandle, StaticVarApi, StaticVarApiFlags, StaticVarApiImpl}, types::LockableStaticBuffer, }; @@ -65,32 +65,6 @@ impl StaticVarApiImpl for VMHooksApi { self.with_static_data(|data| data.static_vars_cell.borrow().flags) } - fn set_call_value_egld_handle(&self, handle: RawHandle) { - self.with_static_data(|data| { - data.static_vars_cell.borrow_mut().call_value_egld_handle = handle; - }) - } - - fn get_call_value_egld_handle(&self) -> RawHandle { - self.with_static_data(|data| { - use_raw_handle(data.static_vars_cell.borrow().call_value_egld_handle) - }) - } - - fn set_call_value_multi_esdt_handle(&self, handle: RawHandle) { - self.with_static_data(|data| { - data.static_vars_cell - .borrow_mut() - .call_value_multi_esdt_handle = handle; - }) - } - - fn get_call_value_multi_esdt_handle(&self) -> RawHandle { - self.with_static_data(|data| { - use_raw_handle(data.static_vars_cell.borrow().call_value_multi_esdt_handle) - }) - } - fn is_scaling_factor_cached(&self, decimals: usize) -> bool { self.with_static_data(|data| data.static_vars_cell.borrow().scaling_factor_init[decimals]) } diff --git a/framework/scenario/src/debug_executor/tx_static_vars.rs b/framework/scenario/src/debug_executor/tx_static_vars.rs index bca543d8ba..3468d14da6 100644 --- a/framework/scenario/src/debug_executor/tx_static_vars.rs +++ b/framework/scenario/src/debug_executor/tx_static_vars.rs @@ -6,8 +6,6 @@ pub struct TxStaticVars { pub next_handle: RawHandle, pub num_arguments: i32, pub flags: StaticVarApiFlags, - pub call_value_egld_handle: RawHandle, - pub call_value_multi_esdt_handle: RawHandle, /// Vec of true/false, true if bit from handle = scaling_start + index is not empty pub scaling_factor_init: [bool; const_handles::SCALING_FACTOR_LENGTH], @@ -19,8 +17,6 @@ impl Default for TxStaticVars { external_view_target_address_handle: 0, next_handle: const_handles::NEW_HANDLE_START_FROM, num_arguments: -1, - call_value_egld_handle: const_handles::UNINITIALIZED_HANDLE, - call_value_multi_esdt_handle: const_handles::UNINITIALIZED_HANDLE, scaling_factor_init: [false; const_handles::SCALING_FACTOR_LENGTH], flags: StaticVarApiFlags::NONE, } diff --git a/framework/wasm-adapter/src/api/managed_types/static_var_api_node.rs b/framework/wasm-adapter/src/api/managed_types/static_var_api_node.rs index b282449c94..3c6b19996f 100644 --- a/framework/wasm-adapter/src/api/managed_types/static_var_api_node.rs +++ b/framework/wasm-adapter/src/api/managed_types/static_var_api_node.rs @@ -10,8 +10,6 @@ static mut EXTERNAL_VIEW_TARGET_ADDRESS_HANDLE: i32 = 0; static mut NEXT_HANDLE: i32 = const_handles::NEW_HANDLE_START_FROM; static mut NUM_ARGUMENTS: i32 = 0; static mut FLAGS: StaticVarApiFlags = StaticVarApiFlags::NONE; -static mut CALL_VALUE_EGLD_HANDLE: i32 = const_handles::UNINITIALIZED_HANDLE; -static mut CALL_VALUE_MULTI_ESDT_HANDLE: i32 = const_handles::UNINITIALIZED_HANDLE; static mut SCALING_FACTOR_INIT: [bool; const_handles::SCALING_FACTOR_LENGTH] = [false; const_handles::SCALING_FACTOR_LENGTH]; @@ -73,26 +71,6 @@ impl StaticVarApiImpl for VmApiImpl { unsafe { FLAGS } } - fn set_call_value_egld_handle(&self, handle: RawHandle) { - unsafe { - CALL_VALUE_EGLD_HANDLE = handle; - } - } - - fn get_call_value_egld_handle(&self) -> RawHandle { - unsafe { CALL_VALUE_EGLD_HANDLE } - } - - fn set_call_value_multi_esdt_handle(&self, handle: RawHandle) { - unsafe { - CALL_VALUE_MULTI_ESDT_HANDLE = handle; - } - } - - fn get_call_value_multi_esdt_handle(&self) -> RawHandle { - unsafe { CALL_VALUE_MULTI_ESDT_HANDLE } - } - fn is_scaling_factor_cached(&self, decimals: usize) -> bool { unsafe { SCALING_FACTOR_INIT[decimals] } }