Skip to content

Commit

Permalink
static api - initialization flags grouped into single bitfield
Browse files Browse the repository at this point in the history
  • Loading branch information
andrei-marinica committed Dec 13, 2024
1 parent 4bc903f commit 5230240
Show file tree
Hide file tree
Showing 8 changed files with 119 additions and 18 deletions.
2 changes: 2 additions & 0 deletions framework/base/src/api/managed_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;
Expand All @@ -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;
18 changes: 17 additions & 1 deletion framework/base/src/api/managed_types/static_var_api.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::types::LockableStaticBuffer;

use super::RawHandle;
use super::{RawHandle, StaticVarApiFlags};

pub trait StaticVarApi {
type StaticVarApiImpl: StaticVarApiImpl;
Expand All @@ -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;
Expand Down
53 changes: 53 additions & 0 deletions framework/base/src/api/managed_types/static_var_api_flags.rs
Original file line number Diff line number Diff line change
@@ -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
);
}
}
10 changes: 9 additions & 1 deletion framework/base/src/api/uncallable/static_var_api_uncallable.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
api::{RawHandle, StaticVarApi, StaticVarApiImpl},
api::{RawHandle, StaticVarApi, StaticVarApiFlags, StaticVarApiImpl},
types::LockableStaticBuffer,
};

Expand Down Expand Up @@ -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!()
}
Expand Down
22 changes: 10 additions & 12 deletions framework/base/src/contract_base/wrappers/call_value_wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -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<A>> {
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) }
Expand All @@ -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<A, EsdtTokenPayment<A>>> {
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) }
Expand Down
12 changes: 11 additions & 1 deletion framework/scenario/src/api/local_api_vh/static_var_api_vh.rs
Original file line number Diff line number Diff line change
@@ -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,
};

Expand Down Expand Up @@ -55,6 +55,16 @@ impl<VHB: VMHooksApiBackend> StaticVarApiImpl for VMHooksApi<VHB> {
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;
Expand Down
7 changes: 5 additions & 2 deletions framework/scenario/src/debug_executor/tx_static_vars.rs
Original file line number Diff line number Diff line change
@@ -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],
}

Expand All @@ -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,
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use multiversx_sc::{
api::{const_handles, RawHandle, StaticVarApi, StaticVarApiImpl},
api::{const_handles, RawHandle, StaticVarApi, StaticVarApiFlags, StaticVarApiImpl},
types::LockableStaticBuffer,
};

Expand All @@ -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] =
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 5230240

Please sign in to comment.