diff --git a/config/config.toml b/config/config.toml index 6f082932f..ea07b524c 100644 --- a/config/config.toml +++ b/config/config.toml @@ -57,6 +57,7 @@ DeleteFromReturnData = 10 GetCodeMetadata = 10 IsBuiltinFunction = 10 + IsReservedFunctionName = 10 [EthAPICost] UseGas = 10 diff --git a/config/gasCost.go b/config/gasCost.go index fbc262cad..2682e4af0 100644 --- a/config/gasCost.go +++ b/config/gasCost.go @@ -82,6 +82,7 @@ type BaseOpsAPICost struct { DeleteFromReturnData uint64 GetCodeMetadata uint64 IsBuiltinFunction uint64 + IsReservedFunctionName uint64 } // DynamicStorageLoadCostCoefficients holds the signed coefficients of the func that will compute the gas cost diff --git a/config/gasSchedule.go b/config/gasSchedule.go index b7d585e9f..30dc4c3a8 100644 --- a/config/gasSchedule.go +++ b/config/gasSchedule.go @@ -313,6 +313,7 @@ func FillGasMapBaseOpsAPICosts(value, asyncCallbackGasLock uint64) map[string]ui gasMap["DeleteFromReturnData"] = value gasMap["GetCodeMetadata"] = value gasMap["IsBuiltinFunction"] = value + gasMap["IsReservedFunctionName"] = value return gasMap } diff --git a/executor/vmHooks.go b/executor/vmHooks.go index e2324f4be..35cc52b42 100644 --- a/executor/vmHooks.go +++ b/executor/vmHooks.go @@ -72,6 +72,7 @@ type MainVMHooks interface { GetNumESDTTransfers() int32 GetCallValueTokenName(callValueOffset MemPtr, tokenNameOffset MemPtr) int32 GetCallValueTokenNameByIndex(callValueOffset MemPtr, tokenNameOffset MemPtr, index int32) int32 + IsReservedFunctionName(nameHandle int32) int32 WriteLog(dataPointer MemPtr, dataLength MemLength, topicPtr MemPtr, numTopics int32) WriteEventLog(numTopics int32, topicLengthsOffset MemPtr, topicOffset MemPtr, dataOffset MemPtr, dataLength MemLength) GetBlockTimestamp() int64 diff --git a/executor/wrapper/wrapperVMHooks.go b/executor/wrapper/wrapperVMHooks.go index 9148420e2..595cf7351 100644 --- a/executor/wrapper/wrapperVMHooks.go +++ b/executor/wrapper/wrapperVMHooks.go @@ -485,6 +485,15 @@ func (w *WrapperVMHooks) GetCallValueTokenNameByIndex(callValueOffset executor.M return result } +// IsReservedFunctionName VM hook wrapper +func (w *WrapperVMHooks) IsReservedFunctionName(nameHandle int32) int32 { + callInfo := fmt.Sprintf("IsReservedFunctionName(%d)", nameHandle) + w.logger.LogVMHookCallBefore(callInfo) + result := w.wrappedVMHooks.IsReservedFunctionName(nameHandle) + w.logger.LogVMHookCallAfter(callInfo) + return result +} + // WriteLog VM hook wrapper func (w *WrapperVMHooks) WriteLog(dataPointer executor.MemPtr, dataLength executor.MemLength, topicPtr executor.MemPtr, numTopics int32) { callInfo := fmt.Sprintf("WriteLog(%d, %d, %d, %d)", dataPointer, dataLength, topicPtr, numTopics) diff --git a/mock/context/executorMockFunc.go b/mock/context/executorMockFunc.go index 5aba34672..fbe383f7b 100644 --- a/mock/context/executorMockFunc.go +++ b/mock/context/executorMockFunc.go @@ -62,6 +62,7 @@ var functionNames = map[string]struct{}{ "getNumESDTTransfers": empty, "getCallValueTokenName": empty, "getCallValueTokenNameByIndex": empty, + "isReservedFunctionName": empty, "writeLog": empty, "writeEventLog": empty, "getBlockTimestamp": empty, diff --git a/mock/context/runtimeContextMock.go b/mock/context/runtimeContextMock.go index a0bd5fac6..a132019f4 100644 --- a/mock/context/runtimeContextMock.go +++ b/mock/context/runtimeContextMock.go @@ -356,6 +356,11 @@ func (r *RuntimeContextMock) ValidateCallbackName(_ string) error { return nil } +// IsReservedFunctionName moked method +func (r *RuntimeContextMock) IsReservedFunctionName(_ string) bool { + return false +} + // HasFunction mocked method func (r *RuntimeContextMock) HasFunction(_ string) bool { return r.HasFunctionResult diff --git a/mock/context/runtimeContextWrapper.go b/mock/context/runtimeContextWrapper.go index d6204227d..541cf6d3d 100644 --- a/mock/context/runtimeContextWrapper.go +++ b/mock/context/runtimeContextWrapper.go @@ -582,6 +582,11 @@ func (contextWrapper *RuntimeContextWrapper) ValidateCallbackName(callbackName s return contextWrapper.runtimeContext.ValidateCallbackName(callbackName) } +// IsReservedFunctionName calls corresponding xxxFunc function, that by default in turn calls the original method of the wrapped RuntimeContext +func (contextWrapper *RuntimeContextWrapper) IsReservedFunctionName(functionName string) bool { + return contextWrapper.runtimeContext.IsReservedFunctionName(functionName) +} + // HasFunction calls corresponding xxxFunc function, that by default in turn calls the original method of the wrapped RuntimeContext func (contextWrapper *RuntimeContextWrapper) HasFunction(functionName string) bool { return contextWrapper.runtimeContext.HasFunction(functionName) diff --git a/scenario/gasSchedules/gasScheduleEmbedGenerated.go b/scenario/gasSchedules/gasScheduleEmbedGenerated.go index ff7d22128..9e9eaea22 100644 --- a/scenario/gasSchedules/gasScheduleEmbedGenerated.go +++ b/scenario/gasSchedules/gasScheduleEmbedGenerated.go @@ -121,6 +121,7 @@ const ( DeleteFromReturnData = 100 GetCodeMetadata = 100 IsBuiltinFunction = 100 + IsReservedFunctionName = 100 [EthAPICost] UseGas = 100 @@ -951,6 +952,7 @@ const ( DeleteFromReturnData = 100 GetCodeMetadata = 100 IsBuiltinFunction = 100 + IsReservedFunctionName = 100 [EthAPICost] UseGas = 100 diff --git a/scenario/gasSchedules/gasScheduleV3.toml b/scenario/gasSchedules/gasScheduleV3.toml index 40c115f8e..9aec4d8a9 100644 --- a/scenario/gasSchedules/gasScheduleV3.toml +++ b/scenario/gasSchedules/gasScheduleV3.toml @@ -109,6 +109,7 @@ DeleteFromReturnData = 100 GetCodeMetadata = 100 IsBuiltinFunction = 100 + IsReservedFunctionName = 100 [EthAPICost] UseGas = 100 diff --git a/scenario/gasSchedules/gasScheduleV4.toml b/scenario/gasSchedules/gasScheduleV4.toml index 34108eed2..e3a324c9e 100644 --- a/scenario/gasSchedules/gasScheduleV4.toml +++ b/scenario/gasSchedules/gasScheduleV4.toml @@ -111,6 +111,7 @@ DeleteFromReturnData = 100 GetCodeMetadata = 100 IsBuiltinFunction = 100 + IsReservedFunctionName = 100 [EthAPICost] UseGas = 100 diff --git a/vmhost/contexts/runtime.go b/vmhost/contexts/runtime.go index 72b39a201..1d2e85ade 100644 --- a/vmhost/contexts/runtime.go +++ b/vmhost/contexts/runtime.go @@ -909,6 +909,11 @@ func (context *runtimeContext) ValidateCallbackName(callbackName string) error { return nil } +// IsReservedFunctionName checks if the function name is reserved +func (context *runtimeContext) IsReservedFunctionName(functionName string) bool { + return context.validator.reserved.IsReserved(functionName) +} + // HasFunction checks if loaded contract has a function (endpoint) with given name. func (context *runtimeContext) HasFunction(functionName string) bool { return context.iTracker.Instance().HasFunction(functionName) diff --git a/vmhost/interface.go b/vmhost/interface.go index b32c8f746..f7844c84b 100644 --- a/vmhost/interface.go +++ b/vmhost/interface.go @@ -161,6 +161,9 @@ type RuntimeContext interface { GetAllErrors() error ValidateCallbackName(callbackName string) error + + IsReservedFunctionName(functionName string) bool + HasFunction(functionName string) bool GetPrevTxHash() []byte EndExecution() diff --git a/vmhost/vmhooks/baseOps.go b/vmhost/vmhooks/baseOps.go index 170ab8c40..52323f273 100644 --- a/vmhost/vmhooks/baseOps.go +++ b/vmhost/vmhooks/baseOps.go @@ -2324,6 +2324,29 @@ func (context *VMHooksImpl) GetCallValueTokenNameByIndex( return int32(len(tokenName)) } +// IsReservedFunctionName VMHooks implementation. +// @autogenerate(VMHooks) +func (context *VMHooksImpl) IsReservedFunctionName(nameHandle int32) int32 { + host := context.host + managedTypes := context.GetManagedTypesContext() + runtime := host.Runtime() + metering := host.Metering() + + gasToUse := metering.GasSchedule().BaseOpsAPICost.IsReservedFunctionName + metering.UseAndTraceGas(gasToUse) + + name, err := managedTypes.GetBytes(nameHandle) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return -1 + } + + if runtime.IsReservedFunctionName(string(name)) { + return 1 + } + + return 0 +} + // WriteLog VMHooks implementation. // @autogenerate(VMHooks) func (context *VMHooksImpl) WriteLog( diff --git a/wasmer/wasmerImportsCgo.go b/wasmer/wasmerImportsCgo.go index 88871d3bc..72f3ea330 100644 --- a/wasmer/wasmerImportsCgo.go +++ b/wasmer/wasmerImportsCgo.go @@ -64,6 +64,7 @@ package wasmer // extern int32_t v1_5_getNumESDTTransfers(void* context); // extern int32_t v1_5_getCallValueTokenName(void* context, int32_t callValueOffset, int32_t tokenNameOffset); // extern int32_t v1_5_getCallValueTokenNameByIndex(void* context, int32_t callValueOffset, int32_t tokenNameOffset, int32_t index); +// extern int32_t v1_5_isReservedFunctionName(void* context, int32_t nameHandle); // extern void v1_5_writeLog(void* context, int32_t dataPointer, int32_t dataLength, int32_t topicPtr, int32_t numTopics); // extern void v1_5_writeEventLog(void* context, int32_t numTopics, int32_t topicLengthsOffset, int32_t topicOffset, int32_t dataOffset, int32_t dataLength); // extern long long v1_5_getBlockTimestamp(void* context); @@ -548,6 +549,11 @@ func populateWasmerImports(imports *wasmerImports) error { return err } + err = imports.append("isReservedFunctionName", v1_5_isReservedFunctionName, C.v1_5_isReservedFunctionName) + if err != nil { + return err + } + err = imports.append("writeLog", v1_5_writeLog, C.v1_5_writeLog) if err != nil { return err @@ -1909,6 +1915,12 @@ func v1_5_getCallValueTokenNameByIndex(context unsafe.Pointer, callValueOffset i return vmHooks.GetCallValueTokenNameByIndex(executor.MemPtr(callValueOffset), executor.MemPtr(tokenNameOffset), index) } +//export v1_5_isReservedFunctionName +func v1_5_isReservedFunctionName(context unsafe.Pointer, nameHandle int32) int32 { + vmHooks := getVMHooksFromContextRawPtr(context) + return vmHooks.IsReservedFunctionName(nameHandle) +} + //export v1_5_writeLog func v1_5_writeLog(context unsafe.Pointer, dataPointer int32, dataLength int32, topicPtr int32, numTopics int32) { vmHooks := getVMHooksFromContextRawPtr(context) diff --git a/wasmer2/libvmexeccapi.dylib b/wasmer2/libvmexeccapi.dylib index b85702ed9..75bc5695d 100644 Binary files a/wasmer2/libvmexeccapi.dylib and b/wasmer2/libvmexeccapi.dylib differ diff --git a/wasmer2/libvmexeccapi.h b/wasmer2/libvmexeccapi.h index fafaac3f0..f4f989a42 100644 --- a/wasmer2/libvmexeccapi.h +++ b/wasmer2/libvmexeccapi.h @@ -91,6 +91,7 @@ typedef struct { int32_t (*get_num_esdt_transfers_func_ptr)(void *context); int32_t (*get_call_value_token_name_func_ptr)(void *context, int32_t call_value_offset, int32_t token_name_offset); int32_t (*get_call_value_token_name_by_index_func_ptr)(void *context, int32_t call_value_offset, int32_t token_name_offset, int32_t index); + int32_t (*is_reserved_function_name_func_ptr)(void *context, int32_t name_handle); void (*write_log_func_ptr)(void *context, int32_t data_pointer, int32_t data_length, int32_t topic_ptr, int32_t num_topics); void (*write_event_log_func_ptr)(void *context, int32_t num_topics, int32_t topic_lengths_offset, int32_t topic_offset, int32_t data_offset, int32_t data_length); int64_t (*get_block_timestamp_func_ptr)(void *context); diff --git a/wasmer2/libvmexeccapi.so b/wasmer2/libvmexeccapi.so index 39e64cb72..b30bdc614 100644 Binary files a/wasmer2/libvmexeccapi.so and b/wasmer2/libvmexeccapi.so differ diff --git a/wasmer2/libvmexeccapi_arm.dylib b/wasmer2/libvmexeccapi_arm.dylib index 2f8a3ddb6..17b3f958d 100644 Binary files a/wasmer2/libvmexeccapi_arm.dylib and b/wasmer2/libvmexeccapi_arm.dylib differ diff --git a/wasmer2/libvmexeccapi_arm.so b/wasmer2/libvmexeccapi_arm.so index 6184a1137..d3e8078fb 100644 Binary files a/wasmer2/libvmexeccapi_arm.so and b/wasmer2/libvmexeccapi_arm.so differ diff --git a/wasmer2/wasmer2ImportsCgo.go b/wasmer2/wasmer2ImportsCgo.go index 47b3cce64..44bc33019 100644 --- a/wasmer2/wasmer2ImportsCgo.go +++ b/wasmer2/wasmer2ImportsCgo.go @@ -64,6 +64,7 @@ package wasmer2 // extern int32_t w2_getNumESDTTransfers(void* context); // extern int32_t w2_getCallValueTokenName(void* context, int32_t callValueOffset, int32_t tokenNameOffset); // extern int32_t w2_getCallValueTokenNameByIndex(void* context, int32_t callValueOffset, int32_t tokenNameOffset, int32_t index); +// extern int32_t w2_isReservedFunctionName(void* context, int32_t nameHandle); // extern void w2_writeLog(void* context, int32_t dataPointer, int32_t dataLength, int32_t topicPtr, int32_t numTopics); // extern void w2_writeEventLog(void* context, int32_t numTopics, int32_t topicLengthsOffset, int32_t topicOffset, int32_t dataOffset, int32_t dataLength); // extern long long w2_getBlockTimestamp(void* context); @@ -336,6 +337,7 @@ func populateCgoFunctionPointers() *cWasmerVmHookPointers { get_num_esdt_transfers_func_ptr: funcPointer(C.w2_getNumESDTTransfers), get_call_value_token_name_func_ptr: funcPointer(C.w2_getCallValueTokenName), get_call_value_token_name_by_index_func_ptr: funcPointer(C.w2_getCallValueTokenNameByIndex), + is_reserved_function_name_func_ptr: funcPointer(C.w2_isReservedFunctionName), write_log_func_ptr: funcPointer(C.w2_writeLog), write_event_log_func_ptr: funcPointer(C.w2_writeEventLog), get_block_timestamp_func_ptr: funcPointer(C.w2_getBlockTimestamp), @@ -865,6 +867,12 @@ func w2_getCallValueTokenNameByIndex(context unsafe.Pointer, callValueOffset int return vmHooks.GetCallValueTokenNameByIndex(executor.MemPtr(callValueOffset), executor.MemPtr(tokenNameOffset), index) } +//export w2_isReservedFunctionName +func w2_isReservedFunctionName(context unsafe.Pointer, nameHandle int32) int32 { + vmHooks := getVMHooksFromContextRawPtr(context) + return vmHooks.IsReservedFunctionName(nameHandle) +} + //export w2_writeLog func w2_writeLog(context unsafe.Pointer, dataPointer int32, dataLength int32, topicPtr int32, numTopics int32) { vmHooks := getVMHooksFromContextRawPtr(context) diff --git a/wasmer2/wasmer2Names.go b/wasmer2/wasmer2Names.go index b2aeb1765..501383d0c 100644 --- a/wasmer2/wasmer2Names.go +++ b/wasmer2/wasmer2Names.go @@ -62,6 +62,7 @@ var functionNames = map[string]struct{}{ "getNumESDTTransfers": empty, "getCallValueTokenName": empty, "getCallValueTokenNameByIndex": empty, + "isReservedFunctionName": empty, "writeLog": empty, "writeEventLog": empty, "getBlockTimestamp": empty,