Skip to content

Commit 5dd344e

Browse files
Merge pull request #913 from multiversx/reserved-functions-activations-flags
add activation flags for barnard reserved functions and rename GetRou…
2 parents ac975aa + b10bb1d commit 5dd344e

File tree

19 files changed

+279
-113
lines changed

19 files changed

+279
-113
lines changed

executor/vmHooks.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

executor/wrapper/wrapperVMHooks.go

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mock/context/executorMockFunc.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Binary file not shown.

test/contracts/new-blockchain-hooks/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ fn panic(_info: &core::panic::PanicInfo) -> ! {
99
#[no_mangle]
1010
pub extern "C" fn test_round_time() {
1111
unsafe {
12-
let result = getRoundTime();
12+
let result = getBlockRoundTimeInMilliseconds();
1313
let result: [u8; 1] = [(result & 0xff) as u8];
1414
finish(result.as_ref().as_ptr(), 1);
1515
};
@@ -44,7 +44,7 @@ pub extern "C" fn test_epoch_start_block_round() {
4444

4545
extern {
4646
fn finish(data: *const u8, len: i32);
47-
fn getRoundTime() -> i64;
47+
fn getBlockRoundTimeInMilliseconds() -> i64;
4848
fn epochStartBlockTimeStamp() -> i64;
4949
fn epochStartBlockNonce() -> i64;
5050
fn epochStartBlockRound() -> i64;

vmhost/contexts/reservedFunctions.go

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,29 @@
11
package contexts
22

33
import (
4+
"github.com/multiversx/mx-chain-core-go/core"
45
vmcommon "github.com/multiversx/mx-chain-vm-common-go"
56
"github.com/multiversx/mx-chain-vm-go/vmhost"
67
)
78

89
// reservedFunctions holds the reserved function names
910
type reservedFunctions struct {
10-
functionNames vmcommon.FunctionNames
11+
epochsHandler vmcommon.EnableEpochsHandler
12+
functionNames vmcommon.FunctionNames
13+
functionActivationFlags map[string]core.EnableEpochFlag
1114
}
1215

1316
// NewReservedFunctions creates a new reservedFunctions
1417
func NewReservedFunctions(
1518
scAPINames vmcommon.FunctionNames,
1619
builtInFuncContainer vmcommon.BuiltInFunctionContainer,
20+
functionActivationFlags map[string]core.EnableEpochFlag,
21+
epochsHandler vmcommon.EnableEpochsHandler,
1722
) *reservedFunctions {
1823
result := &reservedFunctions{
19-
functionNames: make(vmcommon.FunctionNames),
24+
functionNames: make(vmcommon.FunctionNames),
25+
functionActivationFlags: functionActivationFlags,
26+
epochsHandler: epochsHandler,
2027
}
2128

2229
protocolFuncNames := builtInFuncContainer.Keys()
@@ -43,6 +50,14 @@ func NewReservedFunctions(
4350
// IsReserved returns whether a function is reserved
4451
func (reservedFunctions *reservedFunctions) IsReserved(functionName string) bool {
4552
if _, ok := reservedFunctions.functionNames[functionName]; ok {
53+
barnardOpcodesEnabled := reservedFunctions.epochsHandler.IsFlagEnabled(vmhost.BarnardOpcodesFlag)
54+
55+
if !barnardOpcodesEnabled {
56+
if flag, ok := reservedFunctions.functionActivationFlags[functionName]; ok {
57+
return reservedFunctions.epochsHandler.IsFlagEnabled(flag)
58+
}
59+
}
60+
4661
return true
4762
}
4863

@@ -53,8 +68,18 @@ func (reservedFunctions *reservedFunctions) IsReserved(functionName string) bool
5368
func (reservedFunctions *reservedFunctions) GetReserved() []string {
5469
keys := make([]string, len(reservedFunctions.functionNames))
5570

71+
barnardOpcodesEnabled := reservedFunctions.epochsHandler.IsFlagEnabled(vmhost.BarnardOpcodesFlag)
72+
5673
i := 0
5774
for key := range reservedFunctions.functionNames {
75+
if !barnardOpcodesEnabled {
76+
if flag, ok := reservedFunctions.functionActivationFlags[key]; ok {
77+
if !reservedFunctions.epochsHandler.IsFlagEnabled(flag) {
78+
continue
79+
}
80+
}
81+
}
82+
5883
keys[i] = key
5984
i++
6085
}

vmhost/contexts/reservedFunctions_test.go

Lines changed: 124 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package contexts
33
import (
44
"testing"
55

6+
"github.com/multiversx/mx-chain-core-go/core"
7+
"github.com/multiversx/mx-chain-scenario-go/worldmock"
68
vmcommon "github.com/multiversx/mx-chain-vm-common-go"
79
"github.com/multiversx/mx-chain-vm-common-go/builtInFunctions"
810
"github.com/multiversx/mx-chain-vm-go/vmhost"
@@ -12,16 +14,136 @@ import (
1214

1315
func TestReservedFunctions_IsFunctionReserved(t *testing.T) {
1416
scAPINames := vmcommon.FunctionNames{
15-
"rockets": {},
17+
"rockets": struct{}{},
1618
}
1719

1820
builtInFuncContainer := builtInFunctions.NewBuiltInFunctionContainer()
1921
_ = builtInFuncContainer.Add("protocolFunctionFoo", &mock.BuiltInFunctionStub{})
2022
_ = builtInFuncContainer.Add("protocolFunctionBar", &mock.BuiltInFunctionStub{})
2123

22-
reserved := NewReservedFunctions(scAPINames, builtInFuncContainer)
24+
enableEpochsHandler := worldmock.EnableEpochsHandlerStubAllFlags()
25+
26+
activationFlags := map[string]core.EnableEpochFlag{}
27+
28+
reserved := NewReservedFunctions(scAPINames, builtInFuncContainer, activationFlags, enableEpochsHandler)
29+
30+
require.False(t, reserved.IsReserved("foo"))
31+
require.True(t, reserved.IsReserved("rockets"))
32+
require.True(t, reserved.IsReserved("protocolFunctionFoo"))
33+
require.True(t, reserved.IsReserved("protocolFunctionBar"))
34+
require.True(t, reserved.IsReserved(vmhost.DeleteFunctionName))
35+
}
36+
37+
func TestReservedFunctions_IsFunctionReserved_WithBarnardOpcodesFlag(t *testing.T) {
38+
scAPINames := vmcommon.FunctionNames{
39+
"rockets": struct{}{},
40+
"paper": struct{}{},
41+
}
42+
43+
builtInFuncContainer := builtInFunctions.NewBuiltInFunctionContainer()
44+
_ = builtInFuncContainer.Add("protocolFunctionFoo", &mock.BuiltInFunctionStub{})
45+
_ = builtInFuncContainer.Add("protocolFunctionBar", &mock.BuiltInFunctionStub{})
46+
47+
paperFlag := core.EnableEpochFlag("paper_flag")
48+
49+
activationFlags := map[string]core.EnableEpochFlag{
50+
"paper": paperFlag,
51+
}
52+
53+
enableEpochsHandler := worldmock.EnableEpochsHandlerStubAllFlags()
54+
enableEpochsHandler.IsFlagEnabledCalled = func(flag core.EnableEpochFlag) bool {
55+
if flag == vmhost.BarnardOpcodesFlag {
56+
return true
57+
}
58+
59+
if flag == paperFlag {
60+
return false
61+
}
62+
63+
return true
64+
}
65+
66+
reserved := NewReservedFunctions(scAPINames, builtInFuncContainer, activationFlags, enableEpochsHandler)
67+
68+
require.False(t, reserved.IsReserved("foo"))
69+
require.True(t, reserved.IsReserved("paper"))
70+
require.True(t, reserved.IsReserved("rockets"))
71+
require.True(t, reserved.IsReserved("protocolFunctionFoo"))
72+
require.True(t, reserved.IsReserved("protocolFunctionBar"))
73+
require.True(t, reserved.IsReserved(vmhost.DeleteFunctionName))
74+
75+
enableEpochsHandler.IsFlagEnabledCalled = func(flag core.EnableEpochFlag) bool {
76+
if flag == vmhost.BarnardOpcodesFlag {
77+
return true
78+
}
79+
80+
if flag == paperFlag {
81+
return true
82+
}
83+
84+
return true
85+
}
86+
87+
require.False(t, reserved.IsReserved("foo"))
88+
require.True(t, reserved.IsReserved("paper"))
89+
require.True(t, reserved.IsReserved("rockets"))
90+
require.True(t, reserved.IsReserved("protocolFunctionFoo"))
91+
require.True(t, reserved.IsReserved("protocolFunctionBar"))
92+
require.True(t, reserved.IsReserved(vmhost.DeleteFunctionName))
93+
}
94+
95+
func TestReservedFunctions_IsFunctionReserved_WithBarnardOpcodesFlag_Disabled(t *testing.T) {
96+
scAPINames := vmcommon.FunctionNames{
97+
"rockets": struct{}{},
98+
"paper": struct{}{},
99+
}
100+
101+
builtInFuncContainer := builtInFunctions.NewBuiltInFunctionContainer()
102+
_ = builtInFuncContainer.Add("protocolFunctionFoo", &mock.BuiltInFunctionStub{})
103+
_ = builtInFuncContainer.Add("protocolFunctionBar", &mock.BuiltInFunctionStub{})
104+
105+
paperFlag := core.EnableEpochFlag("paper_flag")
106+
107+
activationFlags := map[string]core.EnableEpochFlag{
108+
"paper": paperFlag,
109+
}
110+
111+
enableEpochsHandler := worldmock.EnableEpochsHandlerStubAllFlags()
112+
enableEpochsHandler.IsFlagEnabledCalled = func(flag core.EnableEpochFlag) bool {
113+
if flag == vmhost.BarnardOpcodesFlag {
114+
return false
115+
}
116+
117+
if flag == paperFlag {
118+
return false
119+
}
120+
121+
return true
122+
}
123+
124+
reserved := NewReservedFunctions(scAPINames, builtInFuncContainer, activationFlags, enableEpochsHandler)
125+
126+
require.False(t, reserved.IsReserved("foo"))
127+
require.False(t, reserved.IsReserved("paper"))
128+
require.True(t, reserved.IsReserved("rockets"))
129+
require.True(t, reserved.IsReserved("protocolFunctionFoo"))
130+
require.True(t, reserved.IsReserved("protocolFunctionBar"))
131+
require.True(t, reserved.IsReserved(vmhost.DeleteFunctionName))
132+
133+
enableEpochsHandler.IsFlagEnabledCalled = func(flag core.EnableEpochFlag) bool {
134+
if flag == vmhost.BarnardOpcodesFlag {
135+
return false
136+
}
137+
138+
if flag == paperFlag {
139+
return true
140+
}
141+
142+
return true
143+
}
23144

24145
require.False(t, reserved.IsReserved("foo"))
146+
require.True(t, reserved.IsReserved("paper"))
25147
require.True(t, reserved.IsReserved("rockets"))
26148
require.True(t, reserved.IsReserved("protocolFunctionFoo"))
27149
require.True(t, reserved.IsReserved("protocolFunctionBar"))

vmhost/contexts/runtime.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ var mapBarnardOpcodes = map[string]struct{}{
3232
"mbufferToSmallIntSigned": {},
3333
"mbufferFromSmallIntUnsigned": {},
3434
"mbufferFromSmallIntSigned": {},
35-
"getRoundTime": {},
35+
"getBlockRoundTimeInMilliseconds": {},
3636
"epochStartBlockTimeStamp": {},
3737
"epochStartBlockNonce": {},
3838
"epochStartBlockRound": {},
@@ -92,12 +92,13 @@ func NewRuntimeContext(
9292
}
9393

9494
scAPINames := vmExecutor.FunctionNames()
95+
enableEpochsHandler := host.EnableEpochsHandler()
9596

9697
context := &runtimeContext{
9798
host: host,
9899
vmType: vmType,
99100
stateStack: make([]*runtimeContext, 0),
100-
validator: newWASMValidator(scAPINames, builtInFuncContainer),
101+
validator: newWASMValidator(scAPINames, builtInFuncContainer, enableEpochsHandler),
101102
hasher: hasher,
102103
errors: nil,
103104
}

vmhost/contexts/validator.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,30 @@ import (
44
"fmt"
55
"strings"
66

7+
"github.com/multiversx/mx-chain-core-go/core"
78
vmcommon "github.com/multiversx/mx-chain-vm-common-go"
89
"github.com/multiversx/mx-chain-vm-go/executor"
910
"github.com/multiversx/mx-chain-vm-go/vmhost"
1011
)
1112

1213
const allowedCharsInFunctionName = "abcdefghijklmnopqrstuvwxyz0123456789_"
1314

15+
var reservedFunctionsActivationFlag = map[string]core.EnableEpochFlag{
16+
"mbufferToSmallIntUnsigned": vmhost.BarnardOpcodesFlag,
17+
"mbufferToSmallIntSigned": vmhost.BarnardOpcodesFlag,
18+
"mbufferFromSmallIntUnsigned": vmhost.BarnardOpcodesFlag,
19+
"mbufferFromSmallIntSigned": vmhost.BarnardOpcodesFlag,
20+
"getBlockRoundTimeInMilliseconds": vmhost.BarnardOpcodesFlag,
21+
"epochStartBlockTimeStamp": vmhost.BarnardOpcodesFlag,
22+
"epochStartBlockNonce": vmhost.BarnardOpcodesFlag,
23+
"epochStartBlockRound": vmhost.BarnardOpcodesFlag,
24+
"managedGetAllTransfersCallValue": vmhost.BarnardOpcodesFlag,
25+
"managedExecuteOnDestContextWithErrorReturn": vmhost.BarnardOpcodesFlag,
26+
"managedMultiTransferESDTNFTExecuteWithReturn": vmhost.BarnardOpcodesFlag,
27+
"managedGetCodeHash": vmhost.BarnardOpcodesFlag,
28+
"managedGetESDTTokenType": vmhost.BarnardOpcodesFlag,
29+
}
30+
1431
// wasmValidator is a validator for WASM SmartContracts
1532
type wasmValidator struct {
1633
reserved *reservedFunctions
@@ -20,9 +37,10 @@ type wasmValidator struct {
2037
func newWASMValidator(
2138
scAPINames vmcommon.FunctionNames,
2239
builtInFuncContainer vmcommon.BuiltInFunctionContainer,
40+
enableEpochsHandler vmcommon.EnableEpochsHandler,
2341
) *wasmValidator {
2442
return &wasmValidator{
25-
reserved: NewReservedFunctions(scAPINames, builtInFuncContainer),
43+
reserved: NewReservedFunctions(scAPINames, builtInFuncContainer, reservedFunctionsActivationFlag, enableEpochsHandler),
2644
}
2745
}
2846

vmhost/contexts/validator_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ func TestFunctionsGuard_isValidFunctionName(t *testing.T) {
2525
_ = builtInFuncContainer.Add("protocolFunctionFoo", &mock.BuiltInFunctionStub{})
2626
_ = builtInFuncContainer.Add("protocolFunctionBar", &mock.BuiltInFunctionStub{})
2727

28-
validator := newWASMValidator(testImportNames(), builtInFuncContainer)
28+
validator := newWASMValidator(testImportNames(), builtInFuncContainer, worldmock.EnableEpochsHandlerStubAllFlags())
2929

3030
require.Nil(t, validator.verifyValidFunctionName("foo"))
3131
require.Nil(t, validator.verifyValidFunctionName("_"))
@@ -55,7 +55,7 @@ func TestFunctionsGuard_isValidFunctionName(t *testing.T) {
5555
func TestFunctionsProtected(t *testing.T) {
5656
host := InitializeVMAndWasmer()
5757

58-
validator := newWASMValidator(testImportNames(), builtInFunctions.NewBuiltInFunctionContainer())
58+
validator := newWASMValidator(testImportNames(), builtInFunctions.NewBuiltInFunctionContainer(), worldmock.EnableEpochsHandlerStubAllFlags())
5959

6060
world := worldmock.NewMockWorld()
6161
imb := contextmock.NewExecutorMock(world)

0 commit comments

Comments
 (0)