Skip to content

Commit f5f852c

Browse files
Merge pull request #1936 from multiversx/rc/v0.56
Release candidate: v0.56
2 parents 8c0f461 + cd4d252 commit f5f852c

29 files changed

+939
-143
lines changed

chain/core/src/types/flags/esdt_local_role.rs

Lines changed: 30 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,10 @@ const ESDT_ROLE_NFT_ADD_QUANTITY: &str = "ESDTRoleNFTAddQuantity";
1212
const ESDT_ROLE_NFT_BURN: &str = "ESDTRoleNFTBurn";
1313
const ESDT_ROLE_NFT_ADD_URI: &str = "ESDTRoleNFTAddURI";
1414
const ESDT_ROLE_NFT_UPDATE_ATTRIBUTES: &str = "ESDTRoleNFTUpdateAttributes";
15-
const ESDT_ROLE_TRANSFER: &str = "ESDTTransferRole";
1615
const ESDT_ROLE_SET_NEW_URI: &str = "ESDTRoleSetNewURI";
1716
const ESDT_ROLE_MODIFY_ROYALTIES: &str = "ESDTRoleModifyRoyalties";
1817
const ESDT_ROLE_MODIFY_CREATOR: &str = "ESDTRoleModifyCreator";
1918
const ESDT_ROLE_NFT_RECREATE: &str = "ESDTRoleNFTRecreate";
20-
const ESDT_ROLE_NFT_UPDATE: &str = "ESDTRoleNFTUpdate";
2119

2220
#[derive(TopDecode, TopEncode, NestedDecode, NestedEncode, Clone, PartialEq, Eq, Debug, Copy)]
2321
pub enum EsdtLocalRole {
@@ -27,14 +25,12 @@ pub enum EsdtLocalRole {
2725
NftCreate,
2826
NftAddQuantity,
2927
NftBurn,
30-
NftAddUri,
3128
NftUpdateAttributes,
32-
Transfer,
33-
SetNewUri,
29+
NftAddUri,
30+
NftRecreate,
3431
ModifyRoyalties,
3532
ModifyCreator,
36-
NftRecreate,
37-
NftUpdate,
33+
SetNewUri,
3834
}
3935

4036
impl EsdtLocalRole {
@@ -46,14 +42,12 @@ impl EsdtLocalRole {
4642
Self::NftCreate => 3,
4743
Self::NftAddQuantity => 4,
4844
Self::NftBurn => 5,
49-
Self::NftAddUri => 6,
50-
Self::NftUpdateAttributes => 7,
51-
Self::Transfer => 8,
52-
Self::SetNewUri => 9,
45+
Self::NftUpdateAttributes => 6,
46+
Self::NftAddUri => 7,
47+
Self::NftRecreate => 8,
48+
Self::ModifyCreator => 9,
5349
Self::ModifyRoyalties => 10,
54-
Self::ModifyCreator => 11,
55-
Self::NftRecreate => 12,
56-
Self::NftUpdate => 13,
50+
Self::SetNewUri => 11,
5751
}
5852
}
5953

@@ -69,14 +63,12 @@ impl EsdtLocalRole {
6963
Self::NftCreate => ESDT_ROLE_NFT_CREATE,
7064
Self::NftAddQuantity => ESDT_ROLE_NFT_ADD_QUANTITY,
7165
Self::NftBurn => ESDT_ROLE_NFT_BURN,
72-
Self::NftAddUri => ESDT_ROLE_NFT_ADD_URI,
7366
Self::NftUpdateAttributes => ESDT_ROLE_NFT_UPDATE_ATTRIBUTES,
74-
Self::Transfer => ESDT_ROLE_TRANSFER,
75-
Self::SetNewUri => ESDT_ROLE_SET_NEW_URI,
67+
Self::NftAddUri => ESDT_ROLE_NFT_ADD_URI,
68+
Self::NftRecreate => ESDT_ROLE_NFT_RECREATE,
7669
Self::ModifyRoyalties => ESDT_ROLE_MODIFY_ROYALTIES,
7770
Self::ModifyCreator => ESDT_ROLE_MODIFY_CREATOR,
78-
Self::NftRecreate => ESDT_ROLE_NFT_RECREATE,
79-
Self::NftUpdate => ESDT_ROLE_NFT_UPDATE,
71+
Self::SetNewUri => ESDT_ROLE_SET_NEW_URI,
8072
}
8173
}
8274

