Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vh api 7 extra #1139

Merged
merged 6 commits into from
Jun 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions framework/base/src/api/managed_types/handles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ pub trait HandleConstraints:
E::error_api_impl().signal_error(b"Cast type mismatch")
}
}

fn get_raw_handle_unchecked(&self) -> RawHandle {
self.get_raw_handle()
}
}

pub fn use_raw_handle<H>(handle: RawHandle) -> H
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{api::EllipticCurveApiImpl, types::heap::BoxedBytes};

impl EllipticCurveApiImpl for super::UncallableApi {
fn ec_create_from_name_bytes(&self, _name: &[u8]) -> Self::ManagedBufferHandle {
fn ec_create_from_name_bytes(&self, _name: &[u8]) -> Self::EllipticCurveHandle {
unreachable!()
}

Expand Down
119 changes: 5 additions & 114 deletions framework/scenario/src/api.rs
Original file line number Diff line number Diff line change
@@ -1,117 +1,8 @@
mod backend_type;
mod blockchain_api_vh;
mod call_value_api_vh;
mod crypto_api_vh;
mod endpoint_arg_api_vh;
mod endpoint_finish_api_vh;
mod error_api_vh;
mod log_api_vh;
mod core_api_vh;
mod impl_vh;
mod local_api_vh;
mod managed_type_api_vh;
mod print_api_vh;
mod send_api_vh;
mod storage_api_vh;
mod vm_api_vh;

pub use backend_type::*;

use std::ops::Deref;

use multiversx_chain_vm::{
executor::{MemPtr, VMHooks},
tx_mock::{StaticVarData, StaticVarStack, TxContextStack},
vm_hooks::{TxContextWrapper, TxManagedTypesCell, VMHooksDispatcher, VMHooksHandler},
};
use multiversx_sc::api::{HandleTypeInfo, ManagedBufferApiImpl, RawHandle};

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct VMHooksApi<const BACKEND_TYPE: VMHooksBackendType>;

impl<const BACKEND_TYPE: VMHooksBackendType> HandleTypeInfo for VMHooksApi<BACKEND_TYPE> {
type ManagedBufferHandle = RawHandle;
type BigIntHandle = RawHandle;
type BigFloatHandle = RawHandle;
type EllipticCurveHandle = RawHandle;
type ManagedMapHandle = RawHandle;
}

fn new_vh_dispatcher_managed_types_cell() -> Box<dyn VMHooks> {
let vh_handler: Box<dyn VMHooksHandler> = Box::<TxManagedTypesCell>::default();
Box::new(VMHooksDispatcher::new(vh_handler))
}

thread_local! {
static MANAGED_TYPES_CELL: Box<dyn VMHooks> = new_vh_dispatcher_managed_types_cell();

static STATIC_VAR_DATA_CELL: StaticVarData = StaticVarData::default();
}

impl<const BACKEND_TYPE: VMHooksBackendType> VMHooksApi<BACKEND_TYPE> {
pub fn api_impl() -> VMHooksApi<BACKEND_TYPE> {
VMHooksApi {}
}

/// All communication with the VM happens via this method.
pub fn with_vm_hooks<R, F>(&self, f: F) -> R
where
F: FnOnce(&dyn VMHooks) -> R,
{
match BACKEND_TYPE {
STATIC_MANAGED_TYPES => MANAGED_TYPES_CELL.with(|vh| f(vh.deref())),
DEBUGGER_STACK => {
let top_context = TxContextStack::static_peek();
let wrapper = TxContextWrapper::new(top_context);
let dispatcher = VMHooksDispatcher::new(Box::new(wrapper));
f(&dispatcher)
},
_ => panic!("invalid VMHooksBackendType"),
}
}

/// Static data does not belong to the VM, or to the VM hooks. It belongs to the contract only.
pub fn with_static_data<R, F>(&self, f: F) -> R
where
F: FnOnce(&StaticVarData) -> R,
{
match BACKEND_TYPE {
STATIC_MANAGED_TYPES => STATIC_VAR_DATA_CELL.with(|data| f(data)),
DEBUGGER_STACK => {
let top_context = StaticVarStack::static_peek();
f(&top_context)
},
_ => panic!("invalid VMHooksBackendType"),
}
}

/// Convenience method for calling VM hooks with a pointer to a temporary buffer in which we load a managed buffer.
///
/// It is used for
/// - addresses
/// - token identifiers.
///
/// The buffer is 32 bytes long, enough for both addresses and token identifiers.
pub(crate) fn with_temp_buffer_ptr<R, F>(&self, handle: RawHandle, length: usize, f: F) -> R
where
F: FnOnce(MemPtr) -> R,
{
let mut temp_buffer = [0u8; 32];
self.mb_load_slice(handle, 0, &mut temp_buffer[..length])
.expect("error extracting address bytes");
f(temp_buffer.as_ptr() as MemPtr)
}

/// Convenience method for calling VM hooks with a pointer to a temporary buffer in which we load an address.
pub(crate) fn with_temp_address_ptr<R, F>(&self, handle: RawHandle, f: F) -> R
where
F: FnOnce(MemPtr) -> R,
{
self.with_temp_buffer_ptr(handle, 32, f)
}
}

pub(crate) fn i32_to_bool(vm_hooks_result: i32) -> bool {
vm_hooks_result > 0
}

pub type StaticApi = VMHooksApi<STATIC_MANAGED_TYPES>;

pub type DebuggerApi = VMHooksApi<DEBUGGER_STACK>;
pub(crate) use impl_vh::i32_to_bool;
pub use impl_vh::{DebugHandle, DebuggerApi, StaticApi, VMHooksApi, VMHooksApiBackend};
12 changes: 0 additions & 12 deletions framework/scenario/src/api/backend_type.rs

This file was deleted.

9 changes: 9 additions & 0 deletions framework/scenario/src/api/core_api_vh.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
mod blockchain_api_vh;
mod call_value_api_vh;
mod crypto_api_vh;
mod endpoint_arg_api_vh;
mod endpoint_finish_api_vh;
mod error_api_vh;
mod log_api_vh;
mod send_api_vh;
mod storage_api_vh;
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
use multiversx_sc::{
api::{BlockchainApi, BlockchainApiImpl, ManagedBufferApiImpl, RawHandle},
api::{BlockchainApi, BlockchainApiImpl, HandleConstraints, ManagedBufferApiImpl, RawHandle},
types::{Address, EsdtLocalRoleFlags, H256},
};

use super::{i32_to_bool, VMHooksApi, VMHooksBackendType};
use crate::api::{i32_to_bool, VMHooksApi, VMHooksApiBackend};

impl<const BACKEND_TYPE: VMHooksBackendType> BlockchainApi for VMHooksApi<BACKEND_TYPE> {
impl<VHB: VMHooksApiBackend> BlockchainApi for VMHooksApi<VHB> {
type BlockchainApiImpl = Self;

fn blockchain_api_impl() -> Self::BlockchainApiImpl {
Self::api_impl()
}
}

impl<const BACKEND_TYPE: VMHooksBackendType> BlockchainApiImpl for VMHooksApi<BACKEND_TYPE> {
impl<VHB: VMHooksApiBackend> BlockchainApiImpl for VMHooksApi<VHB> {
fn get_caller_legacy(&self) -> Address {
panic!("legacy BlockchainApi functionality no longer supported")
}

fn load_caller_managed(&self, dest: Self::ManagedBufferHandle) {
self.with_vm_hooks(|vh| vh.managed_caller(dest));
self.with_vm_hooks(|vh| vh.managed_caller(dest.get_raw_handle_unchecked()));
}

fn get_sc_address_legacy(&self) -> Address {
panic!("legacy BlockchainApi functionality no longer supported")
}

fn load_sc_address_managed(&self, dest: Self::ManagedBufferHandle) {
self.with_vm_hooks(|vh| vh.managed_sc_address(dest));
self.with_vm_hooks(|vh| vh.managed_sc_address(dest.get_raw_handle_unchecked()));
}

fn load_owner_address_managed(&self, dest: Self::ManagedBufferHandle) {
self.with_vm_hooks(|vh| vh.managed_owner_address(dest));
self.with_vm_hooks(|vh| vh.managed_owner_address(dest.get_raw_handle_unchecked()));
}

fn get_shard_of_address_legacy(&self, _address: &Address) -> u32 {
Expand Down Expand Up @@ -61,7 +61,9 @@ impl<const BACKEND_TYPE: VMHooksBackendType> BlockchainApiImpl for VMHooksApi<BA

fn load_balance(&self, dest: Self::BigIntHandle, address_handle: Self::ManagedBufferHandle) {
self.with_temp_address_ptr(address_handle, |address_ptr: isize| {
self.with_vm_hooks(|vh| vh.big_int_get_external_balance(address_ptr, dest))
self.with_vm_hooks(|vh| {
vh.big_int_get_external_balance(address_ptr, dest.get_raw_handle_unchecked())
})
});
}

Expand All @@ -74,7 +76,7 @@ impl<const BACKEND_TYPE: VMHooksBackendType> BlockchainApiImpl for VMHooksApi<BA
}

fn load_tx_hash_managed(&self, dest: Self::ManagedBufferHandle) {
self.with_vm_hooks(|vh| vh.managed_get_original_tx_hash(dest));
self.with_vm_hooks(|vh| vh.managed_get_original_tx_hash(dest.get_raw_handle_unchecked()));
}

fn get_gas_left(&self) -> u64 {
Expand All @@ -98,7 +100,7 @@ impl<const BACKEND_TYPE: VMHooksBackendType> BlockchainApiImpl for VMHooksApi<BA
}

fn load_block_random_seed_managed(&self, dest: Self::ManagedBufferHandle) {
self.with_vm_hooks(|vh| vh.managed_get_block_random_seed(dest));
self.with_vm_hooks(|vh| vh.managed_get_block_random_seed(dest.get_raw_handle_unchecked()));
}

fn get_prev_block_timestamp(&self) -> u64 {
Expand All @@ -122,15 +124,15 @@ impl<const BACKEND_TYPE: VMHooksBackendType> BlockchainApiImpl for VMHooksApi<BA
}

fn load_prev_block_random_seed_managed(&self, dest: Self::ManagedBufferHandle) {
self.with_vm_hooks(|vh| vh.managed_get_prev_block_random_seed(dest));
self.with_vm_hooks(|vh| vh.managed_get_prev_block_random_seed(dest.get_raw_handle_unchecked()));
}

fn get_current_esdt_nft_nonce(
&self,
address_handle: Self::ManagedBufferHandle,
token_id_handle: Self::ManagedBufferHandle,
) -> u64 {
let token_id_len = self.mb_len(token_id_handle);
let token_id_len = self.mb_len(token_id_handle.clone());
let result = self.with_temp_address_ptr(address_handle, |address_ptr| {
self.with_temp_buffer_ptr(token_id_handle, token_id_len, |token_id_ptr| {
self.with_vm_hooks(|vh| {
Expand All @@ -148,7 +150,7 @@ impl<const BACKEND_TYPE: VMHooksBackendType> BlockchainApiImpl for VMHooksApi<BA
nonce: u64,
dest: Self::BigIntHandle,
) {
let token_id_len = self.mb_len(token_id_handle);
let token_id_len = self.mb_len(token_id_handle.clone());
self.with_temp_address_ptr(address_handle, |address_ptr| {
self.with_temp_buffer_ptr(token_id_handle, token_id_len, |token_id_ptr| {
self.with_vm_hooks(|vh| {
Expand All @@ -157,7 +159,7 @@ impl<const BACKEND_TYPE: VMHooksBackendType> BlockchainApiImpl for VMHooksApi<BA
token_id_ptr,
token_id_len as isize,
nonce as i64,
dest,
dest.get_raw_handle_unchecked(),
);
})
})
Expand Down Expand Up @@ -202,26 +204,34 @@ impl<const BACKEND_TYPE: VMHooksBackendType> BlockchainApiImpl for VMHooksApi<BA
nonce: u64,
) -> bool {
let result = self.with_vm_hooks(|vh| {
vh.managed_is_esdt_frozen(address_handle, token_id_handle, nonce as i64)
vh.managed_is_esdt_frozen(
address_handle.get_raw_handle_unchecked(),
token_id_handle.get_raw_handle_unchecked(),
nonce as i64,
)
});
i32_to_bool(result)
}

fn check_esdt_paused(&self, token_id_handle: Self::ManagedBufferHandle) -> bool {
let result = self.with_vm_hooks(|vh| vh.managed_is_esdt_paused(token_id_handle));
let result =
self.with_vm_hooks(|vh| vh.managed_is_esdt_paused(token_id_handle.get_raw_handle_unchecked()));
i32_to_bool(result)
}

fn check_esdt_limited_transfer(&self, token_id_handle: Self::ManagedBufferHandle) -> bool {
let result = self.with_vm_hooks(|vh| vh.managed_is_esdt_limited_transfer(token_id_handle));
let result = self.with_vm_hooks(|vh| {
vh.managed_is_esdt_limited_transfer(token_id_handle.get_raw_handle_unchecked())
});
i32_to_bool(result)
}

fn load_esdt_local_roles(
&self,
token_id_handle: Self::ManagedBufferHandle,
) -> EsdtLocalRoleFlags {
let result = self.with_vm_hooks(|vh| vh.get_esdt_local_roles(token_id_handle));
let result =
self.with_vm_hooks(|vh| vh.get_esdt_local_roles(token_id_handle.get_raw_handle_unchecked()));
unsafe { EsdtLocalRoleFlags::from_bits_unchecked(result as u64) }
}
}
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
use multiversx_sc::api::{CallValueApi, CallValueApiImpl};
use multiversx_sc::api::{CallValueApi, CallValueApiImpl, HandleConstraints};

use super::{VMHooksApi, VMHooksBackendType};
use crate::api::{VMHooksApi, VMHooksApiBackend};

impl<const BACKEND_TYPE: VMHooksBackendType> CallValueApi for VMHooksApi<BACKEND_TYPE> {
impl<VHB: VMHooksApiBackend> CallValueApi for VMHooksApi<VHB> {
type CallValueApiImpl = Self;

fn call_value_api_impl() -> Self::CallValueApiImpl {
Self::api_impl()
}
}

impl<const BACKEND_TYPE: VMHooksBackendType> CallValueApiImpl for VMHooksApi<BACKEND_TYPE> {
impl<VHB: VMHooksApiBackend> CallValueApiImpl for VMHooksApi<VHB> {
fn check_not_payable(&self) {
self.with_vm_hooks(|vh| vh.check_no_payment())
}

fn load_egld_value(&self, dest: Self::BigIntHandle) {
self.with_vm_hooks(|vh| vh.big_int_get_call_value(dest));
self.with_vm_hooks(|vh| vh.big_int_get_call_value(dest.get_raw_handle_unchecked()));
}

fn load_all_esdt_transfers(&self, dest_handle: Self::ManagedBufferHandle) {
self.with_vm_hooks(|vh| vh.managed_get_multi_esdt_call_value(dest_handle));
self.with_vm_hooks(|vh| vh.managed_get_multi_esdt_call_value(dest_handle.get_raw_handle_unchecked()));
}

fn esdt_num_transfers(&self) -> usize {
Expand Down
Loading
Loading