multiversx_sc_scenario/api/impl_vh/
vm_hooks_api.rs

1use crate::executor::debug::StaticVarData;
2
3use super::VMHooksApiBackend;
4
5use std::marker::PhantomData;
6
7use multiversx_chain_vm::executor::{MemPtr, VMHooks};
8use multiversx_chain_vm_executor::VMHooksEarlyExit;
9use multiversx_sc::api::{HandleTypeInfo, ManagedBufferApiImpl};
10
11#[derive(Clone, Debug)]
12pub struct VMHooksApi<S: VMHooksApiBackend> {
13    _phantom: PhantomData<S>,
14}
15
16impl<VHB: VMHooksApiBackend> VMHooksApi<VHB> {
17    pub fn api_impl() -> VMHooksApi<VHB> {
18        VMHooksApi {
19            _phantom: PhantomData,
20        }
21    }
22
23    /// All communication with the VM happens via this method.
24    pub fn with_vm_hooks<R, F>(&self, f: F) -> R
25    where
26        F: FnOnce(&mut dyn VMHooks) -> Result<R, VMHooksEarlyExit>,
27    {
28        VHB::with_vm_hooks(f)
29    }
30
31    /// Works with the VM hooks given by the context of 1 handle.
32    pub fn with_vm_hooks_ctx_1<R, F>(&self, handle: &VHB::HandleType, f: F) -> R
33    where
34        F: FnOnce(&mut dyn VMHooks) -> Result<R, VMHooksEarlyExit>,
35    {
36        VHB::with_vm_hooks_ctx_1(handle.clone(), f)
37    }
38
39    /// Works with the VM hooks given by the context of 2 handles.
40    pub fn with_vm_hooks_ctx_2<R, F>(
41        &self,
42        handle1: &VHB::HandleType,
43        handle2: &VHB::HandleType,
44        f: F,
45    ) -> R
46    where
47        F: FnOnce(&mut dyn VMHooks) -> Result<R, VMHooksEarlyExit>,
48    {
49        VHB::with_vm_hooks_ctx_2(handle1.clone(), handle2.clone(), f)
50    }
51
52    /// Works with the VM hooks given by the context of 3 handles.
53    pub fn with_vm_hooks_ctx_3<R, F>(
54        &self,
55        handle1: &VHB::HandleType,
56        handle2: &VHB::HandleType,
57        handle3: &VHB::HandleType,
58        f: F,
59    ) -> R
60    where
61        F: FnOnce(&mut dyn VMHooks) -> Result<R, VMHooksEarlyExit>,
62    {
63        VHB::with_vm_hooks_ctx_3(handle1.clone(), handle2.clone(), handle3.clone(), f)
64    }
65
66    /// Checks that the handle refers to the current active context (if possible).
67    ///
68    /// This is to prevent working with handles pointing to the wrong context, when debugging.
69    pub fn assert_live_handle(&self, handle: &VHB::HandleType) {
70        VHB::assert_live_handle(handle);
71    }
72
73    /// Static data does not belong to the VM, or to the VM hooks. It belongs to the contract only.
74    pub fn with_static_data<R, F>(&self, f: F) -> R
75    where
76        F: FnOnce(&StaticVarData) -> R,
77    {
78        VHB::with_static_data(f)
79    }
80
81    /// Convenience method for calling VM hooks with a pointer to a temporary buffer in which we load a managed buffer.
82    ///
83    /// It is used for
84    /// - addresses
85    /// - token identifiers.
86    ///
87    /// The buffer is 32 bytes long, enough for both addresses and token identifiers.
88    pub(crate) fn with_temp_buffer_ptr<R, F>(
89        &self,
90        handle: <Self as HandleTypeInfo>::ManagedBufferHandle,
91        length: usize,
92        f: F,
93    ) -> R
94    where
95        F: FnOnce(MemPtr) -> R,
96    {
97        let mut temp_buffer = [0u8; 32];
98        self.mb_load_slice(handle, 0, &mut temp_buffer[..length])
99            .expect("error extracting address bytes");
100        f(temp_buffer.as_ptr() as MemPtr)
101    }
102
103    /// Convenience method for calling VM hooks with a pointer to a temporary buffer in which we load an address.
104    pub(crate) fn with_temp_address_ptr<R, F>(
105        &self,
106        handle: <Self as HandleTypeInfo>::ManagedBufferHandle,
107        f: F,
108    ) -> R
109    where
110        F: FnOnce(MemPtr) -> R,
111    {
112        self.with_temp_buffer_ptr(handle, 32, f)
113    }
114}
115
116pub(crate) fn i32_to_bool(vm_hooks_result: i32) -> bool {
117    vm_hooks_result > 0
118}
119
120impl<VHB: VMHooksApiBackend> HandleTypeInfo for VMHooksApi<VHB> {
121    type ManagedBufferHandle = VHB::HandleType;
122    type BigIntHandle = VHB::HandleType;
123    type BigFloatHandle = VHB::HandleType;
124    type EllipticCurveHandle = VHB::HandleType;
125    type ManagedMapHandle = VHB::HandleType;
126}
127
128impl<VHB: VMHooksApiBackend> PartialEq for VMHooksApi<VHB> {
129    fn eq(&self, _: &Self) -> bool {
130        true
131    }
132}
133
134impl<VHB: VMHooksApiBackend> Eq for VMHooksApi<VHB> {}