@@ -88,34 +80,30 @@ impl EsdtLocalRole {
8880
Self::NftCreate => EsdtLocalRoleFlags::NFT_CREATE,
8981
Self::NftAddQuantity => EsdtLocalRoleFlags::NFT_ADD_QUANTITY,
9082
Self::NftBurn => EsdtLocalRoleFlags::NFT_BURN,
91-
Self::NftAddUri => EsdtLocalRoleFlags::NFT_ADD_URI,
9283
Self::NftUpdateAttributes => EsdtLocalRoleFlags::NFT_UPDATE_ATTRIBUTES,
93-
Self::Transfer => EsdtLocalRoleFlags::TRANSFER,
94-
Self::SetNewUri => EsdtLocalRoleFlags::SET_NEW_URI,
84+
Self::NftAddUri => EsdtLocalRoleFlags::NFT_ADD_URI,
85+
Self::NftRecreate => EsdtLocalRoleFlags::NFT_RECREATE,
9586
Self::ModifyRoyalties => EsdtLocalRoleFlags::MODIFY_ROYALTIES,
9687
Self::ModifyCreator => EsdtLocalRoleFlags::MODIFY_CREATOR,
97-
Self::NftRecreate => EsdtLocalRoleFlags::NFT_RECREATE,
98-
Self::NftUpdate => EsdtLocalRoleFlags::NFT_UPDATE,
88+
Self::SetNewUri => EsdtLocalRoleFlags::SET_NEW_URI,
9989
}
10090
}
10191
}
10292

