diff --git a/framework/scenario/src/facade/scenario_world_whitebox.rs b/framework/scenario/src/facade/scenario_world_whitebox.rs index 1866eeb6f3..814c73fd59 100644 --- a/framework/scenario/src/facade/scenario_world_whitebox.rs +++ b/framework/scenario/src/facade/scenario_world_whitebox.rs @@ -55,7 +55,7 @@ impl ScenarioWorld { ) -> &mut Self where ContractObj: ContractBase + CallableContract + 'static, - F: FnOnce(ContractObj) + 'static, + F: FnOnce(ContractObj), { self.whitebox_call_check(whitebox_contract, sc_call_step, f, |tx_result| { tx_result.assert_ok(); @@ -71,7 +71,7 @@ impl ScenarioWorld { ) -> &mut Self where ContractObj: ContractBase + CallableContract + 'static, - F: FnOnce(ContractObj) + 'static, + F: FnOnce(ContractObj), C: FnOnce(TxResult), { // the recipient can be deduced from the contract object, it is redundant to provide it in the step @@ -102,7 +102,7 @@ impl ScenarioWorld { ) -> &mut Self where ContractObj: ContractBase + CallableContract + 'static, - F: FnOnce(ContractObj) + 'static, + F: FnOnce(ContractObj), { self.whitebox_deploy_check(whitebox_contract, sc_deploy_step, f, |tx_result| { tx_result.assert_ok(); @@ -118,7 +118,7 @@ impl ScenarioWorld { ) -> &mut Self where ContractObj: ContractBase + CallableContract + 'static, - F: FnOnce(ContractObj) + 'static, + F: FnOnce(ContractObj), C: FnOnce(TxResult), { let contract_obj = (whitebox_contract.contract_obj_builder)(); diff --git a/framework/scenario/src/scenario/run_vm/sc_call.rs b/framework/scenario/src/scenario/run_vm/sc_call.rs index 6ffd05f7e4..336cb504fb 100644 --- a/framework/scenario/src/scenario/run_vm/sc_call.rs +++ b/framework/scenario/src/scenario/run_vm/sc_call.rs @@ -40,7 +40,7 @@ impl ScenarioVMRunner { pub fn perform_sc_call_lambda(&mut self, sc_call_step: &ScCallStep, f: F) -> TxResult where - F: FnOnce() + 'static, + F: FnOnce(), { let tx_input = tx_input_from_call(sc_call_step); @@ -62,7 +62,7 @@ impl ScenarioVMRunner { f: F, ) -> TxResult where - F: FnOnce() + 'static, + F: FnOnce(), { let tx_result = self.perform_sc_call_lambda(sc_call_step, f); if let Some(tx_expect) = &sc_call_step.expect { diff --git a/vm/src/tx_execution/blockchain_vm.rs b/vm/src/tx_execution/blockchain_vm.rs index bd6f57d7a2..521e6728b5 100644 --- a/vm/src/tx_execution/blockchain_vm.rs +++ b/vm/src/tx_execution/blockchain_vm.rs @@ -2,10 +2,10 @@ use std::{ops::Deref, rc::Rc}; use multiversx_chain_vm_executor::Executor; -use crate::tx_execution::{init_builtin_functions, BuiltinFunctionMap}; +use super::BuiltinFunctionContainer; pub struct BlockchainVM { - pub builtin_functions: Rc, + pub builtin_functions: BuiltinFunctionContainer, pub executor: Box, } @@ -15,7 +15,7 @@ pub struct BlockchainVMRef(Rc); impl BlockchainVM { pub fn new(executor: Box) -> Self { BlockchainVM { - builtin_functions: Rc::new(init_builtin_functions()), + builtin_functions: BuiltinFunctionContainer, executor, } } diff --git a/vm/src/tx_execution/builtin_function_mocks.rs b/vm/src/tx_execution/builtin_function_mocks.rs index b5cf1ab94c..dff42101cc 100644 --- a/vm/src/tx_execution/builtin_function_mocks.rs +++ b/vm/src/tx_execution/builtin_function_mocks.rs @@ -1,13 +1,10 @@ -mod builtin_func_exec; -mod builtin_func_map; -mod builtin_func_role_check_wrapper; +mod builtin_func_container; mod builtin_func_trait; mod esdt_nft; mod general; mod transfer; pub mod vm_builtin_function_names; -pub use builtin_func_exec::init_builtin_functions; -pub use builtin_func_map::BuiltinFunctionMap; +pub use builtin_func_container::BuiltinFunctionContainer; pub use builtin_func_trait::{BuiltinFunction, BuiltinFunctionEsdtTransferInfo}; pub use vm_builtin_function_names as builtin_function_names; diff --git a/vm/src/tx_execution/builtin_function_mocks/builtin_func_container.rs b/vm/src/tx_execution/builtin_function_mocks/builtin_func_container.rs new file mode 100644 index 0000000000..55625fd31d --- /dev/null +++ b/vm/src/tx_execution/builtin_function_mocks/builtin_func_container.rs @@ -0,0 +1,158 @@ +use super::{ + builtin_func_trait::BuiltinFunction, + builtin_function_names::*, + esdt_nft::{ + ESDTLocalBurn, ESDTLocalMint, ESDTNftAddQuantity, ESDTNftAddUri, ESDTNftBurn, + ESDTNftCreate, ESDTNftUpdateAttributes, + }, + general::{ChangeOwner, ClaimDeveloperRewards, SetUsername, UpgradeContract}, + transfer::{ESDTMultiTransfer, ESDTNftTransfer, ESDTTransfer}, + BuiltinFunctionEsdtTransferInfo, +}; +use crate::{ + tx_execution::BlockchainVMRef, + tx_mock::{BlockchainUpdate, TxCache, TxInput, TxResult}, + types::EsdtLocalRole, +}; + +/// Container for builtin function logic. +/// +/// Currently has no data, but could conceivably be configurable in the future. +pub struct BuiltinFunctionContainer; + +impl BuiltinFunctionContainer { + /// If the call points to a builtin function, it executes it, otherwise calls the `or_else` closure. + /// + /// It also checks that the appropriate roles are set, where applicable. + pub fn execute_builtin_function_or_else( + &self, + vm: &BlockchainVMRef, + tx_input: TxInput, + tx_cache: TxCache, + f: F, + or_else: Else, + ) -> (TxResult, BlockchainUpdate) + where + F: FnOnce(), + Else: FnOnce(TxInput, TxCache, F) -> (TxResult, BlockchainUpdate), + { + BuiltinFunctionCall::new(vm, tx_input, tx_cache).execute_or_else(f, or_else) + } + + /// Provides data on the builtin functions that perform ESDT token transfers. + pub fn extract_token_transfers(&self, tx_input: &TxInput) -> BuiltinFunctionEsdtTransferInfo { + match tx_input.func_name.as_str() { + ESDT_MULTI_TRANSFER_FUNC_NAME => bf_extract_transfers(ESDTMultiTransfer, tx_input), + ESDT_NFT_TRANSFER_FUNC_NAME => bf_extract_transfers(ESDTNftTransfer, tx_input), + ESDT_TRANSFER_FUNC_NAME => bf_extract_transfers(ESDTTransfer, tx_input), + _ => BuiltinFunctionEsdtTransferInfo::empty(tx_input), + } + } +} + +fn bf_extract_transfers(builtin_func: B, tx_input: &TxInput) -> BuiltinFunctionEsdtTransferInfo +where + B: BuiltinFunction, +{ + builtin_func.extract_esdt_transfers(tx_input) +} + +/// Syntax helper for the big builtin function match in `execute_or_else`. +/// Thanks to it we do not need to write out the arguments for each match arm. +struct BuiltinFunctionCall<'a> { + vm: &'a BlockchainVMRef, + tx_input: TxInput, + tx_cache: TxCache, +} + +impl<'a> BuiltinFunctionCall<'a> { + pub fn new(vm: &'a BlockchainVMRef, tx_input: TxInput, tx_cache: TxCache) -> Self { + BuiltinFunctionCall { + vm, + tx_input, + tx_cache, + } + } + + pub fn execute_or_else(self, f: F, or_else: Else) -> (TxResult, BlockchainUpdate) + where + F: FnOnce(), + Else: FnOnce(TxInput, TxCache, F) -> (TxResult, BlockchainUpdate), + { + match self.tx_input.func_name.as_str() { + ESDT_LOCAL_MINT_FUNC_NAME => { + self.check_role_and_execute(EsdtLocalRole::Mint, ESDTLocalMint, f) + }, + ESDT_LOCAL_BURN_FUNC_NAME => { + self.check_role_and_execute(EsdtLocalRole::Burn, ESDTLocalBurn, f) + }, + ESDT_NFT_CREATE_FUNC_NAME => { + self.check_role_and_execute(EsdtLocalRole::NftCreate, ESDTNftCreate, f) + }, + ESDT_NFT_BURN_FUNC_NAME => { + self.check_role_and_execute(EsdtLocalRole::NftBurn, ESDTNftBurn, f) + }, + ESDT_NFT_ADD_QUANTITY_FUNC_NAME => { + self.check_role_and_execute(EsdtLocalRole::NftAddQuantity, ESDTNftAddQuantity, f) + }, + ESDT_NFT_ADD_URI_FUNC_NAME => { + self.check_role_and_execute(EsdtLocalRole::NftAddUri, ESDTNftAddUri, f) + }, + ESDT_NFT_UPDATE_ATTRIBUTES_FUNC_NAME => self.check_role_and_execute( + EsdtLocalRole::NftUpdateAttributes, + ESDTNftUpdateAttributes, + f, + ), + + ESDT_MULTI_TRANSFER_FUNC_NAME => self.execute_bf(ESDTMultiTransfer, f), + ESDT_NFT_TRANSFER_FUNC_NAME => self.execute_bf(ESDTNftTransfer, f), + ESDT_TRANSFER_FUNC_NAME => self.execute_bf(ESDTTransfer, f), + CHANGE_OWNER_BUILTIN_FUNC_NAME => self.execute_bf(ChangeOwner, f), + CLAIM_DEVELOPER_REWARDS_FUNC_NAME => self.execute_bf(ClaimDeveloperRewards, f), + SET_USERNAME_FUNC_NAME => self.execute_bf(SetUsername, f), + UPGRADE_CONTRACT_FUNC_NAME => self.execute_bf(UpgradeContract, f), + MIGRATE_USERNAME_FUNC_NAME => { + panic!("builtin function {MIGRATE_USERNAME_FUNC_NAME} not implemented") + }, + _ => or_else(self.tx_input, self.tx_cache, f), + } + } + + fn execute_bf(self, builtin_func: B, f: F) -> (TxResult, BlockchainUpdate) + where + B: BuiltinFunction, + F: FnOnce(), + { + builtin_func.execute_lambda(self.vm, self.tx_input, self.tx_cache, f) + } + + fn check_role_and_execute( + self, + role: EsdtLocalRole, + builtin_func: B, + f: F, + ) -> (TxResult, BlockchainUpdate) + where + B: BuiltinFunction, + F: FnOnce(), + { + if check_allowed_to_execute(role, &self.tx_input, &self.tx_cache) { + self.execute_bf(builtin_func, f) + } else { + ( + TxResult::from_vm_error("action is not allowed"), + BlockchainUpdate::empty(), + ) + } + } +} + +fn check_allowed_to_execute(role: EsdtLocalRole, tx_input: &TxInput, tx_cache: &TxCache) -> bool { + let token_identifier = tx_input.args[0].clone(); + let available_roles = tx_cache.with_account_mut(&tx_input.to, |account| { + account.esdt.get_roles(&token_identifier) + }); + available_roles + .iter() + .any(|available_role| available_role.as_slice() == role.name().as_bytes()) +} diff --git a/vm/src/tx_execution/builtin_function_mocks/builtin_func_exec.rs b/vm/src/tx_execution/builtin_function_mocks/builtin_func_exec.rs deleted file mode 100644 index 2f3b265e82..0000000000 --- a/vm/src/tx_execution/builtin_function_mocks/builtin_func_exec.rs +++ /dev/null @@ -1,63 +0,0 @@ -use super::{ - builtin_func_map::BuiltinFunctionMap, - builtin_func_role_check_wrapper::BuiltinFunctionRoleCheckWrapper, - builtin_func_trait::BuiltinFunction, - esdt_nft::{ - ESDTLocalBurn, ESDTLocalMint, ESDTNftAddQuantity, ESDTNftAddUri, ESDTNftBurn, - ESDTNftCreate, ESDTNftUpdateAttributes, - }, - general::{ChangeOwner, ClaimDeveloperRewards, SetUsername, UpgradeContract}, - transfer::{ESDTMultiTransfer, ESDTNftTransfer, ESDTTransfer}, -}; - -const ESDT_ROLE_LOCAL_MINT: &str = "ESDTRoleLocalMint"; -const ESDT_ROLE_LOCAL_BURN: &str = "ESDTRoleLocalBurn"; -const ESDT_ROLE_NFT_CREATE: &str = "ESDTRoleNFTCreate"; -const ESDT_ROLE_NFT_ADD_QUANTITY: &str = "ESDTRoleNFTAddQuantity"; -const ESDT_ROLE_NFT_BURN: &str = "ESDTRoleNFTBurn"; -const ESDT_ROLE_NFT_ADD_URI: &str = "ESDTRoleNFTAddURI"; -const ESDT_ROLE_NFT_UPDATE_ATTRIBUTES: &str = "ESDTRoleNFTUpdateAttributes"; - -fn builtin_function_impls() -> Vec> { - vec![ - Box::new(BuiltinFunctionRoleCheckWrapper::new( - ESDT_ROLE_LOCAL_MINT, - Box::new(ESDTLocalMint), - )), - Box::new(BuiltinFunctionRoleCheckWrapper::new( - ESDT_ROLE_LOCAL_BURN, - Box::new(ESDTLocalBurn), - )), - Box::new(BuiltinFunctionRoleCheckWrapper::new( - ESDT_ROLE_NFT_CREATE, - Box::new(ESDTNftCreate), - )), - Box::new(BuiltinFunctionRoleCheckWrapper::new( - ESDT_ROLE_NFT_ADD_QUANTITY, - Box::new(ESDTNftAddQuantity), - )), - Box::new(BuiltinFunctionRoleCheckWrapper::new( - ESDT_ROLE_NFT_BURN, - Box::new(ESDTNftBurn), - )), - Box::new(BuiltinFunctionRoleCheckWrapper::new( - ESDT_ROLE_NFT_ADD_URI, - Box::new(ESDTNftAddUri), - )), - Box::new(BuiltinFunctionRoleCheckWrapper::new( - ESDT_ROLE_NFT_UPDATE_ATTRIBUTES, - Box::new(ESDTNftUpdateAttributes), - )), - Box::new(ESDTMultiTransfer), - Box::new(ESDTNftTransfer), - Box::new(ESDTTransfer), - Box::new(ChangeOwner), - Box::new(ClaimDeveloperRewards), - Box::new(SetUsername), - Box::new(UpgradeContract), - ] -} - -pub fn init_builtin_functions() -> BuiltinFunctionMap { - BuiltinFunctionMap::init(builtin_function_impls()) -} diff --git a/vm/src/tx_execution/builtin_function_mocks/builtin_func_map.rs b/vm/src/tx_execution/builtin_function_mocks/builtin_func_map.rs deleted file mode 100644 index 06e7558c85..0000000000 --- a/vm/src/tx_execution/builtin_function_mocks/builtin_func_map.rs +++ /dev/null @@ -1,44 +0,0 @@ -use std::collections::HashMap; - -use crate::tx_mock::{TxFunctionName, TxInput}; - -use super::builtin_func_trait::{BuiltinFunction, BuiltinFunctionEsdtTransferInfo}; - -pub struct BuiltinFunctionMap { - func_map: HashMap>, -} - -impl BuiltinFunctionMap { - pub fn init(builtin_funcs: Vec>) -> Self { - let mut func_map = HashMap::new(); - for builtin_func in builtin_funcs.into_iter() { - assert!( - !func_map.contains_key(builtin_func.name()), - "duplicate builtin function: {}", - builtin_func.name() - ); - func_map.insert(builtin_func.name().to_string(), builtin_func); - } - - Self { func_map } - } - - #[allow(clippy::borrowed_box)] - pub fn get(&self, name: &TxFunctionName) -> Option<&Box> { - self.func_map.get(name.as_str()) - } - - pub fn extract_token_transfers(&self, tx_input: &TxInput) -> BuiltinFunctionEsdtTransferInfo { - if let Some(builtin_func) = self.get(&tx_input.func_name) { - builtin_func.extract_esdt_transfers(tx_input) - } else { - BuiltinFunctionEsdtTransferInfo::empty(tx_input) - } - } -} - -impl std::fmt::Debug for BuiltinFunctionMap { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - f.debug_struct("BuiltinFunctionMap").finish() - } -} diff --git a/vm/src/tx_execution/builtin_function_mocks/builtin_func_role_check_wrapper.rs b/vm/src/tx_execution/builtin_function_mocks/builtin_func_role_check_wrapper.rs deleted file mode 100644 index 5ea4dcfcb3..0000000000 --- a/vm/src/tx_execution/builtin_function_mocks/builtin_func_role_check_wrapper.rs +++ /dev/null @@ -1,57 +0,0 @@ -use crate::{ - tx_execution::BlockchainVMRef, - tx_mock::{BlockchainUpdate, TxCache, TxInput, TxResult}, -}; - -use super::builtin_func_trait::{BuiltinFunction, BuiltinFunctionEsdtTransferInfo}; - -/// Checks that user has appropriate role before calling the builtin function. -pub struct BuiltinFunctionRoleCheckWrapper { - role_name: &'static str, - builtin_function: Box, -} - -impl BuiltinFunctionRoleCheckWrapper { - pub fn new(role_name: &'static str, builtin_function: Box) -> Self { - Self { - role_name, - builtin_function, - } - } -} - -impl BuiltinFunction for BuiltinFunctionRoleCheckWrapper { - fn name(&self) -> &str { - self.builtin_function.name() - } - - fn extract_esdt_transfers(&self, tx_input: &TxInput) -> BuiltinFunctionEsdtTransferInfo { - self.builtin_function.extract_esdt_transfers(tx_input) - } - - fn execute( - &self, - vm: &BlockchainVMRef, - tx_input: TxInput, - tx_cache: TxCache, - ) -> (TxResult, BlockchainUpdate) { - if check_allowed_to_execute(self.role_name, &tx_input, &tx_cache) { - self.builtin_function.execute(vm, tx_input, tx_cache) - } else { - ( - TxResult::from_vm_error("action is not allowed"), - BlockchainUpdate::empty(), - ) - } - } -} - -pub fn check_allowed_to_execute(role_name: &str, tx_input: &TxInput, tx_cache: &TxCache) -> bool { - let token_identifier = tx_input.args[0].clone(); - let available_roles = tx_cache.with_account_mut(&tx_input.to, |account| { - account.esdt.get_roles(&token_identifier) - }); - available_roles - .iter() - .any(|available_role| available_role.as_slice() == role_name.as_bytes()) -} diff --git a/vm/src/tx_execution/builtin_function_mocks/builtin_func_trait.rs b/vm/src/tx_execution/builtin_function_mocks/builtin_func_trait.rs index 7562ac2811..65a5dd4573 100644 --- a/vm/src/tx_execution/builtin_function_mocks/builtin_func_trait.rs +++ b/vm/src/tx_execution/builtin_function_mocks/builtin_func_trait.rs @@ -25,13 +25,16 @@ pub trait BuiltinFunction { ) } - fn execute_lambda( + fn execute_lambda( &self, vm: &BlockchainVMRef, tx_input: TxInput, tx_cache: TxCache, - _f: Box, - ) -> (TxResult, BlockchainUpdate) { + _f: F, + ) -> (TxResult, BlockchainUpdate) + where + F: FnOnce(), + { self.execute(vm, tx_input, tx_cache) } } diff --git a/vm/src/tx_execution/builtin_function_mocks/general/upgrade_contract.rs b/vm/src/tx_execution/builtin_function_mocks/general/upgrade_contract.rs index fbe6446185..3c8f9ea7f1 100644 --- a/vm/src/tx_execution/builtin_function_mocks/general/upgrade_contract.rs +++ b/vm/src/tx_execution/builtin_function_mocks/general/upgrade_contract.rs @@ -11,13 +11,16 @@ impl BuiltinFunction for UpgradeContract { UPGRADE_CONTRACT_FUNC_NAME } - fn execute_lambda( + fn execute_lambda( &self, vm: &BlockchainVMRef, tx_input: TxInput, tx_cache: TxCache, - f: Box, - ) -> (TxResult, BlockchainUpdate) { + f: F, + ) -> (TxResult, BlockchainUpdate) + where + F: FnOnce(), + { if tx_input.args.len() < 2 { return ( TxResult::from_vm_error("upgradeContract expects at least 2 arguments"), diff --git a/vm/src/tx_execution/builtin_function_mocks/transfer/esdt_multi_transfer_mock.rs b/vm/src/tx_execution/builtin_function_mocks/transfer/esdt_multi_transfer_mock.rs index 91df49058c..46250897a4 100644 --- a/vm/src/tx_execution/builtin_function_mocks/transfer/esdt_multi_transfer_mock.rs +++ b/vm/src/tx_execution/builtin_function_mocks/transfer/esdt_multi_transfer_mock.rs @@ -32,13 +32,16 @@ impl BuiltinFunction for ESDTMultiTransfer { } } - fn execute_lambda( + fn execute_lambda( &self, vm: &BlockchainVMRef, tx_input: TxInput, tx_cache: TxCache, - f: Box, - ) -> (TxResult, BlockchainUpdate) { + f: F, + ) -> (TxResult, BlockchainUpdate) + where + F: FnOnce(), + { match try_parse_input(&tx_input) { Ok(parsed_tx) => { execute_transfer_builtin_func(vm, parsed_tx, self.name(), tx_input, tx_cache, f) diff --git a/vm/src/tx_execution/builtin_function_mocks/transfer/esdt_nft_transfer_mock.rs b/vm/src/tx_execution/builtin_function_mocks/transfer/esdt_nft_transfer_mock.rs index 5455813bb0..e0fdd2b678 100644 --- a/vm/src/tx_execution/builtin_function_mocks/transfer/esdt_nft_transfer_mock.rs +++ b/vm/src/tx_execution/builtin_function_mocks/transfer/esdt_nft_transfer_mock.rs @@ -30,13 +30,16 @@ impl BuiltinFunction for ESDTNftTransfer { } } - fn execute_lambda( + fn execute_lambda( &self, vm: &BlockchainVMRef, tx_input: TxInput, tx_cache: TxCache, - f: Box, - ) -> (TxResult, BlockchainUpdate) { + f: F, + ) -> (TxResult, BlockchainUpdate) + where + F: FnOnce(), + { match try_parse_input(&tx_input) { Ok(parsed_tx) => { execute_transfer_builtin_func(vm, parsed_tx, self.name(), tx_input, tx_cache, f) diff --git a/vm/src/tx_execution/builtin_function_mocks/transfer/esdt_transfer_mock.rs b/vm/src/tx_execution/builtin_function_mocks/transfer/esdt_transfer_mock.rs index d8990140f5..4fef98f60f 100644 --- a/vm/src/tx_execution/builtin_function_mocks/transfer/esdt_transfer_mock.rs +++ b/vm/src/tx_execution/builtin_function_mocks/transfer/esdt_transfer_mock.rs @@ -29,13 +29,16 @@ impl BuiltinFunction for ESDTTransfer { } } - fn execute_lambda( + fn execute_lambda( &self, vm: &BlockchainVMRef, tx_input: TxInput, tx_cache: TxCache, - f: Box, - ) -> (TxResult, BlockchainUpdate) { + f: F, + ) -> (TxResult, BlockchainUpdate) + where + F: FnOnce(), + { match try_parse_input(&tx_input) { Ok(parsed_tx) => { execute_transfer_builtin_func(vm, parsed_tx, self.name(), tx_input, tx_cache, f) diff --git a/vm/src/tx_execution/builtin_function_mocks/transfer/transfer_common.rs b/vm/src/tx_execution/builtin_function_mocks/transfer/transfer_common.rs index 0d1c729daa..089ca8e18e 100644 --- a/vm/src/tx_execution/builtin_function_mocks/transfer/transfer_common.rs +++ b/vm/src/tx_execution/builtin_function_mocks/transfer/transfer_common.rs @@ -48,14 +48,17 @@ pub(super) fn extract_transfer_info( } } -pub(super) fn execute_transfer_builtin_func( +pub(super) fn execute_transfer_builtin_func( vm: &BlockchainVMRef, parsed_tx: ParsedTransferBuiltinFunCall, builtin_function_name: &str, tx_input: TxInput, tx_cache: TxCache, - f: Box, -) -> (TxResult, BlockchainUpdate) { + f: F, +) -> (TxResult, BlockchainUpdate) +where + F: FnOnce(), +{ let mut builtin_logs = Vec::new(); for raw_esdt_transfer in &parsed_tx.raw_esdt_transfers { builtin_logs.push(TxLog { diff --git a/vm/src/tx_execution/exec_call.rs b/vm/src/tx_execution/exec_call.rs index 13ffc3afbb..d7777497dd 100644 --- a/vm/src/tx_execution/exec_call.rs +++ b/vm/src/tx_execution/exec_call.rs @@ -66,13 +66,15 @@ impl BlockchainVMRef { f: F, ) -> (TxResult, BlockchainUpdate) where - F: FnOnce() + 'static, + F: FnOnce(), { - if let Some(builtin_func) = self.builtin_functions.get(&tx_input.func_name) { - builtin_func.execute_lambda(self, tx_input, tx_cache, Box::new(f)) - } else { - self.default_execution(tx_input, tx_cache, f) - } + self.builtin_functions.execute_builtin_function_or_else( + self, + tx_input, + tx_cache, + f, + |tx_input, tx_cache, f| self.default_execution(tx_input, tx_cache, f), + ) } pub fn execute_sc_call_lambda( @@ -82,7 +84,7 @@ impl BlockchainVMRef { f: F, ) -> TxResult where - F: FnOnce() + 'static, + F: FnOnce(), { state.subtract_tx_gas(&tx_input.from, tx_input.gas_limit, tx_input.gas_price); @@ -144,7 +146,7 @@ impl BlockchainVMRef { f: F, ) -> TxResult where - F: FnOnce() + 'static, + F: FnOnce(), { // main call let contract_address = tx_input.to.clone(); diff --git a/vm/src/tx_mock/tx_async_call_data.rs b/vm/src/tx_mock/tx_async_call_data.rs index 4ee37cdc7c..2a7e0af46e 100644 --- a/vm/src/tx_mock/tx_async_call_data.rs +++ b/vm/src/tx_mock/tx_async_call_data.rs @@ -1,5 +1,5 @@ use crate::{ - tx_execution::BuiltinFunctionMap, + tx_execution::BuiltinFunctionContainer, tx_mock::{TxInput, TxResult}, types::{top_encode_u64, VMAddress, H256}, }; @@ -44,7 +44,7 @@ fn result_status_bytes(result_status: u64) -> Vec { pub fn async_callback_tx_input( async_data: &AsyncCallTxData, async_result: &TxResult, - builtin_functions: &BuiltinFunctionMap, + builtin_functions: &BuiltinFunctionContainer, ) -> TxInput { let mut args: Vec> = vec![result_status_bytes(async_result.result_status)]; if async_result.result_status == 0 { @@ -72,7 +72,7 @@ pub fn async_callback_tx_input( fn extract_callback_payments( callback_contract_address: &VMAddress, async_result: &TxResult, - builtin_functions: &BuiltinFunctionMap, + builtin_functions: &BuiltinFunctionContainer, ) -> CallbackPayments { let mut callback_payments = CallbackPayments::default(); for async_call in &async_result.all_calls { diff --git a/vm/src/types/vm_esdt_local_role.rs b/vm/src/types/vm_esdt_local_role.rs index eb6cd0c565..40c383b869 100644 --- a/vm/src/types/vm_esdt_local_role.rs +++ b/vm/src/types/vm_esdt_local_role.rs @@ -1,14 +1,14 @@ use super::EsdtLocalRoleFlags; -static ESDT_ROLE_NONE: &[u8] = &[]; -static ESDT_ROLE_LOCAL_MINT: &[u8] = b"ESDTRoleLocalMint"; -static ESDT_ROLE_LOCAL_BURN: &[u8] = b"ESDTRoleLocalBurn"; -static ESDT_ROLE_NFT_CREATE: &[u8] = b"ESDTRoleNFTCreate"; -static ESDT_ROLE_NFT_ADD_QUANTITY: &[u8] = b"ESDTRoleNFTAddQuantity"; -static ESDT_ROLE_NFT_BURN: &[u8] = b"ESDTRoleNFTBurn"; -static ESDT_ROLE_NFT_ADD_URI: &[u8] = b"ESDTRoleNFTAddURI"; -static ESDT_ROLE_NFT_UPDATE_ATTRIBUTES: &[u8] = b"ESDTRoleNFTUpdateAttributes"; -static ESDT_ROLE_TRANSFER: &[u8] = b"ESDTTransferRole"; +const ESDT_ROLE_NONE: &str = ""; +const ESDT_ROLE_LOCAL_MINT: &str = "ESDTRoleLocalMint"; +const ESDT_ROLE_LOCAL_BURN: &str = "ESDTRoleLocalBurn"; +const ESDT_ROLE_NFT_CREATE: &str = "ESDTRoleNFTCreate"; +const ESDT_ROLE_NFT_ADD_QUANTITY: &str = "ESDTRoleNFTAddQuantity"; +const ESDT_ROLE_NFT_BURN: &str = "ESDTRoleNFTBurn"; +const ESDT_ROLE_NFT_ADD_URI: &str = "ESDTRoleNFTAddURI"; +const ESDT_ROLE_NFT_UPDATE_ATTRIBUTES: &str = "ESDTRoleNFTUpdateAttributes"; +const ESDT_ROLE_TRANSFER: &str = "ESDTTransferRole"; /// The VM implementation for EsdtLocalRole, used internally in builtin functions. /// @@ -43,7 +43,7 @@ impl EsdtLocalRole { } } - pub fn as_role_name(&self) -> &'static [u8] { + pub fn name(&self) -> &'static str { match self { Self::None => ESDT_ROLE_NONE, Self::Mint => ESDT_ROLE_LOCAL_MINT, @@ -111,21 +111,21 @@ impl From for EsdtLocalRole { impl<'a> From<&'a [u8]> for EsdtLocalRole { #[inline] fn from(byte_slice: &'a [u8]) -> Self { - if byte_slice == ESDT_ROLE_LOCAL_MINT { + if byte_slice == ESDT_ROLE_LOCAL_MINT.as_bytes() { Self::Mint - } else if byte_slice == ESDT_ROLE_LOCAL_BURN { + } else if byte_slice == ESDT_ROLE_LOCAL_BURN.as_bytes() { Self::Burn - } else if byte_slice == ESDT_ROLE_NFT_CREATE { + } else if byte_slice == ESDT_ROLE_NFT_CREATE.as_bytes() { Self::NftCreate - } else if byte_slice == ESDT_ROLE_NFT_ADD_QUANTITY { + } else if byte_slice == ESDT_ROLE_NFT_ADD_QUANTITY.as_bytes() { Self::NftAddQuantity - } else if byte_slice == ESDT_ROLE_NFT_BURN { + } else if byte_slice == ESDT_ROLE_NFT_BURN.as_bytes() { Self::NftBurn - } else if byte_slice == ESDT_ROLE_NFT_ADD_URI { + } else if byte_slice == ESDT_ROLE_NFT_ADD_URI.as_bytes() { Self::NftAddUri - } else if byte_slice == ESDT_ROLE_NFT_UPDATE_ATTRIBUTES { + } else if byte_slice == ESDT_ROLE_NFT_UPDATE_ATTRIBUTES.as_bytes() { Self::NftUpdateAttributes - } else if byte_slice == ESDT_ROLE_TRANSFER { + } else if byte_slice == ESDT_ROLE_TRANSFER.as_bytes() { Self::Transfer } else { Self::None