multiversx_sc_scenario/api/impl_vh/
single_tx_api.rs

1use std::sync::Mutex;
2
3use multiversx_chain_vm::{
4    blockchain::state::AccountData, executor::VMHooks, host::vm_hooks::VMHooksDispatcher,
5    types::VMAddress,
6};
7use multiversx_chain_vm_executor::VMHooksEarlyExit;
8use multiversx_sc::api::RawHandle;
9
10use crate::executor::debug::{ContractDebugInstanceState, StaticVarData};
11
12use super::{SingleTxApiData, SingleTxApiVMHooksContext, VMHooksApi, VMHooksApiBackend};
13
14thread_local! {
15    static SINGLE_TX_API_VH_CELL: Mutex<SingleTxApiVMHooksContext> = Mutex::default();
16
17    static SINGLE_TX_API_STATIC_CELL: StaticVarData = StaticVarData::default();
18}
19
20#[derive(Clone)]
21pub struct SingleTxApiBackend;
22
23impl VMHooksApiBackend for SingleTxApiBackend {
24    type HandleType = RawHandle;
25
26    fn with_vm_hooks<R, F>(f: F) -> R
27    where
28        F: FnOnce(&mut dyn VMHooks) -> Result<R, VMHooksEarlyExit>,
29    {
30        SINGLE_TX_API_VH_CELL.with(|cell| {
31            let vh_context = cell.lock().unwrap().clone();
32            let mut dispatcher = VMHooksDispatcher::new(vh_context);
33            f(&mut dispatcher)
34                .unwrap_or_else(|err| ContractDebugInstanceState::early_exit_panic(err))
35        })
36    }
37
38    fn with_static_data<R, F>(f: F) -> R
39    where
40        F: FnOnce(&StaticVarData) -> R,
41    {
42        SINGLE_TX_API_STATIC_CELL.with(|data| f(data))
43    }
44}
45
46/// Similar to the `StaticApi`, but offers allows calls to storage, input, and even creating results.
47pub type SingleTxApi = VMHooksApi<SingleTxApiBackend>;
48
49impl SingleTxApi {
50    pub fn clear_global() {
51        SINGLE_TX_API_VH_CELL.with(|cell| {
52            let _ = std::mem::take(&mut *cell.lock().unwrap());
53        })
54    }
55
56    pub fn with_global<F, R>(f: F) -> R
57    where
58        F: FnOnce(&mut SingleTxApiData) -> R,
59    {
60        SINGLE_TX_API_VH_CELL.with(|cell| {
61            let mut handler = cell.lock().unwrap();
62            handler.with_mut_data(f)
63        })
64    }
65
66    pub fn with_global_default_account<F, R>(f: F) -> R
67    where
68        F: FnOnce(&mut AccountData) -> R,
69    {
70        Self::with_global(|data| data.with_account_mut(&VMAddress::zero(), f))
71    }
72}
73
74impl std::fmt::Debug for SingleTxApi {
75    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
76        f.debug_struct("SingleTxApi").finish()
77    }
78}