diff --git a/contracts/feature-tests/basic-features/src/storage_direct_load.rs b/contracts/feature-tests/basic-features/src/storage_direct_load.rs index efdd51a20f..7d19f83eb5 100644 --- a/contracts/feature-tests/basic-features/src/storage_direct_load.rs +++ b/contracts/feature-tests/basic-features/src/storage_direct_load.rs @@ -1,7 +1,5 @@ multiversx_sc::imports!(); -use multiversx_sc::api::{use_raw_handle, HandleTypeInfo}; - use crate::types::*; /// Storage tests: direct load. @@ -78,16 +76,15 @@ pub trait StorageLoadFeatures { #[endpoint] fn load_from_address_raw(&self, address: ManagedAddress, key: ManagedBuffer) -> ManagedBuffer { // TODO: maybe wrap this kind of functionality in a StorageRawWrapper - use multiversx_sc::api::{ - StaticVarApi, StaticVarApiImpl, StorageReadApi, StorageReadApiImpl, - }; - let value_handle: <::Api as HandleTypeInfo>::ManagedBufferHandle = - use_raw_handle(Self::Api::static_var_api_impl().next_handle()); - Self::Api::storage_read_api_impl().storage_load_from_address( - address.get_handle(), - key.get_handle(), - value_handle.clone(), - ); - ManagedBuffer::from_handle(value_handle) + use multiversx_sc::api::{StorageReadApi, StorageReadApiImpl}; + unsafe { + let value = ManagedBuffer::new_uninit(); + Self::Api::storage_read_api_impl().storage_load_from_address( + address.get_handle(), + key.get_handle(), + value.get_handle(), + ); + value + } } } diff --git a/contracts/modules/src/esdt.rs b/contracts/modules/src/esdt.rs index ea977f53be..42314e9608 100644 --- a/contracts/modules/src/esdt.rs +++ b/contracts/modules/src/esdt.rs @@ -84,7 +84,9 @@ pub trait EsdtModule { fn nft_create(&self, amount: &BigUint, attributes: &T) -> u64 { let token_id = self.token_id().get(); let empty_buffer = ManagedBuffer::new(); - let empty_vec = ManagedVec::from_handle(empty_buffer.get_handle()); + + // sneakily reuses the same handle + let empty_vec = unsafe { ManagedRef::wrap_handle(empty_buffer.get_handle()) }; self.send().esdt_nft_create( &token_id, diff --git a/framework/base/src/contract_base/wrappers/blockchain_wrapper.rs b/framework/base/src/contract_base/wrappers/blockchain_wrapper.rs index c499c9f663..e769bb69c7 100644 --- a/framework/base/src/contract_base/wrappers/blockchain_wrapper.rs +++ b/framework/base/src/contract_base/wrappers/blockchain_wrapper.rs @@ -11,8 +11,8 @@ use crate::{ storage::{self}, types::{ BackTransfers, BigUint, CodeMetadata, EgldOrEsdtTokenIdentifier, EsdtLocalRoleFlags, - EsdtTokenData, EsdtTokenType, ManagedAddress, ManagedBuffer, ManagedByteArray, ManagedType, - ManagedVec, TokenIdentifier, + EsdtTokenData, EsdtTokenType, ManagedAddress, ManagedBuffer, ManagedByteArray, + ManagedRefMut, ManagedType, ManagedVec, TokenIdentifier, }, }; @@ -49,9 +49,11 @@ where #[inline] pub fn get_caller(&self) -> ManagedAddress { - let handle: A::ManagedBufferHandle = use_raw_handle(A::static_var_api_impl().next_handle()); - A::blockchain_api_impl().load_caller_managed(handle.clone()); - ManagedAddress::from_handle(handle) + unsafe { + let result = ManagedAddress::new_uninit(); + A::blockchain_api_impl().load_caller_managed(result.get_handle()); + result + } } #[deprecated(since = "0.41.0", note = "Please use method `get_sc_address` instead.")] @@ -63,16 +65,20 @@ where #[inline] pub fn get_sc_address(&self) -> ManagedAddress { - let handle: A::ManagedBufferHandle = use_raw_handle(A::static_var_api_impl().next_handle()); - A::blockchain_api_impl().load_sc_address_managed(handle.clone()); - ManagedAddress::from_handle(handle) + unsafe { + let result = ManagedAddress::new_uninit(); + A::blockchain_api_impl().load_sc_address_managed(result.get_handle()); + result + } } #[inline] pub fn get_owner_address(&self) -> ManagedAddress { - let handle: A::ManagedBufferHandle = use_raw_handle(A::static_var_api_impl().next_handle()); - A::blockchain_api_impl().load_owner_address_managed(handle.clone()); - ManagedAddress::from_handle(handle) + unsafe { + let result = ManagedAddress::new_uninit(); + A::blockchain_api_impl().load_owner_address_managed(result.get_handle()); + result + } } pub fn check_caller_is_owner(&self) { @@ -123,16 +129,20 @@ where #[cfg(feature = "alloc")] #[inline] pub fn get_balance_legacy(&self, address: &crate::types::Address) -> BigUint { - let handle: A::BigIntHandle = use_raw_handle(A::static_var_api_impl().next_handle()); - A::blockchain_api_impl().load_balance_legacy(handle.clone(), address); - BigUint::from_handle(handle) + unsafe { + let result = BigUint::new_uninit(); + A::blockchain_api_impl().load_balance_legacy(result.get_handle(), address); + result + } } #[inline] pub fn get_balance(&self, address: &ManagedAddress) -> BigUint { - let handle: A::BigIntHandle = use_raw_handle(A::static_var_api_impl().next_handle()); - A::blockchain_api_impl().load_balance(handle.clone(), address.get_handle()); - BigUint::from_handle(handle) + unsafe { + let result = BigUint::new_uninit(); + A::blockchain_api_impl().load_balance(result.get_handle(), address.get_handle()); + result + } } #[inline] @@ -141,7 +151,10 @@ where A::blockchain_api_impl() .managed_get_code_metadata(address.get_handle(), mbuf_temp_1.clone()); let mut buffer = [0u8; 2]; - ManagedBuffer::::from_handle(mbuf_temp_1).load_to_byte_array(&mut buffer); + unsafe { + ManagedRefMut::<'static, A, ManagedBuffer>::wrap_handle(mbuf_temp_1) + .load_to_byte_array(&mut buffer); + } CodeMetadata::from(buffer) } @@ -173,9 +186,11 @@ where #[inline] pub fn get_state_root_hash(&self) -> ManagedByteArray { - let handle: A::ManagedBufferHandle = use_raw_handle(A::static_var_api_impl().next_handle()); - A::blockchain_api_impl().load_state_root_hash_managed(handle.clone()); - ManagedByteArray::from_handle(handle) + unsafe { + let result = ManagedByteArray::new_uninit(); + A::blockchain_api_impl().load_state_root_hash_managed(result.get_handle()); + result + } } #[deprecated(since = "0.41.0", note = "Please use method `get_tx_hash` instead.")] @@ -187,9 +202,11 @@ where #[inline] pub fn get_tx_hash(&self) -> ManagedByteArray { - let handle: A::ManagedBufferHandle = use_raw_handle(A::static_var_api_impl().next_handle()); - A::blockchain_api_impl().load_tx_hash_managed(handle.clone()); - ManagedByteArray::from_handle(handle) + unsafe { + let result = ManagedByteArray::new_uninit(); + A::blockchain_api_impl().load_tx_hash_managed(result.get_handle()); + result + } } #[inline] @@ -229,9 +246,11 @@ where #[inline] pub fn get_block_random_seed(&self) -> ManagedByteArray { - let handle: A::ManagedBufferHandle = use_raw_handle(A::static_var_api_impl().next_handle()); - A::blockchain_api_impl().load_block_random_seed_managed(handle.clone()); - ManagedByteArray::from_handle(handle) + unsafe { + let result = ManagedByteArray::new_uninit(); + A::blockchain_api_impl().load_block_random_seed_managed(result.get_handle()); + result + } } #[inline] @@ -266,9 +285,11 @@ where #[inline] pub fn get_prev_block_random_seed(&self) -> ManagedByteArray { - let handle: A::ManagedBufferHandle = use_raw_handle(A::static_var_api_impl().next_handle()); - A::blockchain_api_impl().load_prev_block_random_seed_managed(handle.clone()); - ManagedByteArray::from_handle(handle) + unsafe { + let result = ManagedByteArray::new_uninit(); + A::blockchain_api_impl().load_prev_block_random_seed_managed(result.get_handle()); + result + } } #[inline] @@ -288,14 +309,16 @@ where token_id: &TokenIdentifier, nonce: u64, ) -> BigUint { - let result_handle: A::BigIntHandle = use_raw_handle(A::static_var_api_impl().next_handle()); - A::blockchain_api_impl().load_esdt_balance( - address.get_handle(), - token_id.get_handle(), - nonce, - result_handle.clone(), - ); - BigUint::from_handle(result_handle) + unsafe { + let result = BigUint::new_uninit(); + A::blockchain_api_impl().load_esdt_balance( + address.get_handle(), + token_id.get_handle(), + nonce, + result.get_handle(), + ); + result + } } pub fn get_esdt_token_data( @@ -346,16 +369,18 @@ where let _ = managed_api_impl.mb_load_slice(properties_handle, 0, &mut properties_bytes[..]); let frozen = esdt_is_frozen(&properties_bytes); - EsdtTokenData { - token_type, - amount: BigUint::from_raw_handle(value_handle.get_raw_handle()), - frozen, - hash: ManagedBuffer::from_raw_handle(hash_handle.get_raw_handle()), - name: ManagedBuffer::from_raw_handle(name_handle.get_raw_handle()), - attributes: ManagedBuffer::from_raw_handle(attributes_handle.get_raw_handle()), - creator: ManagedAddress::from_raw_handle(creator_handle.get_raw_handle()), - royalties: BigUint::from_raw_handle(royalties_handle.get_raw_handle()), - uris: ManagedVec::from_raw_handle(uris_handle.get_raw_handle()), + unsafe { + EsdtTokenData { + token_type, + amount: BigUint::from_raw_handle(value_handle.get_raw_handle()), + frozen, + hash: ManagedBuffer::from_raw_handle(hash_handle.get_raw_handle()), + name: ManagedBuffer::from_raw_handle(name_handle.get_raw_handle()), + attributes: ManagedBuffer::from_raw_handle(attributes_handle.get_raw_handle()), + creator: ManagedAddress::from_raw_handle(creator_handle.get_raw_handle()), + royalties: BigUint::from_raw_handle(royalties_handle.get_raw_handle()), + uris: ManagedVec::from_raw_handle(uris_handle.get_raw_handle()), + } } } @@ -375,9 +400,13 @@ where call_value_handle.get_raw_handle(), ); - BackTransfers { - total_egld_amount: BigUint::from_raw_handle(call_value_handle.get_raw_handle()), - esdt_payments: ManagedVec::from_raw_handle(esdt_transfer_value_handle.get_raw_handle()), + unsafe { + BackTransfers { + total_egld_amount: BigUint::from_raw_handle(call_value_handle.get_raw_handle()), + esdt_payments: ManagedVec::from_raw_handle( + esdt_transfer_value_handle.get_raw_handle(), + ), + } } } @@ -441,13 +470,11 @@ where // load value A::storage_read_api_impl() .storage_load_managed_buffer_raw(temp_handle_1, temp_handle_2.clone()); - let result_handle: A::BigIntHandle = use_raw_handle(A::static_var_api_impl().next_handle()); // convert value to BigUint - A::managed_type_impl().mb_to_big_int_unsigned(temp_handle_2, result_handle.clone()); - - //wrap - BigUint::from_handle(result_handle) + let result = unsafe { BigUint::new_uninit() }; + A::managed_type_impl().mb_to_big_int_unsigned(temp_handle_2, result.get_handle()); + result } } diff --git a/framework/base/src/contract_base/wrappers/crypto_wrapper.rs b/framework/base/src/contract_base/wrappers/crypto_wrapper.rs index 369cca1a63..3731d4a964 100644 --- a/framework/base/src/contract_base/wrappers/crypto_wrapper.rs +++ b/framework/base/src/contract_base/wrappers/crypto_wrapper.rs @@ -1,10 +1,7 @@ use core::marker::PhantomData; use crate::{ - api::{ - use_raw_handle, CryptoApi, CryptoApiImpl, StaticVarApiImpl, KECCAK256_RESULT_LEN, - SHA256_RESULT_LEN, - }, + api::{CryptoApi, CryptoApiImpl, KECCAK256_RESULT_LEN, SHA256_RESULT_LEN}, types::{ManagedBuffer, ManagedByteArray, ManagedType, ManagedVec, MessageHashType}, }; @@ -30,30 +27,33 @@ where &self, data: B, ) -> ManagedByteArray { - let new_handle: A::ManagedBufferHandle = - use_raw_handle(A::static_var_api_impl().next_handle()); - A::crypto_api_impl().sha256_managed(new_handle.clone(), data.borrow().get_handle()); - ManagedByteArray::from_handle(new_handle) + unsafe { + let result = ManagedByteArray::new_uninit(); + A::crypto_api_impl().sha256_managed(result.get_handle(), data.borrow().get_handle()); + result + } } pub fn keccak256>>( &self, data: B, ) -> ManagedByteArray { - let new_handle: A::ManagedBufferHandle = - use_raw_handle(A::static_var_api_impl().next_handle()); - A::crypto_api_impl().keccak256_managed(new_handle.clone(), data.borrow().get_handle()); - ManagedByteArray::from_handle(new_handle) + unsafe { + let result = ManagedByteArray::new_uninit(); + A::crypto_api_impl().keccak256_managed(result.get_handle(), data.borrow().get_handle()); + result + } } pub fn ripemd160>>( &self, data: B, ) -> ManagedByteArray { - let new_handle: A::ManagedBufferHandle = - use_raw_handle(A::static_var_api_impl().next_handle()); - A::crypto_api_impl().ripemd160_managed(new_handle.clone(), data.borrow().get_handle()); - ManagedByteArray::from_handle(new_handle) + unsafe { + let result = ManagedByteArray::new_uninit(); + A::crypto_api_impl().ripemd160_managed(result.get_handle(), data.borrow().get_handle()); + result + } } pub fn verify_bls( @@ -122,14 +122,15 @@ where r: &ManagedBuffer, s: &ManagedBuffer, ) -> ManagedBuffer { - let new_handle: A::ManagedBufferHandle = - use_raw_handle(A::static_var_api_impl().next_handle()); - A::crypto_api_impl().encode_secp256k1_der_signature_managed( - r.get_handle(), - s.get_handle(), - new_handle.clone(), - ); - ManagedBuffer::from_handle(new_handle) + unsafe { + let result = ManagedBuffer::new_uninit(); + A::crypto_api_impl().encode_secp256k1_der_signature_managed( + r.get_handle(), + s.get_handle(), + result.get_handle(), + ); + result + } } /// Calls the Vm to verify secp256r1 signature. diff --git a/framework/base/src/contract_base/wrappers/send_raw_wrapper.rs b/framework/base/src/contract_base/wrappers/send_raw_wrapper.rs index 5d290369df..07466ac234 100644 --- a/framework/base/src/contract_base/wrappers/send_raw_wrapper.rs +++ b/framework/base/src/contract_base/wrappers/send_raw_wrapper.rs @@ -192,10 +192,12 @@ where new_address_handle, result_handle, ); - ( - ManagedAddress::from_raw_handle(new_address_handle), - ManagedVec::from_raw_handle(result_handle), - ) + unsafe { + ( + ManagedAddress::from_raw_handle(new_address_handle), + ManagedVec::from_raw_handle(result_handle), + ) + } } /// Deploys a new contract in the same shard by re-using the code of an already deployed source contract. @@ -222,10 +224,12 @@ where new_address_handle, result_handle, ); - ( - ManagedAddress::from_raw_handle(new_address_handle), - ManagedVec::from_raw_handle(result_handle), - ) + unsafe { + ( + ManagedAddress::from_raw_handle(new_address_handle), + ManagedVec::from_raw_handle(result_handle), + ) + } } pub fn upgrade_from_source_contract( @@ -291,7 +295,7 @@ where arg_buffer.get_handle().get_raw_handle(), result_handle, ); - ManagedVec::from_raw_handle(result_handle) + unsafe { ManagedVec::from_raw_handle(result_handle) } } pub fn execute_on_same_context_raw( @@ -311,7 +315,7 @@ where arg_buffer.get_handle().get_raw_handle(), result_handle, ); - ManagedVec::from_raw_handle(result_handle) + unsafe { ManagedVec::from_raw_handle(result_handle) } } /// Same shard, in-line execution of another contract. @@ -330,7 +334,7 @@ where arg_buffer.get_handle().get_raw_handle(), result_handle, ); - ManagedVec::from_raw_handle(result_handle) + unsafe { ManagedVec::from_raw_handle(result_handle) } } /// Allows synchronously calling a local function by name. Execution is resumed afterwards. @@ -357,8 +361,7 @@ where ); self.clean_return_data(); - - ManagedVec::from_raw_handle(result_handle) + unsafe { ManagedVec::from_raw_handle(result_handle) } } pub fn clean_return_data(&self) { diff --git a/framework/base/src/contract_base/wrappers/send_wrapper.rs b/framework/base/src/contract_base/wrappers/send_wrapper.rs index 3a11bde247..0c23b67cd4 100644 --- a/framework/base/src/contract_base/wrappers/send_wrapper.rs +++ b/framework/base/src/contract_base/wrappers/send_wrapper.rs @@ -2,6 +2,7 @@ use core::marker::PhantomData; use crate::codec::Empty; +use crate::types::ManagedRef; use crate::{ api::{BlockchainApi, CallTypeApi, StorageReadApi}, codec, @@ -589,7 +590,9 @@ where ) -> u64 { let big_zero = BigUint::zero(); let empty_buffer = ManagedBuffer::new(); - let empty_vec = ManagedVec::from_handle(empty_buffer.get_handle()); + + // sneakily reuses the same handle + let empty_vec = unsafe { ManagedRef::wrap_handle(empty_buffer.get_handle()) }; self.esdt_nft_create( token, diff --git a/framework/base/src/contract_base/wrappers/storage_raw_wrapper.rs b/framework/base/src/contract_base/wrappers/storage_raw_wrapper.rs index 7417d6ca52..9fd49e115b 100644 --- a/framework/base/src/contract_base/wrappers/storage_raw_wrapper.rs +++ b/framework/base/src/contract_base/wrappers/storage_raw_wrapper.rs @@ -59,7 +59,8 @@ where V: TopDecode, { let key: StorageKey = storage_key.into(); - let result_buffer = ManagedBuffer::::from_handle(use_raw_handle(MBUF_TEMPORARY_1)); + let result_buffer = + unsafe { ManagedBuffer::::from_handle(use_raw_handle(MBUF_TEMPORARY_1)) }; A::storage_read_api_impl().storage_load_from_address( address.get_handle(), key.get_handle(), diff --git a/framework/base/src/io/arg_de_input.rs b/framework/base/src/io/arg_de_input.rs index 98faef2899..1b5502b6fa 100644 --- a/framework/base/src/io/arg_de_input.rs +++ b/framework/base/src/io/arg_de_input.rs @@ -1,10 +1,7 @@ use core::marker::PhantomData; use crate::{ - api::{ - use_raw_handle, EndpointArgumentApi, EndpointArgumentApiImpl, ManagedTypeApi, - StaticVarApiImpl, - }, + api::{EndpointArgumentApi, EndpointArgumentApiImpl, ManagedTypeApi}, codec::{ try_execute_then_cast, DecodeError, DecodeErrorHandler, TopDecodeInput, TryStaticCast, }, @@ -43,22 +40,30 @@ where } fn to_managed_buffer(&self) -> ManagedBuffer { - let mbuf_handle: AA::ManagedBufferHandle = - use_raw_handle(AA::static_var_api_impl().next_handle()); - AA::argument_api_impl().load_argument_managed_buffer(self.arg_index, mbuf_handle.clone()); - ManagedBuffer::from_handle(mbuf_handle) + unsafe { + let result = ManagedBuffer::new_uninit(); + AA::argument_api_impl() + .load_argument_managed_buffer(self.arg_index, result.get_handle()); + result + } } fn to_big_int(&self) -> BigInt { - let bi_handle: AA::BigIntHandle = use_raw_handle(AA::static_var_api_impl().next_handle()); - AA::argument_api_impl().load_argument_big_int_signed(self.arg_index, bi_handle.clone()); - BigInt::from_handle(bi_handle) + unsafe { + let result = BigInt::new_uninit(); + AA::argument_api_impl() + .load_argument_big_int_signed(self.arg_index, result.get_handle()); + result + } } fn to_big_uint(&self) -> BigUint { - let bi_handle: AA::BigIntHandle = use_raw_handle(AA::static_var_api_impl().next_handle()); - AA::argument_api_impl().load_argument_big_int_unsigned(self.arg_index, bi_handle.clone()); - BigUint::from_handle(bi_handle) + unsafe { + let result = BigUint::new_uninit(); + AA::argument_api_impl() + .load_argument_big_int_unsigned(self.arg_index, result.get_handle()); + result + } } } diff --git a/framework/base/src/io/arg_nested_tuple.rs b/framework/base/src/io/arg_nested_tuple.rs index fca34c9886..1a0eaace7a 100644 --- a/framework/base/src/io/arg_nested_tuple.rs +++ b/framework/base/src/io/arg_nested_tuple.rs @@ -198,13 +198,15 @@ fn callback_closure_args_loader() -> ManagedResultArgLoader where AA: VMApi, { - AA::argument_api_impl() - .load_callback_closure_buffer(use_raw_handle(const_handles::MBUF_TEMPORARY_1)); - let cb_closure_args_serialized = - ManagedBuffer::::from_raw_handle(const_handles::MBUF_TEMPORARY_1); - let mut cb_closure_args_buffer = - ManagedArgBuffer::::from_raw_handle(const_handles::CALLBACK_CLOSURE_ARGS_BUFFER); - cb_closure_args_buffer.deserialize_overwrite(cb_closure_args_serialized); - - ManagedResultArgLoader::new(cb_closure_args_buffer.into_vec_of_buffers()) + unsafe { + AA::argument_api_impl() + .load_callback_closure_buffer(use_raw_handle(const_handles::MBUF_TEMPORARY_1)); + let cb_closure_args_serialized = + ManagedBuffer::::from_raw_handle(const_handles::MBUF_TEMPORARY_1); + let mut cb_closure_args_buffer = + ManagedArgBuffer::::from_raw_handle(const_handles::CALLBACK_CLOSURE_ARGS_BUFFER); + cb_closure_args_buffer.deserialize_overwrite(cb_closure_args_serialized); + + ManagedResultArgLoader::new(cb_closure_args_buffer.into_vec_of_buffers()) + } } diff --git a/framework/base/src/storage/storage_get.rs b/framework/base/src/storage/storage_get.rs index 85107896dd..b33b5e1dcb 100644 --- a/framework/base/src/storage/storage_get.rs +++ b/framework/base/src/storage/storage_get.rs @@ -3,7 +3,7 @@ use core::{convert::Infallible, marker::PhantomData}; use crate::{ api::{ const_handles, use_raw_handle, ErrorApi, ErrorApiImpl, HandleConstraints, - ManagedBufferApiImpl, ManagedTypeApi, StaticVarApiImpl, StorageReadApi, StorageReadApiImpl, + ManagedBufferApiImpl, ManagedTypeApi, StorageReadApi, StorageReadApiImpl, }, codec::*, err_msg, @@ -33,11 +33,12 @@ where } fn to_managed_buffer(&self) -> ManagedBuffer { - let mbuf_handle: A::ManagedBufferHandle = - use_raw_handle(A::static_var_api_impl().next_handle()); - A::storage_read_api_impl() - .storage_load_managed_buffer_raw(self.key.buffer.get_handle(), mbuf_handle.clone()); - ManagedBuffer::from_handle(mbuf_handle) + unsafe { + let result = ManagedBuffer::new_uninit(); + A::storage_read_api_impl() + .storage_load_managed_buffer_raw(self.key.buffer.get_handle(), result.get_handle()); + result + } } fn to_big_uint(&self) -> BigUint { diff --git a/framework/base/src/storage/storage_get_from_address.rs b/framework/base/src/storage/storage_get_from_address.rs index 2b40987bd3..13a467d2f0 100644 --- a/framework/base/src/storage/storage_get_from_address.rs +++ b/framework/base/src/storage/storage_get_from_address.rs @@ -1,7 +1,7 @@ use crate::{ api::{ const_handles, use_raw_handle, ErrorApi, HandleConstraints, ManagedBufferApiImpl, - ManagedTypeApi, StaticVarApiImpl, StorageReadApi, StorageReadApiImpl, + ManagedTypeApi, StorageReadApi, StorageReadApiImpl, }, codec::*, types::{ @@ -35,15 +35,15 @@ where } fn to_managed_buffer(&self) -> ManagedBuffer { - let mbuf_handle: A::ManagedBufferHandle = - use_raw_handle(A::static_var_api_impl().next_handle()); - A::storage_read_api_impl().storage_load_from_address( - self.addr.get_handle(), - self.key.buffer.get_handle(), - mbuf_handle.clone(), - ); - - ManagedBuffer::from_handle(mbuf_handle) + unsafe { + let result = ManagedBuffer::new_uninit(); + A::storage_read_api_impl().storage_load_from_address( + self.addr.get_handle(), + self.key.buffer.get_handle(), + result.get_handle(), + ); + result + } } fn to_big_uint(&self) -> BigUint { diff --git a/framework/base/src/storage/storage_key.rs b/framework/base/src/storage/storage_key.rs index b56358218b..b3a35643e1 100644 --- a/framework/base/src/storage/storage_key.rs +++ b/framework/base/src/storage/storage_key.rs @@ -22,7 +22,7 @@ where type OwnHandle = A::ManagedBufferHandle; #[inline] - fn from_handle(handle: A::ManagedBufferHandle) -> Self { + unsafe fn from_handle(handle: A::ManagedBufferHandle) -> Self { StorageKey { buffer: ManagedBuffer::from_handle(handle), } @@ -35,6 +35,10 @@ where fn transmute_from_handle_ref(handle_ref: &A::ManagedBufferHandle) -> &Self { unsafe { core::mem::transmute(handle_ref) } } + + fn transmute_from_handle_ref_mut(handle_ref: &mut A::ManagedBufferHandle) -> &mut Self { + unsafe { core::mem::transmute(handle_ref) } + } } impl StorageKey diff --git a/framework/base/src/types/interaction/contract_call_legacy/async_call_promises.rs b/framework/base/src/types/interaction/contract_call_legacy/async_call_promises.rs index ee3726c0eb..f2d091e2b3 100644 --- a/framework/base/src/types/interaction/contract_call_legacy/async_call_promises.rs +++ b/framework/base/src/types/interaction/contract_call_legacy/async_call_promises.rs @@ -1,5 +1,7 @@ +use core::ops::DerefMut; + use crate::{ - api::CallTypeApi, + api::{const_handles, CallTypeApi}, contract_base::SendRawWrapper, types::{BigUint, CallbackClosure, FunctionCall, ManagedAddress, ManagedBuffer}, }; @@ -41,16 +43,14 @@ where } pub fn register_promise(self) { - use crate::{api::const_handles, types::ManagedType}; - let mut cb_closure_args_serialized = - ManagedBuffer::::from_raw_handle(const_handles::MBUF_TEMPORARY_1); + unsafe { ManagedBuffer::temp_const_ref_mut(const_handles::MBUF_TEMPORARY_1) }; let callback_name; if let Some(callback_call) = self.callback_call { callback_name = callback_call.callback_name; callback_call .closure_args - .serialize_overwrite(&mut cb_closure_args_serialized); + .serialize_overwrite(cb_closure_args_serialized.deref_mut()); } else { callback_name = ""; cb_closure_args_serialized.overwrite(&[]); diff --git a/framework/base/src/types/interaction/contract_call_legacy/contract_call_exec.rs b/framework/base/src/types/interaction/contract_call_legacy/contract_call_exec.rs index 427218f1c8..f0f1722f24 100644 --- a/framework/base/src/types/interaction/contract_call_legacy/contract_call_exec.rs +++ b/framework/base/src/types/interaction/contract_call_legacy/contract_call_exec.rs @@ -36,10 +36,12 @@ where call_value_handle.get_raw_handle(), ); - ( - BigUint::from_raw_handle(call_value_handle.get_raw_handle()), - ManagedVec::from_raw_handle(esdt_transfer_value_handle.get_raw_handle()), - ) + unsafe { + ( + BigUint::from_raw_handle(call_value_handle.get_raw_handle()), + ManagedVec::from_raw_handle(esdt_transfer_value_handle.get_raw_handle()), + ) + } } pub fn to_call_data_string(&self) -> ManagedBuffer { diff --git a/framework/base/src/types/interaction/managed_arg_buffer.rs b/framework/base/src/types/interaction/managed_arg_buffer.rs index c6dae76afd..009ad74e3a 100644 --- a/framework/base/src/types/interaction/managed_arg_buffer.rs +++ b/framework/base/src/types/interaction/managed_arg_buffer.rs @@ -33,7 +33,7 @@ where type OwnHandle = M::ManagedBufferHandle; #[inline] - fn from_handle(handle: M::ManagedBufferHandle) -> Self { + unsafe fn from_handle(handle: M::ManagedBufferHandle) -> Self { ManagedArgBuffer { data: ManagedVec::from_handle(handle), } @@ -46,6 +46,10 @@ where fn transmute_from_handle_ref(handle_ref: &M::ManagedBufferHandle) -> &Self { unsafe { core::mem::transmute(handle_ref) } } + + fn transmute_from_handle_ref_mut(handle_ref: &mut M::ManagedBufferHandle) -> &mut Self { + unsafe { core::mem::transmute(handle_ref) } + } } impl ManagedArgBuffer diff --git a/framework/base/src/types/interaction/markers/to_caller.rs b/framework/base/src/types/interaction/markers/to_caller.rs index f24191ce9f..9066a16239 100644 --- a/framework/base/src/types/interaction/markers/to_caller.rs +++ b/framework/base/src/types/interaction/markers/to_caller.rs @@ -1,5 +1,5 @@ use crate::{ - api::{const_handles, use_raw_handle, BlockchainApi, BlockchainApiImpl, CallTypeApi}, + api::{const_handles, BlockchainApi, BlockchainApiImpl, CallTypeApi}, contract_base::BlockchainWrapper, types::{ AnnotatedValue, ManagedAddress, ManagedBuffer, ManagedType, TxScEnv, TxTo, TxToSpecified, @@ -25,9 +25,11 @@ where where F: FnOnce(&ManagedAddress) -> R, { - let caller_handle: Api::ManagedBufferHandle = use_raw_handle(const_handles::ADDRESS_CALLER); - Api::blockchain_api_impl().load_caller_managed(caller_handle.clone()); - f(&ManagedAddress::from_handle(caller_handle)) + unsafe { + let temp = ManagedAddress::temp_const_ref(const_handles::ADDRESS_CALLER); + Api::blockchain_api_impl().load_caller_managed(temp.get_handle()); + f(&temp) + } } } diff --git a/framework/base/src/types/interaction/markers/to_self.rs b/framework/base/src/types/interaction/markers/to_self.rs index f339a448e2..8a78e13d6d 100644 --- a/framework/base/src/types/interaction/markers/to_self.rs +++ b/framework/base/src/types/interaction/markers/to_self.rs @@ -1,5 +1,5 @@ use crate::{ - api::{const_handles, use_raw_handle, BlockchainApi, BlockchainApiImpl, CallTypeApi}, + api::{const_handles, BlockchainApi, BlockchainApiImpl, CallTypeApi}, contract_base::BlockchainWrapper, types::{ AnnotatedValue, ManagedAddress, ManagedBuffer, ManagedType, TxScEnv, TxTo, TxToSpecified, @@ -26,10 +26,11 @@ where where F: FnOnce(&ManagedAddress) -> R, { - let sc_address_handle: Api::ManagedBufferHandle = - use_raw_handle(const_handles::ADDRESS_CALLER); - Api::blockchain_api_impl().load_sc_address_managed(sc_address_handle.clone()); - f(&ManagedAddress::from_handle(sc_address_handle)) + unsafe { + let temp = ManagedAddress::temp_const_ref(const_handles::ADDRESS_CALLER); + Api::blockchain_api_impl().load_sc_address_managed(temp.get_handle()); + f(&temp) + } } } diff --git a/framework/base/src/types/interaction/tx_exec/tx_exec_async_promises.rs b/framework/base/src/types/interaction/tx_exec/tx_exec_async_promises.rs index 38e38fcbcd..333bbf9379 100644 --- a/framework/base/src/types/interaction/tx_exec/tx_exec_async_promises.rs +++ b/framework/base/src/types/interaction/tx_exec/tx_exec_async_promises.rs @@ -3,8 +3,8 @@ use crate::{ contract_base::{ErrorHelper, SendRawWrapper}, types::{ interaction::callback_closure::CallbackClosureWithGas, CallbackClosure, ExplicitGas, - FunctionCall, ManagedBuffer, ManagedType, OriginalResultMarker, Tx, TxGas, TxGasValue, - TxPayment, TxResultHandler, TxScEnv, TxToSpecified, + FunctionCall, ManagedBuffer, OriginalResultMarker, Tx, TxGas, TxGasValue, TxPayment, + TxResultHandler, TxScEnv, TxToSpecified, }, }; @@ -160,7 +160,7 @@ where pub fn register_promise(self) { let callback_name = self.result_handler.callback_name(); let mut cb_closure_args_serialized = - ManagedBuffer::::from_raw_handle(const_handles::MBUF_TEMPORARY_1); + unsafe { ManagedBuffer::temp_const_ref_mut(const_handles::MBUF_TEMPORARY_1) }; self.result_handler .overwrite_with_serialized_args(&mut cb_closure_args_serialized); let extra_gas_for_callback = self.result_handler.gas_for_callback(); diff --git a/framework/base/src/types/managed/basic/big_float.rs b/framework/base/src/types/managed/basic/big_float.rs index 54850a1672..634d76f67d 100644 --- a/framework/base/src/types/managed/basic/big_float.rs +++ b/framework/base/src/types/managed/basic/big_float.rs @@ -27,7 +27,7 @@ pub struct BigFloat { impl ManagedType for BigFloat { type OwnHandle = M::BigFloatHandle; - fn from_handle(handle: M::BigFloatHandle) -> Self { + unsafe fn from_handle(handle: M::BigFloatHandle) -> Self { BigFloat { handle } } @@ -38,6 +38,10 @@ impl ManagedType for BigFloat { fn transmute_from_handle_ref(handle_ref: &M::BigFloatHandle) -> &Self { unsafe { core::mem::transmute(handle_ref) } } + + fn transmute_from_handle_ref_mut(handle_ref: &mut M::BigFloatHandle) -> &mut Self { + unsafe { core::mem::transmute(handle_ref) } + } } impl From<&ManagedBuffer> for BigFloat { @@ -81,10 +85,11 @@ macro_rules! big_float_conv_num { impl From<$num_ty> for BigFloat { #[inline] fn from(value: $num_ty) -> Self { - let new_bf_handle: M::BigFloatHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().bf_set_i64(new_bf_handle.clone(), value as i64); - BigFloat::from_handle(new_bf_handle) + unsafe { + let result = BigFloat::new_uninit(); + M::managed_type_impl().bf_set_i64(result.get_handle(), value as i64); + result + } } } }; @@ -98,31 +103,31 @@ big_float_conv_num! {i8} impl BigFloat { pub fn neg(&self) -> Self { - let new_bf_handle: M::BigFloatHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().bf_neg(new_bf_handle.clone(), self.handle.clone()); - BigFloat::from_handle(new_bf_handle) + unsafe { + let result = BigFloat::new_uninit(); + M::managed_type_impl().bf_neg(result.get_handle(), self.handle.clone()); + result + } } pub fn abs(&self) -> Self { - let new_bf_handle: M::BigFloatHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().bf_abs(new_bf_handle.clone(), self.handle.clone()); - BigFloat::from_handle(new_bf_handle) + unsafe { + let result = BigFloat::new_uninit(); + M::managed_type_impl().bf_abs(result.get_handle(), self.handle.clone()); + result + } } - pub fn from_big_uint(big_uint: &BigUint) -> Self { - let new_bf_handle: M::BigFloatHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().bf_set_bi(new_bf_handle.clone(), big_uint.value.handle.clone()); - BigFloat::from_handle(new_bf_handle) + pub fn from_big_int(big_int: &BigInt) -> Self { + unsafe { + let result = BigFloat::new_uninit(); + M::managed_type_impl().bf_set_bi(result.get_handle(), big_int.handle.clone()); + result + } } - pub fn from_big_int(big_int: &BigInt) -> Self { - let new_bf_handle: M::BigFloatHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().bf_set_bi(new_bf_handle.clone(), big_int.handle.clone()); - BigFloat::from_handle(new_bf_handle) + pub fn from_big_uint(big_uint: &BigUint) -> Self { + Self::from_big_int(big_uint.as_big_int()) } #[inline] @@ -134,42 +139,45 @@ impl BigFloat { let api = M::managed_type_impl(); let new_bf_handle = api.bf_from_parts(integral_part_value, fractional_part_value, exponent_value); - BigFloat::from_handle(new_bf_handle) + unsafe { BigFloat::from_handle(new_bf_handle) } } #[inline] pub fn from_frac(numerator_value: i64, denominator_value: i64) -> Self { let api = M::managed_type_impl(); let new_bf_handle = api.bf_from_frac(numerator_value, denominator_value); - BigFloat::from_handle(new_bf_handle) + unsafe { BigFloat::from_handle(new_bf_handle) } } #[inline] pub fn from_sci(significand_value: i64, exponent_value: i32) -> Self { let api = M::managed_type_impl(); let new_bf_handle = api.bf_from_sci(significand_value, exponent_value as i64); - BigFloat::from_handle(new_bf_handle) + unsafe { BigFloat::from_handle(new_bf_handle) } } pub fn trunc(&self) -> BigInt { - let result: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - let api = M::managed_type_impl(); - api.bf_trunc(result.clone(), self.handle.clone()); - BigInt::from_handle(result) + unsafe { + let result = BigInt::new_uninit(); + M::managed_type_impl().bf_trunc(result.get_handle(), self.handle.clone()); + result + } } pub fn floor(&self) -> BigInt { - let result: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - let api = M::managed_type_impl(); - api.bf_floor(result.clone(), self.handle.clone()); - BigInt::from_handle(result) + unsafe { + let result = BigInt::new_uninit(); + M::managed_type_impl().bf_floor(result.get_handle(), self.handle.clone()); + result + } } pub fn ceil(&self) -> BigInt { - let result: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - let api = M::managed_type_impl(); - api.bf_ceil(result.clone(), self.handle.clone()); - BigInt::from_handle(result) + unsafe { + let result = BigInt::new_uninit(); + M::managed_type_impl().bf_ceil(result.get_handle(), self.handle.clone()); + result + } } pub fn to_fixed_point(&self, denominator: &BigFloat) -> BigInt { @@ -250,38 +258,52 @@ impl BigFloat { #[inline] pub fn zero() -> Self { - BigFloat::from_handle(M::managed_type_impl().bf_new_zero()) + unsafe { BigFloat::from_handle(M::managed_type_impl().bf_new_zero()) } } pub fn from_buffer(managed_buffer: &ManagedBuffer) -> Self { - let new_bf_handle: M::BigFloatHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl() - .mb_to_big_float(managed_buffer.handle.clone(), new_bf_handle.clone()); - BigFloat::from_handle(new_bf_handle) + unsafe { + let result = BigFloat::new_uninit(); + M::managed_type_impl() + .mb_to_big_float(managed_buffer.handle.clone(), result.get_handle()); + result + } } pub fn to_buffer(&self) -> ManagedBuffer { - let new_man_buf_handle: M::ManagedBufferHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().mb_from_big_float(self.handle.clone(), new_man_buf_handle.clone()); - ManagedBuffer::from_handle(new_man_buf_handle) + unsafe { + let result = ManagedBuffer::new_uninit(); + M::managed_type_impl().mb_from_big_float(self.get_handle(), result.get_handle()); + result + } + } + + /// Creates a new object, without initializing it. + /// + /// ## Safety + /// + /// The value needs to be initialized after creation, otherwise the VM will halt the first time the value is attempted to be read. + pub unsafe fn new_uninit() -> Self { + let new_handle: M::BigFloatHandle = use_raw_handle(M::static_var_api_impl().next_handle()); + BigFloat::from_handle(new_handle) } } impl BigFloat { pub fn sqrt(&self) -> Self { - let api = M::managed_type_impl(); - let new_handle: M::BigFloatHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - api.bf_sqrt(new_handle.clone(), self.handle.clone()); - BigFloat::from_handle(new_handle) + unsafe { + let result = BigFloat::new_uninit(); + M::managed_type_impl().bf_sqrt(result.get_handle(), self.handle.clone()); + result + } } pub fn pow(&self, exp: i32) -> Self { - let api = M::managed_type_impl(); - let new_handle: M::BigFloatHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - api.bf_pow(new_handle.clone(), self.handle.clone(), exp); - BigFloat::from_handle(new_handle) + unsafe { + let result = BigFloat::new_uninit(); + M::managed_type_impl().bf_pow(result.get_handle(), self.handle.clone(), exp); + result + } } /// Returns the sign of the `BigFloat` as a `Sign`. @@ -295,9 +317,11 @@ impl BigFloat { /// Returns the magnitude of the `BigFloat` pub fn magnitude(&self) -> BigFloat { - let result: M::BigFloatHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().bf_abs(result.clone(), self.handle.clone()); - BigFloat::from_handle(result) + unsafe { + let result = BigFloat::new_uninit(); + M::managed_type_impl().bf_abs(result.get_handle(), self.handle.clone()); + result + } } /// Convert this `BigFloat` into its `Sign` and its magnitude, @@ -337,9 +361,11 @@ impl BigFloat { impl Clone for BigFloat { fn clone(&self) -> Self { - let new_handle: M::BigFloatHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().bf_clone(new_handle.clone(), self.handle.clone()); - BigFloat::from_handle(new_handle) + unsafe { + let result = BigFloat::new_uninit(); + M::managed_type_impl().bf_clone(result.get_handle(), self.handle.clone()); + result + } } } diff --git a/framework/base/src/types/managed/basic/big_float_operators.rs b/framework/base/src/types/managed/basic/big_float_operators.rs index 7874c1ab86..e8d27016a8 100644 --- a/framework/base/src/types/managed/basic/big_float_operators.rs +++ b/framework/base/src/types/managed/basic/big_float_operators.rs @@ -1,6 +1,6 @@ use super::BigFloat; use crate::{ - api::{use_raw_handle, BigFloatApiImpl, ManagedTypeApi, StaticVarApiImpl}, + api::{BigFloatApiImpl, ManagedTypeApi}, types::managed::managed_type_trait::ManagedType, }; use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; @@ -16,7 +16,7 @@ macro_rules! binary_operator { self.handle.clone(), other.handle.clone(), ); - BigFloat::from_handle(self.handle.clone()) + self } } @@ -24,14 +24,15 @@ macro_rules! binary_operator { type Output = BigFloat; fn $method(self, other: &BigFloat) -> BigFloat { - let result_handle: M::BigFloatHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().$api_func( - result_handle.clone(), - self.handle.clone(), - other.handle.clone(), - ); - BigFloat::from_handle(result_handle) + unsafe { + let result = BigFloat::new_uninit(); + M::managed_type_impl().$api_func( + result.get_handle(), + self.handle.clone(), + other.handle.clone(), + ); + result + } } } }; @@ -79,9 +80,10 @@ impl Neg for BigFloat { type Output = BigFloat; fn neg(self) -> Self::Output { - let result_handle: M::BigFloatHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().bf_neg(result_handle.clone(), self.handle); - BigFloat::from_handle(result_handle) + unsafe { + let result = BigFloat::new_uninit(); + M::managed_type_impl().bf_neg(result.get_handle(), self.handle.clone()); + result + } } } diff --git a/framework/base/src/types/managed/basic/big_int.rs b/framework/base/src/types/managed/basic/big_int.rs index c705511f56..13c3b965af 100644 --- a/framework/base/src/types/managed/basic/big_int.rs +++ b/framework/base/src/types/managed/basic/big_int.rs @@ -11,7 +11,9 @@ use crate::{ NestedEncodeOutput, TopDecode, TopDecodeInput, TopEncode, TopEncodeOutput, TryStaticCast, }, formatter::{hex_util::encode_bytes_as_hex, FormatByteReceiver, SCDisplay}, - types::{heap::BoxedBytes, BigUint, ManagedBuffer, ManagedOption, ManagedType, Sign}, + types::{ + heap::BoxedBytes, BigUint, ManagedBuffer, ManagedOption, ManagedRef, ManagedType, Sign, + }, }; use super::cast_to_i64::cast_to_i64; @@ -25,7 +27,7 @@ pub struct BigInt { impl ManagedType for BigInt { type OwnHandle = M::BigIntHandle; - fn from_handle(handle: M::BigIntHandle) -> Self { + unsafe fn from_handle(handle: M::BigIntHandle) -> Self { BigInt { handle, _phantom: PhantomData, @@ -39,6 +41,10 @@ impl ManagedType for BigInt { fn transmute_from_handle_ref(handle_ref: &M::BigIntHandle) -> &Self { unsafe { core::mem::transmute(handle_ref) } } + + fn transmute_from_handle_ref_mut(handle_ref: &mut M::BigIntHandle) -> &mut Self { + unsafe { core::mem::transmute(handle_ref) } + } } impl Default for BigInt { @@ -63,6 +69,16 @@ impl From> for BigInt { } impl BigInt { + /// Creates a new object, without initializing it. + /// + /// ## Safety + /// + /// The value needs to be initialized after creation, otherwise the VM will halt the first time the value is attempted to be read. + pub unsafe fn new_uninit() -> Self { + let new_handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); + BigInt::from_handle(new_handle) + } + pub(crate) fn set_value(handle: M::BigIntHandle, value: T) where T: TryInto, @@ -83,7 +99,7 @@ impl BigInt { impl From> for BigInt { #[inline] fn from(item: BigUint) -> Self { - BigInt::from_handle(item.get_handle()) + item.into_big_int() } } @@ -92,10 +108,11 @@ macro_rules! big_int_conv_num { impl From<$num_ty> for BigInt { #[inline] fn from(value: $num_ty) -> Self { - let handle: M::BigIntHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - Self::set_value(handle.clone(), value); - BigInt::from_handle(handle) + unsafe { + let result = BigInt::new_uninit(); + Self::set_value(result.get_handle(), value); + result + } } } @@ -151,10 +168,11 @@ impl From for BigInt { impl BigInt { #[inline] pub fn zero() -> Self { - let handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - // TODO: seting 0 will no longer be needed once we fix VM handle error - M::managed_type_impl().bi_set_int64(handle.clone(), 0); - BigInt::from_handle(handle) + unsafe { + let result = BigInt::new_uninit(); + M::managed_type_impl().bi_set_int64(result.get_handle(), 0); + result + } } #[inline] @@ -171,9 +189,11 @@ impl BigInt { pub fn from_signed_bytes_be(bytes: &[u8]) -> Self { let mb_handle: M::ManagedBufferHandle = use_raw_handle(const_handles::MBUF_TEMPORARY_1); M::managed_type_impl().mb_overwrite(mb_handle.clone(), bytes); - let handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().mb_to_big_int_signed(mb_handle, handle.clone()); - BigInt::from_handle(handle) + unsafe { + let result = BigInt::new_uninit(); + M::managed_type_impl().mb_to_big_int_signed(mb_handle, result.get_handle()); + result + } } #[inline] @@ -185,41 +205,47 @@ impl BigInt { #[inline] pub fn from_signed_bytes_be_buffer(managed_buffer: &ManagedBuffer) -> Self { - let handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().mb_to_big_int_signed(managed_buffer.handle.clone(), handle.clone()); - BigInt::from_handle(handle) + unsafe { + let result = BigInt::new_uninit(); + M::managed_type_impl() + .mb_to_big_int_signed(managed_buffer.handle.clone(), result.get_handle()); + result + } } #[inline] pub fn to_signed_bytes_be_buffer(&self) -> ManagedBuffer { - let mb_handle: M::ManagedBufferHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().mb_from_big_int_signed(self.handle.clone(), mb_handle.clone()); - ManagedBuffer::from_handle(mb_handle) + unsafe { + let result = ManagedBuffer::new_uninit(); + M::managed_type_impl().mb_from_big_int_signed(self.handle.clone(), result.get_handle()); + result + } } } impl Clone for BigInt { fn clone(&self) -> Self { let api = M::managed_type_impl(); - let clone_handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - api.bi_set_int64(clone_handle.clone(), 0); - api.bi_add( - clone_handle.clone(), - clone_handle.clone(), - self.handle.clone(), - ); - BigInt::from_handle(clone_handle) + unsafe { + let result = BigInt::new_uninit(); + api.bi_set_int64(result.get_handle(), 0); + api.bi_add( + result.get_handle(), + result.get_handle(), + self.handle.clone(), + ); + result + } } } impl BigInt { pub fn from_biguint(sign: Sign, unsigned: BigUint) -> Self { - let api = M::managed_type_impl(); + let result = unsigned.into_big_int(); if sign.is_minus() { - api.bi_neg(unsigned.value.handle.clone(), unsigned.value.handle.clone()); + M::managed_type_impl().bi_neg(result.handle.clone(), result.handle.clone()); } - BigInt::from_handle(unsigned.value.handle) + result } /// Returns the sign of the `BigInt` as a `Sign`. @@ -234,10 +260,11 @@ impl BigInt { /// Returns the magnitude of the `BigInt` as a `BigUint`. pub fn magnitude(&self) -> BigUint { - let api = M::managed_type_impl(); - let result_handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - api.bi_abs(result_handle.clone(), self.handle.clone()); - BigUint::from_handle(result_handle) + unsafe { + let result = BigUint::new_uninit(); + M::managed_type_impl().bi_abs(result.get_handle(), self.get_handle()); + result + } } /// Convert this `BigInt` into its `Sign` and `BigUint` magnitude, @@ -252,7 +279,7 @@ impl BigInt { /// /// If the number is negative, undefined behavior might occur further down the execution. pub unsafe fn into_big_uint_unchecked(self) -> BigUint { - BigUint::from_handle(self.handle) + BigUint { value: self } } /// Converts this `BigInt` into a `BigUint`, if it's not negative. @@ -327,10 +354,12 @@ impl TopDecode for BigInt { impl BigInt { #[must_use] pub fn pow(&self, exp: u32) -> Self { - let result_handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); let exp_handle = BigUint::::make_temp(const_handles::BIG_INT_TEMPORARY_1, exp); - M::managed_type_impl().bi_pow(result_handle.clone(), self.handle.clone(), exp_handle); - BigInt::from_handle(result_handle) + unsafe { + let result = BigInt::new_uninit(); + M::managed_type_impl().bi_pow(result.get_handle(), self.get_handle(), exp_handle); + result + } } } @@ -338,9 +367,9 @@ impl SCDisplay for BigInt { fn fmt(&self, f: &mut F) { let str_handle: M::ManagedBufferHandle = use_raw_handle(const_handles::MBUF_TEMPORARY_1); M::managed_type_impl().bi_to_string(self.handle.clone(), str_handle.clone()); - f.append_managed_buffer(&ManagedBuffer::from_handle( - str_handle.cast_or_signal_error::(), - )); + let cast_handle = str_handle.cast_or_signal_error::(); + let wrap_cast = unsafe { ManagedRef::wrap_handle(cast_handle) }; + f.append_managed_buffer(&wrap_cast); } } diff --git a/framework/base/src/types/managed/basic/big_int_operators.rs b/framework/base/src/types/managed/basic/big_int_operators.rs index fed47d5a26..9edf670cb9 100644 --- a/framework/base/src/types/managed/basic/big_int_operators.rs +++ b/framework/base/src/types/managed/basic/big_int_operators.rs @@ -3,7 +3,7 @@ use core::ops::{ }; use crate::{ - api::{use_raw_handle, BigIntApiImpl, ManagedTypeApi, StaticVarApiImpl}, + api::{BigIntApiImpl, ManagedTypeApi}, types::{BigInt, BigUint, ManagedType, Sign}, }; @@ -19,7 +19,7 @@ macro_rules! binary_operator { self.handle.clone(), other.handle.clone(), ); - BigInt::from_handle(self.handle.clone()) + self } } @@ -44,14 +44,15 @@ macro_rules! binary_operator { fn $method(self, other: &BigInt) -> BigInt { let api = M::managed_type_impl(); - let result_handle: M::BigIntHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - api.$api_func( - result_handle.clone(), - self.handle.clone(), - other.handle.clone(), - ); - BigInt::from_handle(result_handle) + unsafe { + let result = BigInt::new_uninit(); + api.$api_func( + result.get_handle(), + self.handle.clone(), + other.handle.clone(), + ); + result + } } } @@ -59,7 +60,7 @@ macro_rules! binary_operator { type Output = BigInt; fn $method(self, other: &BigUint) -> BigInt { - self.$method(&BigInt::from_handle(other.get_handle())) + self.$method(other.as_big_int()) } } @@ -67,7 +68,7 @@ macro_rules! binary_operator { type Output = BigInt; fn $method(self, other: &BigInt) -> BigInt { - (&BigInt::from_handle(self.get_handle())).$method(other) + self.as_big_int().$method(other) } } }; @@ -117,9 +118,10 @@ impl Neg for BigInt { type Output = BigInt; fn neg(self) -> Self::Output { - let api = M::managed_type_impl(); - let result_handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - api.bi_neg(result_handle.clone(), self.handle); - BigInt::from_handle(result_handle) + unsafe { + let result = BigInt::new_uninit(); + M::managed_type_impl().bi_neg(result.get_handle(), self.handle); + result + } } } diff --git a/framework/base/src/types/managed/basic/elliptic_curve.rs b/framework/base/src/types/managed/basic/elliptic_curve.rs index 99189d06c5..2cc7097a18 100644 --- a/framework/base/src/types/managed/basic/elliptic_curve.rs +++ b/framework/base/src/types/managed/basic/elliptic_curve.rs @@ -35,7 +35,7 @@ pub struct EllipticCurve { impl ManagedType for EllipticCurve { type OwnHandle = M::EllipticCurveHandle; - fn from_handle(handle: M::EllipticCurveHandle) -> Self { + unsafe fn from_handle(handle: M::EllipticCurveHandle) -> Self { EllipticCurve { handle } } @@ -46,17 +46,21 @@ impl ManagedType for EllipticCurve { fn transmute_from_handle_ref(handle_ref: &M::EllipticCurveHandle) -> &Self { unsafe { core::mem::transmute(handle_ref) } } + + fn transmute_from_handle_ref_mut(handle_ref: &mut M::EllipticCurveHandle) -> &mut Self { + unsafe { core::mem::transmute(handle_ref) } + } } impl EllipticCurve { pub fn from_name(name: &ManagedBuffer) -> Self { let handle = M::managed_type_impl().ec_create_from_name_mb(name.get_handle()); - EllipticCurve::from_handle(handle) + unsafe { EllipticCurve::from_handle(handle) } } pub fn from_name_str(name: &str) -> Self { let handle = M::managed_type_impl().ec_create_from_name_bytes(name.as_bytes()); - EllipticCurve::from_handle(handle) + unsafe { EllipticCurve::from_handle(handle) } } pub fn from_bitsize(bitsize: u32) -> Option { @@ -84,14 +88,16 @@ impl EllipticCurve { x_base_point_handle.clone(), y_base_point_handle.clone(), ); - ( - BigUint::from_handle(field_order_handle), - BigUint::from_handle(base_point_order_handle), - BigUint::from_handle(eq_constant_handle), - BigUint::from_handle(x_base_point_handle), - BigUint::from_handle(y_base_point_handle), - api.ec_curve_length(self.handle.clone()), - ) + unsafe { + ( + BigUint::from_handle(field_order_handle), + BigUint::from_handle(base_point_order_handle), + BigUint::from_handle(eq_constant_handle), + BigUint::from_handle(x_base_point_handle), + BigUint::from_handle(y_base_point_handle), + api.ec_curve_length(self.handle.clone()), + ) + } } pub fn get_curve_length(&self) -> u32 { @@ -123,10 +129,12 @@ impl EllipticCurve { x_second_point.value.handle, y_second_point.value.handle, ); - ( - BigUint::from_handle(x_result_handle), - BigUint::from_handle(y_result_handle), - ) + unsafe { + ( + BigUint::from_handle(x_result_handle), + BigUint::from_handle(y_result_handle), + ) + } } pub fn double(&self, x_point: BigUint, y_point: BigUint) -> (BigUint, BigUint) { @@ -140,10 +148,12 @@ impl EllipticCurve { x_point.value.handle, y_point.value.handle, ); - ( - BigUint::from_handle(x_result_handle), - BigUint::from_handle(y_result_handle), - ) + unsafe { + ( + BigUint::from_handle(x_result_handle), + BigUint::from_handle(y_result_handle), + ) + } } pub fn is_on_curve(&self, x_point: BigUint, y_point: BigUint) -> bool { @@ -173,10 +183,12 @@ impl EllipticCurve { y_point.value.handle, data, ); - ( - BigUint::from_handle(x_result_handle), - BigUint::from_handle(y_result_handle), - ) + unsafe { + ( + BigUint::from_handle(x_result_handle), + BigUint::from_handle(y_result_handle), + ) + } } pub fn scalar_mult( @@ -196,10 +208,12 @@ impl EllipticCurve { y_point.value.handle, data.get_handle(), ); - ( - BigUint::from_handle(x_result_handle), - BigUint::from_handle(y_result_handle), - ) + unsafe { + ( + BigUint::from_handle(x_result_handle), + BigUint::from_handle(y_result_handle), + ) + } } #[deprecated( @@ -216,10 +230,12 @@ impl EllipticCurve { self.handle.clone(), data, ); - ( - BigUint::from_handle(x_result_handle), - BigUint::from_handle(y_result_handle), - ) + unsafe { + ( + BigUint::from_handle(x_result_handle), + BigUint::from_handle(y_result_handle), + ) + } } pub fn scalar_base_mult(&self, data: &ManagedBuffer) -> (BigUint, BigUint) { @@ -232,10 +248,12 @@ impl EllipticCurve { self.handle.clone(), data.get_handle(), ); - ( - BigUint::from_handle(x_result_handle), - BigUint::from_handle(y_result_handle), - ) + unsafe { + ( + BigUint::from_handle(x_result_handle), + BigUint::from_handle(y_result_handle), + ) + } } #[deprecated(since = "0.41.0", note = "Please use method `marshal` instead.")] @@ -262,7 +280,7 @@ impl EllipticCurve { y_pair.value.handle, result_handle.clone(), ); - ManagedBuffer::from_handle(result_handle) + unsafe { ManagedBuffer::from_handle(result_handle) } } #[deprecated( @@ -292,7 +310,7 @@ impl EllipticCurve { y_pair.value.handle, result_handle.clone(), ); - ManagedBuffer::from_handle(result_handle) + unsafe { ManagedBuffer::from_handle(result_handle) } } #[deprecated(since = "0.41.0", note = "Please use method `unmarshal` instead.")] @@ -306,10 +324,12 @@ impl EllipticCurve { self.handle.clone(), data, ); - ( - BigUint::from_handle(x_pair_handle), - BigUint::from_handle(y_pair_handle), - ) + unsafe { + ( + BigUint::from_handle(x_pair_handle), + BigUint::from_handle(y_pair_handle), + ) + } } pub fn unmarshal(&self, data: &ManagedBuffer) -> (BigUint, BigUint) { @@ -322,10 +342,12 @@ impl EllipticCurve { self.handle.clone(), data.get_handle(), ); - ( - BigUint::from_handle(x_pair_handle), - BigUint::from_handle(y_pair_handle), - ) + unsafe { + ( + BigUint::from_handle(x_pair_handle), + BigUint::from_handle(y_pair_handle), + ) + } } #[deprecated( @@ -342,10 +364,12 @@ impl EllipticCurve { self.handle.clone(), data, ); - ( - BigUint::from_handle(x_pair_handle), - BigUint::from_handle(y_pair_handle), - ) + unsafe { + ( + BigUint::from_handle(x_pair_handle), + BigUint::from_handle(y_pair_handle), + ) + } } pub fn unmarshal_compressed(&self, data: &ManagedBuffer) -> (BigUint, BigUint) { @@ -358,10 +382,12 @@ impl EllipticCurve { self.handle.clone(), data.get_handle(), ); - ( - BigUint::from_handle(x_pair_handle), - BigUint::from_handle(y_pair_handle), - ) + unsafe { + ( + BigUint::from_handle(x_pair_handle), + BigUint::from_handle(y_pair_handle), + ) + } } #[deprecated(since = "0.41.0", note = "Please use method `generate_key` instead.")] @@ -375,11 +401,13 @@ impl EllipticCurve { y_pub_key_handle.clone(), self.handle.clone(), ); - ( - BigUint::from_handle(x_pub_key_handle), - BigUint::from_handle(y_pub_key_handle), - private_key, - ) + unsafe { + ( + BigUint::from_handle(x_pub_key_handle), + BigUint::from_handle(y_pub_key_handle), + private_key, + ) + } } pub fn generate_key(&self) -> (BigUint, BigUint, ManagedBuffer) { @@ -394,11 +422,13 @@ impl EllipticCurve { self.handle.clone(), private_key_handle.clone(), ); - ( - BigUint::from_handle(x_pub_key_handle), - BigUint::from_handle(y_pub_key_handle), - ManagedBuffer::from_handle(private_key_handle), - ) + unsafe { + ( + BigUint::from_handle(x_pub_key_handle), + BigUint::from_handle(y_pub_key_handle), + ManagedBuffer::from_handle(private_key_handle), + ) + } } } diff --git a/framework/base/src/types/managed/basic/managed_buffer.rs b/framework/base/src/types/managed/basic/managed_buffer.rs index de2dc63bb8..d1e0b52f9e 100644 --- a/framework/base/src/types/managed/basic/managed_buffer.rs +++ b/framework/base/src/types/managed/basic/managed_buffer.rs @@ -2,7 +2,7 @@ use crate::{ abi::{TypeAbi, TypeAbiFrom, TypeName}, api::{ use_raw_handle, ErrorApiImpl, HandleConstraints, InvalidSliceError, ManagedBufferApiImpl, - ManagedTypeApi, StaticVarApiImpl, + ManagedTypeApi, RawHandle, StaticVarApiImpl, }, codec::{ DecodeErrorHandler, Empty, EncodeErrorHandler, NestedDecode, NestedDecodeInput, @@ -13,7 +13,10 @@ use crate::{ hex_util::encode_bytes_as_hex, FormatBuffer, FormatByteReceiver, SCBinary, SCDisplay, SCLowerHex, }, - types::{heap::BoxedBytes, ManagedBufferCachedBuilder, ManagedType, StaticBufferRef}, + types::{ + heap::BoxedBytes, ManagedBufferCachedBuilder, ManagedRef, ManagedRefMut, ManagedType, + StaticBufferRef, + }, }; /// A byte buffer managed by an external API. @@ -26,7 +29,7 @@ impl ManagedType for ManagedBuffer { type OwnHandle = M::ManagedBufferHandle; #[inline] - fn from_handle(handle: M::ManagedBufferHandle) -> Self { + unsafe fn from_handle(handle: M::ManagedBufferHandle) -> Self { ManagedBuffer { handle } } @@ -37,34 +40,70 @@ impl ManagedType for ManagedBuffer { fn transmute_from_handle_ref(handle_ref: &M::ManagedBufferHandle) -> &Self { unsafe { core::mem::transmute(handle_ref) } } + + fn transmute_from_handle_ref_mut(handle_ref: &mut M::ManagedBufferHandle) -> &mut Self { + unsafe { core::mem::transmute(handle_ref) } + } } impl ManagedBuffer { #[inline] pub fn new() -> Self { - let new_handle: M::ManagedBufferHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - // TODO: remove after VM no longer crashes with "unknown handle": - M::managed_type_impl().mb_overwrite(new_handle.clone(), &[]); - ManagedBuffer::from_handle(new_handle) + Self::new_from_bytes(&[]) } #[inline] pub fn new_from_bytes(bytes: &[u8]) -> Self { - let new_handle: M::ManagedBufferHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().mb_overwrite(new_handle.clone(), bytes); - ManagedBuffer::from_handle(new_handle) + unsafe { + let result = Self::new_uninit(); + M::managed_type_impl().mb_overwrite(result.get_handle(), bytes); + result + } } #[inline] pub fn new_random(nr_bytes: usize) -> Self { + unsafe { + let result = Self::new_uninit(); + M::managed_type_impl().mb_set_random(result.get_handle(), nr_bytes); + result + } + } + + /// Creates a new object, without initializing it. + /// + /// ## Safety + /// + /// The value needs to be initialized after creation, otherwise the VM will halt the first time the value is attempted to be read. + pub unsafe fn new_uninit() -> Self { let new_handle: M::ManagedBufferHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().mb_set_random(new_handle.clone(), nr_bytes); ManagedBuffer::from_handle(new_handle) } + /// Creates a shared managed reference to a given raw handle. + /// + /// ## Safety + /// + /// The reference points to a shared value. Make sure the handle is not leaked. + + pub unsafe fn temp_const_ref( + raw_handle: RawHandle, + ) -> ManagedRef<'static, M, ManagedBuffer> { + ManagedRef::wrap_handle(use_raw_handle(raw_handle)) + } + + /// Creates a shared managed reference to a given raw handle. + /// + /// ## Safety + /// + /// The reference points to a shared value. Make sure the handle is not leaked. + pub unsafe fn temp_const_ref_mut( + raw_handle: RawHandle, + ) -> ManagedRefMut<'static, M, ManagedBuffer> { + ManagedRefMut::wrap_handle(use_raw_handle(raw_handle)) + } + fn load_static_cache(&self) -> StaticBufferRef where M: ManagedTypeApi, @@ -233,7 +272,7 @@ impl ManagedBuffer { result_handle.clone(), ); if err_result.is_ok() { - Some(ManagedBuffer::from_handle(result_handle)) + Some(unsafe { ManagedBuffer::from_handle(result_handle) }) } else { None } @@ -346,7 +385,7 @@ impl Clone for ManagedBuffer { let api = M::managed_type_impl(); let clone_handle = api.mb_new_empty(); api.mb_append(clone_handle.clone(), self.handle.clone()); - ManagedBuffer::from_handle(clone_handle) + unsafe { ManagedBuffer::from_handle(clone_handle) } } } @@ -476,9 +515,9 @@ impl TypeAbi for ManagedBuffer { impl SCDisplay for ManagedBuffer { fn fmt(&self, f: &mut F) { - f.append_managed_buffer(&ManagedBuffer::from_handle( - self.get_handle().cast_or_signal_error::(), - )); + let cast_handle = self.get_handle().cast_or_signal_error::(); + let wrap_cast = unsafe { ManagedRef::wrap_handle(cast_handle) }; + f.append_managed_buffer(&wrap_cast); } } @@ -487,18 +526,18 @@ impl SCLowerHex for ManagedBuffer { let hex_handle: M::ManagedBufferHandle = use_raw_handle(crate::api::const_handles::MBUF_TEMPORARY_1); M::managed_type_impl().mb_to_hex(self.handle.clone(), hex_handle.clone()); - f.append_managed_buffer(&ManagedBuffer::from_handle( - hex_handle.cast_or_signal_error::(), - )); + let cast_handle = hex_handle.cast_or_signal_error::(); + let wrap_cast = unsafe { ManagedRef::wrap_handle(cast_handle) }; + f.append_managed_buffer(&wrap_cast); } } impl SCBinary for ManagedBuffer { fn fmt(&self, f: &mut F) { // TODO: in Rust thr `0b` prefix appears only when writing "{:#x}", not "{:x}" - f.append_managed_buffer_binary(&ManagedBuffer::from_handle( - self.get_handle().cast_or_signal_error::(), - )); + let cast_handle = self.get_handle().cast_or_signal_error::(); + let wrap_cast = unsafe { ManagedRef::wrap_handle(cast_handle) }; + f.append_managed_buffer_binary(&wrap_cast); } } diff --git a/framework/base/src/types/managed/basic/managed_map.rs b/framework/base/src/types/managed/basic/managed_map.rs index 1f0c0be867..139f93cf9c 100644 --- a/framework/base/src/types/managed/basic/managed_map.rs +++ b/framework/base/src/types/managed/basic/managed_map.rs @@ -1,5 +1,5 @@ use crate::{ - api::{use_raw_handle, ManagedMapApiImpl, ManagedTypeApi, StaticVarApiImpl}, + api::{ManagedMapApiImpl, ManagedTypeApi}, types::ManagedType, }; @@ -15,7 +15,7 @@ impl ManagedType for ManagedMap { type OwnHandle = M::ManagedMapHandle; #[inline] - fn from_handle(handle: M::ManagedMapHandle) -> Self { + unsafe fn from_handle(handle: M::ManagedMapHandle) -> Self { ManagedMap { handle } } @@ -26,12 +26,16 @@ impl ManagedType for ManagedMap { fn transmute_from_handle_ref(handle_ref: &M::ManagedMapHandle) -> &Self { unsafe { core::mem::transmute(handle_ref) } } + + fn transmute_from_handle_ref_mut(handle_ref: &mut M::ManagedMapHandle) -> &mut Self { + unsafe { core::mem::transmute(handle_ref) } + } } impl ManagedMap { pub fn new() -> Self { let new_handle = M::managed_type_impl().mm_new(); - ManagedMap::from_handle(new_handle) + unsafe { ManagedMap::from_handle(new_handle) } } } @@ -44,10 +48,15 @@ impl Default for ManagedMap { impl ManagedMap { pub fn get(&self, key: &ManagedBuffer) -> ManagedBuffer { - let new_handle: M::ManagedBufferHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().mm_get(self.handle.clone(), key.handle.clone(), new_handle.clone()); - ManagedBuffer::from_handle(new_handle) + unsafe { + let result = ManagedBuffer::new_uninit(); + M::managed_type_impl().mm_get( + self.handle.clone(), + key.handle.clone(), + result.get_handle(), + ); + result + } } pub fn put(&mut self, key: &ManagedBuffer, value: &ManagedBuffer) { @@ -59,14 +68,15 @@ impl ManagedMap { } pub fn remove(&mut self, key: &ManagedBuffer) -> ManagedBuffer { - let new_handle: M::ManagedBufferHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().mm_remove( - self.handle.clone(), - key.handle.clone(), - new_handle.clone(), - ); - ManagedBuffer::from_handle(new_handle) + unsafe { + let result = ManagedBuffer::new_uninit(); + M::managed_type_impl().mm_remove( + self.handle.clone(), + key.handle.clone(), + result.get_handle(), + ); + result + } } pub fn contains(&self, key: &ManagedBuffer) -> bool { diff --git a/framework/base/src/types/managed/managed_type_trait.rs b/framework/base/src/types/managed/managed_type_trait.rs index ae9b48e4d0..ca9210d594 100644 --- a/framework/base/src/types/managed/managed_type_trait.rs +++ b/framework/base/src/types/managed/managed_type_trait.rs @@ -7,12 +7,12 @@ pub trait ManagedType: Sized { type OwnHandle: HandleConstraints; #[doc(hidden)] - fn from_handle(handle: Self::OwnHandle) -> Self; + unsafe fn from_handle(handle: Self::OwnHandle) -> Self; fn get_handle(&self) -> Self::OwnHandle; #[doc(hidden)] - fn from_raw_handle(handle: RawHandle) -> Self { + unsafe fn from_raw_handle(handle: RawHandle) -> Self { Self::from_handle(Self::OwnHandle::new(handle)) } @@ -26,6 +26,8 @@ pub trait ManagedType: Sized { /// For types that just wrap another managed type it is easier, call for the wrapped object. fn transmute_from_handle_ref(handle_ref: &Self::OwnHandle) -> &Self; + fn transmute_from_handle_ref_mut(handle_ref: &mut Self::OwnHandle) -> &mut Self; + fn as_ref(&self) -> ManagedRef<'_, M, Self> { ManagedRef::new(self) } diff --git a/framework/base/src/types/managed/multi_value/multi_value_encoded.rs b/framework/base/src/types/managed/multi_value/multi_value_encoded.rs index 04dbde9357..31d9a25e64 100644 --- a/framework/base/src/types/managed/multi_value/multi_value_encoded.rs +++ b/framework/base/src/types/managed/multi_value/multi_value_encoded.rs @@ -115,7 +115,7 @@ where M: ManagedTypeApi, { pub fn to_arg_buffer(&self) -> ManagedArgBuffer { - ManagedArgBuffer::from_handle(self.raw_buffers.get_handle()) + unsafe { ManagedArgBuffer::from_handle(self.raw_buffers.get_handle()) } } } diff --git a/framework/base/src/types/managed/multi_value/multi_value_managed_vec.rs b/framework/base/src/types/managed/multi_value/multi_value_managed_vec.rs index a168711af1..6ad36a25e8 100644 --- a/framework/base/src/types/managed/multi_value/multi_value_managed_vec.rs +++ b/framework/base/src/types/managed/multi_value/multi_value_managed_vec.rs @@ -46,7 +46,7 @@ where type OwnHandle = M::ManagedBufferHandle; #[inline] - fn from_handle(handle: M::ManagedBufferHandle) -> Self { + unsafe fn from_handle(handle: M::ManagedBufferHandle) -> Self { Self(ManagedVec::from_handle(handle)) } @@ -57,6 +57,10 @@ where fn transmute_from_handle_ref(handle_ref: &M::ManagedBufferHandle) -> &Self { unsafe { core::mem::transmute(handle_ref) } } + + fn transmute_from_handle_ref_mut(handle_ref: &mut M::ManagedBufferHandle) -> &mut Self { + unsafe { core::mem::transmute(handle_ref) } + } } impl MultiValueManagedVec diff --git a/framework/base/src/types/managed/wrapped/big_uint.rs b/framework/base/src/types/managed/wrapped/big_uint.rs index 615d790480..344842c2a3 100644 --- a/framework/base/src/types/managed/wrapped/big_uint.rs +++ b/framework/base/src/types/managed/wrapped/big_uint.rs @@ -4,7 +4,7 @@ use crate::{ abi::{TypeAbi, TypeAbiFrom, TypeName}, api::{ const_handles, use_raw_handle, BigIntApiImpl, HandleConstraints, ManagedBufferApiImpl, - ManagedTypeApi, ManagedTypeApiImpl, RawHandle, StaticVarApiImpl, + ManagedTypeApi, ManagedTypeApiImpl, RawHandle, }, codec::{ DecodeErrorHandler, EncodeErrorHandler, NestedDecode, NestedDecodeInput, NestedEncode, @@ -26,7 +26,7 @@ pub struct BigUint { impl ManagedType for BigUint { type OwnHandle = M::BigIntHandle; - fn from_handle(handle: M::BigIntHandle) -> Self { + unsafe fn from_handle(handle: M::BigIntHandle) -> Self { BigUint { value: BigInt::from_handle(handle), } @@ -39,6 +39,10 @@ impl ManagedType for BigUint { fn transmute_from_handle_ref(handle_ref: &M::BigIntHandle) -> &Self { unsafe { core::mem::transmute(handle_ref) } } + + fn transmute_from_handle_ref_mut(handle_ref: &mut M::BigIntHandle) -> &mut Self { + unsafe { core::mem::transmute(handle_ref) } + } } impl From for BigUint { @@ -62,6 +66,17 @@ impl From<&ManagedBuffer> for BigUint { } impl BigUint { + /// Creates a new object, without initializing it. + /// + /// ## Safety + /// + /// The value needs to be initialized after creation, otherwise the VM will halt the first time the value is attempted to be read. + pub unsafe fn new_uninit() -> Self { + BigUint { + value: BigInt::new_uninit(), + } + } + pub(crate) fn set_value(handle: M::BigIntHandle, value: T) where T: TryInto + num_traits::Unsigned, @@ -73,9 +88,11 @@ impl BigUint { where T: TryInto + num_traits::Unsigned, { - let handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - Self::set_value(handle.clone(), value); - BigUint::from_handle(handle) + unsafe { + let result = Self::new_uninit(); + Self::set_value(result.get_handle(), value); + result + } } pub(crate) fn make_temp(handle: RawHandle, value: T) -> M::BigIntHandle @@ -169,9 +186,11 @@ impl Default for BigUint { impl BigUint { #[inline] pub fn zero() -> Self { - let handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().bi_set_int64(handle.clone(), 0); - BigUint::from_handle(handle) + unsafe { + let result = Self::new_uninit(); + M::managed_type_impl().bi_set_int64(result.get_handle(), 0); + result + } } pub fn zero_ref() -> ManagedRef<'static, M, BigUint> { @@ -191,16 +210,16 @@ impl BigUint { Self::set_value(self.value.handle.clone(), value); } - #[inline] pub fn from_bytes_be(bytes: &[u8]) -> Self { let mb_handle: M::ManagedBufferHandle = use_raw_handle(const_handles::MBUF_TEMPORARY_1); M::managed_type_impl().mb_overwrite(mb_handle.clone(), bytes); - let handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().mb_to_big_int_unsigned(mb_handle, handle.clone()); - BigUint::from_handle(handle) + unsafe { + let result = Self::new_uninit(); + M::managed_type_impl().mb_to_big_int_unsigned(mb_handle, result.get_handle()); + result + } } - #[inline] pub fn to_bytes_be(&self) -> BoxedBytes { let mb_handle: M::ManagedBufferHandle = use_raw_handle(const_handles::MBUF_TEMPORARY_1); M::managed_type_impl() @@ -208,44 +227,40 @@ impl BigUint { M::managed_type_impl().mb_to_boxed_bytes(mb_handle) } - #[inline] pub fn from_bytes_be_buffer(managed_buffer: &ManagedBuffer) -> Self { - let handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl() - .mb_to_big_int_unsigned(managed_buffer.handle.clone(), handle.clone()); - BigUint::from_handle(handle) + unsafe { + let result = BigUint::new_uninit(); + M::managed_type_impl() + .mb_to_big_int_unsigned(managed_buffer.handle.clone(), result.get_handle()); + result + } } - #[inline] pub fn to_bytes_be_buffer(&self) -> ManagedBuffer { - let mb_handle: M::ManagedBufferHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl() - .mb_from_big_int_unsigned(self.value.handle.clone(), mb_handle.clone()); - ManagedBuffer::from_handle(mb_handle) + unsafe { + let result = ManagedBuffer::new_uninit(); + M::managed_type_impl().mb_from_big_int_unsigned(self.get_handle(), result.get_handle()); + result + } } } impl BigUint { - #[inline] - #[must_use] pub fn sqrt(&self) -> Self { - let api = M::managed_type_impl(); - let result_handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - api.bi_sqrt(result_handle.clone(), self.value.handle.clone()); - BigUint::from_handle(result_handle) + unsafe { + let result = BigUint::new_uninit(); + M::managed_type_impl().bi_sqrt(result.get_handle(), self.get_handle()); + result + } } - #[must_use] pub fn pow(&self, exp: u32) -> Self { - let result_handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); let big_int_temp_1 = BigUint::::make_temp(const_handles::BIG_INT_TEMPORARY_1, exp); - M::managed_type_impl().bi_pow( - result_handle.clone(), - self.value.handle.clone(), - big_int_temp_1, - ); - BigUint::from_handle(result_handle) + unsafe { + let result = BigUint::new_uninit(); + M::managed_type_impl().bi_pow(result.get_handle(), self.get_handle(), big_int_temp_1); + result + } } /// The whole part of the base-2 logarithm. @@ -254,7 +269,6 @@ impl BigUint { /// More specifically, the log2 floor is the position of the most significant bit minus one. /// /// Will return `None` for the number zero (the logarithm in this case would approach -inf). - #[inline] pub fn log2_floor(&self) -> Option { let api = M::managed_type_impl(); let result = api.bi_log2(self.value.handle.clone()); @@ -298,15 +312,7 @@ impl BigUint { impl Clone for BigUint { fn clone(&self) -> Self { - let api = M::managed_type_impl(); - let clone_handle: M::BigIntHandle = use_raw_handle(M::static_var_api_impl().next_handle()); - api.bi_set_int64(clone_handle.clone(), 0); - api.bi_add( - clone_handle.clone(), - clone_handle.clone(), - self.value.handle.clone(), - ); - BigUint::from_handle(clone_handle) + unsafe { self.as_big_int().clone().into_big_uint_unchecked() } } } @@ -372,9 +378,9 @@ impl SCDisplay for BigUint { fn fmt(&self, f: &mut F) { let str_handle: M::ManagedBufferHandle = use_raw_handle(const_handles::MBUF_TEMPORARY_1); M::managed_type_impl().bi_to_string(self.value.handle.clone(), str_handle.clone()); - f.append_managed_buffer(&ManagedBuffer::from_handle( - str_handle.cast_or_signal_error::(), - )); + let cast_handle = str_handle.cast_or_signal_error::(); + let wrap_cast = unsafe { ManagedRef::wrap_handle(cast_handle) }; + f.append_managed_buffer(&wrap_cast); } } diff --git a/framework/base/src/types/managed/wrapped/big_uint_operators.rs b/framework/base/src/types/managed/wrapped/big_uint_operators.rs index 934079eef7..5ca27f783e 100644 --- a/framework/base/src/types/managed/wrapped/big_uint_operators.rs +++ b/framework/base/src/types/managed/wrapped/big_uint_operators.rs @@ -1,5 +1,5 @@ use crate::{ - api::{const_handles, use_raw_handle, BigIntApiImpl, ManagedTypeApi, StaticVarApiImpl}, + api::{const_handles, BigIntApiImpl, ManagedTypeApi}, types::{BigUint, ManagedType}, }; use core::ops::{ @@ -14,11 +14,11 @@ macro_rules! binary_operator { fn $method(self, other: BigUint) -> BigUint { M::managed_type_impl().$api_func( - self.value.handle.clone(), - self.value.handle.clone(), - other.value.handle.clone(), + self.get_handle(), + self.get_handle(), + other.get_handle(), ); - BigUint::from_handle(self.value.handle.clone()) + self } } @@ -26,14 +26,15 @@ macro_rules! binary_operator { type Output = BigUint; fn $method(self, other: &BigUint) -> BigUint { - let result_handle: M::BigIntHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().$api_func( - result_handle.clone(), - self.value.handle.clone(), - other.value.handle.clone(), - ); - BigUint::from_handle(result_handle) + unsafe { + let result = BigUint::new_uninit(); + M::managed_type_impl().$api_func( + result.get_handle(), + self.get_handle(), + other.get_handle(), + ); + result + } } } @@ -42,11 +43,11 @@ macro_rules! binary_operator { fn $method(self, other: &BigUint) -> BigUint { M::managed_type_impl().$api_func( - self.value.handle.clone(), - self.value.handle.clone(), - other.value.handle.clone(), + self.get_handle(), + self.get_handle(), + other.get_handle(), ); - BigUint::from_handle(self.value.handle.clone()) + self } } @@ -56,11 +57,11 @@ macro_rules! binary_operator { fn $method(self, other: u32) -> BigUint { let big_int_temp_1 = Self::make_temp(const_handles::BIG_INT_TEMPORARY_1, other); M::managed_type_impl().$api_func( - self.value.handle.clone(), - self.value.handle.clone(), + self.get_handle(), + self.get_handle(), big_int_temp_1, ); - BigUint::from_handle(self.value.handle.clone()) + self } } @@ -70,14 +71,15 @@ macro_rules! binary_operator { fn $method(self, other: u32) -> BigUint { let big_int_temp_1 = BigUint::::make_temp(const_handles::BIG_INT_TEMPORARY_1, other); - let result_handle: M::BigIntHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().$api_func( - result_handle.clone(), - self.value.handle.clone(), - big_int_temp_1, - ); - BigUint::from_handle(result_handle) + unsafe { + let result = BigUint::new_uninit(); + M::managed_type_impl().$api_func( + result.get_handle(), + self.get_handle(), + big_int_temp_1, + ); + result + } } } @@ -91,7 +93,7 @@ macro_rules! binary_operator { self.value.handle.clone(), big_int_temp_1, ); - BigUint::from_handle(self.value.handle.clone()) + self } } @@ -101,14 +103,15 @@ macro_rules! binary_operator { fn $method(self, other: u64) -> BigUint { let big_int_temp_1 = BigUint::::make_temp(const_handles::BIG_INT_TEMPORARY_1, other); - let result_handle: M::BigIntHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().$api_func( - result_handle.clone(), - self.value.handle.clone(), - big_int_temp_1, - ); - BigUint::from_handle(result_handle) + unsafe { + let result = BigUint::new_uninit(); + M::managed_type_impl().$api_func( + result.get_handle(), + self.get_handle(), + big_int_temp_1, + ); + result + } } } }; @@ -200,14 +203,11 @@ macro_rules! shift_traits { type Output = BigUint; fn $method(self, rhs: usize) -> BigUint { - let result_handle: M::BigIntHandle = - use_raw_handle(M::static_var_api_impl().next_handle()); - M::managed_type_impl().$api_func( - result_handle.clone(), - self.value.handle.clone(), - rhs, - ); - BigUint::from_handle(result_handle) + unsafe { + let result = BigUint::new_uninit(); + M::managed_type_impl().$api_func(result.get_handle(), self.get_handle(), rhs); + result + } } } }; diff --git a/framework/base/src/types/managed/wrapped/egld_or_esdt_token_identifier.rs b/framework/base/src/types/managed/wrapped/egld_or_esdt_token_identifier.rs index 19506645a2..6221188618 100644 --- a/framework/base/src/types/managed/wrapped/egld_or_esdt_token_identifier.rs +++ b/framework/base/src/types/managed/wrapped/egld_or_esdt_token_identifier.rs @@ -58,7 +58,7 @@ impl EgldOrEsdtTokenIdentifier { pub fn from_opt_raw_handle(opt_handle: Option) -> Self { match opt_handle { - Some(handle) => Self::esdt(TokenIdentifier::from_handle(handle)), + Some(handle) => Self::esdt(unsafe { TokenIdentifier::from_handle(handle) }), None => Self::egld(), } } @@ -240,9 +240,9 @@ impl TypeAbi for EgldOrEsdtTokenIdentifier { impl SCDisplay for EgldOrEsdtTokenIdentifier { fn fmt(&self, f: &mut F) { if let Some(token_identifier) = self.data.as_option() { - f.append_managed_buffer(&ManagedBuffer::from_handle( - token_identifier.get_handle().cast_or_signal_error::(), - )); + let cast_handle = token_identifier.get_handle().cast_or_signal_error::(); + let wrap_cast = unsafe { ManagedRef::wrap_handle(cast_handle) }; + f.append_managed_buffer(&wrap_cast); } else { f.append_bytes(Self::EGLD_REPRESENTATION); } @@ -254,9 +254,9 @@ const EGLD_REPRESENTATION_HEX: &[u8] = b"45474C44"; impl SCLowerHex for EgldOrEsdtTokenIdentifier { fn fmt(&self, f: &mut F) { if let Some(token_identifier) = self.data.as_option() { - f.append_managed_buffer_lower_hex(&ManagedBuffer::from_handle( - token_identifier.get_handle().cast_or_signal_error::(), - )); + let cast_handle = token_identifier.get_handle().cast_or_signal_error::(); + let wrap_cast = unsafe { ManagedRef::wrap_handle(cast_handle) }; + f.append_managed_buffer_lower_hex(&wrap_cast); } else { f.append_bytes(EGLD_REPRESENTATION_HEX); } diff --git a/framework/base/src/types/managed/wrapped/managed_address.rs b/framework/base/src/types/managed/wrapped/managed_address.rs index a90482fb04..a12200a039 100644 --- a/framework/base/src/types/managed/wrapped/managed_address.rs +++ b/framework/base/src/types/managed/wrapped/managed_address.rs @@ -2,7 +2,7 @@ use core::convert::{TryFrom, TryInto}; use crate::{ abi::{TypeAbi, TypeAbiFrom, TypeName}, - api::ManagedTypeApi, + api::{use_raw_handle, ManagedTypeApi, RawHandle}, codec::{ DecodeError, DecodeErrorHandler, EncodeErrorHandler, NestedDecode, NestedDecodeInput, NestedEncode, NestedEncodeOutput, TopDecode, TopDecodeInput, TopEncode, TopEncodeOutput, @@ -11,6 +11,8 @@ use crate::{ types::{heap::Address, ManagedBuffer, ManagedByteArray, ManagedType}, }; +use super::ManagedRef; + #[repr(transparent)] #[derive(Clone)] pub struct ManagedAddress { @@ -49,6 +51,28 @@ where } } + /// Creates a new object, without initializing it. + /// + /// ## Safety + /// + /// The value needs to be initialized after creation, otherwise the VM will halt the first time the value is attempted to be read. + pub unsafe fn new_uninit() -> Self { + ManagedAddress { + bytes: ManagedByteArray::new_uninit(), + } + } + + /// Creates a shared managed reference to a given raw handle. + /// + /// ## Safety + /// + /// The reference points to a shared value. Make sure the handle is not leaked. + pub unsafe fn temp_const_ref( + raw_handle: RawHandle, + ) -> ManagedRef<'static, M, ManagedAddress> { + ManagedRef::wrap_handle(use_raw_handle(raw_handle)) + } + #[inline] pub fn as_managed_buffer(&self) -> &ManagedBuffer { self.bytes.as_managed_buffer() @@ -133,7 +157,7 @@ where type OwnHandle = M::ManagedBufferHandle; #[inline] - fn from_handle(handle: M::ManagedBufferHandle) -> Self { + unsafe fn from_handle(handle: M::ManagedBufferHandle) -> Self { ManagedAddress { bytes: ManagedByteArray::from_handle(handle), } @@ -146,6 +170,10 @@ where fn transmute_from_handle_ref(handle_ref: &M::ManagedBufferHandle) -> &Self { unsafe { core::mem::transmute(handle_ref) } } + + fn transmute_from_handle_ref_mut(handle_ref: &mut M::ManagedBufferHandle) -> &mut Self { + unsafe { core::mem::transmute(handle_ref) } + } } impl Default for ManagedAddress diff --git a/framework/base/src/types/managed/wrapped/managed_byte_array.rs b/framework/base/src/types/managed/wrapped/managed_byte_array.rs index 83e95d332c..5ef3e661b7 100644 --- a/framework/base/src/types/managed/wrapped/managed_byte_array.rs +++ b/framework/base/src/types/managed/wrapped/managed_byte_array.rs @@ -35,7 +35,7 @@ where type OwnHandle = M::ManagedBufferHandle; #[inline] - fn from_handle(handle: M::ManagedBufferHandle) -> Self { + unsafe fn from_handle(handle: M::ManagedBufferHandle) -> Self { ManagedByteArray { buffer: ManagedBuffer::from_handle(handle), } @@ -48,6 +48,10 @@ where fn transmute_from_handle_ref(handle_ref: &M::ManagedBufferHandle) -> &Self { unsafe { core::mem::transmute(handle_ref) } } + + fn transmute_from_handle_ref_mut(handle_ref: &mut M::ManagedBufferHandle) -> &mut Self { + unsafe { core::mem::transmute(handle_ref) } + } } impl Default for ManagedByteArray @@ -81,6 +85,17 @@ where } } + /// Creates a new object, without initializing it. + /// + /// ## Safety + /// + /// The value needs to be initialized after creation, otherwise the VM will halt the first time the value is attempted to be read. + pub unsafe fn new_uninit() -> Self { + ManagedByteArray { + buffer: ManagedBuffer::new_uninit(), + } + } + /// Number of items. #[inline] pub fn len(&self) -> usize { diff --git a/framework/base/src/types/managed/wrapped/managed_decimal/managed_decimal_logarithm.rs b/framework/base/src/types/managed/wrapped/managed_decimal/managed_decimal_logarithm.rs index 41f173a50a..43c4debbac 100644 --- a/framework/base/src/types/managed/wrapped/managed_decimal/managed_decimal_logarithm.rs +++ b/framework/base/src/types/managed/wrapped/managed_decimal/managed_decimal_logarithm.rs @@ -2,7 +2,7 @@ use super::decimals::{ConstDecimals, Decimals}; use super::ManagedDecimalSigned; use super::{ManagedDecimal, NumDecimals}; -use crate::proxy_imports::ManagedType; +use crate::types::ManagedRef; use crate::{ api::ManagedTypeApi, contract_base::ErrorHelper, @@ -104,7 +104,7 @@ impl ManagedDecimalSigned { return None; } - let bu = BigUint::from_handle(self.data.handle.clone()); + let bu = unsafe { ManagedRef::wrap_handle(self.data.handle.clone()) }; compute_ln(&bu, self.decimals.num_decimals()) } @@ -118,7 +118,7 @@ impl ManagedDecimalSigned { return None; } - let bu = BigUint::from_handle(self.data.handle.clone()); + let bu = unsafe { ManagedRef::wrap_handle(self.data.handle.clone()) }; compute_log2(&bu, self.decimals.num_decimals()) } } diff --git a/framework/base/src/types/managed/wrapped/managed_decimal/managed_decimal_signed.rs b/framework/base/src/types/managed/wrapped/managed_decimal/managed_decimal_signed.rs index c8ee403f37..0338417f82 100644 --- a/framework/base/src/types/managed/wrapped/managed_decimal/managed_decimal_signed.rs +++ b/framework/base/src/types/managed/wrapped/managed_decimal/managed_decimal_signed.rs @@ -6,7 +6,7 @@ use crate::{ }, err_msg, formatter::{FormatBuffer, FormatByteReceiver, SCDisplay}, - types::{BigFloat, BigInt, BigUint, ManagedBuffer, ManagedType, Sign}, + types::{BigFloat, BigInt, BigUint, Sign}, }; use alloc::string::ToString; @@ -354,15 +354,15 @@ pub(super) fn managed_decimal_fmt( if len > num_dec { let temp_str_handle: M::ManagedBufferHandle = use_raw_handle(const_handles::MBUF_TEMPORARY_2); + let cast_handle = temp_str_handle.clone().cast_or_signal_error::(); + let temp_str_ref = unsafe { ManagedRef::wrap_handle(cast_handle) }; let _ = M::managed_type_impl().mb_copy_slice( full_str_handle.clone(), 0, len - num_dec, temp_str_handle.clone(), ); - f.append_managed_buffer(&ManagedBuffer::from_raw_handle( - temp_str_handle.get_raw_handle(), - )); + f.append_managed_buffer(&temp_str_ref); f.append_bytes(b"."); let _ = M::managed_type_impl().mb_copy_slice( full_str_handle.clone(), @@ -370,17 +370,15 @@ pub(super) fn managed_decimal_fmt( num_dec, temp_str_handle.clone(), ); - f.append_managed_buffer(&ManagedBuffer::from_raw_handle( - temp_str_handle.get_raw_handle(), - )); + f.append_managed_buffer(&temp_str_ref); } else { f.append_bytes(b"0."); for _ in len..num_dec { f.append_bytes(b"0"); } - f.append_managed_buffer(&ManagedBuffer::from_raw_handle( - full_str_handle.get_raw_handle(), - )); + let cast_handle = full_str_handle.clone().cast_or_signal_error::(); + let full_str_ref = unsafe { ManagedRef::wrap_handle(cast_handle) }; + f.append_managed_buffer(&full_str_ref); } } diff --git a/framework/base/src/types/managed/wrapped/managed_option.rs b/framework/base/src/types/managed/wrapped/managed_option.rs index e448ae8e88..e433913835 100644 --- a/framework/base/src/types/managed/wrapped/managed_option.rs +++ b/framework/base/src/types/managed/wrapped/managed_option.rs @@ -143,7 +143,7 @@ where F: FnOnce(Context, &T) -> R, { if self.is_some() { - f(context, &T::from_handle(self.handle.clone())) + f(context, unsafe { &T::from_handle(self.handle.clone()) }) } else { default(context) } @@ -158,7 +158,7 @@ where #[allow(clippy::redundant_clone)] // the clone is not redundant fn clone(&self) -> Self { if self.is_some() { - Self::some(T::from_handle(self.handle.clone()).clone()) + Self::some(unsafe { T::from_handle(self.handle.clone()) }.clone()) } else { Self::none() } @@ -177,7 +177,10 @@ where return true; } if self.is_some() && other.is_some() { - return T::from_handle(self.handle.clone()) == T::from_handle(other.handle.clone()); + unsafe { + return ManagedRef::<'_, _, T>::wrap_handle(self.handle.clone()) + == ManagedRef::<'_, _, T>::wrap_handle(other.handle.clone()); + } } false } @@ -327,7 +330,7 @@ where fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { if self.is_some() { f.debug_tuple("ManagedOption::Some") - .field(&T::from_handle(self.handle.clone())) + .field(unsafe { &T::from_handle(self.handle.clone()) }) .finish() } else { f.write_str("ManagedOption::None") diff --git a/framework/base/src/types/managed/wrapped/managed_ref.rs b/framework/base/src/types/managed/wrapped/managed_ref.rs index 143d79e1d4..ef0e20fb9f 100644 --- a/framework/base/src/types/managed/wrapped/managed_ref.rs +++ b/framework/base/src/types/managed/wrapped/managed_ref.rs @@ -34,7 +34,7 @@ where /// Will completely disregard lifetimes, use with care. #[doc(hidden)] - pub(crate) unsafe fn wrap_handle(handle: T::OwnHandle) -> Self { + pub unsafe fn wrap_handle(handle: T::OwnHandle) -> Self { Self { _phantom_m: PhantomData, _phantom_t: PhantomData, diff --git a/framework/base/src/types/managed/wrapped/managed_ref_mut.rs b/framework/base/src/types/managed/wrapped/managed_ref_mut.rs new file mode 100644 index 0000000000..81315b89b2 --- /dev/null +++ b/framework/base/src/types/managed/wrapped/managed_ref_mut.rs @@ -0,0 +1,174 @@ +use core::ops::DerefMut; +use core::{borrow::Borrow, marker::PhantomData, ops::Deref}; + +use crate::codec::{ + EncodeErrorHandler, NestedEncode, NestedEncodeOutput, TopEncode, TopEncodeOutput, +}; + +use crate::{api::ManagedTypeApi, types::ManagedType}; + +/// A very efficient mutable reference to a managed type. +/// +/// It can be dereferenced mutably (DerefMut). +pub struct ManagedRefMut<'a, M, T> +where + M: ManagedTypeApi, + T: ManagedType, +{ + pub(super) _phantom_m: PhantomData, + pub(super) _phantom_t: PhantomData<&'a mut T>, + pub(super) handle: T::OwnHandle, +} + +impl<'a, M, T> ManagedRefMut<'a, M, T> +where + M: ManagedTypeApi, + T: ManagedType, +{ + pub fn new(value: &'a mut T) -> Self { + Self { + _phantom_m: PhantomData, + _phantom_t: PhantomData, + handle: value.get_handle(), + } + } + + /// Will completely disregard lifetimes, use with care. + #[doc(hidden)] + pub(crate) unsafe fn wrap_handle(handle: T::OwnHandle) -> Self { + Self { + _phantom_m: PhantomData, + _phantom_t: PhantomData, + handle, + } + } +} + +impl<'a, M, T> ManagedRefMut<'a, M, T> +where + M: ManagedTypeApi, + T: ManagedType + Clone, +{ + /// Syntactic sugar for dereferencing and cloning the object. + pub fn clone_value(&self) -> T { + self.deref().clone() + } +} + +impl<'a, M, T> Clone for ManagedRefMut<'a, M, T> +where + M: ManagedTypeApi, + T: ManagedType, +{ + #[inline] + fn clone(&self) -> Self { + Self { + _phantom_m: PhantomData, + _phantom_t: PhantomData, + handle: self.handle.clone(), + } + } +} + +impl<'a, M, T> Deref for ManagedRefMut<'a, M, T> +where + M: ManagedTypeApi, + T: ManagedType, +{ + type Target = T; + + #[inline] + fn deref(&self) -> &Self::Target { + Self::Target::transmute_from_handle_ref(&self.handle) + } +} + +impl<'a, M, T> DerefMut for ManagedRefMut<'a, M, T> +where + M: ManagedTypeApi, + T: ManagedType, +{ + fn deref_mut(&mut self) -> &mut Self::Target { + Self::Target::transmute_from_handle_ref_mut(&mut self.handle) + } +} + +impl<'a, M, T> Borrow for ManagedRefMut<'a, M, T> +where + M: ManagedTypeApi, + T: ManagedType, +{ + #[inline] + fn borrow(&self) -> &T { + self.deref() + } +} + +impl<'a, M, T> From<&'a mut T> for ManagedRefMut<'a, M, T> +where + M: ManagedTypeApi, + T: ManagedType, +{ + #[inline] + fn from(value_ref: &'a mut T) -> Self { + Self::new(value_ref) + } +} + +impl<'a, M, T> PartialEq for ManagedRefMut<'a, M, T> +where + M: ManagedTypeApi, + T: ManagedType + PartialEq, +{ + #[inline] + fn eq(&self, other: &Self) -> bool { + self.deref() == other.deref() + } +} + +impl<'a, M, T> Eq for ManagedRefMut<'a, M, T> +where + M: ManagedTypeApi, + T: ManagedType + PartialEq, +{ +} + +impl<'a, M, T> TopEncode for ManagedRefMut<'a, M, T> +where + M: ManagedTypeApi, + T: ManagedType + TopEncode, +{ + #[inline] + fn top_encode_or_handle_err(&self, output: O, h: H) -> Result<(), H::HandledErr> + where + O: TopEncodeOutput, + H: EncodeErrorHandler, + { + self.deref().top_encode_or_handle_err(output, h) + } +} + +impl<'a, M, T> NestedEncode for ManagedRefMut<'a, M, T> +where + M: ManagedTypeApi, + T: ManagedType + NestedEncode, +{ + #[inline] + fn dep_encode_or_handle_err(&self, dest: &mut O, h: H) -> Result<(), H::HandledErr> + where + O: NestedEncodeOutput, + H: EncodeErrorHandler, + { + self.deref().dep_encode_or_handle_err(dest, h) + } +} + +impl<'a, M, T> core::fmt::Debug for ManagedRefMut<'a, M, T> +where + M: ManagedTypeApi, + T: ManagedType + core::fmt::Debug, +{ + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_tuple("ManagedRefMut").field(self.deref()).finish() + } +} diff --git a/framework/base/src/types/managed/wrapped/managed_vec.rs b/framework/base/src/types/managed/wrapped/managed_vec.rs index 3e25360ea4..582054e6ec 100644 --- a/framework/base/src/types/managed/wrapped/managed_vec.rs +++ b/framework/base/src/types/managed/wrapped/managed_vec.rs @@ -45,7 +45,7 @@ where type OwnHandle = M::ManagedBufferHandle; #[inline] - fn from_handle(handle: M::ManagedBufferHandle) -> Self { + unsafe fn from_handle(handle: M::ManagedBufferHandle) -> Self { ManagedVec { buffer: ManagedBuffer::from_handle(handle), _phantom: PhantomData, @@ -59,6 +59,10 @@ where fn transmute_from_handle_ref(handle_ref: &M::ManagedBufferHandle) -> &Self { unsafe { core::mem::transmute(handle_ref) } } + + fn transmute_from_handle_ref_mut(handle_ref: &mut M::ManagedBufferHandle) -> &mut Self { + unsafe { core::mem::transmute(handle_ref) } + } } impl ManagedVec @@ -233,7 +237,7 @@ where ManagedVec::new() }; - self.buffer = part_before.buffer; + *self = part_before; self.buffer.append(&part_after.buffer); } diff --git a/framework/base/src/types/managed/wrapped/managed_vec_item.rs b/framework/base/src/types/managed/wrapped/managed_vec_item.rs index 8e7dc5512a..8e88624d75 100644 --- a/framework/base/src/types/managed/wrapped/managed_vec_item.rs +++ b/framework/base/src/types/managed/wrapped/managed_vec_item.rs @@ -192,7 +192,7 @@ macro_rules! impl_managed_type { fn from_byte_reader(reader: Reader) -> Self { let handle = <$ty as ManagedType>::OwnHandle::from_byte_reader(reader); - $ty::from_handle(handle) + unsafe { $ty::from_handle(handle) } } unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>( @@ -226,7 +226,7 @@ where fn from_byte_reader(reader: Reader) -> Self { let handle = >::OwnHandle::from_byte_reader(reader); - Self::from_handle(handle) + unsafe { Self::from_handle(handle) } } unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>( @@ -255,7 +255,7 @@ where fn from_byte_reader(reader: Reader) -> Self { let handle = M::ManagedBufferHandle::from_byte_reader(reader); - Self::from_handle(handle) + unsafe { Self::from_handle(handle) } } unsafe fn from_byte_reader_as_borrow<'a, Reader: FnMut(&mut [u8])>( diff --git a/framework/base/src/types/managed/wrapped/managed_vec_ref.rs b/framework/base/src/types/managed/wrapped/managed_vec_ref.rs index b69a124668..b339d1cdaf 100644 --- a/framework/base/src/types/managed/wrapped/managed_vec_ref.rs +++ b/framework/base/src/types/managed/wrapped/managed_vec_ref.rs @@ -1,6 +1,6 @@ use crate::{ api::ManagedTypeApi, - types::{ManagedType, ManagedVec, ManagedVecItem}, + types::{ManagedVec, ManagedVecItem}, }; use core::{ marker::PhantomData, @@ -8,6 +8,8 @@ use core::{ ops::{Deref, DerefMut}, }; +use super::{ManagedRef, ManagedRefMut}; + pub struct ManagedVecRef<'a, M, T> where M: ManagedTypeApi, @@ -26,8 +28,10 @@ where T: ManagedVecItem, { #[inline] - fn wrap_as_managed_vec(managed_vec_handle: M::ManagedBufferHandle) -> ManagedVec { - ManagedVec::from_handle(managed_vec_handle) + unsafe fn wrap_as_managed_vec( + managed_vec_handle: M::ManagedBufferHandle, + ) -> ManagedRef<'static, M, ManagedVec> { + ManagedRef::wrap_handle(managed_vec_handle) } pub(super) fn new(managed_vec_handle: M::ManagedBufferHandle, item_index: usize) -> Self { @@ -50,8 +54,12 @@ where { fn drop(&mut self) { let item = unsafe { ManuallyDrop::take(&mut self.item) }; - let _ = - Self::wrap_as_managed_vec(self.managed_vec_handle.clone()).set(self.item_index, item); + unsafe { + let _ = + ManagedRefMut::>::wrap_handle(self.managed_vec_handle.clone()) + .set(self.item_index, item); + } + // core::mem::forget(item); } } diff --git a/framework/base/src/types/managed/wrapped/mod.rs b/framework/base/src/types/managed/wrapped/mod.rs index 1874dc48b0..37849e0b6c 100644 --- a/framework/base/src/types/managed/wrapped/mod.rs +++ b/framework/base/src/types/managed/wrapped/mod.rs @@ -14,6 +14,7 @@ mod managed_byte_array; mod managed_decimal; mod managed_option; mod managed_ref; +mod managed_ref_mut; mod managed_vec; mod managed_vec_item; mod managed_vec_item_nested_tuple; @@ -43,6 +44,7 @@ pub use managed_decimal::{ }; pub use managed_option::ManagedOption; pub use managed_ref::ManagedRef; +pub use managed_ref_mut::ManagedRefMut; pub use managed_vec::ManagedVec; pub use managed_vec_item::ManagedVecItem; pub use managed_vec_item_nested_tuple::ManagedVecItemNestedTuple; diff --git a/framework/base/src/types/managed/wrapped/token_identifier.rs b/framework/base/src/types/managed/wrapped/token_identifier.rs index 1e66615199..10c92475a3 100644 --- a/framework/base/src/types/managed/wrapped/token_identifier.rs +++ b/framework/base/src/types/managed/wrapped/token_identifier.rs @@ -9,7 +9,7 @@ use crate::{ types::{ManagedBuffer, ManagedType}, }; -use super::EgldOrEsdtTokenIdentifier; +use super::{EgldOrEsdtTokenIdentifier, ManagedRef}; /// Specialized type for handling token identifiers. /// It wraps a BoxedBytes with the full ASCII name of the token. @@ -26,7 +26,7 @@ impl ManagedType for TokenIdentifier { type OwnHandle = M::ManagedBufferHandle; #[inline] - fn from_handle(handle: M::ManagedBufferHandle) -> Self { + unsafe fn from_handle(handle: M::ManagedBufferHandle) -> Self { TokenIdentifier { buffer: ManagedBuffer::from_handle(handle), } @@ -39,6 +39,10 @@ impl ManagedType for TokenIdentifier { fn transmute_from_handle_ref(handle_ref: &M::ManagedBufferHandle) -> &Self { unsafe { core::mem::transmute(handle_ref) } } + + fn transmute_from_handle_ref_mut(handle_ref: &mut M::ManagedBufferHandle) -> &mut Self { + unsafe { core::mem::transmute(handle_ref) } + } } impl TokenIdentifier { @@ -190,17 +194,17 @@ impl TypeAbi for TokenIdentifier { impl SCDisplay for TokenIdentifier { fn fmt(&self, f: &mut F) { - f.append_managed_buffer(&ManagedBuffer::from_handle( - self.buffer.get_handle().cast_or_signal_error::(), - )); + let cast_handle = self.buffer.get_handle().cast_or_signal_error::(); + let wrap_cast = unsafe { ManagedRef::wrap_handle(cast_handle) }; + f.append_managed_buffer(&wrap_cast); } } impl SCLowerHex for TokenIdentifier { fn fmt(&self, f: &mut F) { - f.append_managed_buffer_lower_hex(&ManagedBuffer::from_handle( - self.buffer.get_handle().cast_or_signal_error::(), - )); + let cast_handle = self.buffer.get_handle().cast_or_signal_error::(); + let wrap_cast = unsafe { ManagedRef::wrap_handle(cast_handle) }; + f.append_managed_buffer_lower_hex(&wrap_cast); } } diff --git a/tools/rust-debugger/format-tests/src/format_tests.rs b/tools/rust-debugger/format-tests/src/format_tests.rs index 2c72e4acda..755bbbda17 100644 --- a/tools/rust-debugger/format-tests/src/format_tests.rs +++ b/tools/rust-debugger/format-tests/src/format_tests.rs @@ -181,7 +181,7 @@ fn main() { let invalid_handle = DebugHandle::from(-1000); let biguint_with_invalid_handle: BigUint = - BigUint::from_handle(invalid_handle.clone()); + unsafe { BigUint::from_handle(invalid_handle.clone()) }; push!( to_check, biguint_with_invalid_handle, @@ -189,7 +189,7 @@ fn main() { ); let big_float_with_invalid_handle: BigFloat = - BigFloat::from_handle(invalid_handle.clone()); + unsafe { BigFloat::from_handle(invalid_handle.clone()) }; push!( to_check, big_float_with_invalid_handle, @@ -197,7 +197,7 @@ fn main() { ); let managed_buffer_with_invalid_handle: ManagedBuffer = - ManagedBuffer::from_handle(invalid_handle.clone()); + unsafe { ManagedBuffer::from_handle(invalid_handle.clone()) }; push!( to_check, managed_buffer_with_invalid_handle, @@ -205,7 +205,7 @@ fn main() { ); let token_identifier_with_invalid_handle: TokenIdentifier = - TokenIdentifier::from_handle(invalid_handle.clone()); + unsafe { TokenIdentifier::from_handle(invalid_handle.clone()) }; push!( to_check, token_identifier_with_invalid_handle, @@ -213,7 +213,7 @@ fn main() { ); let optional_value_some_with_invalid_handle: OptionalValue> = - OptionalValue::Some(BigUint::from_handle(invalid_handle.clone())); + OptionalValue::Some(unsafe { BigUint::from_handle(invalid_handle.clone()) }); push!( to_check, optional_value_some_with_invalid_handle,