multiversx_chain_vm/vm_hooks/vh_impl/
vh_single_tx_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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
use std::{
    collections::HashMap,
    sync::{Arc, Mutex, MutexGuard},
};

use multiversx_chain_core::types::ReturnCode;

use crate::{
    tx_mock::{BackTransfers, TxFunctionName, TxInput, TxManagedTypes, TxResult},
    types::{VMAddress, VMCodeMetadata},
    vm_hooks::{
        VMHooksBigFloat, VMHooksBigInt, VMHooksBlockchain, VMHooksCallValue, VMHooksCrypto,
        VMHooksEndpointArgument, VMHooksEndpointFinish, VMHooksError, VMHooksErrorManaged,
        VMHooksHandler, VMHooksHandlerSource, VMHooksLog, VMHooksManagedBuffer, VMHooksManagedMap,
        VMHooksManagedTypes, VMHooksSend, VMHooksStorageRead, VMHooksStorageWrite,
    },
    world_mock::{AccountData, BlockInfo},
};

#[derive(Default, Debug)]
pub struct SingleTxApiData {
    pub tx_input_box: Box<TxInput>,
    pub accounts: Mutex<HashMap<VMAddress, AccountData>>,
    pub managed_types: Mutex<TxManagedTypes>,
    pub tx_result_cell: Mutex<TxResult>,
    pub previous_block_info: BlockInfo,
    pub current_block_info: BlockInfo,
}

impl SingleTxApiData {
    pub fn with_account_mut<R, F>(&self, address: &VMAddress, f: F) -> R
    where
        F: FnOnce(&mut AccountData) -> R,
    {
        let mut accounts = self.accounts.lock().unwrap();
        let account = accounts
            .entry(address.clone())
            .or_insert(AccountData::new_empty(address.clone()));
        f(account)
    }
}

#[derive(Default, Debug, Clone)]
pub struct SingleTxApiVMHooksHandler(Arc<SingleTxApiData>);

impl SingleTxApiVMHooksHandler {
    pub fn with_mut_data<F, R>(&mut self, f: F) -> R
    where
        F: FnOnce(&mut SingleTxApiData) -> R,
    {
        let data = Arc::get_mut(&mut self.0)
            .expect("could not retrieve mutable reference to SingleTxApi data");
        f(data)
    }
}

impl VMHooksHandlerSource for SingleTxApiVMHooksHandler {
    fn m_types_lock(&self) -> MutexGuard<TxManagedTypes> {
        self.0.managed_types.lock().unwrap()
    }

    fn halt_with_error(&self, status: ReturnCode, message: &str) -> ! {
        panic!("VM error occured, status: {status}, message: {message}")
    }

    fn input_ref(&self) -> &TxInput {
        &self.0.tx_input_box
    }

    fn random_next_bytes(&self, _length: usize) -> Vec<u8> {
        panic!("cannot access the random bytes generator in the SingleTxApi")
    }

    fn result_lock(&self) -> MutexGuard<TxResult> {
        self.0.tx_result_cell.lock().unwrap()
    }

    fn storage_read_any_address(&self, address: &VMAddress, key: &[u8]) -> Vec<u8> {
        self.0.with_account_mut(address, |account| {
            account.storage.get(key).cloned().unwrap_or_default()
        })
    }

    fn storage_write(&self, key: &[u8], value: &[u8]) {
        self.0.with_account_mut(&self.0.tx_input_box.to, |account| {
            account.storage.insert(key.to_vec(), value.to_vec());
        });
    }

    fn get_previous_block_info(&self) -> &BlockInfo {
        &self.0.previous_block_info
    }

    fn get_current_block_info(&self) -> &BlockInfo {
        &self.0.current_block_info
    }

    fn back_transfers_lock(&self) -> MutexGuard<BackTransfers> {
        panic!("cannot access back transfers in the SingleTxApi")
    }

    fn account_data(&self, address: &VMAddress) -> Option<AccountData> {
        Some(self.0.with_account_mut(address, |account| account.clone()))
    }

    fn account_code(&self, _address: &VMAddress) -> Vec<u8> {
        vec![]
    }

    fn perform_async_call(
        &self,
        _to: VMAddress,
        _egld_value: num_bigint::BigUint,
        _func_name: TxFunctionName,
        _args: Vec<Vec<u8>>,
    ) -> ! {
        panic!("cannot launch contract calls in the SingleTxApi")
    }

    fn perform_execute_on_dest_context(
        &self,
        _to: VMAddress,
        _egld_value: num_bigint::BigUint,
        _func_name: TxFunctionName,
        _args: Vec<Vec<u8>>,
    ) -> Vec<Vec<u8>> {
        panic!("cannot launch contract calls in the SingleTxApi")
    }

    fn perform_deploy(
        &self,
        _egld_value: num_bigint::BigUint,
        _contract_code: Vec<u8>,
        _code_metadata: VMCodeMetadata,
        _args: Vec<Vec<u8>>,
    ) -> (VMAddress, Vec<Vec<u8>>) {
        panic!("cannot launch contract calls in the SingleTxApi")
    }

    fn perform_transfer_execute(
        &self,
        _to: VMAddress,
        _egld_value: num_bigint::BigUint,
        _func_name: TxFunctionName,
        _arguments: Vec<Vec<u8>>,
    ) {
        panic!("cannot launch contract calls in the SingleTxApi")
    }
}

impl VMHooksBigInt for SingleTxApiVMHooksHandler {}
impl VMHooksManagedBuffer for SingleTxApiVMHooksHandler {}
impl VMHooksManagedMap for SingleTxApiVMHooksHandler {}
impl VMHooksBigFloat for SingleTxApiVMHooksHandler {}
impl VMHooksManagedTypes for SingleTxApiVMHooksHandler {}

impl VMHooksCallValue for SingleTxApiVMHooksHandler {}
impl VMHooksEndpointArgument for SingleTxApiVMHooksHandler {}
impl VMHooksEndpointFinish for SingleTxApiVMHooksHandler {}
impl VMHooksError for SingleTxApiVMHooksHandler {}
impl VMHooksErrorManaged for SingleTxApiVMHooksHandler {}
impl VMHooksStorageRead for SingleTxApiVMHooksHandler {}
impl VMHooksStorageWrite for SingleTxApiVMHooksHandler {}
impl VMHooksCrypto for SingleTxApiVMHooksHandler {}
impl VMHooksBlockchain for SingleTxApiVMHooksHandler {}
impl VMHooksLog for SingleTxApiVMHooksHandler {}
impl VMHooksSend for SingleTxApiVMHooksHandler {}

impl VMHooksHandler for SingleTxApiVMHooksHandler {}