10393
// TODO: can be done with macros, but I didn't find a public library that does it and is no_std
10494
// we can implement it, it's easy
105-
const ALL_ROLES: [EsdtLocalRole; 13] = [
95+
const ALL_ROLES: [EsdtLocalRole; 11] = [
10696
EsdtLocalRole::Mint,
10797
EsdtLocalRole::Burn,
10898
EsdtLocalRole::NftCreate,
10999
EsdtLocalRole::NftAddQuantity,
110100
EsdtLocalRole::NftBurn,
111-
EsdtLocalRole::NftAddUri,
112101
EsdtLocalRole::NftUpdateAttributes,
113-
EsdtLocalRole::Transfer,
114-
EsdtLocalRole::SetNewUri,
102+
EsdtLocalRole::NftAddUri,
103+
EsdtLocalRole::NftRecreate,
115104
EsdtLocalRole::ModifyRoyalties,
116105
EsdtLocalRole::ModifyCreator,
117-
EsdtLocalRole::NftRecreate,
118-
EsdtLocalRole::NftUpdate,
106+
EsdtLocalRole::SetNewUri,
119107
];
120108

121109
impl EsdtLocalRole {
@@ -133,14 +121,12 @@ impl From<u16> for EsdtLocalRole {
133121
3 => Self::NftCreate,
134122
4 => Self::NftAddQuantity,
135123
5 => Self::NftBurn,
136-
6 => Self::NftAddUri,
137-
7 => Self::NftUpdateAttributes,
138-
8 => Self::Transfer,
139-
9 => Self::SetNewUri,
140-
10 => Self::ModifyRoyalties,
141-
11 => Self::ModifyCreator,
142-
12 => Self::NftRecreate,
143-
13 => Self::NftUpdate,
124+
6 => Self::NftUpdateAttributes,
125+
7 => Self::NftAddUri,
126+
8 => Self::NftRecreate,
127+
9 => Self::ModifyRoyalties,
128+
10 => Self::ModifyCreator,
129+
11 => Self::SetNewUri,
144130
_ => Self::None,
145131
}
146132
}
@@ -159,22 +145,18 @@ impl<'a> From<&'a [u8]> for EsdtLocalRole {
159145
Self::NftAddQuantity
160146
} else if byte_slice == ESDT_ROLE_NFT_BURN.as_bytes() {
161147
Self::NftBurn
162-
} else if byte_slice == ESDT_ROLE_NFT_ADD_URI.as_bytes() {
163-
Self::NftAddUri
164148
} else if byte_slice == ESDT_ROLE_NFT_UPDATE_ATTRIBUTES.as_bytes() {
165149
Self::NftUpdateAttributes
166-
} else if byte_slice == ESDT_ROLE_TRANSFER.as_bytes() {
167-
Self::Transfer
168-
} else if byte_slice == ESDT_ROLE_SET_NEW_URI.as_bytes() {
169-
Self::SetNewUri
150+
} else if byte_slice == ESDT_ROLE_NFT_ADD_URI.as_bytes() {
151+
Self::NftAddUri
152+
} else if byte_slice == ESDT_ROLE_NFT_RECREATE.as_bytes() {
153+
Self::NftRecreate
170154
} else if byte_slice == ESDT_ROLE_MODIFY_ROYALTIES.as_bytes() {
171155
Self::ModifyRoyalties
172156
} else if byte_slice == ESDT_ROLE_MODIFY_CREATOR.as_bytes() {
173157
Self::ModifyCreator
174-
} else if byte_slice == ESDT_ROLE_NFT_RECREATE.as_bytes() {
175-
Self::NftRecreate
176-
} else if byte_slice == ESDT_ROLE_NFT_UPDATE.as_bytes() {
177-
Self::NftUpdate
158+
} else if byte_slice == ESDT_ROLE_SET_NEW_URI.as_bytes() {
159+
Self::SetNewUri
178160
} else {
179161
Self::None
180162
}

chain/core/src/types/flags/esdt_local_role_flags.rs

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,21 @@
1-
#![allow(clippy::bad_bit_mask)]
2-
31
use super::EsdtLocalRole;
42
use bitflags::bitflags;
53

64
bitflags! {
75
#[derive(PartialEq, Clone, Copy)]
86
pub struct EsdtLocalRoleFlags: u64 {
9-
const NONE = 0b00000000;
10-
const MINT = 0b00000001;
11-
const BURN = 0b00000010;
12-
const NFT_CREATE = 0b00000100;
13-
const NFT_ADD_QUANTITY = 0b00001000;
14-
const NFT_BURN = 0b00010000;
15-
const NFT_ADD_URI = 0b00100000;
16-
const NFT_UPDATE_ATTRIBUTES = 0b01000000;
17-
const TRANSFER = 0b10000000;
18-
const SET_NEW_URI = 0b00000001_00000000;
7+
const NONE = 0b00000000_00000000;
8+
const MINT = 0b00000000_00000001;
9+
const BURN = 0b00000000_00000010;
10+
const NFT_CREATE = 0b00000000_00000100;
11+
const NFT_ADD_QUANTITY = 0b00000000_00001000;
12+
const NFT_BURN = 0b00000000_00010000;
13+
const NFT_UPDATE_ATTRIBUTES = 0b00000000_00100000;
14+
const NFT_ADD_URI = 0b00000000_01000000;
15+
const NFT_RECREATE = 0b00000000_10000000;
16+
const MODIFY_CREATOR = 0b00000001_00000000;
1917
const MODIFY_ROYALTIES = 0b00000010_00000000;
20-
const MODIFY_CREATOR = 0b00000100_00000000;
21-
const NFT_RECREATE = 0b00001000_00000000;
22-
const NFT_UPDATE = 0b00010000_00000000;
18+
const SET_NEW_URI = 0b00000100_00000000;
2319
}
2420
}
2521

chain/vm/src/tx_mock/tx_input.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pub struct TxInput {
1818
pub func_name: TxFunctionName,
1919
pub args: Vec<Vec<u8>>,
2020
pub call_type: CallType,
21+
pub readonly: bool, // should probably be in TxContext, but it is easier to keep it here, for now
2122
pub gas_limit: u64,
2223
pub gas_price: u64,
2324
pub tx_hash: H256,
@@ -35,6 +36,7 @@ impl Default for TxInput {
3536
func_name: TxFunctionName::EMPTY,
3637
args: Vec::new(),
3738
call_type: CallType::DirectCall,
39+
readonly: false,
3840
gas_limit: 0,
3941
gas_price: 0,
4042
tx_hash: H256::zero(),

chain/vm/src/vm_err_msg.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ pub const EXPONENT_IS_POSITIVE: &str = "exponent must be negative";
99
pub const NUMBER_IS_NOT_NORMAL: &str =
1010
"number is not normal. It is either infinite, NaN or subnormal";
1111
pub const CANNOT_COMPARE_VALUES: &str = "values are not comparable";
12+
pub const WRITE_RESERVED: &str = "cannot write to storage under reserved key";
13+
pub const WRITE_READONLY: &str = "cannot write on read only mode";
1214

1315
pub const ERROR_SIGNALLED_BY_SMARTCONTRACT: &str = "error signalled by smartcontract";
1416

chain/vm/src/vm_hooks/vh_dispatcher.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -848,7 +848,14 @@ impl VMHooks for VMHooksDispatcher {
848848
arguments_handle: i32,
849849
result_handle: i32,
850850
) -> i32 {
851-
panic!("Unavailable: managed_execute_read_only")
851+
self.handler.execute_on_dest_context_readonly_raw(
852+
gas as u64,
853+
address_handle,
854+
function_handle,
855+
arguments_handle,
856+
result_handle,
857+
);
858+
0
852859
}
853860

854861
fn managed_execute_on_same_context(

chain/vm/src/vm_hooks/vh_handler/vh_send.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,26 @@ pub trait VMHooksSend: VMHooksHandlerSource {
375375
.mb_set_vec_of_bytes(result_handle, result);
376376
}
377377

378+
fn execute_on_dest_context_readonly_raw(
379+
&self,
380+
_gas: u64,
381+
to_handle: RawHandle,
382+
endpoint_name_handle: RawHandle,
383+
arg_buffer_handle: RawHandle,
384+
result_handle: RawHandle,
385+
) {
386+
let to = self.m_types_lock().mb_to_address(to_handle);
387+
let endpoint_name = self
388+
.m_types_lock()
389+
.mb_to_function_name(endpoint_name_handle);
390+
let arg_buffer = self.m_types_lock().mb_get_vec_of_bytes(arg_buffer_handle);
391+
392+
let result = self.perform_execute_on_dest_context_readonly(to, endpoint_name, arg_buffer);
393+
394+
self.m_types_lock()
395+
.mb_set_vec_of_bytes(result_handle, result);
396+
}
397+
378398
fn clean_return_data(&self) {
379399
let mut tx_result = self.result_lock();
380400
tx_result.result_values.clear();

chain/vm/src/vm_hooks/vh_impl/vh_debug_api.rs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use std::sync::{Arc, MutexGuard};
22

33
use multiversx_chain_core::types::ReturnCode;
44
use multiversx_chain_vm_executor::BreakpointValue;
5+
use num_bigint::BigUint;
6+
use num_traits::Zero;
57

68
use crate::{
79
tx_execution::execute_current_tx_context_input,
@@ -66,6 +68,7 @@ impl VMHooksHandlerSource for DebugApiVMHooksHandler {
6668

6769
fn storage_write(&self, key: &[u8], value: &[u8]) {
6870
self.check_reserved_key(key);
71+
self.check_not_readonly();
6972

7073
self.0.with_contract_account_mut(|account| {
7174
account.storage.insert(key.to_vec(), value.to_vec());
@@ -136,6 +139,31 @@ impl VMHooksHandlerSource for DebugApiVMHooksHandler {
136139
}
137140
}
138141

142+
fn perform_execute_on_dest_context_readonly(
143+
&self,
144+
to: VMAddress,
145+
func_name: TxFunctionName,
146+
arguments: Vec<Vec<u8>>,
147+
) -> Vec<Vec<u8>> {
148+
let async_call_data =
149+
self.create_async_call_data(to, BigUint::zero(), func_name, arguments);
150+
let mut tx_input = async_call_tx_input(&async_call_data, CallType::ExecuteOnDestContext);
151+
tx_input.readonly = true;
152+
let tx_cache = TxCache::new(self.0.blockchain_cache_arc());
153+
let (tx_result, blockchain_updates) = self.0.vm_ref.execute_builtin_function_or_default(
154+
tx_input,
155+
tx_cache,
156+
execute_current_tx_context_input,
157+
);
158+
159+
if tx_result.result_status.is_success() {
160+
self.sync_call_post_processing(tx_result, blockchain_updates)
161+
} else {
162+
// also kill current execution
163+
self.halt_with_error(tx_result.result_status, &tx_result.result_message)
164+
}
165+
}
166+
139167
fn perform_deploy(
140168
&self,
141169
egld_value: num_bigint::BigUint,
@@ -249,7 +277,14 @@ impl DebugApiVMHooksHandler {
249277

250278
fn check_reserved_key(&self, key: &[u8]) {
251279
if key.starts_with(STORAGE_RESERVED_PREFIX) {
252-
self.vm_error("cannot write to storage under reserved key");
280+
self.vm_error(vm_err_msg::WRITE_RESERVED);
281+
}
282+
}
283+
284+
/// TODO: only checked on storage writes, needs more checks for calls, transfers, etc.
285+
fn check_not_readonly(&self) {
286+
if self.0.input_ref().readonly {
287+
self.vm_error(vm_err_msg::WRITE_READONLY);
253288
}
254289
}
255290

chain/vm/src/vm_hooks/vh_impl/vh_single_tx_api.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,15 @@ impl VMHooksHandlerSource for SingleTxApiVMHooksHandler {
127127
panic!("cannot launch contract calls in the SingleTxApi")
128128
}
129129

130+
fn perform_execute_on_dest_context_readonly(
131+
&self,
132+
_to: VMAddress,
133+
_func_name: TxFunctionName,
134+
_arguments: Vec<Vec<u8>>,
135+
) -> Vec<Vec<u8>> {
136+
panic!("cannot launch contract calls in the SingleTxApi")
137+
}
138+
130139
fn perform_deploy(
131140
&self,
132141
_egld_value: num_bigint::BigUint,

chain/vm/src/vm_hooks/vh_impl/vh_static_api.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,15 @@ impl VMHooksHandlerSource for StaticApiVMHooksHandler {
102102
panic!("cannot launch contract calls in the StaticApi")
103103
}
104104

105+
fn perform_execute_on_dest_context_readonly(
106+
&self,
107+
_to: VMAddress,
108+
_func_name: TxFunctionName,
109+
_arguments: Vec<Vec<u8>>,
110+
) -> Vec<Vec<u8>> {
111+
panic!("cannot launch contract calls in the StaticApi")
112+
}
113+
105114
fn perform_deploy(
106115
&self,
107116
_egld_value: num_bigint::BigUint,

chain/vm/src/vm_hooks/vh_source.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,13 @@ pub trait VMHooksHandlerSource: Debug {
8282
args: Vec<Vec<u8>>,
8383
) -> Vec<Vec<u8>>;
8484

85+
fn perform_execute_on_dest_context_readonly(
86+
&self,
87+
to: VMAddress,
88+
func_name: TxFunctionName,
89+
arguments: Vec<Vec<u8>>,
90+
) -> Vec<Vec<u8>>;
91+
8592
fn perform_deploy(
8693
&self,
8794
egld_value: num_bigint::BigUint,

0 commit comments

Comments
 (0)