multiversx_sc_scenario/api/impl_vh/
single_tx_api.rs1use 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
46pub 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}