multiversx_sc_scenario/api/impl_vh/
vm_hooks_api.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use crate::debug_executor::StaticVarData;

use super::VMHooksApiBackend;

use std::marker::PhantomData;

use multiversx_chain_vm::executor::{MemPtr, VMHooks};
use multiversx_sc::api::{HandleTypeInfo, ManagedBufferApiImpl};

#[derive(Clone, Debug)]
pub struct VMHooksApi<S: VMHooksApiBackend> {
    _phantom: PhantomData<S>,
}

impl<VHB: VMHooksApiBackend> VMHooksApi<VHB> {
    pub fn api_impl() -> VMHooksApi<VHB> {
        VMHooksApi {
            _phantom: PhantomData,
        }
    }

    /// 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,
    {
        VHB::with_vm_hooks(f)
    }

    /// Works with the VM hooks given by the context of 1 handle.
    pub fn with_vm_hooks_ctx_1<R, F>(&self, handle: &VHB::HandleType, f: F) -> R
    where
        F: FnOnce(&dyn VMHooks) -> R,
    {
        VHB::with_vm_hooks_ctx_1(handle.clone(), f)
    }

    /// Works with the VM hooks given by the context of 2 handles.
    pub fn with_vm_hooks_ctx_2<R, F>(
        &self,
        handle1: &VHB::HandleType,
        handle2: &VHB::HandleType,
        f: F,
    ) -> R
    where
        F: FnOnce(&dyn VMHooks) -> R,
    {
        VHB::with_vm_hooks_ctx_2(handle1.clone(), handle2.clone(), f)
    }

    /// Works with the VM hooks given by the context of 3 handles.
    pub fn with_vm_hooks_ctx_3<R, F>(
        &self,
        handle1: &VHB::HandleType,
        handle2: &VHB::HandleType,
        handle3: &VHB::HandleType,
        f: F,
    ) -> R
    where
        F: FnOnce(&dyn VMHooks) -> R,
    {
        VHB::with_vm_hooks_ctx_3(handle1.clone(), handle2.clone(), handle3.clone(), f)
    }

    /// Checks that the handle refers to the current active context (if possible).
    ///
    /// This is to prevent working with handles pointing to the wrong context, when debugging.
    pub fn assert_live_handle(&self, handle: &VHB::HandleType) {
        VHB::assert_live_handle(handle);
    }

    /// 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,
    {
        VHB::with_static_data(f)
    }

    /// 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: <Self as HandleTypeInfo>::ManagedBufferHandle,
        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: <Self as HandleTypeInfo>::ManagedBufferHandle,
        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
}

impl<VHB: VMHooksApiBackend> HandleTypeInfo for VMHooksApi<VHB> {
    type ManagedBufferHandle = VHB::HandleType;
    type BigIntHandle = VHB::HandleType;
    type BigFloatHandle = VHB::HandleType;
    type EllipticCurveHandle = VHB::HandleType;
    type ManagedMapHandle = VHB::HandleType;
}

impl<VHB: VMHooksApiBackend> PartialEq for VMHooksApi<VHB> {
    fn eq(&self, _: &Self) -> bool {
        true
    }
}

impl<VHB: VMHooksApiBackend> Eq for VMHooksApi<VHB> {}