From 5b30d71344b648dd27ba4072ab1b592ec61e14bd Mon Sep 17 00:00:00 2001 From: robertsasu Date: Thu, 8 Aug 2024 15:14:29 +0300 Subject: [PATCH 01/24] refactoring gasUsage --- mock/context/meteringContextMock.go | 10 +- mock/contracts/asyncChildSC.go | 2 +- mock/contracts/directSimpleSC.go | 4 +- mock/contracts/transferAndExecuteSC.go | 4 +- vmhost/contexts/managedType.go | 59 +++++-- vmhost/contexts/metering.go | 20 +-- vmhost/contexts/metering_test.go | 20 +-- vmhost/contexts/output.go | 6 +- vmhost/contexts/storage.go | 51 ++++-- vmhost/hostCore/execution.go | 19 +- vmhost/hosttest/execution_test.go | 10 +- vmhost/interface.go | 3 - vmhost/vmhooks/baseOps.go | 230 +++++++++++++++++++------ vmhost/vmhooks/bigIntOps.go | 22 ++- vmhost/vmhooks/vmHooksImpl.go | 2 +- 15 files changed, 325 insertions(+), 137 deletions(-) diff --git a/mock/context/meteringContextMock.go b/mock/context/meteringContextMock.go index 7fc82f008..8ac22e2a2 100644 --- a/mock/context/meteringContextMock.go +++ b/mock/context/meteringContextMock.go @@ -50,7 +50,7 @@ func (m *MeteringContextMock) GasSchedule() *config.GasCost { } // UseGas mocked method -func (m *MeteringContextMock) UseGas(gas uint64) { +func (m *MeteringContextMock) useGas(gas uint64) { if gas > m.GasLeftMock { m.GasLeftMock = 0 return @@ -59,12 +59,6 @@ func (m *MeteringContextMock) UseGas(gas uint64) { m.GasLeftMock -= gas } -// UseAndTraceGas mocked method -func (m *MeteringContextMock) UseAndTraceGas(_ uint64) {} - -// UseGasAndAddTracedGas mocked method -func (m *MeteringContextMock) UseGasAndAddTracedGas(_ string, _ uint64) {} - // UseGasBoundedAndAddTracedGas - func (m *MeteringContextMock) UseGasBoundedAndAddTracedGas(_ string, _ uint64) error { return nil @@ -159,7 +153,7 @@ func (m *MeteringContextMock) UseGasBounded(gas uint64) error { if m.GasLeft() <= gas { return vmhost.ErrNotEnoughGas } - m.UseGas(gas) + m.useGas(gas) return nil } diff --git a/mock/contracts/asyncChildSC.go b/mock/contracts/asyncChildSC.go index b73bb8d38..9f6ffe142 100644 --- a/mock/contracts/asyncChildSC.go +++ b/mock/contracts/asyncChildSC.go @@ -17,7 +17,7 @@ func TransferToAsyncParentOnCallbackChildMock(instanceMock *mock.InstanceMock, c host := instanceMock.Host instance := mock.GetMockInstance(host) - host.Metering().UseGas(testConfig.GasUsedByChild) + _ = host.Metering().UseGasBounded(testConfig.GasUsedByChild) runtime := host.Runtime() output := host.Output() diff --git a/mock/contracts/directSimpleSC.go b/mock/contracts/directSimpleSC.go index 7dbdc1e92..44cd475dd 100644 --- a/mock/contracts/directSimpleSC.go +++ b/mock/contracts/directSimpleSC.go @@ -161,7 +161,7 @@ func ExecOnDestCtxSingleCallParentMock(instanceMock *mock.InstanceMock, config i testConfig := config.(*test.TestConfig) host := instanceMock.Host instance := mock.GetMockInstance(host) - host.Metering().UseGas(testConfig.GasUsedByParent) + _ = host.Metering().UseGasBounded(testConfig.GasUsedByParent) arguments := host.Runtime().Arguments() if len(arguments) < 2 { @@ -287,7 +287,7 @@ func esdtTransferToParentMock(instanceMock *mock.InstanceMock, config interface{ testConfig := config.(*test.TestConfig) host := instanceMock.Host instance := mock.GetMockInstance(host) - host.Metering().UseGas(testConfig.GasUsedByChild) + _ = host.Metering().UseGasBounded(testConfig.GasUsedByChild) switch behavior { case esdtOnCallbackSuccess: diff --git a/mock/contracts/transferAndExecuteSC.go b/mock/contracts/transferAndExecuteSC.go index fd298e9ad..69047b32f 100644 --- a/mock/contracts/transferAndExecuteSC.go +++ b/mock/contracts/transferAndExecuteSC.go @@ -23,7 +23,7 @@ func TransferAndExecute(instanceMock *mock.InstanceMock, config interface{}) { host := instanceMock.Host instance := mock.GetMockInstance(host) - host.Metering().UseGas(testConfig.GasUsedByParent) + _ = host.Metering().UseGasBounded(testConfig.GasUsedByParent) arguments := host.Runtime().Arguments() noOfTransfers := int(big.NewInt(0).SetBytes(arguments[0]).Int64()) @@ -50,7 +50,7 @@ func TransferEGLDToParent(instanceMock *mock.InstanceMock, config interface{}) { host := instanceMock.Host instance := mock.GetMockInstance(host) - host.Metering().UseGas(testConfig.GasUsedByChild) + _ = host.Metering().UseGasBounded(testConfig.GasUsedByChild) vmhooks.TransferValueExecuteWithTypedArgs(host, test.ParentAddress, diff --git a/vmhost/contexts/managedType.go b/vmhost/contexts/managedType.go index 40e26aa0b..dc3175bba 100644 --- a/vmhost/contexts/managedType.go +++ b/vmhost/contexts/managedType.go @@ -236,32 +236,42 @@ func (context *managedTypesContext) IsInterfaceNil() bool { } // ConsumeGasForBigIntCopy uses gas for Copy operations -func (context *managedTypesContext) ConsumeGasForBigIntCopy(values ...*big.Int) { +func (context *managedTypesContext) ConsumeGasForBigIntCopy(values ...*big.Int) error { for _, val := range values { byteLen := val.BitLen() / 8 - context.ConsumeGasForThisIntNumberOfBytes(byteLen) + err := context.ConsumeGasForThisIntNumberOfBytes(byteLen) + if err != nil { + return err + } } + return nil } // ConsumeGasForThisIntNumberOfBytes uses gas for the number of bytes given -func (context *managedTypesContext) ConsumeGasForThisIntNumberOfBytes(byteLen int) { +func (context *managedTypesContext) ConsumeGasForThisIntNumberOfBytes(byteLen int) error { gasToUse := uint64(0) metering := context.host.Metering() if byteLen > maxBigIntByteLenForNormalCost { gasToUse = math.MulUint64(uint64(byteLen), metering.GasSchedule().BigIntAPICost.CopyPerByteForTooBig) - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if err != nil { + return err + } } + + return nil } // ConsumeGasForBytes uses gas for the given bytes -func (context *managedTypesContext) ConsumeGasForBytes(bytes []byte) { +func (context *managedTypesContext) ConsumeGasForBytes(bytes []byte) error { metering := context.host.Metering() gasToUse := math.MulUint64(uint64(len(bytes)), metering.GasSchedule().BaseOperationCost.DataCopyPerByte) - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + return err } // ConsumeGasForThisBigIntNumberOfBytes uses gas for the number of bytes given that are being copied -func (context *managedTypesContext) ConsumeGasForThisBigIntNumberOfBytes(byteLen *big.Int) { +func (context *managedTypesContext) ConsumeGasForThisBigIntNumberOfBytes(byteLen *big.Int) error { metering := context.host.Metering() gasToUseBigInt := big.NewInt(0).Mul(byteLen, big.NewInt(int64(metering.GasSchedule().BigIntAPICost.CopyPerByteForTooBig))) @@ -270,12 +280,12 @@ func (context *managedTypesContext) ConsumeGasForThisBigIntNumberOfBytes(byteLen if gasToUseBigInt.Cmp(maxGasBigInt) < 0 { gasToUse = gasToUseBigInt.Uint64() } - metering.UseAndTraceGas(gasToUse) + return metering.UseGasBounded(gasToUse) } // ConsumeGasForBigFloatCopy uses gas for the given big float values -func (context *managedTypesContext) ConsumeGasForBigFloatCopy(values ...*big.Float) { - context.ConsumeGasForThisIntNumberOfBytes(encodedBigFloatMaxByteLen * len(values)) +func (context *managedTypesContext) ConsumeGasForBigFloatCopy(values ...*big.Float) error { + return context.ConsumeGasForThisIntNumberOfBytes(encodedBigFloatMaxByteLen * len(values)) } // BIGINT @@ -663,7 +673,10 @@ func (context *managedTypesContext) ReadManagedVecOfManagedBuffers( if err != nil { return nil, 0, err } - context.ConsumeGasForBytes(managedVecBytes) + err = context.ConsumeGasForBytes(managedVecBytes) + if err != nil { + return nil, 0, err + } if len(managedVecBytes)%handleLen != 0 { return nil, 0, errors.New("invalid managed vector of managed buffer handles") @@ -679,7 +692,10 @@ func (context *managedTypesContext) ReadManagedVecOfManagedBuffers( if err != nil { return nil, 0, err } - context.ConsumeGasForBytes(itemBytes) + err = context.ConsumeGasForBytes(itemBytes) + if err != nil { + return nil, 0, err + } sumOfItemByteLengths += uint64(len(itemBytes)) result = append(result, itemBytes) @@ -692,7 +708,7 @@ func (context *managedTypesContext) ReadManagedVecOfManagedBuffers( func (context *managedTypesContext) WriteManagedVecOfManagedBuffers( data [][]byte, destinationHandle int32, -) { +) error { sumOfItemByteLengths := uint64(0) destinationBytes := make([]byte, handleLen*len(data)) dataIndex := 0 @@ -705,7 +721,7 @@ func (context *managedTypesContext) WriteManagedVecOfManagedBuffers( context.SetBytes(destinationHandle, destinationBytes) metering := context.host.Metering() - metering.UseAndTraceGas(sumOfItemByteLengths * metering.GasSchedule().BaseOperationCost.DataCopyPerByte) + return metering.UseGasBounded(sumOfItemByteLengths * metering.GasSchedule().BaseOperationCost.DataCopyPerByte) } // NewManagedMap creates a new empty managed map in the managed buffers map and returns the handle @@ -741,7 +757,10 @@ func (context *managedTypesContext) ManagedMapPut(mMapHandle int32, keyHandle in valueCopy := make([]byte, len(value)) copy(valueCopy, value) - context.ConsumeGasForBytes(value) + err = context.ConsumeGasForBytes(value) + if err != nil { + return err + } mMap[string(key)] = valueCopy @@ -756,9 +775,8 @@ func (context *managedTypesContext) ManagedMapGet(mMapHandle int32, keyHandle in } context.SetBytes(outValueHandle, value) - context.ConsumeGasForBytes(value) - - return nil + err = context.ConsumeGasForBytes(value) + return err } // ManagedMapRemove removes the bytes stored as the key handle and returns it in an output value handle @@ -769,7 +787,10 @@ func (context *managedTypesContext) ManagedMapRemove(mMapHandle int32, keyHandle } context.SetBytes(outValueHandle, value) - context.ConsumeGasForBytes(value) + err = context.ConsumeGasForBytes(value) + if err != nil { + return err + } delete(mMap, string(key)) return nil diff --git a/vmhost/contexts/metering.go b/vmhost/contexts/metering.go index 435372110..691b46b62 100644 --- a/vmhost/contexts/metering.go +++ b/vmhost/contexts/metering.go @@ -230,7 +230,7 @@ func (context *meteringContext) TrackGasUsedByOutOfVMFunction( gasUsed = math.SubUint64(gasUsed, postBuiltinInput.GasProvided) } - context.UseGas(gasUsed) + context.useGas(gasUsed) logMetering.Trace("gas used by builtin function", "gas", gasUsed) } @@ -339,22 +339,22 @@ func (context *meteringContext) SetGasSchedule(gasMap config.GasScheduleMap) { context.gasSchedule = gasSchedule } -// UseGas consumes the specified amount of gas on the currently running Wasmer instance. -func (context *meteringContext) UseGas(gas uint64) { +// useGas consumes the specified amount of gas on the currently running Wasmer instance. +func (context *meteringContext) useGas(gas uint64) { gasUsed := math.AddUint64(context.host.Runtime().GetPointsUsed(), gas) context.host.Runtime().SetPointsUsed(gasUsed) logMetering.Trace("used gas", "gas", gas) } -// UseAndTraceGas sets in the runtime context the given gas as gas used and adds to current trace -func (context *meteringContext) UseAndTraceGas(gas uint64) { - context.UseGas(gas) +// useAndTraceGas sets in the runtime context the given gas as gas used and adds to current trace +func (context *meteringContext) useAndTraceGas(gas uint64) { + context.useGas(gas) context.traceGas(gas) } -// UseGasAndAddTracedGas sets in the runtime context the given gas as gas used and adds to current trace -func (context *meteringContext) UseGasAndAddTracedGas(functionName string, gas uint64) { - context.UseGas(gas) +// useGasAndAddTracedGas sets in the runtime context the given gas as gas used and adds to current trace +func (context *meteringContext) useGasAndAddTracedGas(functionName string, gas uint64) { + context.useGas(gas) context.addToGasTrace(functionName, gas) } @@ -474,7 +474,7 @@ func (context *meteringContext) UseGasBounded(gasToUse uint64) error { if context.GasLeft() < gasToUse { return vmhost.ErrNotEnoughGas } - context.UseGas(gasToUse) + context.useGas(gasToUse) context.traceGas(gasToUse) return nil } diff --git a/vmhost/contexts/metering_test.go b/vmhost/contexts/metering_test.go index 6dce8ae49..595373740 100644 --- a/vmhost/contexts/metering_test.go +++ b/vmhost/contexts/metering_test.go @@ -58,7 +58,7 @@ func TestMeteringContext_UseGas(t *testing.T) { gasProvided := uint64(1001) meteringCtx.gasForExecution = gasProvided gasUsed := uint64(1000) - meteringCtx.UseGas(gasUsed) + _ = meteringCtx.UseGasBounded(gasUsed) require.Equal(t, mockRuntime.GetPointsUsed(), gasUsed) require.Equal(t, gasProvided-gasUsed, meteringCtx.GasLeft()) @@ -68,7 +68,7 @@ func TestMeteringContext_UseGas(t *testing.T) { meteringCtx.gasForExecution = gasProvided require.Equal(t, gasProvided, meteringCtx.GasLeft()) - meteringCtx.UseGas(gasUsed) + _ = meteringCtx.UseGasBounded(gasUsed) require.Equal(t, gasProvided-gasUsed, meteringCtx.GasLeft()) } @@ -288,7 +288,7 @@ func TestMeteringContext_GasUsed_NoStacking(t *testing.T) { require.Equal(t, gasAfterDeductingInitial, metering.GasLeft()) gasUsed := uint64(400) - metering.UseGas(gasUsed) + _ = metering.UseGasBounded(gasUsed) require.Equal(t, gasAfterDeductingInitial-gasUsed, metering.GasLeft()) totalGasUsed := metering.initialGasProvided - metering.GasLeft() @@ -335,14 +335,14 @@ func initStateFromChildGetParentPointsBeforeStacking(t *testing.T, host *context require.Equal(t, parentGasProvided-parentExecutionGas, host.MeteringContext.GasLeft()) parentUsedGas := uint64(400) - host.MeteringContext.UseGas(parentUsedGas) + _ = host.MeteringContext.UseGasBounded(parentUsedGas) require.Equal(t, parentGasProvided-parentExecutionGas-parentUsedGas, host.MeteringContext.GasLeft()) gasSpentByContract := host.MeteringContext.GasSpentByContract() require.Equal(t, parentExecutionGas+parentUsedGas, gasSpentByContract) childProvidedGas := childInput.GasProvided - host.MeteringContext.UseGas(childProvidedGas) + _ = host.MeteringContext.UseGasBounded(childProvidedGas) parentPointsBeforeStacking := host.RuntimeContext.GetPointsUsed() require.Equal(t, childProvidedGas+parentUsedGas, parentPointsBeforeStacking) require.Equal(t, parentGasProvided-parentExecutionGas-parentPointsBeforeStacking, host.MeteringContext.GasLeft()) @@ -378,7 +378,7 @@ func TestMeteringContext_GasUsed_StackOneLevel(t *testing.T) { require.Equal(t, childInput.GasProvided-childExecutionGas, metering.GasLeft()) childUsedGas := uint64(50) - metering.UseGas(childUsedGas) + _ = metering.UseGasBounded(childUsedGas) gasRemaining := metering.GasLeft() require.Equal(t, childInput.GasProvided-childExecutionGas-childUsedGas, metering.GasLeft()) @@ -399,7 +399,7 @@ func TestMeteringContext_GasUsed_StackOneLevel(t *testing.T) { gasSpentByContract = metering.GasSpentByContract() require.Equal(t, parentExecutionGas+parentUsedGas+childUsedGas+childExecutionGas, gasSpentByContract) - metering.UseGas(50) + _ = metering.UseGasBounded(50) parentUsedGas += 50 require.Equal(t, parentInput.GasProvided-parentExecutionGas-parentUsedGas-childExecutionGas-childUsedGas, metering.GasLeft()) @@ -548,7 +548,7 @@ func TestMeteringContext_GasTracer(t *testing.T) { meteringCtx.StartGasTracing("function1") gasTrace := meteringCtx.GetGasTrace() require.Equal(t, 0, len(gasTrace)) - meteringCtx.UseGasAndAddTracedGas("function2", gasUsed2) + _ = meteringCtx.UseGasBoundedAndAddTracedGas("function2", gasUsed2) gasTrace = meteringCtx.GetGasTrace() require.Equal(t, 0, len(gasTrace)) @@ -559,12 +559,12 @@ func TestMeteringContext_GasTracer(t *testing.T) { require.Equal(t, 1, len(gasTrace["scAddress1"])) require.Equal(t, 1, len(gasTrace["scAddress1"]["function1"])) require.Equal(t, uint64(0), gasTrace["scAddress1"]["function1"][0]) - meteringCtx.UseAndTraceGas(gasUsed1) + _ = meteringCtx.UseGasBounded(gasUsed1) gasTrace = meteringCtx.GetGasTrace() require.Equal(t, gasUsed1, gasTrace["scAddress1"]["function1"][0]) host.RuntimeContext.SetCodeAddress([]byte("scAddress2")) - meteringCtx.UseGasAndAddTracedGas("function2", gasUsed2) + _ = meteringCtx.UseGasBoundedAndAddTracedGas("function2", gasUsed2) gasTrace = meteringCtx.GetGasTrace() require.Equal(t, 2, len(gasTrace)) require.Equal(t, gasUsed2, gasTrace["scAddress2"]["function2"][0]) diff --git a/vmhost/contexts/output.go b/vmhost/contexts/output.go index 1c7e93207..1cf8ddad6 100644 --- a/vmhost/contexts/output.go +++ b/vmhost/contexts/output.go @@ -482,7 +482,11 @@ func (context *outputContext) TransferESDT( } if !sameShard { - context.host.Metering().UseGas(gasRemaining) + err = context.host.Metering().UseGasBounded(gasRemaining) + if err != nil { + logOutput.Trace("ESDT post-transfer execution", "error", vmhost.ErrNotEnoughGas) + return 0, vmhost.ErrNotEnoughGas + } } } diff --git a/vmhost/contexts/storage.go b/vmhost/contexts/storage.go index dd8483d0a..cfa55cf22 100644 --- a/vmhost/contexts/storage.go +++ b/vmhost/contexts/storage.go @@ -118,38 +118,50 @@ func (context *storageContext) GetStorage(key []byte) ([]byte, uint32, bool, err if err != nil { return nil, trieDepth, false, err } - context.useExtraGasForKeyIfNeeded(key, usedCache) - context.useGasForValueIfNeeded(value, usedCache) + + errGas := context.useExtraGasForKeyIfNeeded(key, usedCache) + if errGas != nil { + return nil, 0, false, nil + } + + errGas = context.useGasForValueIfNeeded(value, usedCache) + if errGas != nil { + return nil, 0, false, nil + } + logStorage.Trace("get", "key", key, "value", value) return value, trieDepth, usedCache, nil } -func (context *storageContext) useGasForValueIfNeeded(value []byte, usedCache bool) { +func (context *storageContext) useGasForValueIfNeeded(value []byte, usedCache bool) error { metering := context.host.Metering() enableEpochsHandler := context.host.EnableEpochsHandler() gasFlagSet := enableEpochsHandler.IsFlagEnabled(vmhost.StorageAPICostOptimizationFlag) if !usedCache || !gasFlagSet { costPerByte := metering.GasSchedule().BaseOperationCost.DataCopyPerByte gasToUse := math.MulUint64(costPerByte, uint64(len(value))) - // TODO replace UseGas with UseGasBounded - metering.UseGas(gasToUse) + return metering.UseGasBounded(gasToUse) } + + return nil } -func (context *storageContext) useExtraGasForKeyIfNeeded(key []byte, usedCache bool) { +func (context *storageContext) useExtraGasForKeyIfNeeded(key []byte, usedCache bool) error { metering := context.host.Metering() extraBytes := len(key) - vmhost.AddressLen if extraBytes <= 0 { - return + return nil } + enableEpochsHandler := context.host.EnableEpochsHandler() gasFlagSet := enableEpochsHandler.IsFlagEnabled(vmhost.StorageAPICostOptimizationFlag) if !gasFlagSet || !usedCache { gasToUse := math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(extraBytes)) - // TODO replace UseGas with UseGasBounded - metering.UseGas(gasToUse) + return metering.UseGasBounded(gasToUse) } + + return nil } // GetStorageFromAddress returns the data under the given key from the account mapped to the given address. @@ -157,21 +169,34 @@ func (context *storageContext) GetStorageFromAddress(address []byte, key []byte) if !bytes.Equal(address, context.address) { userAcc, err := context.blockChainHook.GetUserAccount(address) if err != nil || check.IfNil(userAcc) { - context.useExtraGasForKeyIfNeeded(key, false) + errGas := context.useExtraGasForKeyIfNeeded(key, false) + if errGas != nil { + return nil, 0, false, errGas + } return nil, 0, false, nil } metadata := vmcommon.CodeMetadataFromBytes(userAcc.GetCodeMetadata()) if !metadata.Readable { - context.useExtraGasForKeyIfNeeded(key, false) + errGas := context.useExtraGasForKeyIfNeeded(key, false) + if errGas != nil { + return nil, 0, false, errGas + } + return nil, 0, false, nil } } value, trieDepth, usedCache, err := context.getStorageFromAddressUnmetered(address, key) - context.useExtraGasForKeyIfNeeded(key, usedCache) - context.useGasForValueIfNeeded(value, usedCache) + errGas := context.useExtraGasForKeyIfNeeded(key, usedCache) + if errGas != nil { + return nil, 0, false, nil + } + errGas = context.useGasForValueIfNeeded(value, usedCache) + if errGas != nil { + return nil, 0, false, nil + } logStorage.Trace("get from address", "address", address, "key", key, "value", value) return value, trieDepth, usedCache, err diff --git a/vmhost/hostCore/execution.go b/vmhost/hostCore/execution.go index ef3711dcd..91c4b0c28 100644 --- a/vmhost/hostCore/execution.go +++ b/vmhost/hostCore/execution.go @@ -868,7 +868,10 @@ func (host *vmHost) execute(input *vmcommon.ContractCallInput) error { // Use all gas initially, on the Wasmer instance of the caller. In case of // successful execution, the unused gas will be restored. - metering.UseGas(input.GasProvided) + err := metering.UseGasBounded(input.GasProvided) + if err != nil { + return err + } isUpgrade := input.Function == vmhost.UpgradeFunctionName if isUpgrade { @@ -1016,7 +1019,11 @@ func (host *vmHost) ExecuteESDTTransfer(transfersArgs *vmhost.ESDTTransfersArgs, log.Trace("ESDT transfer", "error", vmhost.ErrNotEnoughGas) return vmOutput, esdtTransferInput.GasProvided, vmhost.ErrNotEnoughGas } - metering.UseGas(gasConsumed) + err = metering.UseGasBounded(gasConsumed) + if err != nil { + log.Trace("ESDT transfer", "error", vmhost.ErrNotEnoughGas) + return vmOutput, esdtTransferInput.GasProvided, vmhost.ErrNotEnoughGas + } } return vmOutput, gasConsumed, nil @@ -1027,7 +1034,7 @@ func (host *vmHost) callFunctionOnOtherVM(input *vmcommon.ContractCallInput) (*v vmOutput, err := host.Blockchain().ExecuteSmartContractCallOnOtherVM(input) if err != nil { - metering.UseGas(input.GasProvided) + _ = metering.UseGasBounded(input.GasProvided) return nil, err } @@ -1052,13 +1059,13 @@ func (host *vmHost) callBuiltinFunction(input *vmcommon.ContractCallInput) (*vmc vmOutput, err := host.Blockchain().ProcessBuiltInFunction(input) if err != nil { - metering.UseGas(input.GasProvided) + _ = metering.UseGasBounded(input.GasProvided) return nil, nil, err } newVMInput, err := host.isSCExecutionAfterBuiltInFunc(input, vmOutput) if err != nil { - metering.UseGas(input.GasProvided) + _ = metering.UseGasBounded(input.GasProvided) return nil, nil, err } @@ -1235,7 +1242,7 @@ func (host *vmHost) callSCMethodAsynchronousCallBack() error { if callbackErr != nil { metering := host.Metering() - metering.UseGas(metering.GasLeft()) + _ = metering.UseGasBounded(metering.GasLeft()) } // TODO matei-p R2 Returning an error here will cause the VMOutput to be diff --git a/vmhost/hosttest/execution_test.go b/vmhost/hosttest/execution_test.go index f2edcfdd0..8907ebe15 100644 --- a/vmhost/hosttest/execution_test.go +++ b/vmhost/hosttest/execution_test.go @@ -2140,7 +2140,7 @@ func TestExecution_ExecuteOnDestContext_GasRemaining(t *testing.T) { require.Nil(t, err) // Use a lot of gas on the parent contract - metering.UseGas(500000) + _ = metering.UseGasBounded(500000) require.Equal(t, input.GasProvided-500001, metering.GasLeft()) // Create a second ContractCallInput, used to call the child SC using @@ -3178,7 +3178,7 @@ func TestExecution_Mocked_Wasmer_Instances(t *testing.T) { parentInstance.AddMockMethod("callChild", func() *contextmock.InstanceMock { host := parentInstance.Host host.Output().Finish([]byte("parent returns this")) - host.Metering().UseGas(500) + _ = host.Metering().UseGasBounded(500) _, err := host.Storage().SetStorage([]byte("parent"), []byte("parent storage")) require.Nil(t, err) childInput := test.DefaultTestContractCallInput() @@ -3202,7 +3202,7 @@ func TestExecution_Mocked_Wasmer_Instances(t *testing.T) { childInstance.AddMockMethod("doSomething", func() *contextmock.InstanceMock { host := childInstance.Host host.Output().Finish([]byte("child returns this")) - host.Metering().UseGas(100) + _ = host.Metering().UseGasBounded(100) _, err := host.Storage().SetStorage([]byte("child"), []byte("child storage")) require.Nil(t, err) return childInstance @@ -3645,7 +3645,7 @@ func TestExecution_Mocked_OnSameFollowedByOnDest(t *testing.T) { parentInstance.AddMockMethod("callChild", func() *contextmock.InstanceMock { host := parentInstance.Host host.Output().Finish([]byte("parent returns this")) - host.Metering().UseGas(500) + _ = host.Metering().UseGasBounded(500) vmhooks.ExecuteOnSameContextWithTypedArgs(host, 1000, big.NewInt(4), []byte("doSomething"), test.ChildAddress, make([][]byte, 2)) return parentInstance }) @@ -3656,7 +3656,7 @@ func TestExecution_Mocked_OnSameFollowedByOnDest(t *testing.T) { childInstance.AddMockMethod("doSomething", func() *contextmock.InstanceMock { host := childInstance.Host host.Output().Finish([]byte("child returns this")) - host.Metering().UseGas(100) + _ = host.Metering().UseGasBounded(100) vmhooks.ExecuteOnDestContextWithTypedArgs(host, 100, big.NewInt(2), []byte("doSomethingNephew"), test.NephewAddress, make([][]byte, 2)) return childInstance }) diff --git a/vmhost/interface.go b/vmhost/interface.go index 2b201e4ce..6538486f6 100644 --- a/vmhost/interface.go +++ b/vmhost/interface.go @@ -270,9 +270,6 @@ type MeteringContext interface { InitStateFromContractCallInput(input *vmcommon.VMInput) SetGasSchedule(gasMap config.GasScheduleMap) GasSchedule() *config.GasCost - UseGas(gas uint64) - UseAndTraceGas(gas uint64) - UseGasAndAddTracedGas(functionName string, gas uint64) UseGasBoundedAndAddTracedGas(functionName string, gas uint64) error FreeGas(gas uint64) RestoreGas(gas uint64) diff --git a/vmhost/vmhooks/baseOps.go b/vmhost/vmhooks/baseOps.go index 935f19185..9b10aaeec 100644 --- a/vmhost/vmhooks/baseOps.go +++ b/vmhost/vmhooks/baseOps.go @@ -134,7 +134,10 @@ func (context *VMHooksImpl) GetGasLeft() int64 { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetGasLeft - metering.UseGasAndAddTracedGas(getGasLeftName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getGasLeftName, gasToUse) + if context.WithFault(err, context.GetRuntimeContext().BaseOpsErrorShouldFailExecution()) { + return 0 + } return int64(metering.GasLeft()) } @@ -146,10 +149,13 @@ func (context *VMHooksImpl) GetSCAddress(resultOffset executor.MemPtr) { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetSCAddress - metering.UseGasAndAddTracedGas(getSCAddressName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getSCAddressName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } owner := runtime.GetContextAddress() - err := context.MemStore(resultOffset, owner) + err = context.MemStore(resultOffset, owner) if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { return } @@ -163,7 +169,10 @@ func (context *VMHooksImpl) GetOwnerAddress(resultOffset executor.MemPtr) { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetOwnerAddress - metering.UseGasAndAddTracedGas(getOwnerAddressName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getOwnerAddressName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } owner, err := blockchain.GetOwnerAddress() if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -184,7 +193,10 @@ func (context *VMHooksImpl) GetShardOfAddress(addressOffset executor.MemPtr) int metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetShardOfAddress - metering.UseGasAndAddTracedGas(getShardOfAddressName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getShardOfAddressName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return -1 + } address, err := context.MemLoad(addressOffset, vmhost.AddressLen) if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -202,7 +214,10 @@ func (context *VMHooksImpl) IsSmartContract(addressOffset executor.MemPtr) int32 metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.IsSmartContract - metering.UseGasAndAddTracedGas(isSmartContractName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(isSmartContractName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return -1 + } address, err := context.MemLoad(addressOffset, vmhost.AddressLen) if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -245,7 +260,10 @@ func (context *VMHooksImpl) GetExternalBalance(addressOffset executor.MemPtr, re metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetExternalBalance - metering.UseGasAndAddTracedGas(getExternalBalanceName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getExternalBalanceName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } address, err := context.MemLoad(addressOffset, vmhost.AddressLen) if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -268,10 +286,13 @@ func (context *VMHooksImpl) GetBlockHash(nonce int64, resultOffset executor.MemP metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetBlockHash - metering.UseGasAndAddTracedGas(blockHashName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(blockHashName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return 1 + } hash := blockchain.BlockHash(uint64(nonce)) - err := context.MemStore(resultOffset, hash) + err = context.MemStore(resultOffset, hash) if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { return 1 } @@ -290,7 +311,10 @@ func getESDTDataFromBlockchainHook( blockchain := context.GetBlockchainContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetExternalBalance - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if err != nil { + return nil, err + } address, err := context.MemLoad(addressOffset, vmhost.AddressLen) if err != nil { @@ -523,7 +547,10 @@ func (context *VMHooksImpl) ValidateTokenIdentifier( metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetArgument - metering.UseGasAndAddTracedGas(validateTokenIdentifierName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(validateTokenIdentifierName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return -1 + } tokenID, err := managedType.GetBytes(tokenIdHandle) if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -553,7 +580,10 @@ func (context *VMHooksImpl) TransferValue( metering.StartGasTracing(transferValueName) gasToUse := metering.GasSchedule().BaseOpsAPICost.TransferValue - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return 1 + } sender := runtime.GetContextAddress() dest, err := context.MemLoad(destOffset, vmhost.AddressLen) @@ -567,7 +597,10 @@ func (context *VMHooksImpl) TransferValue( } gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.PersistPerByte, uint64(length)) - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return 1 + } data, err := context.MemLoad(dataOffset, length) if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -684,7 +717,10 @@ func (context *VMHooksImpl) extractIndirectContractCallArguments( } gasToUse := math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(actualLen)) - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if err != nil { + return nil, err + } return &indirectContractCallArguments{ dest: dest, @@ -738,7 +774,10 @@ func (context *VMHooksImpl) TransferValueExecuteWithHost( metering.StartGasTracing(transferValueExecuteName) gasToUse := metering.GasSchedule().BaseOpsAPICost.TransferValue - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return 1 + } callArgs, err := context.extractIndirectContractCallArgumentsWithValue( host, destOffset, valueOffset, functionOffset, functionLength, numArguments, argumentsLengthOffset, dataOffset) @@ -770,13 +809,14 @@ func TransferValueExecuteWithTypedArgs( output := host.Output() gasToUse := metering.GasSchedule().BaseOpsAPICost.TransferValue - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return 1 + } sender := runtime.GetContextAddress() - var err error var contractCallInput *vmcommon.ContractCallInput - if len(function) > 0 { contractCallInput, err = prepareIndirectContractCallInput( host, @@ -819,7 +859,11 @@ func TransferValueExecuteWithTypedArgs( data = makeCrossShardCallFromInput(contractCallInput.Function, contractCallInput.Arguments) } - metering.UseAndTraceGas(uint64(gasLimit)) + err = metering.UseGasBounded(uint64(gasLimit)) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return 1 + } + err = output.Transfer(dest, sender, uint64(gasLimit), 0, value, nil, []byte(data), vm.DirectCall) if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { return 1 @@ -920,7 +964,10 @@ func (context *VMHooksImpl) MultiTransferESDTNFTExecute( } gasToUse := math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(callArgs.actualLen)) - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return 1 + } transferArgs, actualLen, err := context.getArgumentsFromMemory( host, @@ -934,7 +981,10 @@ func (context *VMHooksImpl) MultiTransferESDTNFTExecute( } gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(actualLen)) - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return 1 + } transfers := make([]*vmcommon.ESDTTransfer, numTokenTransfers) for i := int32(0); i < numTokenTransfers; i++ { @@ -991,7 +1041,10 @@ func (context *VMHooksImpl) TransferESDTNFTExecuteWithHost( } gasToUse := math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(callArgs.actualLen)) - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return 1 + } transfer := &vmcommon.ESDTTransfer{ ESDTValue: callArgs.value, @@ -1029,7 +1082,10 @@ func TransferESDTNFTExecuteWithTypedArgs( output := host.Output() gasToUse := metering.GasSchedule().BaseOpsAPICost.TransferValue * uint64(len(transfers)) - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return 1 + } sender := runtime.GetContextAddress() @@ -1182,7 +1238,10 @@ func CreateAsyncCallWithTypedArgs(host vmhost.VMHost, metering.StartGasTracing(createAsyncCallName) gasToUse := metering.GasSchedule().BaseOpsAPICost.CreateAsyncCall - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return 1 + } asyncCall := &vmhost.AsyncCall{ Status: vmhost.AsyncCallPending, @@ -1198,10 +1257,13 @@ func CreateAsyncCallWithTypedArgs(host vmhost.VMHost, if asyncCall.HasDefinedAnyCallback() { gasToUse := metering.GasSchedule().BaseOpsAPICost.SetAsyncCallback - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return 1 + } } - err := async.RegisterAsyncCall("", asyncCall) + err = async.RegisterAsyncCall("", asyncCall) if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { return 1 } @@ -1225,7 +1287,10 @@ func (context *VMHooksImpl) SetAsyncContextCallback( metering.StartGasTracing(setAsyncContextCallbackName) gasToUse := metering.GasSchedule().BaseOpsAPICost.SetAsyncContextCallback - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return 1 + } callbackNameBytes, err := context.MemLoad(callback, callbackLength) if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -1268,7 +1333,10 @@ func (context *VMHooksImpl) UpgradeContract( metering.StartGasTracing(upgradeContractName) gasToUse := metering.GasSchedule().BaseOpsAPICost.CreateContract - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } value, err := context.MemLoad(valueOffset, vmhost.BalanceLen) if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -1293,7 +1361,10 @@ func (context *VMHooksImpl) UpgradeContract( ) gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(actualLen)) - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { return @@ -1306,7 +1377,10 @@ func (context *VMHooksImpl) UpgradeContract( gasSchedule := metering.GasSchedule() gasToUse = math.MulUint64(gasSchedule.BaseOperationCost.DataCopyPerByte, uint64(length)) - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } upgradeContract(host, calledSCAddress, code, codeMetadata, value, data, gasLimit) } @@ -1329,7 +1403,10 @@ func (context *VMHooksImpl) UpgradeFromSourceContract( metering.StartGasTracing(upgradeFromSourceContractName) gasToUse := metering.GasSchedule().BaseOpsAPICost.CreateContract - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } value, err := context.MemLoad(valueOffset, vmhost.BalanceLen) if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -1354,7 +1431,10 @@ func (context *VMHooksImpl) UpgradeFromSourceContract( ) gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(actualLen)) - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { return @@ -1457,7 +1537,10 @@ func (context *VMHooksImpl) DeleteContract( metering.StartGasTracing(deleteContractName) gasToUse := metering.GasSchedule().BaseOpsAPICost.CreateContract - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } data, actualLen, err := context.getArgumentsFromMemory( host, @@ -1467,7 +1550,10 @@ func (context *VMHooksImpl) DeleteContract( ) gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(actualLen)) - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { return @@ -1541,7 +1627,10 @@ func (context *VMHooksImpl) AsyncCall( gasSchedule := metering.GasSchedule() gasToUse := gasSchedule.BaseOpsAPICost.AsyncCallStep - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } calledSCAddress, err := context.MemLoad(destOffset, vmhost.AddressLen) if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -1554,7 +1643,10 @@ func (context *VMHooksImpl) AsyncCall( } gasToUse = math.MulUint64(gasSchedule.BaseOperationCost.DataCopyPerByte, uint64(length)) - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } data, err := context.MemLoad(dataOffset, length) if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -1578,7 +1670,10 @@ func (context *VMHooksImpl) GetArgumentLength(id int32) int32 { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetArgument - metering.UseGasAndAddTracedGas(getArgumentLengthName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getArgumentLengthName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return -1 + } args := runtime.Arguments() if id < 0 || int32(len(args)) <= id { @@ -1596,7 +1691,10 @@ func (context *VMHooksImpl) GetArgument(id int32, argOffset executor.MemPtr) int metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetArgument - metering.UseGasAndAddTracedGas(getArgumentName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getArgumentName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return -1 + } args := runtime.Arguments() if id < 0 || int32(len(args)) <= id { @@ -1604,7 +1702,7 @@ func (context *VMHooksImpl) GetArgument(id int32, argOffset executor.MemPtr) int return -1 } - err := context.MemStore(argOffset, args[id]) + err = context.MemStore(argOffset, args[id]) if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { return -1 } @@ -1619,10 +1717,13 @@ func (context *VMHooksImpl) GetFunction(functionOffset executor.MemPtr) int32 { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetFunction - metering.UseGasAndAddTracedGas(getFunctionName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getFunctionName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return -1 + } function := runtime.FunctionName() - err := context.MemStore(functionOffset, []byte(function)) + err = context.MemStore(functionOffset, []byte(function)) if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { return -1 } @@ -1637,7 +1738,10 @@ func (context *VMHooksImpl) GetNumArguments() int32 { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetNumArguments - metering.UseGasAndAddTracedGas(getNumArgumentsName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getNumArgumentsName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return -1 + } args := runtime.Arguments() return int32(len(args)) @@ -1691,7 +1795,10 @@ func StorageStoreWithTypedArgs(host vmhost.VMHost, key []byte, data []byte) int3 metering := host.Metering() gasToUse := metering.GasSchedule().BaseOpsAPICost.StorageStore - metering.UseGasAndAddTracedGas(storageStoreName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(storageStoreName, gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return -1 + } storageStatus, err := storage.SetStorage(key, data) if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -2553,7 +2660,10 @@ func ExecuteOnSameContextWithTypedArgs( metering := host.Metering() gasToUse := metering.GasSchedule().BaseOpsAPICost.ExecuteOnSameContext - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return -1 + } sender := runtime.GetContextAddress() @@ -2657,7 +2767,10 @@ func ExecuteOnDestContextWithTypedArgs( metering := host.Metering() gasToUse := metering.GasSchedule().BaseOpsAPICost.ExecuteOnDestContext - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return -1 + } sender := runtime.GetContextAddress() @@ -2753,7 +2866,10 @@ func ExecuteReadOnlyWithTypedArguments( metering := host.Metering() gasToUse := metering.GasSchedule().BaseOpsAPICost.ExecuteReadOnly - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return -1 + } sender := runtime.GetContextAddress() @@ -2835,7 +2951,10 @@ func (context *VMHooksImpl) createContractWithHost( metering.StartGasTracing(createContractName) gasToUse := metering.GasSchedule().BaseOpsAPICost.CreateContract - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return -1 + } sender := runtime.GetContextAddress() value, err := context.MemLoad(valueOffset, vmhost.BalanceLen) @@ -2859,10 +2978,12 @@ func (context *VMHooksImpl) createContractWithHost( argumentsLengthOffset, dataOffset, ) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return 1 + } gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(actualLen)) - metering.UseAndTraceGas(gasToUse) - + err = metering.UseGasBounded(gasToUse) if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { return 1 } @@ -2900,7 +3021,10 @@ func (context *VMHooksImpl) DeployFromSourceContract( metering.StartGasTracing(deployFromSourceContractName) gasToUse := metering.GasSchedule().BaseOpsAPICost.CreateContract - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return 1 + } value, err := context.MemLoad(valueOffset, vmhost.BalanceLen) if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -2923,10 +3047,12 @@ func (context *VMHooksImpl) DeployFromSourceContract( argumentsLengthOffset, dataOffset, ) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return 1 + } gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(actualLen)) - metering.UseAndTraceGas(gasToUse) - + err = metering.UseGasBounded(gasToUse) if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { return 1 } diff --git a/vmhost/vmhooks/bigIntOps.go b/vmhost/vmhooks/bigIntOps.go index c2dada30e..1642a2034 100644 --- a/vmhost/vmhooks/bigIntOps.go +++ b/vmhost/vmhooks/bigIntOps.go @@ -361,14 +361,21 @@ func (context *VMHooksImpl) BigIntSetUnsignedBytes(destinationHandle int32, byte metering.StartGasTracing(bigIntSetUnsignedBytesName) gasToUse := metering.GasSchedule().BigIntAPICost.BigIntSetUnsignedBytes - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } bytes, err := context.MemLoad(byteOffset, byteLength) if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { return } gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(len(bytes))) - metering.UseGas(gasToUse) + + err = metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } value := managedType.GetBigIntOrCreate(destinationHandle) value.SetBytes(bytes) @@ -383,14 +390,21 @@ func (context *VMHooksImpl) BigIntSetSignedBytes(destinationHandle int32, byteOf metering.StartGasTracing(bigIntSetSignedBytesName) gasToUse := metering.GasSchedule().BigIntAPICost.BigIntSetSignedBytes - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } bytes, err := context.MemLoad(byteOffset, byteLength) if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { return } gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(len(bytes))) - metering.UseGas(gasToUse) + + err = metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } value := managedType.GetBigIntOrCreate(destinationHandle) twos.SetBytes(value, bytes) diff --git a/vmhost/vmhooks/vmHooksImpl.go b/vmhost/vmhooks/vmHooksImpl.go index 7cb0d9c50..c55fb00b9 100644 --- a/vmhost/vmhooks/vmHooksImpl.go +++ b/vmhost/vmhooks/vmHooksImpl.go @@ -107,7 +107,7 @@ func WithFaultAndHost(host vmhost.VMHost, err error, failExecution bool) bool { if failExecution { runtime := host.Runtime() metering := host.Metering() - metering.UseGas(metering.GasLeft()) + _ = metering.UseGasBounded(metering.GasLeft()) runtime.FailExecution(err) } From b0886828902a89cffd94c6ac9019c71ced6abf55 Mon Sep 17 00:00:00 2001 From: robertsasu Date: Thu, 8 Aug 2024 15:26:22 +0300 Subject: [PATCH 02/24] refactoring gasUsage --- vmhost/vmhooks/baseOps.go | 181 +++++++++++++++++++++++++++++--------- 1 file changed, 137 insertions(+), 44 deletions(-) diff --git a/vmhost/vmhooks/baseOps.go b/vmhost/vmhooks/baseOps.go index 9b10aaeec..c6c2584d1 100644 --- a/vmhost/vmhooks/baseOps.go +++ b/vmhost/vmhooks/baseOps.go @@ -1981,7 +1981,10 @@ func (context *VMHooksImpl) SetStorageLockWithHost(host vmhost.VMHost, keyOffset metering := host.Metering() gasToUse := metering.GasSchedule().BaseOpsAPICost.Int64StorageStore - metering.UseGasAndAddTracedGas(setStorageLockName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(setStorageLockName, gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return -1 + } key, err := context.MemLoad(keyOffset, keyLength) if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -2013,7 +2016,10 @@ func (context *VMHooksImpl) GetStorageLock(keyOffset executor.MemPtr, keyLength storage := context.GetStorageContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.StorageLoad - metering.UseGasAndAddTracedGas(getStorageLockName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getStorageLockName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return -1 + } key, err := context.MemLoad(keyOffset, keyLength) if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -2073,11 +2079,14 @@ func (context *VMHooksImpl) GetCaller(resultOffset executor.MemPtr) { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetCaller - metering.UseGasAndAddTracedGas(getCallerName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getCallerName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } caller := runtime.GetVMInput().CallerAddr - err := context.MemStore(resultOffset, caller) + err = context.MemStore(resultOffset, caller) if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { return } @@ -2090,7 +2099,10 @@ func (context *VMHooksImpl) CheckNoPayment() { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetCallValue - metering.UseGasAndAddTracedGas(checkNoPaymentName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(checkNoPaymentName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } vmInput := runtime.GetVMInput() if vmInput.CallValue.Sign() > 0 { @@ -2110,12 +2122,15 @@ func (context *VMHooksImpl) GetCallValue(resultOffset executor.MemPtr) int32 { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetCallValue - metering.UseGasAndAddTracedGas(callValueName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(callValueName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return -1 + } value := runtime.GetVMInput().CallValue.Bytes() value = vmhost.PadBytesLeft(value, vmhost.BalanceLen) - err := context.MemStore(resultOffset, value) + err = context.MemStore(resultOffset, value) if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { return -1 } @@ -2140,7 +2155,10 @@ func (context *VMHooksImpl) GetESDTValueByIndex(resultOffset executor.MemPtr, in metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetCallValue - metering.UseGasAndAddTracedGas(getESDTValueByIndexName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getESDTValueByIndexName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return -1 + } var value []byte @@ -2150,7 +2168,7 @@ func (context *VMHooksImpl) GetESDTValueByIndex(resultOffset executor.MemPtr, in value = vmhost.PadBytesLeft(value, vmhost.BalanceLen) } - err := context.MemStore(resultOffset, value) + err = context.MemStore(resultOffset, value) if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { return -1 } @@ -2175,7 +2193,10 @@ func (context *VMHooksImpl) GetESDTTokenNameByIndex(resultOffset executor.MemPtr metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetCallValue - metering.UseGasAndAddTracedGas(getESDTTokenNameByIndexName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getESDTTokenNameByIndexName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return -1 + } esdtTransfer := getESDTTransferFromInputFailIfWrongIndex(context.GetVMHost(), index) var tokenName []byte @@ -2183,7 +2204,7 @@ func (context *VMHooksImpl) GetESDTTokenNameByIndex(resultOffset executor.MemPtr tokenName = esdtTransfer.ESDTTokenName } - err := context.MemStore(resultOffset, tokenName) + err = context.MemStore(resultOffset, tokenName) if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { return -1 } @@ -2207,7 +2228,10 @@ func (context *VMHooksImpl) GetESDTTokenNonceByIndex(index int32) int64 { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetCallValue - metering.UseGasAndAddTracedGas(getESDTTokenNonceByIndexName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getESDTTokenNonceByIndexName, gasToUse) + if context.WithFault(err, context.GetRuntimeContext().BaseOpsErrorShouldFailExecution()) { + return -1 + } esdtTransfer := getESDTTransferFromInputFailIfWrongIndex(context.GetVMHost(), index) nonce := uint64(0) @@ -2273,7 +2297,10 @@ func (context *VMHooksImpl) GetESDTTokenTypeByIndex(index int32) int32 { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetCallValue - metering.UseGasAndAddTracedGas(getESDTTokenTypeByIndexName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getESDTTokenTypeByIndexName, gasToUse) + if context.WithFault(err, context.GetRuntimeContext().BaseOpsErrorShouldFailExecution()) { + return -1 + } esdtTransfer := getESDTTransferFromInputFailIfWrongIndex(context.GetVMHost(), index) if esdtTransfer != nil { @@ -2289,7 +2316,10 @@ func (context *VMHooksImpl) GetNumESDTTransfers() int32 { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetCallValue - metering.UseGasAndAddTracedGas(getNumESDTTransfersName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getNumESDTTransfersName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return -1 + } return int32(len(runtime.GetVMInput().ESDTTransfers)) } @@ -2315,7 +2345,10 @@ func (context *VMHooksImpl) GetCallValueTokenNameByIndex( metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetCallValue - metering.UseGasAndAddTracedGas(getCallValueTokenNameByIndexName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getCallValueTokenNameByIndexName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return -1 + } callValue := runtime.GetVMInput().CallValue.Bytes() tokenName := make([]byte, 0) @@ -2328,7 +2361,7 @@ func (context *VMHooksImpl) GetCallValueTokenNameByIndex( } callValue = vmhost.PadBytesLeft(callValue, vmhost.BalanceLen) - err := context.MemStore(tokenNameOffset, tokenName) + err = context.MemStore(tokenNameOffset, tokenName) if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { return -1 } @@ -2357,7 +2390,10 @@ func (context *VMHooksImpl) WriteLog( gasToUse := metering.GasSchedule().BaseOpsAPICost.Log gas := math.MulUint64(metering.GasSchedule().BaseOperationCost.PersistPerByte, uint64(numTopics*vmhost.HashLen+dataLength)) gasToUse = math.AddUint64(gasToUse, gas) - metering.UseGasAndAddTracedGas(writeLogName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(writeLogName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } if numTopics < 0 || dataLength < 0 { err := vmhost.ErrNegativeLength @@ -2416,7 +2452,10 @@ func (context *VMHooksImpl) WriteEventLog( metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(topicDataTotalLen+dataLength)) gasToUse = math.AddUint64(gasToUse, gasForData) - metering.UseGasAndAddTracedGas(writeEventLogName, gasToUse) + err = metering.UseGasBoundedAndAddTracedGas(writeEventLogName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } output.WriteLog(runtime.GetContextAddress(), topics, [][]byte{data}) } @@ -2428,7 +2467,10 @@ func (context *VMHooksImpl) GetBlockTimestamp() int64 { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetBlockTimeStamp - metering.UseGasAndAddTracedGas(getBlockTimestampName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getBlockTimestampName, gasToUse) + if context.WithFault(err, context.GetRuntimeContext().BaseOpsErrorShouldFailExecution()) { + return -1 + } return int64(blockchain.CurrentTimeStamp()) } @@ -2440,7 +2482,10 @@ func (context *VMHooksImpl) GetBlockNonce() int64 { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetBlockNonce - metering.UseGasAndAddTracedGas(getBlockNonceName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getBlockNonceName, gasToUse) + if context.WithFault(err, context.GetRuntimeContext().BaseOpsErrorShouldFailExecution()) { + return -1 + } return int64(blockchain.CurrentNonce()) } @@ -2452,7 +2497,10 @@ func (context *VMHooksImpl) GetBlockRound() int64 { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetBlockRound - metering.UseGasAndAddTracedGas(getBlockRoundName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getBlockRoundName, gasToUse) + if context.WithFault(err, context.GetRuntimeContext().BaseOpsErrorShouldFailExecution()) { + return -1 + } return int64(blockchain.CurrentRound()) } @@ -2464,7 +2512,10 @@ func (context *VMHooksImpl) GetBlockEpoch() int64 { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetBlockEpoch - metering.UseGasAndAddTracedGas(getBlockEpochName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getBlockEpochName, gasToUse) + if context.WithFault(err, context.GetRuntimeContext().BaseOpsErrorShouldFailExecution()) { + return -1 + } return int64(blockchain.CurrentEpoch()) } @@ -2477,10 +2528,13 @@ func (context *VMHooksImpl) GetBlockRandomSeed(pointer executor.MemPtr) { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetBlockRandomSeed - metering.UseGasAndAddTracedGas(getBlockRandomSeedName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getBlockRandomSeedName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } randomSeed := blockchain.CurrentRandomSeed() - err := context.MemStore(pointer, randomSeed) + err = context.MemStore(pointer, randomSeed) context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) } @@ -2492,10 +2546,13 @@ func (context *VMHooksImpl) GetStateRootHash(pointer executor.MemPtr) { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetStateRootHash - metering.UseGasAndAddTracedGas(getStateRootHashName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getStateRootHashName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } stateRootHash := blockchain.GetStateRootHash() - err := context.MemStore(pointer, stateRootHash) + err = context.MemStore(pointer, stateRootHash) context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) } @@ -2506,7 +2563,10 @@ func (context *VMHooksImpl) GetPrevBlockTimestamp() int64 { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetBlockTimeStamp - metering.UseGasAndAddTracedGas(getPrevBlockTimestampName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getPrevBlockTimestampName, gasToUse) + if context.WithFault(err, context.GetRuntimeContext().BaseOpsErrorShouldFailExecution()) { + return -1 + } return int64(blockchain.LastTimeStamp()) } @@ -2518,7 +2578,10 @@ func (context *VMHooksImpl) GetPrevBlockNonce() int64 { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetBlockNonce - metering.UseGasAndAddTracedGas(getPrevBlockNonceName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getPrevBlockNonceName, gasToUse) + if context.WithFault(err, context.GetRuntimeContext().BaseOpsErrorShouldFailExecution()) { + return -1 + } return int64(blockchain.LastNonce()) } @@ -2530,7 +2593,10 @@ func (context *VMHooksImpl) GetPrevBlockRound() int64 { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetBlockRound - metering.UseGasAndAddTracedGas(getPrevBlockRoundName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getPrevBlockRoundName, gasToUse) + if context.WithFault(err, context.GetRuntimeContext().BaseOpsErrorShouldFailExecution()) { + return -1 + } return int64(blockchain.LastRound()) } @@ -2542,7 +2608,10 @@ func (context *VMHooksImpl) GetPrevBlockEpoch() int64 { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetBlockEpoch - metering.UseGasAndAddTracedGas(getPrevBlockEpochName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getPrevBlockEpochName, gasToUse) + if context.WithFault(err, context.GetRuntimeContext().BaseOpsErrorShouldFailExecution()) { + return -1 + } return int64(blockchain.LastEpoch()) } @@ -2555,10 +2624,13 @@ func (context *VMHooksImpl) GetPrevBlockRandomSeed(pointer executor.MemPtr) { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetBlockRandomSeed - metering.UseGasAndAddTracedGas(getPrevBlockRandomSeedName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getPrevBlockRandomSeedName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } randomSeed := blockchain.LastRandomSeed() - err := context.MemStore(pointer, randomSeed) + err = context.MemStore(pointer, randomSeed) context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) } @@ -2574,7 +2646,6 @@ func (context *VMHooksImpl) Finish(pointer executor.MemPtr, length executor.MemL gas := math.MulUint64(metering.GasSchedule().BaseOperationCost.PersistPerByte, uint64(length)) gasToUse = math.AddUint64(gasToUse, gas) err := metering.UseGasBounded(gasToUse) - if err != nil { _ = context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) return @@ -3134,7 +3205,10 @@ func (context *VMHooksImpl) GetNumReturnData() int32 { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetNumReturnData - metering.UseGasAndAddTracedGas(getNumReturnDataName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getNumReturnDataName, gasToUse) + if context.WithFault(err, context.GetRuntimeContext().BaseOpsErrorShouldFailExecution()) { + return -1 + } returnData := output.ReturnData() return int32(len(returnData)) @@ -3148,7 +3222,10 @@ func (context *VMHooksImpl) GetReturnDataSize(resultID int32) int32 { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetReturnDataSize - metering.UseGasAndAddTracedGas(getReturnDataSizeName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getReturnDataSizeName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return -1 + } returnData := output.ReturnData() if resultID >= int32(len(returnData)) || resultID < 0 { @@ -3183,7 +3260,10 @@ func GetReturnDataWithHostAndTypedArgs(host vmhost.VMHost, resultID int32) []byt metering := host.Metering() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetReturnData - metering.UseGasAndAddTracedGas(getReturnDataName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getReturnDataName, gasToUse) + if WithFaultAndHost(host, err, host.Runtime().BaseOpsErrorShouldFailExecution()) { + return nil + } returnData := output.ReturnData() if resultID >= int32(len(returnData)) || resultID < 0 { @@ -3207,7 +3287,10 @@ func CleanReturnDataWithHost(host vmhost.VMHost) { metering := host.Metering() gasToUse := metering.GasSchedule().BaseOpsAPICost.CleanReturnData - metering.UseGasAndAddTracedGas(cleanReturnDataName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(cleanReturnDataName, gasToUse) + if WithFaultAndHost(host, err, host.Runtime().BaseOpsErrorShouldFailExecution()) { + return + } output.ClearReturnData() } @@ -3225,7 +3308,10 @@ func DeleteFromReturnDataWithHost(host vmhost.VMHost, resultID int32) { metering := host.Metering() gasToUse := metering.GasSchedule().BaseOpsAPICost.DeleteFromReturnData - metering.UseGasAndAddTracedGas(deleteFromReturnDataName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(deleteFromReturnDataName, gasToUse) + if WithFaultAndHost(host, err, host.Runtime().BaseOpsErrorShouldFailExecution()) { + return + } returnData := output.ReturnData() if resultID < int32(len(returnData)) { @@ -3240,9 +3326,12 @@ func (context *VMHooksImpl) GetOriginalTxHash(dataOffset executor.MemPtr) { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetOriginalTxHash - metering.UseGasAndAddTracedGas(getOriginalTxHashName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getOriginalTxHashName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } - err := context.MemStore(dataOffset, runtime.GetOriginalTxHash()) + err = context.MemStore(dataOffset, runtime.GetOriginalTxHash()) _ = context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) } @@ -3253,9 +3342,12 @@ func (context *VMHooksImpl) GetCurrentTxHash(dataOffset executor.MemPtr) { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetCurrentTxHash - metering.UseGasAndAddTracedGas(getCurrentTxHashName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getCurrentTxHashName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } - err := context.MemStore(dataOffset, runtime.GetCurrentTxHash()) + err = context.MemStore(dataOffset, runtime.GetCurrentTxHash()) _ = context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) } @@ -3266,9 +3358,10 @@ func (context *VMHooksImpl) GetPrevTxHash(dataOffset executor.MemPtr) { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetPrevTxHash - metering.UseGasAndAddTracedGas(getPrevTxHashName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getPrevTxHashName, gasToUse) + context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) - err := context.MemStore(dataOffset, runtime.GetPrevTxHash()) + err = context.MemStore(dataOffset, runtime.GetPrevTxHash()) _ = context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) } From 143497008850c7afcacc754754b802008d711098 Mon Sep 17 00:00:00 2001 From: robertsasu Date: Thu, 8 Aug 2024 15:57:48 +0300 Subject: [PATCH 03/24] refactoring gasUsage --- vmhost/vmhooks/bigFloatOps.go | 113 +++++++++++++---- vmhost/vmhooks/bigIntOps.go | 225 +++++++++++++++++++++++++++------- 2 files changed, 269 insertions(+), 69 deletions(-) diff --git a/vmhost/vmhooks/bigFloatOps.go b/vmhost/vmhooks/bigFloatOps.go index 3fba2993f..d53c091d2 100644 --- a/vmhost/vmhooks/bigFloatOps.go +++ b/vmhost/vmhooks/bigFloatOps.go @@ -72,13 +72,16 @@ func (context *VMHooksImpl) BigFloatNewFromParts(integralPart, fractionalPart, e metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BigFloatAPICost.BigFloatNewFromParts - metering.UseGasAndAddTracedGas(bigFloatNewFromPartsName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(bigFloatNewFromPartsName, gasToUse) + if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { + return -1 + } if exponent > 0 { _ = context.WithFault(vmhost.ErrPositiveExponent, runtime.BigFloatAPIErrorShouldFailExecution()) return -1 } - var err error + var bigFractional *big.Float if exponent < -322 { bigFractional = big.NewFloat(0) @@ -118,7 +121,10 @@ func (context *VMHooksImpl) BigFloatNewFromFrac(numerator, denominator int64) in metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BigFloatAPICost.BigFloatNewFromParts - metering.UseGasAndAddTracedGas(bigFloatNewFromFracName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(bigFloatNewFromFracName, gasToUse) + if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { + return -1 + } if denominator == 0 { _ = context.WithFault(vmhost.ErrDivZero, runtime.BigFloatAPIErrorShouldFailExecution()) @@ -146,7 +152,10 @@ func (context *VMHooksImpl) BigFloatNewFromSci(significand, exponent int64) int3 metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BigFloatAPICost.BigFloatNewFromParts - metering.UseGasAndAddTracedGas(bigFloatNewFromSciName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(bigFloatNewFromSciName, gasToUse) + if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { + return -1 + } if exponent > 0 { _ = context.WithFault(vmhost.ErrPositiveExponent, runtime.BigFloatAPIErrorShouldFailExecution()) @@ -182,7 +191,10 @@ func (context *VMHooksImpl) BigFloatAdd(destinationHandle, op1Handle, op2Handle metering.StartGasTracing(bigFloatAddName) gasToUse := metering.GasSchedule().BigFloatAPICost.BigFloatAdd - metering.UseGasAndAddTracedGas(bigFloatAddName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(bigFloatAddName, gasToUse) + if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { + return + } op1, op2, err := managedType.GetTwoBigFloats(op1Handle, op2Handle) if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { @@ -206,7 +218,10 @@ func (context *VMHooksImpl) BigFloatSub(destinationHandle, op1Handle, op2Handle metering.StartGasTracing(bigFloatSubName) gasToUse := metering.GasSchedule().BigFloatAPICost.BigFloatSub - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { + return + } op1, op2, err := managedType.GetTwoBigFloats(op1Handle, op2Handle) if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { @@ -229,7 +244,10 @@ func (context *VMHooksImpl) BigFloatMul(destinationHandle, op1Handle, op2Handle metering.StartGasTracing(bigFloatMulName) gasToUse := metering.GasSchedule().BigFloatAPICost.BigFloatMul - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { + return + } op1, op2, err := managedType.GetTwoBigFloats(op1Handle, op2Handle) @@ -253,7 +271,10 @@ func (context *VMHooksImpl) BigFloatDiv(destinationHandle, op1Handle, op2Handle metering.StartGasTracing(bigFloatDivName) gasToUse := metering.GasSchedule().BigFloatAPICost.BigFloatDiv - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { + return + } op1, op2, err := managedType.GetTwoBigFloats(op1Handle, op2Handle) @@ -281,7 +302,10 @@ func (context *VMHooksImpl) BigFloatNeg(destinationHandle, opHandle int32) { metering.StartGasTracing(bigFloatNegName) gasToUse := metering.GasSchedule().BigFloatAPICost.BigFloatNeg - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { + return + } dest, err := managedType.GetBigFloatOrCreate(destinationHandle) if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { @@ -304,7 +328,10 @@ func (context *VMHooksImpl) BigFloatClone(destinationHandle, opHandle int32) { metering.StartGasTracing(bigFloatCloneName) gasToUse := metering.GasSchedule().BigFloatAPICost.BigFloatClone - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { + return + } dest, err := managedType.GetBigFloatOrCreate(destinationHandle) if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { @@ -327,7 +354,10 @@ func (context *VMHooksImpl) BigFloatCmp(op1Handle, op2Handle int32) int32 { metering.StartGasTracing(bigFloatCmpName) gasToUse := metering.GasSchedule().BigFloatAPICost.BigFloatCmp - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { + return -2 + } op1, op2, err := managedType.GetTwoBigFloats(op1Handle, op2Handle) @@ -346,7 +376,10 @@ func (context *VMHooksImpl) BigFloatAbs(destinationHandle, opHandle int32) { metering.StartGasTracing(bigFloatAbsName) gasToUse := metering.GasSchedule().BigFloatAPICost.BigFloatAbs - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { + return + } dest, err := managedType.GetBigFloatOrCreate(destinationHandle) if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { @@ -368,7 +401,10 @@ func (context *VMHooksImpl) BigFloatSign(opHandle int32) int32 { runtime := context.GetRuntimeContext() gasToUse := metering.GasSchedule().BigFloatAPICost.BigFloatAbs - metering.UseGasAndAddTracedGas(bigFloatSignName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(bigFloatSignName, gasToUse) + if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { + return -2 + } op, err := managedType.GetBigFloat(opHandle) if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { @@ -386,7 +422,10 @@ func (context *VMHooksImpl) BigFloatSqrt(destinationHandle, opHandle int32) { metering.StartGasTracing(bigFloatSqrtName) gasToUse := metering.GasSchedule().BigFloatAPICost.BigFloatSqrt - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { + return + } dest, err := managedType.GetBigFloatOrCreate(destinationHandle) if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { @@ -417,7 +456,10 @@ func (context *VMHooksImpl) BigFloatPow(destinationHandle, opHandle, exponent in metering.StartGasTracing(bigFloatPowName) gasToUse := metering.GasSchedule().BigFloatAPICost.BigFloatPow - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { + return + } op, err := managedType.GetBigFloat(opHandle) if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { @@ -470,7 +512,10 @@ func (context *VMHooksImpl) BigFloatFloor(destBigIntHandle, opHandle int32) { metering.StartGasTracing(bigFloatFloorName) gasToUse := metering.GasSchedule().BigFloatAPICost.BigFloatFloor - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { + return + } op, err := managedType.GetBigFloat(opHandle) if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { @@ -497,7 +542,10 @@ func (context *VMHooksImpl) BigFloatCeil(destBigIntHandle, opHandle int32) { metering.StartGasTracing(bigFloatCeilName) gasToUse := metering.GasSchedule().BigFloatAPICost.BigFloatCeil - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { + return + } op, err := managedType.GetBigFloat(opHandle) if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { @@ -524,7 +572,10 @@ func (context *VMHooksImpl) BigFloatTruncate(destBigIntHandle, opHandle int32) { metering.StartGasTracing(bigFloatTruncateName) gasToUse := metering.GasSchedule().BigFloatAPICost.BigFloatTruncate - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { + return + } op, err := managedType.GetBigFloat(opHandle) if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { @@ -544,7 +595,10 @@ func (context *VMHooksImpl) BigFloatSetInt64(destinationHandle int32, value int6 runtime := context.GetRuntimeContext() gasToUse := metering.GasSchedule().BigFloatAPICost.BigFloatSetInt64 - metering.UseGasAndAddTracedGas(bigFloatSetInt64Name, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(bigFloatSetInt64Name, gasToUse) + if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { + return + } dest, err := managedType.GetBigFloatOrCreate(destinationHandle) if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { @@ -562,7 +616,11 @@ func (context *VMHooksImpl) BigFloatIsInt(opHandle int32) int32 { metering.StartGasTracing(bigFloatIsIntName) gasToUse := metering.GasSchedule().BigFloatAPICost.BigFloatIsInt - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { + return -1 + } + op, err := managedType.GetBigFloat(opHandle) if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { return -1 @@ -582,7 +640,10 @@ func (context *VMHooksImpl) BigFloatSetBigInt(destinationHandle, bigIntHandle in metering.StartGasTracing(bigFloatSetBigIntName) gasToUse := metering.GasSchedule().BigFloatAPICost.BigFloatSetBigInt - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { + return + } bigIntValue, err := managedType.GetBigInt(bigIntHandle) managedType.ConsumeGasForBigIntCopy(bigIntValue) @@ -601,7 +662,10 @@ func (context *VMHooksImpl) BigFloatGetConstPi(destinationHandle int32) { runtime := context.GetRuntimeContext() gasToUse := metering.GasSchedule().BigFloatAPICost.BigFloatGetConst - metering.UseGasAndAddTracedGas(bigFloatGetConstPiName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(bigFloatGetConstPiName, gasToUse) + if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { + return + } pi, err := managedType.GetBigFloatOrCreate(destinationHandle) if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { @@ -618,7 +682,10 @@ func (context *VMHooksImpl) BigFloatGetConstE(destinationHandle int32) { runtime := context.GetRuntimeContext() gasToUse := metering.GasSchedule().BigFloatAPICost.BigFloatGetConst - metering.UseGasAndAddTracedGas(bigFloatGetConstEName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(bigFloatGetConstEName, gasToUse) + if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { + return + } e, err := managedType.GetBigFloatOrCreate(destinationHandle) if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { diff --git a/vmhost/vmhooks/bigIntOps.go b/vmhost/vmhooks/bigIntOps.go index 1642a2034..ba0c37536 100644 --- a/vmhost/vmhooks/bigIntOps.go +++ b/vmhost/vmhooks/bigIntOps.go @@ -62,7 +62,10 @@ func (context *VMHooksImpl) BigIntGetUnsignedArgument(id int32, destinationHandl metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BigIntAPICost.BigIntGetUnsignedArgument - metering.UseGasAndAddTracedGas(bigIntGetUnsignedArgumentName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(bigIntGetUnsignedArgumentName, gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } args := runtime.Arguments() if int32(len(args)) <= id || id < 0 { @@ -82,7 +85,10 @@ func (context *VMHooksImpl) BigIntGetSignedArgument(id int32, destinationHandle metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BigIntAPICost.BigIntGetSignedArgument - metering.UseGasAndAddTracedGas(bigIntGetSignedArgumentName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(bigIntGetSignedArgumentName, gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } args := runtime.Arguments() if int32(len(args)) <= id || id < 0 { @@ -103,7 +109,10 @@ func (context *VMHooksImpl) BigIntStorageStoreUnsigned(keyOffset executor.MemPtr metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BigIntAPICost.BigIntStorageStoreUnsigned - metering.UseGasAndAddTracedGas(bigIntStorageStoreUnsignedName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(bigIntStorageStoreUnsignedName, gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return -1 + } key, err := context.MemLoad(keyOffset, keyLength) if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { @@ -161,7 +170,10 @@ func (context *VMHooksImpl) BigIntGetCallValue(destinationHandle int32) { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BigIntAPICost.BigIntGetCallValue - metering.UseGasAndAddTracedGas(bigIntGetCallValueName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(bigIntGetCallValueName, gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } value := managedType.GetBigIntOrCreate(destinationHandle) value.Set(runtime.GetVMInput().CallValue) @@ -184,7 +196,10 @@ func (context *VMHooksImpl) BigIntGetESDTCallValueByIndex(destinationHandle int3 metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BigIntAPICost.BigIntGetCallValue - metering.UseGasAndAddTracedGas(bigIntGetESDTCallValueByIndexName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(bigIntGetESDTCallValueByIndexName, gasToUse) + if context.WithFault(err, context.GetRuntimeContext().BigIntAPIErrorShouldFailExecution()) { + return + } value := managedType.GetBigIntOrCreate(destinationHandle) esdtTransfer := getESDTTransferFromInputFailIfWrongIndex(context.GetVMHost(), index) @@ -204,7 +219,10 @@ func (context *VMHooksImpl) BigIntGetExternalBalance(addressOffset executor.MemP metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BigIntAPICost.BigIntGetExternalBalance - metering.UseGasAndAddTracedGas(bigIntGetExternalBalanceName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(bigIntGetExternalBalanceName, gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } address, err := context.MemLoad(addressOffset, vmhost.AddressLen) if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { @@ -232,7 +250,10 @@ func (context *VMHooksImpl) BigIntGetESDTExternalBalance( metering.StartGasTracing(bigIntGetESDTExternalBalanceName) gasToUse := metering.GasSchedule().BigIntAPICost.BigIntGetExternalBalance - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } esdtData, err := getESDTDataFromBlockchainHook(context, addressOffset, tokenIDOffset, tokenIDLen, nonce) if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { @@ -253,7 +274,10 @@ func (context *VMHooksImpl) BigIntNew(smallValue int64) int32 { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BigIntAPICost.BigIntNew - metering.UseGasAndAddTracedGas(bigIntNewName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(bigIntNewName, gasToUse) + if context.WithFault(err, context.GetRuntimeContext().BigIntAPIErrorShouldFailExecution()) { + return -1 + } return managedType.NewBigIntFromInt64(smallValue) } @@ -266,7 +290,10 @@ func (context *VMHooksImpl) BigIntUnsignedByteLength(referenceHandle int32) int3 runtime := context.GetRuntimeContext() gasToUse := metering.GasSchedule().BigIntAPICost.BigIntUnsignedByteLength - metering.UseGasAndAddTracedGas(bigIntUnsignedByteLengthName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(bigIntUnsignedByteLengthName, gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return -1 + } value, err := managedType.GetBigInt(referenceHandle) if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { @@ -285,7 +312,10 @@ func (context *VMHooksImpl) BigIntSignedByteLength(referenceHandle int32) int32 runtime := context.GetRuntimeContext() gasToUse := metering.GasSchedule().BigIntAPICost.BigIntSignedByteLength - metering.UseGasAndAddTracedGas(bigIntSignedByteLengthName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(bigIntSignedByteLengthName, gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return -1 + } value, err := managedType.GetBigInt(referenceHandle) if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { @@ -305,7 +335,10 @@ func (context *VMHooksImpl) BigIntGetUnsignedBytes(referenceHandle int32, byteOf metering.StartGasTracing(bigIntGetUnsignedBytesName) gasToUse := metering.GasSchedule().BigIntAPICost.BigIntGetUnsignedBytes - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return -1 + } value, err := managedType.GetBigInt(referenceHandle) if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { @@ -319,7 +352,10 @@ func (context *VMHooksImpl) BigIntGetUnsignedBytes(referenceHandle int32, byteOf } gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(len(bytes))) - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return -1 + } return int32(len(bytes)) } @@ -333,7 +369,10 @@ func (context *VMHooksImpl) BigIntGetSignedBytes(referenceHandle int32, byteOffs metering.StartGasTracing(bigIntGetSignedBytesName) gasToUse := metering.GasSchedule().BigIntAPICost.BigIntGetSignedBytes - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return -1 + } value, err := managedType.GetBigInt(referenceHandle) if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { @@ -347,7 +386,10 @@ func (context *VMHooksImpl) BigIntGetSignedBytes(referenceHandle int32, byteOffs } gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(len(bytes))) - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return -1 + } return int32(len(bytes)) } @@ -418,7 +460,10 @@ func (context *VMHooksImpl) BigIntIsInt64(destinationHandle int32) int32 { runtime := context.GetRuntimeContext() gasToUse := metering.GasSchedule().BigIntAPICost.BigIntIsInt64 - metering.UseGasAndAddTracedGas(bigIntIsInt64Name, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(bigIntIsInt64Name, gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return -1 + } value, err := managedType.GetBigInt(destinationHandle) if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { @@ -438,7 +483,10 @@ func (context *VMHooksImpl) BigIntGetInt64(destinationHandle int32) int64 { runtime := context.GetRuntimeContext() gasToUse := metering.GasSchedule().BigIntAPICost.BigIntGetInt64 - metering.UseGasAndAddTracedGas(bigIntGetInt64Name, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(bigIntGetInt64Name, gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return -1 + } value := managedType.GetBigIntOrCreate(destinationHandle) if !value.IsInt64() { @@ -456,7 +504,10 @@ func (context *VMHooksImpl) BigIntSetInt64(destinationHandle int32, value int64) metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BigIntAPICost.BigIntSetInt64 - metering.UseGasAndAddTracedGas(bigIntSetInt64Name, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(bigIntSetInt64Name, gasToUse) + if context.WithFault(err, context.GetRuntimeContext().BigIntAPIErrorShouldFailExecution()) { + return + } dest := managedType.GetBigIntOrCreate(destinationHandle) dest.SetInt64(value) @@ -471,7 +522,10 @@ func (context *VMHooksImpl) BigIntAdd(destinationHandle, op1Handle, op2Handle in metering.StartGasTracing(bigIntAddName) gasToUse := metering.GasSchedule().BigIntAPICost.BigIntAdd - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } dest := managedType.GetBigIntOrCreate(destinationHandle) a, b, err := managedType.GetTwoBigInt(op1Handle, op2Handle) @@ -491,7 +545,10 @@ func (context *VMHooksImpl) BigIntSub(destinationHandle, op1Handle, op2Handle in metering.StartGasTracing(bigIntSubName) gasToUse := metering.GasSchedule().BigIntAPICost.BigIntSub - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } dest := managedType.GetBigIntOrCreate(destinationHandle) a, b, err := managedType.GetTwoBigInt(op1Handle, op2Handle) @@ -511,7 +568,10 @@ func (context *VMHooksImpl) BigIntMul(destinationHandle, op1Handle, op2Handle in metering.StartGasTracing(bigIntMulName) gasToUse := metering.GasSchedule().BigIntAPICost.BigIntMul - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } dest := managedType.GetBigIntOrCreate(destinationHandle) a, b, err := managedType.GetTwoBigInt(op1Handle, op2Handle) @@ -532,7 +592,10 @@ func (context *VMHooksImpl) BigIntTDiv(destinationHandle, op1Handle, op2Handle i metering.StartGasTracing(bigIntTDivName) gasToUse := metering.GasSchedule().BigIntAPICost.BigIntTDiv - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } dest := managedType.GetBigIntOrCreate(destinationHandle) a, b, err := managedType.GetTwoBigInt(op1Handle, op2Handle) @@ -556,7 +619,10 @@ func (context *VMHooksImpl) BigIntTMod(destinationHandle, op1Handle, op2Handle i metering.StartGasTracing(bigIntTModName) gasToUse := metering.GasSchedule().BigIntAPICost.BigIntTMod - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } dest := managedType.GetBigIntOrCreate(destinationHandle) a, b, err := managedType.GetTwoBigInt(op1Handle, op2Handle) @@ -580,7 +646,10 @@ func (context *VMHooksImpl) BigIntEDiv(destinationHandle, op1Handle, op2Handle i metering.StartGasTracing(bigIntEDivName) gasToUse := metering.GasSchedule().BigIntAPICost.BigIntEDiv - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } dest := managedType.GetBigIntOrCreate(destinationHandle) a, b, err := managedType.GetTwoBigInt(op1Handle, op2Handle) @@ -604,7 +673,10 @@ func (context *VMHooksImpl) BigIntEMod(destinationHandle, op1Handle, op2Handle i metering.StartGasTracing(bigIntEModName) gasToUse := metering.GasSchedule().BigIntAPICost.BigIntEMod - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } dest := managedType.GetBigIntOrCreate(destinationHandle) a, b, err := managedType.GetTwoBigInt(op1Handle, op2Handle) @@ -628,7 +700,10 @@ func (context *VMHooksImpl) BigIntSqrt(destinationHandle, opHandle int32) { metering.StartGasTracing(bigIntSqrtName) gasToUse := metering.GasSchedule().BigIntAPICost.BigIntSqrt - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } dest := managedType.GetBigIntOrCreate(destinationHandle) a, err := managedType.GetBigInt(opHandle) @@ -652,7 +727,10 @@ func (context *VMHooksImpl) BigIntPow(destinationHandle, op1Handle, op2Handle in metering.StartGasTracing(bigIntPowName) gasToUse := metering.GasSchedule().BigIntAPICost.BigIntPow - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } dest := managedType.GetBigIntOrCreate(destinationHandle) a, b, err := managedType.GetTwoBigInt(op1Handle, op2Handle) @@ -683,7 +761,10 @@ func (context *VMHooksImpl) BigIntLog2(op1Handle int32) int32 { metering.StartGasTracing(bigIntLog2Name) gasToUse := metering.GasSchedule().BigIntAPICost.BigIntLog - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return -1 + } a, err := managedType.GetBigInt(op1Handle) if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { @@ -707,7 +788,10 @@ func (context *VMHooksImpl) BigIntAbs(destinationHandle, opHandle int32) { metering.StartGasTracing(bigIntAbsName) gasToUse := metering.GasSchedule().BigIntAPICost.BigIntAbs - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } dest := managedType.GetBigIntOrCreate(destinationHandle) a, err := managedType.GetBigInt(opHandle) @@ -727,7 +811,10 @@ func (context *VMHooksImpl) BigIntNeg(destinationHandle, opHandle int32) { metering.StartGasTracing(bigIntNegName) gasToUse := metering.GasSchedule().BigIntAPICost.BigIntNeg - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } dest := managedType.GetBigIntOrCreate(destinationHandle) a, err := managedType.GetBigInt(opHandle) @@ -747,7 +834,10 @@ func (context *VMHooksImpl) BigIntSign(opHandle int32) int32 { metering.StartGasTracing(bigIntSignName) gasToUse := metering.GasSchedule().BigIntAPICost.BigIntSign - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return -2 + } a, err := managedType.GetBigInt(opHandle) if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { @@ -766,7 +856,10 @@ func (context *VMHooksImpl) BigIntCmp(op1Handle, op2Handle int32) int32 { metering.StartGasTracing(bigIntCmpName) gasToUse := metering.GasSchedule().BigIntAPICost.BigIntCmp - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return -2 + } a, b, err := managedType.GetTwoBigInt(op1Handle, op2Handle) if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { @@ -785,7 +878,10 @@ func (context *VMHooksImpl) BigIntNot(destinationHandle, opHandle int32) { metering.StartGasTracing(bigIntNotName) gasToUse := metering.GasSchedule().BigIntAPICost.BigIntNot - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } dest := managedType.GetBigIntOrCreate(destinationHandle) a, err := managedType.GetBigInt(opHandle) @@ -809,7 +905,10 @@ func (context *VMHooksImpl) BigIntAnd(destinationHandle, op1Handle, op2Handle in metering.StartGasTracing(bigIntAndName) gasToUse := metering.GasSchedule().BigIntAPICost.BigIntAnd - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } dest := managedType.GetBigIntOrCreate(destinationHandle) a, b, err := managedType.GetTwoBigInt(op1Handle, op2Handle) @@ -833,7 +932,10 @@ func (context *VMHooksImpl) BigIntOr(destinationHandle, op1Handle, op2Handle int metering.StartGasTracing(bigIntOrName) gasToUse := metering.GasSchedule().BigIntAPICost.BigIntOr - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } dest := managedType.GetBigIntOrCreate(destinationHandle) a, b, err := managedType.GetTwoBigInt(op1Handle, op2Handle) @@ -857,7 +959,10 @@ func (context *VMHooksImpl) BigIntXor(destinationHandle, op1Handle, op2Handle in metering.StartGasTracing(bigIntXorName) gasToUse := metering.GasSchedule().BigIntAPICost.BigIntXor - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } dest := managedType.GetBigIntOrCreate(destinationHandle) a, b, err := managedType.GetTwoBigInt(op1Handle, op2Handle) @@ -881,7 +986,10 @@ func (context *VMHooksImpl) BigIntShr(destinationHandle, opHandle, bits int32) { metering.StartGasTracing(bigIntShrName) gasToUse := metering.GasSchedule().BigIntAPICost.BigIntShr - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } dest := managedType.GetBigIntOrCreate(destinationHandle) a, err := managedType.GetBigInt(opHandle) @@ -906,7 +1014,10 @@ func (context *VMHooksImpl) BigIntShl(destinationHandle, opHandle, bits int32) { metering.StartGasTracing(bigIntShlName) gasToUse := metering.GasSchedule().BigIntAPICost.BigIntShl - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } dest := managedType.GetBigIntOrCreate(destinationHandle) a, err := managedType.GetBigInt(opHandle) @@ -933,17 +1044,24 @@ func (context *VMHooksImpl) BigIntFinishUnsigned(referenceHandle int32) { metering.StartGasTracing(bigIntFinishUnsignedName) gasToUse := metering.GasSchedule().BigIntAPICost.BigIntFinishUnsigned - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } value, err := managedType.GetBigInt(referenceHandle) if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { return } bigIntBytes := value.Bytes() - output.Finish(bigIntBytes) gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.PersistPerByte, uint64(len(value.Bytes()))) - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } + + output.Finish(bigIntBytes) } // BigIntFinishSigned VMHooks implementation. @@ -956,17 +1074,24 @@ func (context *VMHooksImpl) BigIntFinishSigned(referenceHandle int32) { metering.StartGasTracing(bigIntFinishSignedName) gasToUse := metering.GasSchedule().BigIntAPICost.BigIntFinishSigned - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } value, err := managedType.GetBigInt(referenceHandle) if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { return } bigInt2cBytes := twos.ToBytes(value) - output.Finish(bigInt2cBytes) gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.PersistPerByte, uint64(len(bigInt2cBytes))) - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } + + output.Finish(bigInt2cBytes) } // BigIntToString VMHooks implementation. @@ -982,7 +1107,10 @@ func BigIntToStringWithHost(host vmhost.VMHost, bigIntHandle int32, destinationH managedType := host.ManagedTypes() gasToUse := metering.GasSchedule().BigIntAPICost.BigIntFinishSigned - metering.UseGasAndAddTracedGas(bigIntToStringName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(bigIntToStringName, gasToUse) + if WithFaultAndHost(host, err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } value, err := managedType.GetBigInt(bigIntHandle) if WithFaultAndHost(host, err, runtime.BigIntAPIErrorShouldFailExecution()) { @@ -990,7 +1118,12 @@ func BigIntToStringWithHost(host vmhost.VMHost, bigIntHandle int32, destinationH } resultStr := value.String() - managedType.SetBytes(destinationHandle, []byte(resultStr)) + gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(len(resultStr))) - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } + + managedType.SetBytes(destinationHandle, []byte(resultStr)) } From e0948dd42c9511874a74f805866f619f71aae23b Mon Sep 17 00:00:00 2001 From: robertsasu Date: Thu, 8 Aug 2024 16:38:43 +0300 Subject: [PATCH 04/24] refactoring gasUsage --- vmhost/vmhooks/cryptoei.go | 180 +++++++++++++++++++++------ vmhost/vmhooks/manBufOps.go | 117 +++++++++++++---- vmhost/vmhooks/managedConversions.go | 5 +- vmhost/vmhooks/managedei.go | 150 +++++++++++++++++----- 4 files changed, 361 insertions(+), 91 deletions(-) diff --git a/vmhost/vmhooks/cryptoei.go b/vmhost/vmhooks/cryptoei.go index b08496ae1..e3bd01d69 100644 --- a/vmhost/vmhooks/cryptoei.go +++ b/vmhost/vmhooks/cryptoei.go @@ -54,7 +54,10 @@ func (context *VMHooksImpl) Sha256( memLoadGas := math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(length)) gasToUse := math.AddUint64(metering.GasSchedule().CryptoAPICost.SHA256, memLoadGas) - metering.UseGasAndAddTracedGas(sha256Name, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(sha256Name, gasToUse) + if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { + return 1 + } data, err := context.MemLoad(dataOffset, length) if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { @@ -83,7 +86,10 @@ func (context *VMHooksImpl) ManagedSha256(inputHandle, outputHandle int32) int32 crypto := context.GetCryptoContext() metering := context.GetMeteringContext() - metering.UseGasAndAddTracedGas(sha256Name, metering.GasSchedule().CryptoAPICost.SHA256) + err := metering.UseGasBoundedAndAddTracedGas(sha256Name, metering.GasSchedule().CryptoAPICost.SHA256) + if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { + return 1 + } inputBytes, err := managedType.GetBytes(inputHandle) if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { @@ -111,7 +117,10 @@ func (context *VMHooksImpl) Keccak256(dataOffset executor.MemPtr, length executo memLoadGas := math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(length)) gasToUse := math.AddUint64(metering.GasSchedule().CryptoAPICost.Keccak256, memLoadGas) - metering.UseGasAndAddTracedGas(keccak256Name, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(keccak256Name, gasToUse) + if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { + return 1 + } data, err := context.MemLoad(dataOffset, length) if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { @@ -140,7 +149,10 @@ func (context *VMHooksImpl) ManagedKeccak256(inputHandle, outputHandle int32) in crypto := context.GetCryptoContext() metering := context.GetMeteringContext() - metering.UseGasAndAddTracedGas(keccak256Name, metering.GasSchedule().CryptoAPICost.Keccak256) + err := metering.UseGasBoundedAndAddTracedGas(keccak256Name, metering.GasSchedule().CryptoAPICost.Keccak256) + if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { + return 1 + } inputBytes, err := managedType.GetBytes(inputHandle) if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { @@ -168,7 +180,10 @@ func (context *VMHooksImpl) Ripemd160(dataOffset executor.MemPtr, length executo memLoadGas := math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(length)) gasToUse := math.AddUint64(metering.GasSchedule().CryptoAPICost.Ripemd160, memLoadGas) - metering.UseGasAndAddTracedGas(ripemd160Name, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(ripemd160Name, gasToUse) + if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { + return 1 + } data, err := context.MemLoad(dataOffset, length) if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { @@ -203,7 +218,10 @@ func ManagedRipemd160WithHost(host vmhost.VMHost, inputHandle int32, outputHandl managedType := host.ManagedTypes() crypto := host.Crypto() - metering.UseGasAndAddTracedGas(ripemd160Name, metering.GasSchedule().CryptoAPICost.Ripemd160) + err := metering.UseGasBoundedAndAddTracedGas(ripemd160Name, metering.GasSchedule().CryptoAPICost.Ripemd160) + if WithFaultAndHost(host, err, runtime.CryptoAPIErrorShouldFailExecution()) { + return 1 + } inputBytes, err := managedType.GetBytes(inputHandle) if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { @@ -236,7 +254,10 @@ func (context *VMHooksImpl) VerifyBLS( metering.StartGasTracing(verifyBLSName) gasToUse := metering.GasSchedule().CryptoAPICost.VerifyBLS - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { + return 1 + } key, err := context.MemLoad(keyOffset, blsPublicKeyLength) if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { @@ -244,7 +265,10 @@ func (context *VMHooksImpl) VerifyBLS( } gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(messageLength)) - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { + return 1 + } message, err := context.MemLoad(messageOffset, messageLength) if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { @@ -290,7 +314,10 @@ func ManagedVerifyBLSWithHost( metering.StartGasTracing(verifyBLSName) gasToUse := metering.GasSchedule().CryptoAPICost.VerifyBLS - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.CryptoAPIErrorShouldFailExecution()) { + return 1 + } keyBytes, err := managedType.GetBytes(keyHandle) if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { @@ -333,7 +360,10 @@ func (context *VMHooksImpl) VerifyEd25519( metering.StartGasTracing(verifyEd25519Name) gasToUse := metering.GasSchedule().CryptoAPICost.VerifyEd25519 - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { + return 1 + } key, err := context.MemLoad(keyOffset, ed25519PublicKeyLength) if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { @@ -341,7 +371,10 @@ func (context *VMHooksImpl) VerifyEd25519( } gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(messageLength)) - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { + return 1 + } message, err := context.MemLoad(messageOffset, messageLength) if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { @@ -383,7 +416,10 @@ func ManagedVerifyEd25519WithHost( metering.StartGasTracing(verifyEd25519Name) gasToUse := metering.GasSchedule().CryptoAPICost.VerifyEd25519 - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.CryptoAPIErrorShouldFailExecution()) { + return 1 + } keyBytes, err := managedType.GetBytes(keyHandle) if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { @@ -428,7 +464,10 @@ func (context *VMHooksImpl) VerifyCustomSecp256k1( metering.StartGasTracing(verifyCustomSecp256k1Name) gasToUse := metering.GasSchedule().CryptoAPICost.VerifySecp256k1 - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { + return 1 + } if keyLength != secp256k1CompressedPublicKeyLength && keyLength != secp256k1UncompressedPublicKeyLength { _ = context.WithFault(vmhost.ErrInvalidPublicKeySize, runtime.BaseOpsErrorShouldFailExecution()) @@ -441,7 +480,10 @@ func (context *VMHooksImpl) VerifyCustomSecp256k1( } gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(messageLength)) - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { + return 1 + } message, err := context.MemLoad(messageOffset, messageLength) if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { @@ -499,7 +541,10 @@ func ManagedVerifyCustomSecp256k1WithHost( metering.StartGasTracing(verifyCustomSecp256k1Name) gasToUse := metering.GasSchedule().CryptoAPICost.VerifySecp256k1 - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.CryptoAPIErrorShouldFailExecution()) { + return 1 + } keyBytes, err := managedType.GetBytes(keyHandle) if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { @@ -584,7 +629,10 @@ func (context *VMHooksImpl) EncodeSecp256k1DerSignature( metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().CryptoAPICost.EncodeDERSig - metering.UseGasAndAddTracedGas(encodeSecp256k1DerSignatureName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(encodeSecp256k1DerSignatureName, gasToUse) + if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { + return 1 + } r, err := context.MemLoad(rOffset, rLength) if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { @@ -625,7 +673,10 @@ func ManagedEncodeSecp256k1DerSignatureWithHost( crypto := host.Crypto() gasToUse := metering.GasSchedule().CryptoAPICost.EncodeDERSig - metering.UseGasAndAddTracedGas(encodeSecp256k1DerSignatureName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(encodeSecp256k1DerSignatureName, gasToUse) + if WithFaultAndHost(host, err, runtime.CryptoAPIErrorShouldFailExecution()) { + return 1 + } r, err := managedType.GetBytes(rHandle) if WithFaultAndHost(host, err, runtime.CryptoAPIErrorShouldFailExecution()) { @@ -665,7 +716,10 @@ func (context *VMHooksImpl) AddEC( return } gasToUse := metering.GasSchedule().CryptoAPICost.AddECC * uint64(curveMultiplier) / 100 - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { + return + } ec, err1 := managedType.GetEllipticCurve(ecHandle) if context.WithFault(err1, runtime.CryptoAPIErrorShouldFailExecution()) { @@ -719,7 +773,10 @@ func (context *VMHooksImpl) DoubleEC( return } gasToUse := metering.GasSchedule().CryptoAPICost.DoubleECC * uint64(curveMultiplier) / 100 - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { + return + } ec, err1 := managedType.GetEllipticCurve(ecHandle) if context.WithFault(err1, runtime.CryptoAPIErrorShouldFailExecution()) { @@ -762,7 +819,10 @@ func (context *VMHooksImpl) IsOnCurveEC( return 1 } gasToUse := metering.GasSchedule().CryptoAPICost.IsOnCurveECC * uint64(curveMultiplier) / 100 - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { + return -1 + } ec, err := managedType.GetEllipticCurve(ecHandle) if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { @@ -809,7 +869,10 @@ func (context *VMHooksImpl) ScalarBaseMultEC( } oneByteScalarGasCost := metering.GasSchedule().CryptoAPICost.ScalarMultECC * uint64(curveMultiplier) / 100 gasToUse := oneByteScalarGasCost + uint64(length)*oneByteScalarGasCost - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { + return -1 + } data, err := context.MemLoad(dataOffset, length) if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { @@ -864,7 +927,10 @@ func ManagedScalarBaseMultECWithHost( oneByteScalarGasCost := metering.GasSchedule().CryptoAPICost.ScalarMultECC * uint64(curveMultiplier) / 100 gasToUse := oneByteScalarGasCost + uint64(len(data))*oneByteScalarGasCost - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.CryptoAPIErrorShouldFailExecution()) { + return -1 + } return commonScalarBaseMultEC(host, xResultHandle, yResultHandle, ecHandle, data) } @@ -930,7 +996,10 @@ func (context *VMHooksImpl) ScalarMultEC( } oneByteScalarGasCost := metering.GasSchedule().CryptoAPICost.ScalarMultECC * uint64(curveMultiplier) / 100 gasToUse := oneByteScalarGasCost + uint64(length)*oneByteScalarGasCost - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { + return -1 + } data, err := context.MemLoad(dataOffset, length) if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { @@ -991,7 +1060,10 @@ func ManagedScalarMultECWithHost( oneByteScalarGasCost := metering.GasSchedule().CryptoAPICost.ScalarMultECC * uint64(curveMultiplier) / 100 gasToUse := oneByteScalarGasCost + uint64(len(data))*oneByteScalarGasCost - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.CryptoAPIErrorShouldFailExecution()) { + return -1 + } return commonScalarMultEC(host, xResultHandle, yResultHandle, ecHandle, pointXHandle, pointYHandle, data) } @@ -1113,7 +1185,10 @@ func commonMarshalEC( return nil, vmhost.ErrNoEllipticCurveUnderThisHandle } gasToUse := metering.GasSchedule().CryptoAPICost.MarshalECC * uint64(curveMultiplier) / 100 - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if err != nil { + return nil, err + } ec, err := managedType.GetEllipticCurve(ecHandle) if err != nil { @@ -1212,7 +1287,10 @@ func commonMarshalCompressedEC(host vmhost.VMHost, return nil, vmhost.ErrNoEllipticCurveUnderThisHandle } gasToUse := metering.GasSchedule().CryptoAPICost.MarshalCompressedECC * uint64(curveMultiplier) / 100 - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if err != nil { + return nil, err + } ec, err := managedType.GetEllipticCurve(ecHandle) if err != nil { @@ -1256,7 +1334,10 @@ func (context *VMHooksImpl) UnmarshalEC( return 1 } gasToUse := metering.GasSchedule().CryptoAPICost.UnmarshalECC * uint64(curveMultiplier) / 100 - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { + return -1 + } data, err := context.MemLoad(dataOffset, length) if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { @@ -1304,7 +1385,10 @@ func ManagedUnmarshalECWithHost( return 1 } gasToUse := metering.GasSchedule().CryptoAPICost.UnmarshalECC * uint64(curveMultiplier) / 100 - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.CryptoAPIErrorShouldFailExecution()) { + return -1 + } data, err := managedType.GetBytes(dataHandle) if err != nil { @@ -1372,7 +1456,10 @@ func (context *VMHooksImpl) UnmarshalCompressedEC( return 1 } gasToUse := metering.GasSchedule().CryptoAPICost.UnmarshalCompressedECC * uint64(curveMultiplier) / 100 - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { + return -1 + } data, err := context.MemLoad(dataOffset, length) if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { @@ -1420,7 +1507,10 @@ func ManagedUnmarshalCompressedECWithHost( return 1 } gasToUse := metering.GasSchedule().CryptoAPICost.UnmarshalCompressedECC * uint64(curveMultiplier) / 100 - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.CryptoAPIErrorShouldFailExecution()) { + return -1 + } data, err := managedType.GetBytes(dataHandle) if WithFaultAndHost(host, err, runtime.CryptoAPIErrorShouldFailExecution()) { @@ -1545,7 +1635,10 @@ func commonGenerateEC( curveMultiplier = 500 } gasToUse := metering.GasSchedule().CryptoAPICost.GenerateKeyECC * uint64(curveMultiplier) / 100 - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if err != nil { + return nil, err + } ec, err := managedType.GetEllipticCurve(ecHandle) if err != nil { @@ -1578,7 +1671,10 @@ func (context *VMHooksImpl) CreateEC(dataOffset executor.MemPtr, dataLength exec metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().CryptoAPICost.EllipticCurveNew - metering.UseGasAndAddTracedGas(createECName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(createECName, gasToUse) + if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { + return -1 + } if dataLength != curveNameLength { _ = context.WithFault(vmhost.ErrBadBounds, runtime.CryptoAPIErrorShouldFailExecution()) @@ -1620,7 +1716,10 @@ func ManagedCreateECWithHost(host vmhost.VMHost, dataHandle int32) int32 { managedType := host.ManagedTypes() gasToUse := metering.GasSchedule().CryptoAPICost.EllipticCurveNew - metering.UseGasAndAddTracedGas(createECName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(createECName, gasToUse) + if WithFaultAndHost(host, err, runtime.CryptoAPIErrorShouldFailExecution()) { + return -1 + } data, err := managedType.GetBytes(dataHandle) if WithFaultAndHost(host, err, runtime.CryptoAPIErrorShouldFailExecution()) { @@ -1654,7 +1753,10 @@ func (context *VMHooksImpl) GetCurveLengthEC(ecHandle int32) int32 { runtime := context.GetRuntimeContext() gasToUse := metering.GasSchedule().BigIntAPICost.BigIntGetInt64 - metering.UseGasAndAddTracedGas(getCurveLengthECName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getCurveLengthECName, gasToUse) + if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { + return -1 + } ecLength := managedType.GetEllipticCurveSizeOfField(ecHandle) if ecLength == -1 { @@ -1672,7 +1774,10 @@ func (context *VMHooksImpl) GetPrivKeyByteLengthEC(ecHandle int32) int32 { runtime := context.GetRuntimeContext() gasToUse := metering.GasSchedule().BigIntAPICost.BigIntGetInt64 - metering.UseGasAndAddTracedGas(getPrivKeyByteLengthECName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getPrivKeyByteLengthECName, gasToUse) + if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { + return -1 + } byteLength := managedType.GetPrivateKeyByteLengthEC(ecHandle) if byteLength == -1 { @@ -1690,7 +1795,10 @@ func (context *VMHooksImpl) EllipticCurveGetValues(ecHandle int32, fieldOrderHan runtime := context.GetRuntimeContext() gasToUse := metering.GasSchedule().BigIntAPICost.BigIntGetInt64 * 5 - metering.UseGasAndAddTracedGas(ellipticCurveGetValuesName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(ellipticCurveGetValuesName, gasToUse) + if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { + return -1 + } ec, err := managedType.GetEllipticCurve(ecHandle) if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { diff --git a/vmhost/vmhooks/manBufOps.go b/vmhost/vmhooks/manBufOps.go index 5a6e4b5fc..2c1340f18 100644 --- a/vmhost/vmhooks/manBufOps.go +++ b/vmhost/vmhooks/manBufOps.go @@ -41,7 +41,10 @@ func (context *VMHooksImpl) MBufferNew() int32 { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().ManagedBufferAPICost.MBufferNew - metering.UseGasAndAddTracedGas(mBufferNewName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(mBufferNewName, gasToUse) + if context.WithFault(err, context.GetRuntimeContext().ManagedBufferAPIErrorShouldFailExecution()) { + return -1 + } return managedType.NewManagedBuffer() } @@ -54,7 +57,10 @@ func (context *VMHooksImpl) MBufferNewFromBytes(dataOffset executor.MemPtr, data metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().ManagedBufferAPICost.MBufferNewFromBytes - metering.UseGasAndAddTracedGas(mBufferNewFromBytesName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(mBufferNewFromBytesName, gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return -1 + } data, err := context.MemLoad(dataOffset, dataLength) if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { @@ -72,7 +78,10 @@ func (context *VMHooksImpl) MBufferGetLength(mBufferHandle int32) int32 { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().ManagedBufferAPICost.MBufferGetLength - metering.UseGasAndAddTracedGas(mBufferGetLengthName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(mBufferGetLengthName, gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return -1 + } length := managedType.GetLength(mBufferHandle) if length == -1 { @@ -92,7 +101,10 @@ func (context *VMHooksImpl) MBufferGetBytes(mBufferHandle int32, resultOffset ex metering.StartGasTracing(mBufferGetBytesName) gasToUse := metering.GasSchedule().ManagedBufferAPICost.MBufferGetBytes - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } mBufferBytes, err := managedType.GetBytes(mBufferHandle) if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { @@ -122,7 +134,10 @@ func (context *VMHooksImpl) MBufferGetByteSlice( metering.StartGasTracing(mBufferGetByteSliceName) gasToUse := metering.GasSchedule().ManagedBufferAPICost.MBufferGetByteSlice - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } sourceBytes, err := managedType.GetBytes(sourceHandle) if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { @@ -159,7 +174,10 @@ func ManagedBufferCopyByteSliceWithHost(host vmhost.VMHost, sourceHandle int32, metering.StartGasTracing(mBufferCopyByteSliceName) gasToUse := metering.GasSchedule().ManagedBufferAPICost.MBufferCopyByteSlice - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } sourceBytes, err := managedType.GetBytes(sourceHandle) if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { @@ -176,7 +194,10 @@ func ManagedBufferCopyByteSliceWithHost(host vmhost.VMHost, sourceHandle int32, managedType.SetBytes(destinationHandle, slice) gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(len(slice))) - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } return 0 } @@ -190,7 +211,10 @@ func (context *VMHooksImpl) MBufferEq(mBufferHandle1 int32, mBufferHandle2 int32 metering.StartGasTracing(mBufferEqName) gasToUse := metering.GasSchedule().ManagedBufferAPICost.MBufferCopyByteSlice - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } bytes1, err := managedType.GetBytes(mBufferHandle1) if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { @@ -220,7 +244,10 @@ func (context *VMHooksImpl) MBufferSetBytes(mBufferHandle int32, dataOffset exec metering.StartGasTracing(mBufferSetBytesName) gasToUse := metering.GasSchedule().ManagedBufferAPICost.MBufferSetBytes - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } data, err := context.MemLoad(dataOffset, dataLength) if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { @@ -257,7 +284,10 @@ func (context *VMHooksImpl) ManagedBufferSetByteSliceWithHost( metering.StartGasTracing(mBufferGetByteSliceName) gasToUse := metering.GasSchedule().ManagedBufferAPICost.MBufferSetBytes - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } data, err := context.MemLoad(dataOffset, dataLength) if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { @@ -306,7 +336,10 @@ func (context *VMHooksImpl) MBufferAppend(accumulatorHandle int32, dataHandle in metering.StartGasTracing(mBufferAppendName) gasToUse := metering.GasSchedule().ManagedBufferAPICost.MBufferAppend - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } dataBufferBytes, err := managedType.GetBytes(dataHandle) if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { @@ -332,7 +365,10 @@ func (context *VMHooksImpl) MBufferAppendBytes(accumulatorHandle int32, dataOffs metering.StartGasTracing(mBufferAppendBytesName) gasToUse := metering.GasSchedule().ManagedBufferAPICost.MBufferAppendBytes - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } data, err := context.MemLoad(dataOffset, dataLength) if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { @@ -346,7 +382,10 @@ func (context *VMHooksImpl) MBufferAppendBytes(accumulatorHandle int32, dataOffs } gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(len(data))) - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } return 0 } @@ -359,7 +398,10 @@ func (context *VMHooksImpl) MBufferToBigIntUnsigned(mBufferHandle int32, bigIntH metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().ManagedBufferAPICost.MBufferToBigIntUnsigned - metering.UseGasAndAddTracedGas(mBufferToBigIntUnsignedName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(mBufferToBigIntUnsignedName, gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return -1 + } managedBuffer, err := managedType.GetBytes(mBufferHandle) if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { @@ -380,7 +422,10 @@ func (context *VMHooksImpl) MBufferToBigIntSigned(mBufferHandle int32, bigIntHan metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().ManagedBufferAPICost.MBufferToBigIntSigned - metering.UseGasAndAddTracedGas(mBufferToBigIntSignedName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(mBufferToBigIntSignedName, gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return -1 + } managedBuffer, err := managedType.GetBytes(mBufferHandle) if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { @@ -401,7 +446,10 @@ func (context *VMHooksImpl) MBufferFromBigIntUnsigned(mBufferHandle int32, bigIn metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().ManagedBufferAPICost.MBufferFromBigIntUnsigned - metering.UseGasAndAddTracedGas(mBufferFromBigIntUnsignedName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(mBufferFromBigIntUnsignedName, gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return -1 + } value, err := managedType.GetBigInt(bigIntHandle) if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { @@ -421,7 +469,10 @@ func (context *VMHooksImpl) MBufferFromBigIntSigned(mBufferHandle int32, bigIntH metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().ManagedBufferAPICost.MBufferFromBigIntSigned - metering.UseGasAndAddTracedGas(mBufferFromBigIntSignedName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(mBufferFromBigIntSignedName, gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return -1 + } value, err := managedType.GetBigInt(bigIntHandle) if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { @@ -441,7 +492,10 @@ func (context *VMHooksImpl) MBufferToBigFloat(mBufferHandle, bigFloatHandle int3 metering.StartGasTracing(mBufferToBigFloatName) gasToUse := metering.GasSchedule().ManagedBufferAPICost.MBufferToBigFloat - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } managedBuffer, err := managedType.GetBytes(mBufferHandle) if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { @@ -482,7 +536,10 @@ func (context *VMHooksImpl) MBufferFromBigFloat(mBufferHandle, bigFloatHandle in metering.StartGasTracing(mBufferFromBigFloatName) gasToUse := metering.GasSchedule().ManagedBufferAPICost.MBufferFromBigFloat - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } value, err := managedType.GetBigFloat(bigFloatHandle) if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { @@ -509,7 +566,10 @@ func (context *VMHooksImpl) MBufferStorageStore(keyHandle int32, sourceHandle in metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().ManagedBufferAPICost.MBufferStorageStore - metering.UseGasAndAddTracedGas(mBufferStorageStoreName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(mBufferStorageStoreName, gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return -1 + } key, err := managedType.GetBytes(keyHandle) if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { @@ -595,7 +655,10 @@ func (context *VMHooksImpl) MBufferGetArgument(id int32, destinationHandle int32 metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().ManagedBufferAPICost.MBufferGetArgument - metering.UseGasAndAddTracedGas(mBufferGetArgumentName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(mBufferGetArgumentName, gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return -1 + } args := runtime.Arguments() if int32(len(args)) <= id || id < 0 { @@ -616,7 +679,10 @@ func (context *VMHooksImpl) MBufferFinish(sourceHandle int32) int32 { metering.StartGasTracing(mBufferFinishName) gasToUse := metering.GasSchedule().ManagedBufferAPICost.MBufferFinish - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } sourceBytes, err := managedType.GetBytes(sourceHandle) if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { @@ -649,11 +715,14 @@ func (context *VMHooksImpl) MBufferSetRandom(destinationHandle int32, length int baseGasToUse := metering.GasSchedule().ManagedBufferAPICost.MBufferSetRandom lengthDependentGasToUse := math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(length)) gasToUse := math.AddUint64(baseGasToUse, lengthDependentGasToUse) - metering.UseGasAndAddTracedGas(mBufferSetRandomName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(mBufferSetRandomName, gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return -1 + } randomizer := managedType.GetRandReader() buffer := make([]byte, length) - _, err := randomizer.Read(buffer) + _, err = randomizer.Read(buffer) if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { return -1 } diff --git a/vmhost/vmhooks/managedConversions.go b/vmhost/vmhooks/managedConversions.go index 193333435..1c17ec49f 100644 --- a/vmhost/vmhooks/managedConversions.go +++ b/vmhost/vmhooks/managedConversions.go @@ -213,7 +213,10 @@ func readDestinationArguments( vmInput.arguments = data gasToUse := math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, actualLen) - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if err != nil { + return nil, err + } return vmInput, err } diff --git a/vmhost/vmhooks/managedei.go b/vmhost/vmhooks/managedei.go index 908bdc300..fb7afe510 100644 --- a/vmhost/vmhooks/managedei.go +++ b/vmhost/vmhooks/managedei.go @@ -55,7 +55,10 @@ func (context *VMHooksImpl) ManagedSCAddress(destinationHandle int32) { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetSCAddress - metering.UseGasAndAddTracedGas(managedSCAddressName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(managedSCAddressName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } scAddress := runtime.GetContextAddress() @@ -71,7 +74,10 @@ func (context *VMHooksImpl) ManagedOwnerAddress(destinationHandle int32) { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetOwnerAddress - metering.UseGasAndAddTracedGas(managedOwnerAddressName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(managedOwnerAddressName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } owner, err := blockchain.GetOwnerAddress() if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -89,7 +95,10 @@ func (context *VMHooksImpl) ManagedCaller(destinationHandle int32) { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetCaller - metering.UseGasAndAddTracedGas(managedCallerName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(managedCallerName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } caller := runtime.GetVMInput().CallerAddr managedType.SetBytes(destinationHandle, caller) @@ -104,7 +113,10 @@ func (context *VMHooksImpl) ManagedSignalError(errHandle int32) { metering.StartGasTracing(managedSignalErrorName) gasToUse := metering.GasSchedule().BaseOpsAPICost.SignalError - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return + } errBytes, err := managedType.GetBytes(errHandle) if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { @@ -151,7 +163,10 @@ func (context *VMHooksImpl) ManagedWriteLog( metering.GasSchedule().BaseOperationCost.DataCopyPerByte, sumOfTopicByteLengths+dataByteLen) gasToUse = math.AddUint64(gasToUse, gasForData) - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return + } output.WriteLog(runtime.GetContextAddress(), topics, [][]byte{dataBytes}) } @@ -164,7 +179,10 @@ func (context *VMHooksImpl) ManagedGetOriginalTxHash(resultHandle int32) { managedType := context.GetManagedTypesContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetOriginalTxHash - metering.UseGasAndAddTracedGas(managedGetOriginalTxHashName, gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return + } managedType.SetBytes(resultHandle, runtime.GetOriginalTxHash()) } @@ -177,7 +195,10 @@ func (context *VMHooksImpl) ManagedGetStateRootHash(resultHandle int32) { managedType := context.GetManagedTypesContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetStateRootHash - metering.UseGasAndAddTracedGas(managedGetStateRootHashName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(managedGetStateRootHashName, gasToUse) + if context.WithFault(err, context.GetRuntimeContext().BaseOpsErrorShouldFailExecution()) { + return + } managedType.SetBytes(resultHandle, blockchain.GetStateRootHash()) } @@ -190,7 +211,10 @@ func (context *VMHooksImpl) ManagedGetBlockRandomSeed(resultHandle int32) { managedType := context.GetManagedTypesContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetBlockRandomSeed - metering.UseGasAndAddTracedGas(managedGetBlockRandomSeedName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(managedGetBlockRandomSeedName, gasToUse) + if context.WithFault(err, context.GetRuntimeContext().BaseOpsErrorShouldFailExecution()) { + return + } managedType.SetBytes(resultHandle, blockchain.CurrentRandomSeed()) } @@ -203,7 +227,10 @@ func (context *VMHooksImpl) ManagedGetPrevBlockRandomSeed(resultHandle int32) { managedType := context.GetManagedTypesContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetBlockRandomSeed - metering.UseGasAndAddTracedGas(managedGetPrevBlockRandomSeedName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(managedGetPrevBlockRandomSeedName, gasToUse) + if context.WithFault(err, context.GetRuntimeContext().BaseOpsErrorShouldFailExecution()) { + return + } managedType.SetBytes(resultHandle, blockchain.LastRandomSeed()) } @@ -217,7 +244,10 @@ func (context *VMHooksImpl) ManagedGetReturnData(resultID int32, resultHandle in managedType := context.GetManagedTypesContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetReturnData - metering.UseGasAndAddTracedGas(managedGetReturnDataName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(managedGetReturnDataName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } returnData := output.ReturnData() if resultID >= int32(len(returnData)) || resultID < 0 { @@ -236,7 +266,10 @@ func (context *VMHooksImpl) ManagedGetMultiESDTCallValue(multiCallValueHandle in managedType := context.GetManagedTypesContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetCallValue - metering.UseGasAndAddTracedGas(managedGetMultiESDTCallValueName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(managedGetMultiESDTCallValueName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } esdtTransfers := runtime.GetVMInput().ESDTTransfers multiCallBytes := writeESDTTransfersToBytes(managedType, esdtTransfers) @@ -252,7 +285,10 @@ func (context *VMHooksImpl) ManagedGetBackTransfers(esdtTransfersValueHandle int managedType := context.GetManagedTypesContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetCallValue - metering.UseGasAndAddTracedGas(managedGetMultiESDTCallValueName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(managedGetMultiESDTCallValueName, gasToUse) + if context.WithFault(err, context.GetRuntimeContext().BaseOpsErrorShouldFailExecution()) { + return + } esdtTransfers, transferValue := managedType.GetBackTransfers() multiCallBytes := writeESDTTransfersToBytes(managedType, esdtTransfers) @@ -272,7 +308,10 @@ func (context *VMHooksImpl) ManagedGetESDTBalance(addressHandle int32, tokenIDHa managedType := context.GetManagedTypesContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetExternalBalance - metering.UseGasAndAddTracedGas(managedGetESDTBalanceName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(managedGetESDTBalanceName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } address, err := managedType.GetBytes(addressHandle) if err != nil { @@ -325,7 +364,10 @@ func ManagedGetESDTTokenDataWithHost( metering.StartGasTracing(managedGetESDTTokenDataName) gasToUse := metering.GasSchedule().BaseOpsAPICost.GetExternalBalance - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return + } address, err := managedType.GetBytes(addressHandle) if err != nil { @@ -395,7 +437,10 @@ func ManagedAsyncCallWithHost( gasSchedule := metering.GasSchedule() gasToUse := gasSchedule.BaseOpsAPICost.AsyncCallStep - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return + } vmInput, err := readDestinationFunctionArguments(host, destHandle, functionHandle, argumentsHandle) if WithFaultAndHost(host, err, host.Runtime().BaseOpsErrorShouldFailExecution()) { @@ -411,7 +456,10 @@ func ManagedAsyncCallWithHost( } gasToUse = math.MulUint64(gasSchedule.BaseOperationCost.DataCopyPerByte, uint64(len(data))) - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return + } err = async.RegisterLegacyAsyncCall(vmInput.destination, []byte(data), value.Bytes()) if errors.Is(err, vmhost.ErrNotEnoughGas) { @@ -503,7 +551,10 @@ func GetCallbackClosureWithHost( metering.StartGasTracing(managedGetCallbackClosure) gasToUse := metering.GasSchedule().BaseOpsAPICost.GetCallbackClosure - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return + } callbackClosure, err := async.GetCallbackClosure() if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -531,7 +582,10 @@ func (context *VMHooksImpl) ManagedUpgradeFromSourceContract( metering.StartGasTracing(managedUpgradeFromSourceContractName) gasToUse := metering.GasSchedule().BaseOpsAPICost.CreateContract - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return + } vmInput, err := readDestinationValueArguments(host, destHandle, valueHandle, argumentsHandle) if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -580,7 +634,10 @@ func (context *VMHooksImpl) ManagedUpgradeContract( metering.StartGasTracing(managedUpgradeContractName) gasToUse := metering.GasSchedule().BaseOpsAPICost.CreateContract - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return + } vmInput, err := readDestinationValueArguments(host, destHandle, valueHandle, argumentsHandle) if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -635,7 +692,10 @@ func ManagedDeleteContractWithHost( metering.StartGasTracing(deleteContractName) gasToUse := metering.GasSchedule().BaseOpsAPICost.CreateContract - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return + } calledSCAddress, err := managedType.GetBytes(destHandle) if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -673,7 +733,10 @@ func (context *VMHooksImpl) ManagedDeployFromSourceContract( metering.StartGasTracing(managedDeployFromSourceContractName) gasToUse := metering.GasSchedule().BaseOpsAPICost.CreateContract - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return -1 + } vmInput, err := readDestinationValueArguments(host, addressHandle, valueHandle, argumentsHandle) if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -723,7 +786,10 @@ func (context *VMHooksImpl) ManagedCreateContract( metering.StartGasTracing(managedCreateContractName) gasToUse := metering.GasSchedule().BaseOpsAPICost.CreateContract - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return -1 + } sender := runtime.GetContextAddress() value, err := managedType.GetBigInt(valueHandle) @@ -737,7 +803,10 @@ func (context *VMHooksImpl) ManagedCreateContract( } gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, actualLen) - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return -1 + } codeMetadata, err := managedType.GetBytes(codeMetadataHandle) if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -952,7 +1021,10 @@ func ManagedIsESDTFrozenWithHost( managedType := host.ManagedTypes() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetExternalBalance - metering.UseGasAndAddTracedGas(managedIsESDTFrozenName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(managedIsESDTFrozenName, gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return -1 + } address, err := managedType.GetBytes(addressHandle) if err != nil { @@ -992,7 +1064,10 @@ func ManagedIsESDTLimitedTransferWithHost(host vmhost.VMHost, tokenIDHandle int3 managedType := host.ManagedTypes() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetExternalBalance - metering.UseGasAndAddTracedGas(managedIsESDTLimitedTransferName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(managedIsESDTLimitedTransferName, gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return -1 + } tokenID, err := managedType.GetBytes(tokenIDHandle) if err != nil { @@ -1021,7 +1096,10 @@ func ManagedIsESDTPausedWithHost(host vmhost.VMHost, tokenIDHandle int32) int32 managedType := host.ManagedTypes() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetExternalBalance - metering.UseGasAndAddTracedGas(managedIsESDTPausedName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(managedIsESDTPausedName, gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return -1 + } tokenID, err := managedType.GetBytes(tokenIDHandle) if err != nil { @@ -1049,7 +1127,10 @@ func ManagedBufferToHexWithHost(host vmhost.VMHost, sourceHandle int32, destHand managedType := host.ManagedTypes() gasToUse := metering.GasSchedule().ManagedBufferAPICost.MBufferSetBytes - metering.UseGasAndAddTracedGas(managedBufferToHexName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(managedBufferToHexName, gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } mBuff, err := managedType.GetBytes(sourceHandle) if err != nil { @@ -1074,10 +1155,16 @@ func ManagedGetCodeMetadataWithHost(host vmhost.VMHost, addressHandle int32, res managedType := host.ManagedTypes() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetCodeMetadata - metering.UseGasAndAddTracedGas(managedGetCodeMetadataName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(managedGetCodeMetadataName, gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } gasToUse = metering.GasSchedule().ManagedBufferAPICost.MBufferSetBytes - metering.UseGasAndAddTracedGas(managedGetCodeMetadataName, gasToUse) + err = metering.UseGasBoundedAndAddTracedGas(managedGetCodeMetadataName, gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } mBuffAddress, err := managedType.GetBytes(addressHandle) if err != nil { @@ -1109,7 +1196,10 @@ func ManagedIsBuiltinFunctionWithHost(host vmhost.VMHost, functionNameHandle int managedType := host.ManagedTypes() gasToUse := metering.GasSchedule().BaseOpsAPICost.IsBuiltinFunction - metering.UseGasAndAddTracedGas(managedIsBuiltinFunction, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(managedIsBuiltinFunction, gasToUse) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return -1 + } mBuffFunctionName, err := managedType.GetBytes(functionNameHandle) if err != nil { From 085968ea91bd5d2dd6ae3a6997e52adf22fc1846 Mon Sep 17 00:00:00 2001 From: robertsasu Date: Thu, 8 Aug 2024 16:47:07 +0300 Subject: [PATCH 05/24] refactoring gasUsage --- vmhost/interface.go | 12 ++++++------ vmhost/vmhooks/manMapOps.go | 31 +++++++++++++++++++++++-------- vmhost/vmhooks/smallIntOps.go | 30 ++++++++++++++++++++++++------ 3 files changed, 53 insertions(+), 20 deletions(-) diff --git a/vmhost/interface.go b/vmhost/interface.go index 6538486f6..1c4235ab9 100644 --- a/vmhost/interface.go +++ b/vmhost/interface.go @@ -178,11 +178,11 @@ type ManagedTypesContext interface { StateStack GetRandReader() io.Reader - ConsumeGasForThisBigIntNumberOfBytes(byteLen *big.Int) - ConsumeGasForThisIntNumberOfBytes(byteLen int) - ConsumeGasForBytes(bytes []byte) - ConsumeGasForBigIntCopy(values ...*big.Int) - ConsumeGasForBigFloatCopy(values ...*big.Float) + ConsumeGasForThisBigIntNumberOfBytes(byteLen *big.Int) error + ConsumeGasForThisIntNumberOfBytes(byteLen int) error + ConsumeGasForBytes(bytes []byte) error + ConsumeGasForBigIntCopy(values ...*big.Int) error + ConsumeGasForBigFloatCopy(values ...*big.Float) error NewBigInt(value *big.Int) int32 NewBigIntFromInt64(int64Value int64) int32 GetBigIntOrCreate(handle int32) *big.Int @@ -212,7 +212,7 @@ type ManagedTypesContext interface { DeleteSlice(mBufferHandle int32, startPosition int32, lengthOfSlice int32) ([]byte, error) InsertSlice(mBufferHandle int32, startPosition int32, slice []byte) ([]byte, error) ReadManagedVecOfManagedBuffers(managedVecHandle int32) ([][]byte, uint64, error) - WriteManagedVecOfManagedBuffers(data [][]byte, destinationHandle int32) + WriteManagedVecOfManagedBuffers(data [][]byte, destinationHandle int32) error NewManagedMap() int32 ManagedMapPut(mMapHandle int32, keyHandle int32, valueHandle int32) error ManagedMapGet(mMapHandle int32, keyHandle int32, outValueHandle int32) error diff --git a/vmhost/vmhooks/manMapOps.go b/vmhost/vmhooks/manMapOps.go index d7abac6be..db5c3076d 100644 --- a/vmhost/vmhooks/manMapOps.go +++ b/vmhost/vmhooks/manMapOps.go @@ -15,7 +15,10 @@ func (context *VMHooksImpl) ManagedMapNew() int32 { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().ManagedMapAPICost.ManagedMapNew - metering.UseGasAndAddTracedGas(managedMapNewName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(managedMapNewName, gasToUse) + if context.WithFault(err, context.GetRuntimeContext().ManagedMapAPIErrorShouldFailExecution()) { + return 1 + } return managedType.NewManagedMap() } @@ -28,9 +31,12 @@ func (context *VMHooksImpl) ManagedMapPut(mMapHandle int32, keyHandle int32, val runtime := context.GetRuntimeContext() gasToUse := metering.GasSchedule().ManagedMapAPICost.ManagedMapPut - metering.UseGasAndAddTracedGas(managedMapPutName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(managedMapPutName, gasToUse) + if context.WithFault(err, runtime.ManagedMapAPIErrorShouldFailExecution()) { + return 1 + } - err := managedType.ManagedMapPut(mMapHandle, keyHandle, valueHandle) + err = managedType.ManagedMapPut(mMapHandle, keyHandle, valueHandle) if context.WithFault(err, runtime.ManagedMapAPIErrorShouldFailExecution()) { return 1 } @@ -46,9 +52,12 @@ func (context *VMHooksImpl) ManagedMapGet(mMapHandle int32, keyHandle int32, out runtime := context.GetRuntimeContext() gasToUse := metering.GasSchedule().ManagedMapAPICost.ManagedMapGet - metering.UseGasAndAddTracedGas(managedMapGetName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(managedMapGetName, gasToUse) + if context.WithFault(err, runtime.ManagedMapAPIErrorShouldFailExecution()) { + return 1 + } - err := managedType.ManagedMapGet(mMapHandle, keyHandle, outValueHandle) + err = managedType.ManagedMapGet(mMapHandle, keyHandle, outValueHandle) if context.WithFault(err, runtime.ManagedMapAPIErrorShouldFailExecution()) { return 1 } @@ -64,9 +73,12 @@ func (context *VMHooksImpl) ManagedMapRemove(mMapHandle int32, keyHandle int32, runtime := context.GetRuntimeContext() gasToUse := metering.GasSchedule().ManagedMapAPICost.ManagedMapRemove - metering.UseGasAndAddTracedGas(managedMapRemoveName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(managedMapRemoveName, gasToUse) + if context.WithFault(err, runtime.ManagedMapAPIErrorShouldFailExecution()) { + return 1 + } - err := managedType.ManagedMapRemove(mMapHandle, keyHandle, outValueHandle) + err = managedType.ManagedMapRemove(mMapHandle, keyHandle, outValueHandle) if context.WithFault(err, runtime.ManagedMapAPIErrorShouldFailExecution()) { return 1 } @@ -82,7 +94,10 @@ func (context *VMHooksImpl) ManagedMapContains(mMapHandle int32, keyHandle int32 runtime := context.GetRuntimeContext() gasToUse := metering.GasSchedule().ManagedMapAPICost.ManagedMapContains - metering.UseGasAndAddTracedGas(managedMapContainsName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(managedMapContainsName, gasToUse) + if context.WithFault(err, runtime.ManagedMapAPIErrorShouldFailExecution()) { + return 2 + } foundValue, err := managedType.ManagedMapContains(mMapHandle, keyHandle) if context.WithFault(err, runtime.ManagedMapAPIErrorShouldFailExecution()) { diff --git a/vmhost/vmhooks/smallIntOps.go b/vmhost/vmhooks/smallIntOps.go index 9e748c45b..0fa179457 100644 --- a/vmhost/vmhooks/smallIntOps.go +++ b/vmhost/vmhooks/smallIntOps.go @@ -30,7 +30,10 @@ func (context *VMHooksImpl) SmallIntGetUnsignedArgument(id int32) int64 { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.Int64GetArgument - metering.UseGasAndAddTracedGas(smallIntGetUnsignedArgumentName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(smallIntGetUnsignedArgumentName, gasToUse) + if context.WithFault(err, runtime.ManagedMapAPIErrorShouldFailExecution()) { + return 1 + } args := runtime.Arguments() if id < 0 || id >= int32(len(args)) { @@ -54,7 +57,10 @@ func (context *VMHooksImpl) SmallIntGetSignedArgument(id int32) int64 { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.Int64GetArgument - metering.UseGasAndAddTracedGas(smallIntGetSignedArgumentName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(smallIntGetSignedArgumentName, gasToUse) + if context.WithFault(err, runtime.ManagedMapAPIErrorShouldFailExecution()) { + return 1 + } args := runtime.Arguments() if id < 0 || id >= int32(len(args)) { @@ -78,7 +84,10 @@ func (context *VMHooksImpl) SmallIntFinishUnsigned(value int64) { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.Int64Finish - metering.UseGasAndAddTracedGas(smallIntFinishUnsignedName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(smallIntFinishUnsignedName, gasToUse) + if context.WithFault(err, context.GetRuntimeContext().BaseOpsErrorShouldFailExecution()) { + return + } valueBytes := big.NewInt(0).SetUint64(uint64(value)).Bytes() output.Finish(valueBytes) @@ -91,7 +100,10 @@ func (context *VMHooksImpl) SmallIntFinishSigned(value int64) { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.Int64Finish - metering.UseGasAndAddTracedGas(smallIntFinishSignedName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(smallIntFinishSignedName, gasToUse) + if context.WithFault(err, context.GetRuntimeContext().BaseOpsErrorShouldFailExecution()) { + return + } valueBytes := twos.ToBytes(big.NewInt(value)) output.Finish(valueBytes) @@ -105,7 +117,10 @@ func (context *VMHooksImpl) SmallIntStorageStoreUnsigned(keyOffset executor.MemP metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.Int64StorageStore - metering.UseGasAndAddTracedGas(smallIntStorageStoreSignedName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(smallIntStorageStoreSignedName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return -1 + } key, err := context.MemLoad(keyOffset, keyLength) if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -129,7 +144,10 @@ func (context *VMHooksImpl) SmallIntStorageStoreSigned(keyOffset executor.MemPtr metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.Int64StorageStore - metering.UseGasAndAddTracedGas(smallIntStorageStoreSignedName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(smallIntStorageStoreSignedName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return -1 + } key, err := context.MemLoad(keyOffset, keyLength) if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { From e661aca81ec17a30f29809f71d69c0ed805f586c Mon Sep 17 00:00:00 2001 From: robertsasu Date: Thu, 8 Aug 2024 17:11:22 +0300 Subject: [PATCH 06/24] fixes after refactor --- vmhost/contexts/storage.go | 4 ++-- vmhost/contexts/storage_test.go | 1 + vmhost/vmhooks/baseOps.go | 9 +++++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/vmhost/contexts/storage.go b/vmhost/contexts/storage.go index cfa55cf22..dd3e538d3 100644 --- a/vmhost/contexts/storage.go +++ b/vmhost/contexts/storage.go @@ -191,11 +191,11 @@ func (context *storageContext) GetStorageFromAddress(address []byte, key []byte) errGas := context.useExtraGasForKeyIfNeeded(key, usedCache) if errGas != nil { - return nil, 0, false, nil + return nil, 0, false, errGas } errGas = context.useGasForValueIfNeeded(value, usedCache) if errGas != nil { - return nil, 0, false, nil + return nil, 0, false, errGas } logStorage.Trace("get from address", "address", address, "key", key, "value", value) diff --git a/vmhost/contexts/storage_test.go b/vmhost/contexts/storage_test.go index bcef139ae..01480e167 100644 --- a/vmhost/contexts/storage_test.go +++ b/vmhost/contexts/storage_test.go @@ -490,6 +490,7 @@ func TestStorageContext_GetStorageFromAddress(t *testing.T) { mockMetering := &contextmock.MeteringContextMock{} mockMetering.SetGasSchedule(config.MakeGasMapForTests()) mockMetering.BlockGasLimitMock = uint64(15000) + mockMetering.GasLeftMock = uint64(15000) host := &contextmock.VMHostMock{ OutputContext: mockOutput, diff --git a/vmhost/vmhooks/baseOps.go b/vmhost/vmhooks/baseOps.go index c6c2584d1..b1b673fab 100644 --- a/vmhost/vmhooks/baseOps.go +++ b/vmhost/vmhooks/baseOps.go @@ -2390,10 +2390,6 @@ func (context *VMHooksImpl) WriteLog( gasToUse := metering.GasSchedule().BaseOpsAPICost.Log gas := math.MulUint64(metering.GasSchedule().BaseOperationCost.PersistPerByte, uint64(numTopics*vmhost.HashLen+dataLength)) gasToUse = math.AddUint64(gasToUse, gas) - err := metering.UseGasBoundedAndAddTracedGas(writeLogName, gasToUse) - if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { - return - } if numTopics < 0 || dataLength < 0 { err := vmhost.ErrNegativeLength @@ -2401,6 +2397,11 @@ func (context *VMHooksImpl) WriteLog( return } + err := metering.UseGasBoundedAndAddTracedGas(writeLogName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } + log, err := context.MemLoad(dataPointer, dataLength) if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { return From 12aee59624a19df16c057e21f19dd6919088df15 Mon Sep 17 00:00:00 2001 From: robertsasu Date: Thu, 8 Aug 2024 17:38:56 +0300 Subject: [PATCH 07/24] fixes after refactor --- mock/contracts/gasMismatchParent.go | 2 +- vmhost/vmhooks/bigFloatOps.go | 30 +++++- vmhost/vmhooks/bigIntOps.go | 154 +++++++++++++++++++++++---- vmhost/vmhooks/cryptoei.go | 125 ++++++++++++++++++---- vmhost/vmhooks/manBufOps.go | 55 ++++++++-- vmhost/vmhooks/managedConversions.go | 19 +++- vmhost/vmhooks/managedei.go | 91 ++++++++++++---- 7 files changed, 394 insertions(+), 82 deletions(-) diff --git a/mock/contracts/gasMismatchParent.go b/mock/contracts/gasMismatchParent.go index e7ec1eb23..7d9ae3d49 100644 --- a/mock/contracts/gasMismatchParent.go +++ b/mock/contracts/gasMismatchParent.go @@ -19,7 +19,7 @@ func GasMismatchAsyncCallParentMock(instanceMock *mock.InstanceMock, _ interface valueHandle := managedTypes.NewBigIntFromInt64(0) functionHandle := managedTypes.NewManagedBufferFromBytes([]byte("gasMismatchChild")) argumentsHandle := managedTypes.NewManagedBuffer() - managedTypes.WriteManagedVecOfManagedBuffers([][]byte{}, argumentsHandle) + _ = managedTypes.WriteManagedVecOfManagedBuffers([][]byte{}, argumentsHandle) vmhooks.ManagedAsyncCallWithHost( host, diff --git a/vmhost/vmhooks/bigFloatOps.go b/vmhost/vmhooks/bigFloatOps.go index d53c091d2..647bb4f4f 100644 --- a/vmhost/vmhooks/bigFloatOps.go +++ b/vmhost/vmhooks/bigFloatOps.go @@ -475,7 +475,10 @@ func (context *VMHooksImpl) BigFloatPow(destinationHandle, opHandle, exponent in //this calculates the length of the result in bytes lengthOfResult := big.NewInt(0).Div(big.NewInt(0).Mul(op2BigInt, big.NewInt(int64(opBigInt.BitLen()))), big.NewInt(8)) - managedType.ConsumeGasForThisBigIntNumberOfBytes(lengthOfResult) + err = managedType.ConsumeGasForThisBigIntNumberOfBytes(lengthOfResult) + if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { + return + } powResult, err := context.pow(op, exponent) if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { @@ -523,8 +526,12 @@ func (context *VMHooksImpl) BigFloatFloor(destBigIntHandle, opHandle int32) { } bigIntOp := managedType.GetBigIntOrCreate(destBigIntHandle) + err = managedType.ConsumeGasForBigIntCopy(bigIntOp) + if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { + return + } + op.Int(bigIntOp) - managedType.ConsumeGasForBigIntCopy(bigIntOp) if op.IsInt() { return } @@ -553,8 +560,12 @@ func (context *VMHooksImpl) BigFloatCeil(destBigIntHandle, opHandle int32) { } bigIntOp := managedType.GetBigIntOrCreate(destBigIntHandle) + err = managedType.ConsumeGasForBigIntCopy(bigIntOp) + if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { + return + } + op.Int(bigIntOp) - managedType.ConsumeGasForBigIntCopy(bigIntOp) if op.IsInt() { return } @@ -583,8 +594,12 @@ func (context *VMHooksImpl) BigFloatTruncate(destBigIntHandle, opHandle int32) { } bigIntValue := managedType.GetBigIntOrCreate(destBigIntHandle) + err = managedType.ConsumeGasForBigIntCopy(bigIntValue) + if context.WithFault(err, runtime.BigFloatAPIErrorShouldFailExecution()) { + return + } + op.Int(bigIntValue) - managedType.ConsumeGasForBigIntCopy(bigIntValue) } // BigFloatSetInt64 VMHooks implementation. @@ -646,10 +661,15 @@ func (context *VMHooksImpl) BigFloatSetBigInt(destinationHandle, bigIntHandle in } bigIntValue, err := managedType.GetBigInt(bigIntHandle) - managedType.ConsumeGasForBigIntCopy(bigIntValue) if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { return } + + err = managedType.ConsumeGasForBigIntCopy(bigIntValue) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } + resultSetInt := big.NewFloat(0).SetInt(bigIntValue) setResultIfNotInfinity(context.GetVMHost(), resultSetInt, destinationHandle) } diff --git a/vmhost/vmhooks/bigIntOps.go b/vmhost/vmhooks/bigIntOps.go index ba0c37536..0153221b9 100644 --- a/vmhost/vmhooks/bigIntOps.go +++ b/vmhost/vmhooks/bigIntOps.go @@ -532,7 +532,12 @@ func (context *VMHooksImpl) BigIntAdd(destinationHandle, op1Handle, op2Handle in if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { return } - managedType.ConsumeGasForBigIntCopy(dest, a, b) + + err = managedType.ConsumeGasForBigIntCopy(dest, a, b) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } + dest.Add(a, b) } @@ -555,7 +560,12 @@ func (context *VMHooksImpl) BigIntSub(destinationHandle, op1Handle, op2Handle in if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { return } - managedType.ConsumeGasForBigIntCopy(dest, a, b) + + err = managedType.ConsumeGasForBigIntCopy(dest, a, b) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } + dest.Sub(a, b) } @@ -578,7 +588,11 @@ func (context *VMHooksImpl) BigIntMul(destinationHandle, op1Handle, op2Handle in if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { return } - managedType.ConsumeGasForBigIntCopy(dest, a, b) + + err = managedType.ConsumeGasForBigIntCopy(dest, a, b) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } dest.Mul(a, b) } @@ -602,7 +616,12 @@ func (context *VMHooksImpl) BigIntTDiv(destinationHandle, op1Handle, op2Handle i if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { return } - managedType.ConsumeGasForBigIntCopy(dest, a, b) + + err = managedType.ConsumeGasForBigIntCopy(dest, a, b) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } + if b.Sign() == 0 { _ = context.WithFault(vmhost.ErrDivZero, runtime.BigIntAPIErrorShouldFailExecution()) return @@ -629,7 +648,12 @@ func (context *VMHooksImpl) BigIntTMod(destinationHandle, op1Handle, op2Handle i if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { return } - managedType.ConsumeGasForBigIntCopy(dest, a, b) + + err = managedType.ConsumeGasForBigIntCopy(dest, a, b) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } + if b.Sign() == 0 { _ = context.WithFault(vmhost.ErrDivZero, runtime.BigIntAPIErrorShouldFailExecution()) return @@ -656,7 +680,12 @@ func (context *VMHooksImpl) BigIntEDiv(destinationHandle, op1Handle, op2Handle i if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { return } - managedType.ConsumeGasForBigIntCopy(dest, a, b) + + err = managedType.ConsumeGasForBigIntCopy(dest, a, b) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } + if b.Sign() == 0 { _ = context.WithFault(vmhost.ErrDivZero, runtime.BigIntAPIErrorShouldFailExecution()) return @@ -683,7 +712,12 @@ func (context *VMHooksImpl) BigIntEMod(destinationHandle, op1Handle, op2Handle i if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { return } - managedType.ConsumeGasForBigIntCopy(dest, a, b) + + err = managedType.ConsumeGasForBigIntCopy(dest, a, b) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } + if b.Sign() == 0 { _ = context.WithFault(vmhost.ErrDivZero, runtime.BigIntAPIErrorShouldFailExecution()) return @@ -710,7 +744,12 @@ func (context *VMHooksImpl) BigIntSqrt(destinationHandle, opHandle int32) { if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { return } - managedType.ConsumeGasForBigIntCopy(dest, a) + + err = managedType.ConsumeGasForBigIntCopy(dest, a) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } + if a.Sign() < 0 { _ = context.WithFault(vmhost.ErrBadLowerBounds, runtime.BigIntAPIErrorShouldFailExecution()) return @@ -741,8 +780,15 @@ func (context *VMHooksImpl) BigIntPow(destinationHandle, op1Handle, op2Handle in //this calculates the length of the result in bytes lengthOfResult := big.NewInt(0).Div(big.NewInt(0).Mul(b, big.NewInt(int64(a.BitLen()))), big.NewInt(8)) - managedType.ConsumeGasForThisBigIntNumberOfBytes(lengthOfResult) - managedType.ConsumeGasForBigIntCopy(a, b) + err = managedType.ConsumeGasForThisBigIntNumberOfBytes(lengthOfResult) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } + + err = managedType.ConsumeGasForBigIntCopy(a, b) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } if b.Sign() < 0 { _ = context.WithFault(vmhost.ErrBadLowerBounds, runtime.BigIntAPIErrorShouldFailExecution()) @@ -770,7 +816,12 @@ func (context *VMHooksImpl) BigIntLog2(op1Handle int32) int32 { if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { return -1 } - managedType.ConsumeGasForBigIntCopy(a) + + err = managedType.ConsumeGasForBigIntCopy(a) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return -1 + } + if a.Sign() < 0 { _ = context.WithFault(vmhost.ErrBadLowerBounds, runtime.BigIntAPIErrorShouldFailExecution()) return -1 @@ -798,7 +849,12 @@ func (context *VMHooksImpl) BigIntAbs(destinationHandle, opHandle int32) { if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { return } - managedType.ConsumeGasForBigIntCopy(dest, a) + + err = managedType.ConsumeGasForBigIntCopy(dest, a) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } + dest.Abs(a) } @@ -821,7 +877,12 @@ func (context *VMHooksImpl) BigIntNeg(destinationHandle, opHandle int32) { if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { return } - managedType.ConsumeGasForBigIntCopy(dest, a) + + err = managedType.ConsumeGasForBigIntCopy(dest, a) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } + dest.Neg(a) } @@ -843,7 +904,12 @@ func (context *VMHooksImpl) BigIntSign(opHandle int32) int32 { if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { return -2 } - managedType.ConsumeGasForBigIntCopy(a) + + err = managedType.ConsumeGasForBigIntCopy(a) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return -2 + } + return int32(a.Sign()) } @@ -865,7 +931,12 @@ func (context *VMHooksImpl) BigIntCmp(op1Handle, op2Handle int32) int32 { if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { return -2 } - managedType.ConsumeGasForBigIntCopy(a, b) + + err = managedType.ConsumeGasForBigIntCopy(a, b) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return -2 + } + return int32(a.Cmp(b)) } @@ -888,7 +959,12 @@ func (context *VMHooksImpl) BigIntNot(destinationHandle, opHandle int32) { if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { return } - managedType.ConsumeGasForBigIntCopy(dest, a) + + err = managedType.ConsumeGasForBigIntCopy(dest, a) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } + if a.Sign() < 0 { _ = context.WithFault(vmhost.ErrBitwiseNegative, runtime.BigIntAPIErrorShouldFailExecution()) return @@ -915,7 +991,12 @@ func (context *VMHooksImpl) BigIntAnd(destinationHandle, op1Handle, op2Handle in if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { return } - managedType.ConsumeGasForBigIntCopy(a, b) + + err = managedType.ConsumeGasForBigIntCopy(a, b) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } + if a.Sign() < 0 || b.Sign() < 0 { _ = context.WithFault(vmhost.ErrBitwiseNegative, runtime.BigIntAPIErrorShouldFailExecution()) return @@ -942,7 +1023,12 @@ func (context *VMHooksImpl) BigIntOr(destinationHandle, op1Handle, op2Handle int if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { return } - managedType.ConsumeGasForBigIntCopy(a, b) + + err = managedType.ConsumeGasForBigIntCopy(a, b) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } + if a.Sign() < 0 || b.Sign() < 0 { _ = context.WithFault(vmhost.ErrBitwiseNegative, runtime.BigIntAPIErrorShouldFailExecution()) return @@ -969,7 +1055,12 @@ func (context *VMHooksImpl) BigIntXor(destinationHandle, op1Handle, op2Handle in if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { return } - managedType.ConsumeGasForBigIntCopy(a, b) + + err = managedType.ConsumeGasForBigIntCopy(a, b) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } + if a.Sign() < 0 || b.Sign() < 0 { _ = context.WithFault(vmhost.ErrBitwiseNegative, runtime.BigIntAPIErrorShouldFailExecution()) return @@ -996,13 +1087,22 @@ func (context *VMHooksImpl) BigIntShr(destinationHandle, opHandle, bits int32) { if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { return } - managedType.ConsumeGasForBigIntCopy(a) + + err = managedType.ConsumeGasForBigIntCopy(a) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } + if a.Sign() < 0 || bits < 0 { _ = context.WithFault(vmhost.ErrShiftNegative, runtime.BigIntAPIErrorShouldFailExecution()) return } dest.Rsh(a, uint(bits)) - managedType.ConsumeGasForBigIntCopy(dest) + + err = managedType.ConsumeGasForBigIntCopy(dest) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } } // BigIntShl VMHooks implementation. @@ -1024,14 +1124,22 @@ func (context *VMHooksImpl) BigIntShl(destinationHandle, opHandle, bits int32) { if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { return } - managedType.ConsumeGasForBigIntCopy(a) + + err = managedType.ConsumeGasForBigIntCopy(a) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } + if a.Sign() < 0 || bits < 0 { _ = context.WithFault(vmhost.ErrShiftNegative, runtime.BigIntAPIErrorShouldFailExecution()) return } dest.Lsh(a, uint(bits)) - managedType.ConsumeGasForBigIntCopy(dest) + err = managedType.ConsumeGasForBigIntCopy(dest) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return + } } // BigIntFinishUnsigned VMHooks implementation. diff --git a/vmhost/vmhooks/cryptoei.go b/vmhost/vmhooks/cryptoei.go index e3bd01d69..f33e39bf5 100644 --- a/vmhost/vmhooks/cryptoei.go +++ b/vmhost/vmhooks/cryptoei.go @@ -95,7 +95,11 @@ func (context *VMHooksImpl) ManagedSha256(inputHandle, outputHandle int32) int32 if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { return 1 } - managedType.ConsumeGasForBytes(inputBytes) + + err = managedType.ConsumeGasForBytes(inputBytes) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return 1 + } resultBytes, err := crypto.Sha256(inputBytes) if err != nil { @@ -158,7 +162,11 @@ func (context *VMHooksImpl) ManagedKeccak256(inputHandle, outputHandle int32) in if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { return 1 } - managedType.ConsumeGasForBytes(inputBytes) + + err = managedType.ConsumeGasForBytes(inputBytes) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return 1 + } resultBytes, err := crypto.Keccak256(inputBytes) if err != nil { @@ -227,7 +235,11 @@ func ManagedRipemd160WithHost(host vmhost.VMHost, inputHandle int32, outputHandl if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { return 1 } - managedType.ConsumeGasForBytes(inputBytes) + + err = managedType.ConsumeGasForBytes(inputBytes) + if WithFaultAndHost(host, err, runtime.BigIntAPIErrorShouldFailExecution()) { + return 1 + } result, err := crypto.Ripemd160(inputBytes) if err != nil { @@ -323,19 +335,31 @@ func ManagedVerifyBLSWithHost( if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { return 1 } - managedType.ConsumeGasForBytes(keyBytes) + + err = managedType.ConsumeGasForBytes(keyBytes) + if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } msgBytes, err := managedType.GetBytes(messageHandle) if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { return 1 } - managedType.ConsumeGasForBytes(msgBytes) + + err = managedType.ConsumeGasForBytes(msgBytes) + if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } sigBytes, err := managedType.GetBytes(sigHandle) if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { return 1 } - managedType.ConsumeGasForBytes(sigBytes) + + err = managedType.ConsumeGasForBytes(sigBytes) + if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } invalidSigErr := crypto.VerifyBLS(keyBytes, msgBytes, sigBytes) if invalidSigErr != nil { @@ -425,19 +449,31 @@ func ManagedVerifyEd25519WithHost( if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { return 1 } - managedType.ConsumeGasForBytes(keyBytes) + + err = managedType.ConsumeGasForBytes(keyBytes) + if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } msgBytes, err := managedType.GetBytes(messageHandle) if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { return 1 } - managedType.ConsumeGasForBytes(msgBytes) + + err = managedType.ConsumeGasForBytes(msgBytes) + if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } sigBytes, err := managedType.GetBytes(sigHandle) if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { return 1 } - managedType.ConsumeGasForBytes(sigBytes) + + err = managedType.ConsumeGasForBytes(sigBytes) + if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } invalidSigErr := crypto.VerifyEd25519(keyBytes, msgBytes, sigBytes) if invalidSigErr != nil { @@ -550,19 +586,31 @@ func ManagedVerifyCustomSecp256k1WithHost( if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { return 1 } - managedType.ConsumeGasForBytes(keyBytes) + + err = managedType.ConsumeGasForBytes(keyBytes) + if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } msgBytes, err := managedType.GetBytes(messageHandle) if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { return 1 } - managedType.ConsumeGasForBytes(msgBytes) + + err = managedType.ConsumeGasForBytes(msgBytes) + if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } sigBytes, err := managedType.GetBytes(sigHandle) if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { return 1 } - managedType.ConsumeGasForBytes(sigBytes) + + err = managedType.ConsumeGasForBytes(sigBytes) + if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } invalidSigErr := crypto.VerifySecp256k1(keyBytes, msgBytes, sigBytes, uint8(hashType)) if invalidSigErr != nil { @@ -747,7 +795,10 @@ func (context *VMHooksImpl) AddEC( return } - managedType.ConsumeGasForBigIntCopy(xResult, yResult, ec.P, ec.N, ec.B, ec.Gx, ec.Gy, x1, y1, x2, y2) + err = managedType.ConsumeGasForBigIntCopy(xResult, yResult, ec.P, ec.N, ec.B, ec.Gx, ec.Gy, x1, y1, x2, y2) + if context.WithFault(vmhost.ErrPointNotOnCurve, runtime.CryptoAPIErrorShouldFailExecution()) { + return + } xResultAdd, yResultAdd := ec.Add(x1, y1, x2, y2) xResult.Set(xResultAdd) yResult.Set(yResultAdd) @@ -794,7 +845,10 @@ func (context *VMHooksImpl) DoubleEC( return } - managedType.ConsumeGasForBigIntCopy(xResult, yResult, ec.P, ec.N, ec.B, ec.Gx, ec.Gy, x, y) + err = managedType.ConsumeGasForBigIntCopy(xResult, yResult, ec.P, ec.N, ec.B, ec.Gx, ec.Gy, x, y) + if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { + return + } xResultDouble, yResultDouble := ec.Double(x, y) xResult.Set(xResultDouble) @@ -835,7 +889,11 @@ func (context *VMHooksImpl) IsOnCurveEC( return -1 } - managedType.ConsumeGasForBigIntCopy(ec.P, ec.N, ec.B, ec.Gx, ec.Gy, x, y) + err = managedType.ConsumeGasForBigIntCopy(ec.P, ec.N, ec.B, ec.Gx, ec.Gy, x, y) + if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { + return -1 + } + if ec.IsOnCurve(x, y) { return 1 } @@ -955,7 +1013,10 @@ func commonScalarBaseMultEC( return 1 } - managedType.ConsumeGasForBigIntCopy(ec.P, ec.N, ec.B, ec.Gx, ec.Gy, xResult, yResult) + err = managedType.ConsumeGasForBigIntCopy(ec.P, ec.N, ec.B, ec.Gx, ec.Gy, xResult, yResult) + if WithFaultAndHost(host, err, runtime.CryptoAPIErrorShouldFailExecution()) { + return 1 + } xResultSBM, yResultSBM := ec.ScalarBaseMult(data) if !ec.IsOnCurve(xResultSBM, yResultSBM) { @@ -1098,7 +1159,11 @@ func commonScalarMultEC( return 1 } - managedType.ConsumeGasForBigIntCopy(xResult, yResult, ec.P, ec.N, ec.B, ec.Gx, ec.Gy, x, y) + err := managedType.ConsumeGasForBigIntCopy(xResult, yResult, ec.P, ec.N, ec.B, ec.Gx, ec.Gy, x, y) + if WithFaultAndHost(host, err, runtime.CryptoAPIErrorShouldFailExecution()) { + return 1 + } + xResultSM, yResultSM := ec.ScalarMult(x, y, data) if !ec.IsOnCurve(xResultSM, yResultSM) { _ = WithFaultAndHost(host, vmhost.ErrPointNotOnCurve, runtime.CryptoAPIErrorShouldFailExecution()) @@ -1206,7 +1271,10 @@ func commonMarshalEC( return nil, vmhost.ErrLengthOfBufferNotCorrect } - managedType.ConsumeGasForBigIntCopy(ec.P, ec.N, ec.B, ec.Gx, ec.Gy, x, y) + err = managedType.ConsumeGasForBigIntCopy(ec.P, ec.N, ec.B, ec.Gx, ec.Gy, x, y) + if err != nil { + return nil, err + } result := elliptic.Marshal(ec, x, y) return result, nil @@ -1308,7 +1376,10 @@ func commonMarshalCompressedEC(host vmhost.VMHost, return nil, vmhost.ErrLengthOfBufferNotCorrect } - managedType.ConsumeGasForBigIntCopy(ec.P, ec.N, ec.B, ec.Gx, ec.Gy, x, y) + err = managedType.ConsumeGasForBigIntCopy(ec.P, ec.N, ec.B, ec.Gx, ec.Gy, x, y) + if err != nil { + return nil, err + } result := elliptic.MarshalCompressed(ec, x, y) return result, nil @@ -1423,7 +1494,10 @@ func commonUnmarshalEC( return 1 } - managedType.ConsumeGasForBigIntCopy(ec.P, ec.N, ec.B, ec.Gx, ec.Gy, xResult, yResult) + err = managedType.ConsumeGasForBigIntCopy(ec.P, ec.N, ec.B, ec.Gx, ec.Gy, xResult, yResult) + if WithFaultAndHost(host, err, runtime.CryptoAPIErrorShouldFailExecution()) { + return 1 + } xResultU, yResultU := elliptic.Unmarshal(ec, data) if xResultU == nil || yResultU == nil || !ec.IsOnCurve(xResultU, yResultU) { @@ -1545,7 +1619,10 @@ func commonUnmarshalCompressedEC( return 1 } - managedType.ConsumeGasForBigIntCopy(ec.P, ec.N, ec.B, ec.Gx, ec.Gy, xResult, yResult) + err = managedType.ConsumeGasForBigIntCopy(ec.P, ec.N, ec.B, ec.Gx, ec.Gy, xResult, yResult) + if WithFaultAndHost(host, err, runtime.CryptoAPIErrorShouldFailExecution()) { + return 1 + } xResultUC, yResultUC := elliptic.UnmarshalCompressed(ec, data) if xResultUC == nil || yResultUC == nil || !ec.IsOnCurve(xResultUC, yResultUC) { @@ -1649,7 +1726,11 @@ func commonGenerateEC( if err != nil { return nil, err } - managedType.ConsumeGasForBigIntCopy(ec.P, ec.N, ec.B, ec.Gx, ec.Gy, xPubKey, yPubKey) + + err = managedType.ConsumeGasForBigIntCopy(ec.P, ec.N, ec.B, ec.Gx, ec.Gy, xPubKey, yPubKey) + if err != nil { + return nil, err + } ioReader := managedType.GetRandReader() result, xPubKeyGK, yPubKeyGK, err := elliptic.GenerateKey(ec, ioReader) diff --git a/vmhost/vmhooks/manBufOps.go b/vmhost/vmhooks/manBufOps.go index 2c1340f18..c443844fa 100644 --- a/vmhost/vmhooks/manBufOps.go +++ b/vmhost/vmhooks/manBufOps.go @@ -110,7 +110,10 @@ func (context *VMHooksImpl) MBufferGetBytes(mBufferHandle int32, resultOffset ex if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { return 1 } - managedType.ConsumeGasForBytes(mBufferBytes) + err = managedType.ConsumeGasForBytes(mBufferBytes) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } err = context.MemStore(resultOffset, mBufferBytes) if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { @@ -143,7 +146,10 @@ func (context *VMHooksImpl) MBufferGetByteSlice( if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { return 1 } - managedType.ConsumeGasForBytes(sourceBytes) + err = managedType.ConsumeGasForBytes(sourceBytes) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } if startingPosition < 0 || sliceLength < 0 || int(startingPosition+sliceLength) > len(sourceBytes) { // does not fail execution if slice exceeds bounds @@ -183,7 +189,10 @@ func ManagedBufferCopyByteSliceWithHost(host vmhost.VMHost, sourceHandle int32, if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { return 1 } - managedType.ConsumeGasForBytes(sourceBytes) + err = managedType.ConsumeGasForBytes(sourceBytes) + if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } if startingPosition < 0 || sliceLength < 0 || int(startingPosition+sliceLength) > len(sourceBytes) { // does not fail execution if slice exceeds bounds @@ -220,13 +229,19 @@ func (context *VMHooksImpl) MBufferEq(mBufferHandle1 int32, mBufferHandle2 int32 if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { return -1 } - managedType.ConsumeGasForBytes(bytes1) + err = managedType.ConsumeGasForBytes(bytes1) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } bytes2, err := managedType.GetBytes(mBufferHandle2) if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { return -1 } - managedType.ConsumeGasForBytes(bytes2) + err = managedType.ConsumeGasForBytes(bytes2) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } if bytes.Equal(bytes1, bytes2) { return 1 @@ -253,7 +268,12 @@ func (context *VMHooksImpl) MBufferSetBytes(mBufferHandle int32, dataOffset exec if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { return 1 } - managedType.ConsumeGasForBytes(data) + + err = managedType.ConsumeGasForBytes(data) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } + managedType.SetBytes(mBufferHandle, data) return 0 @@ -304,7 +324,10 @@ func ManagedBufferSetByteSliceWithTypedArgs(host vmhost.VMHost, mBufferHandle in metering := host.Metering() metering.StartGasTracing(mBufferGetByteSliceName) - managedType.ConsumeGasForBytes(data) + err := managedType.ConsumeGasForBytes(data) + if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } bufferBytes, err := managedType.GetBytes(mBufferHandle) if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { @@ -345,7 +368,11 @@ func (context *VMHooksImpl) MBufferAppend(accumulatorHandle int32, dataHandle in if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { return 1 } - managedType.ConsumeGasForBytes(dataBufferBytes) + + err = managedType.ConsumeGasForBytes(dataBufferBytes) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } isSuccess := managedType.AppendBytes(accumulatorHandle, dataBufferBytes) if !isSuccess { @@ -502,7 +529,11 @@ func (context *VMHooksImpl) MBufferToBigFloat(mBufferHandle, bigFloatHandle int3 return 1 } - managedType.ConsumeGasForBytes(managedBuffer) + err = managedType.ConsumeGasForBytes(managedBuffer) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } + if managedType.EncodedBigFloatIsNotValid(managedBuffer) { _ = context.WithFault(vmhost.ErrBigFloatWrongPrecision, runtime.BigFloatAPIErrorShouldFailExecution()) return 1 @@ -550,7 +581,11 @@ func (context *VMHooksImpl) MBufferFromBigFloat(mBufferHandle, bigFloatHandle in if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { return 1 } - managedType.ConsumeGasForBytes(encodedFloat) + + err = managedType.ConsumeGasForBytes(encodedFloat) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } managedType.SetBytes(mBufferHandle, encodedFloat) diff --git a/vmhost/vmhooks/managedConversions.go b/vmhost/vmhooks/managedConversions.go index 1c17ec49f..29951f3b9 100644 --- a/vmhost/vmhooks/managedConversions.go +++ b/vmhost/vmhooks/managedConversions.go @@ -27,14 +27,23 @@ func readESDTTransfer( if err != nil { return nil, err } - managedType.ConsumeGasForBytes(tokenIdentifier) + + err = managedType.ConsumeGasForBytes(tokenIdentifier) + if err != nil { + return nil, err + } + nonce := binary.BigEndian.Uint64(data[4:12]) valueHandle := int32(binary.BigEndian.Uint32(data[12:16])) value, err := managedType.GetBigInt(valueHandle) if err != nil { return nil, err } - managedType.ConsumeGasForBigIntCopy(value) + + err = managedType.ConsumeGasForBigIntCopy(value) + if err != nil { + return nil, err + } tokenType := core.Fungible if nonce > 0 { @@ -63,7 +72,11 @@ func readESDTTransfers( if err != nil { return nil, err } - managedType.ConsumeGasForBytes(managedVecBytes) + + err = managedType.ConsumeGasForBytes(managedVecBytes) + if err != nil { + return nil, err + } if len(managedVecBytes)%esdtTransferLen != 0 { return nil, errors.New("invalid managed vector of ESDT transfers") diff --git a/vmhost/vmhooks/managedei.go b/vmhost/vmhooks/managedei.go index fb7afe510..74d3cd9fa 100644 --- a/vmhost/vmhooks/managedei.go +++ b/vmhost/vmhooks/managedei.go @@ -122,7 +122,11 @@ func (context *VMHooksImpl) ManagedSignalError(errHandle int32) { if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { return } - managedType.ConsumeGasForBytes(errBytes) + + err = managedType.ConsumeGasForBytes(errBytes) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return + } gasToUse = metering.GasSchedule().BaseOperationCost.PersistPerByte * uint64(len(errBytes)) err = metering.UseGasBounded(gasToUse) @@ -155,7 +159,12 @@ func (context *VMHooksImpl) ManagedWriteLog( if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { return } - managedType.ConsumeGasForBytes(dataBytes) + + err = managedType.ConsumeGasForBytes(dataBytes) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return + } + dataByteLen := uint64(len(dataBytes)) gasToUse := metering.GasSchedule().BaseOpsAPICost.Log @@ -273,7 +282,10 @@ func (context *VMHooksImpl) ManagedGetMultiESDTCallValue(multiCallValueHandle in esdtTransfers := runtime.GetVMInput().ESDTTransfers multiCallBytes := writeESDTTransfersToBytes(managedType, esdtTransfers) - managedType.ConsumeGasForBytes(multiCallBytes) + err = managedType.ConsumeGasForBytes(multiCallBytes) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } managedType.SetBytes(multiCallValueHandle, multiCallBytes) } @@ -292,7 +304,10 @@ func (context *VMHooksImpl) ManagedGetBackTransfers(esdtTransfersValueHandle int esdtTransfers, transferValue := managedType.GetBackTransfers() multiCallBytes := writeESDTTransfersToBytes(managedType, esdtTransfers) - managedType.ConsumeGasForBytes(multiCallBytes) + err = managedType.ConsumeGasForBytes(multiCallBytes) + if context.WithFault(err, context.GetRuntimeContext().BaseOpsErrorShouldFailExecution()) { + return + } managedType.SetBytes(esdtTransfersValueHandle, multiCallBytes) egldValue := managedType.GetBigIntOrCreate(egldValueHandle) @@ -392,17 +407,32 @@ func ManagedGetESDTTokenDataWithHost( managedType.SetBytes(propertiesHandle, esdtToken.Properties) if esdtToken.TokenMetaData != nil { managedType.SetBytes(hashHandle, esdtToken.TokenMetaData.Hash) - managedType.ConsumeGasForBytes(esdtToken.TokenMetaData.Hash) + err = managedType.ConsumeGasForBytes(esdtToken.TokenMetaData.Hash) + if WithFaultAndHost(host, vmhost.ErrArgOutOfRange, runtime.BaseOpsErrorShouldFailExecution()) { + return + } managedType.SetBytes(nameHandle, esdtToken.TokenMetaData.Name) - managedType.ConsumeGasForBytes(esdtToken.TokenMetaData.Name) + err = managedType.ConsumeGasForBytes(esdtToken.TokenMetaData.Name) + if WithFaultAndHost(host, vmhost.ErrArgOutOfRange, runtime.BaseOpsErrorShouldFailExecution()) { + return + } managedType.SetBytes(attributesHandle, esdtToken.TokenMetaData.Attributes) - managedType.ConsumeGasForBytes(esdtToken.TokenMetaData.Attributes) + err = managedType.ConsumeGasForBytes(esdtToken.TokenMetaData.Attributes) + if WithFaultAndHost(host, vmhost.ErrArgOutOfRange, runtime.BaseOpsErrorShouldFailExecution()) { + return + } managedType.SetBytes(creatorHandle, esdtToken.TokenMetaData.Creator) - managedType.ConsumeGasForBytes(esdtToken.TokenMetaData.Creator) + err = managedType.ConsumeGasForBytes(esdtToken.TokenMetaData.Creator) + if WithFaultAndHost(host, vmhost.ErrArgOutOfRange, runtime.BaseOpsErrorShouldFailExecution()) { + return + } royalties := managedType.GetBigIntOrCreate(royaltiesHandle) royalties.SetUint64(uint64(esdtToken.TokenMetaData.Royalties)) - managedType.WriteManagedVecOfManagedBuffers(esdtToken.TokenMetaData.URIs, urisHandle) + err = managedType.WriteManagedVecOfManagedBuffers(esdtToken.TokenMetaData.URIs, urisHandle) + if WithFaultAndHost(host, vmhost.ErrArgOutOfRange, runtime.BaseOpsErrorShouldFailExecution()) { + return + } } } @@ -613,7 +643,10 @@ func (context *VMHooksImpl) ManagedUpgradeFromSourceContract( gas, codeMetadata, ) - setReturnDataIfExists(host, lenReturnData, resultHandle) + err = setReturnDataIfExists(host, lenReturnData, resultHandle) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } } // ManagedUpgradeContract VMHooks implementation. @@ -661,7 +694,10 @@ func (context *VMHooksImpl) ManagedUpgradeContract( lenReturnData := len(host.Output().ReturnData()) upgradeContract(host, vmInput.destination, code, codeMetadata, vmInput.value.Bytes(), vmInput.arguments, gas) - setReturnDataIfExists(host, lenReturnData, resultHandle) + err = setReturnDataIfExists(host, lenReturnData, resultHandle) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } } // ManagedDeleteContract VMHooks implementation. @@ -763,7 +799,10 @@ func (context *VMHooksImpl) ManagedDeployFromSourceContract( } managedType.SetBytes(resultAddressHandle, newAddress) - setReturnDataIfExists(host, lenReturnData, resultHandle) + err = setReturnDataIfExists(host, lenReturnData, resultHandle) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return 1 + } return 0 } @@ -825,7 +864,10 @@ func (context *VMHooksImpl) ManagedCreateContract( } managedType.SetBytes(resultAddressHandle, newAddress) - setReturnDataIfExists(host, lenReturnData, resultHandle) + err = setReturnDataIfExists(host, lenReturnData, resultHandle) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return 1 + } return 0 } @@ -834,13 +876,14 @@ func setReturnDataIfExists( host vmhost.VMHost, oldLen int, resultHandle int32, -) { +) error { returnData := host.Output().ReturnData() if len(returnData) > oldLen { - host.ManagedTypes().WriteManagedVecOfManagedBuffers(returnData[oldLen:], resultHandle) + return host.ManagedTypes().WriteManagedVecOfManagedBuffers(returnData[oldLen:], resultHandle) } else { host.ManagedTypes().SetBytes(resultHandle, make([]byte, 0)) } + return nil } // ManagedExecuteReadOnly VMHooks implementation. @@ -869,7 +912,11 @@ func (context *VMHooksImpl) ManagedExecuteReadOnly( vmInput.destination, vmInput.arguments, ) - setReturnDataIfExists(host, lenReturnData, resultHandle) + err = setReturnDataIfExists(host, lenReturnData, resultHandle) + if WithFaultAndHost(host, err, host.Runtime().BaseOpsErrorShouldFailExecution()) { + return -1 + } + return returnVal } @@ -901,7 +948,11 @@ func (context *VMHooksImpl) ManagedExecuteOnSameContext( vmInput.destination, vmInput.arguments, ) - setReturnDataIfExists(host, lenReturnData, resultHandle) + err = setReturnDataIfExists(host, lenReturnData, resultHandle) + if WithFaultAndHost(host, err, host.Runtime().BaseOpsErrorShouldFailExecution()) { + return -1 + } + return returnVal } @@ -933,7 +984,11 @@ func (context *VMHooksImpl) ManagedExecuteOnDestContext( vmInput.destination, vmInput.arguments, ) - setReturnDataIfExists(host, lenReturnData, resultHandle) + err = setReturnDataIfExists(host, lenReturnData, resultHandle) + if WithFaultAndHost(host, err, host.Runtime().BaseOpsErrorShouldFailExecution()) { + return -1 + } + return returnVal } From a5630ad3795d048b97cec103aed85334990c1c41 Mon Sep 17 00:00:00 2001 From: robertsasu Date: Thu, 8 Aug 2024 18:28:32 +0300 Subject: [PATCH 08/24] fixes after refactor --- mock/context/meteringContextMock.go | 5 +++++ vmhost/contexts/metering.go | 7 ++++++- vmhost/hostCore/execution.go | 5 +---- vmhost/interface.go | 1 + 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/mock/context/meteringContextMock.go b/mock/context/meteringContextMock.go index 8ac22e2a2..bcbc28b3c 100644 --- a/mock/context/meteringContextMock.go +++ b/mock/context/meteringContextMock.go @@ -145,6 +145,11 @@ func (m *MeteringContextMock) DeductGasIfAsyncStep() error { return m.Err } +// UseGasForContractInit mocked method +func (m *MeteringContextMock) UseGasForContractInit(gasToUse uint64) { + m.useGas(gasToUse) +} + // UseGasBounded mocked method func (m *MeteringContextMock) UseGasBounded(gas uint64) error { if m.Err != nil { diff --git a/vmhost/contexts/metering.go b/vmhost/contexts/metering.go index 691b46b62..62b8f8124 100644 --- a/vmhost/contexts/metering.go +++ b/vmhost/contexts/metering.go @@ -2,7 +2,6 @@ package contexts import ( "fmt" - "github.com/multiversx/mx-chain-core-go/core/check" "github.com/multiversx/mx-chain-core-go/data/vm" logger "github.com/multiversx/mx-chain-logger-go" @@ -468,6 +467,12 @@ func (context *meteringContext) UseGasForAsyncStep() error { return context.UseGasBounded(gasToDeduct) } +// UseGasForContractInit consumes gas on the previous wasmer instance in SC to SC call +func (context *meteringContext) UseGasForContractInit(gasToUse uint64) { + context.useGas(gasToUse) + context.traceGas(gasToUse) +} + // UseGasBounded consumes the specified amount of gas on the currently running // Wasmer instance, but returns an error if there is not enough gas left. func (context *meteringContext) UseGasBounded(gasToUse uint64) error { diff --git a/vmhost/hostCore/execution.go b/vmhost/hostCore/execution.go index 91c4b0c28..c478790ee 100644 --- a/vmhost/hostCore/execution.go +++ b/vmhost/hostCore/execution.go @@ -868,10 +868,7 @@ func (host *vmHost) execute(input *vmcommon.ContractCallInput) error { // Use all gas initially, on the Wasmer instance of the caller. In case of // successful execution, the unused gas will be restored. - err := metering.UseGasBounded(input.GasProvided) - if err != nil { - return err - } + metering.UseGasForContractInit(input.GasProvided) isUpgrade := input.Function == vmhost.UpgradeFunctionName if isUpgrade { diff --git a/vmhost/interface.go b/vmhost/interface.go index 1c4235ab9..767068bbe 100644 --- a/vmhost/interface.go +++ b/vmhost/interface.go @@ -287,6 +287,7 @@ type MeteringContext interface { ComputeExtraGasLockedForAsync() uint64 UseGasForAsyncStep() error UseGasBounded(gasToUse uint64) error + UseGasForContractInit(gasToUse uint64) GetGasLocked() uint64 UpdateGasStateOnSuccess(vmOutput *vmcommon.VMOutput) error UpdateGasStateOnFailure(vmOutput *vmcommon.VMOutput) From 6e8dd5e3f4133cd9d6f2a92772d290d1cc0da00e Mon Sep 17 00:00:00 2001 From: robertsasu Date: Thu, 8 Aug 2024 18:43:40 +0300 Subject: [PATCH 09/24] fixes after refactor --- vmhost/contexts/metering.go | 22 +++++++++++----------- vmhost/hosttest/managedei_test.go | 8 ++++++-- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/vmhost/contexts/metering.go b/vmhost/contexts/metering.go index 62b8f8124..4a95fda27 100644 --- a/vmhost/contexts/metering.go +++ b/vmhost/contexts/metering.go @@ -357,17 +357,6 @@ func (context *meteringContext) useGasAndAddTracedGas(functionName string, gas u context.addToGasTrace(functionName, gas) } -// UseGasBoundedAndAddTracedGas sets in the runtime context the given gas as gas used and adds to current trace -func (context *meteringContext) UseGasBoundedAndAddTracedGas(functionName string, gas uint64) error { - err := context.UseGasBounded(gas) - if err != nil { - return err - } - - context.addToGasTrace(functionName, gas) - return nil -} - // GetGasTrace returns the gasTrace map func (context *meteringContext) GetGasTrace() map[string]map[string][]uint64 { return context.gasTracer.GetGasTrace() @@ -484,6 +473,17 @@ func (context *meteringContext) UseGasBounded(gasToUse uint64) error { return nil } +// UseGasBoundedAndAddTracedGas sets in the runtime context the given gas as gas used and adds to current trace +func (context *meteringContext) UseGasBoundedAndAddTracedGas(functionName string, gas uint64) error { + context.addToGasTrace(functionName, 0) + err := context.UseGasBounded(gas) + if err != nil { + return err + } + + return nil +} + // ComputeExtraGasLockedForAsync calculates the minimum amount of gas to lock for async callbacks func (context *meteringContext) ComputeExtraGasLockedForAsync() uint64 { baseGasSchedule := context.GasSchedule().BaseOperationCost diff --git a/vmhost/hosttest/managedei_test.go b/vmhost/hosttest/managedei_test.go index 43322fa77..687130d3d 100644 --- a/vmhost/hosttest/managedei_test.go +++ b/vmhost/hosttest/managedei_test.go @@ -318,6 +318,10 @@ func bigIntToInt64MockContract(parentInstance *mock.InstanceMock, _ interface{}) inputHandle := int32(0) vmHooksImpl.BigIntGetSignedArgument(0, inputHandle) result := vmHooksImpl.BigIntGetInt64(inputHandle) + if result < 0 { + return parentInstance + } + vmHooksImpl.SmallIntFinishSigned(result) return parentInstance @@ -364,7 +368,7 @@ func Test_BigIntToInt64_NotRepresentable(t *testing.T) { WithInput(test.CreateTestContractCallInputBuilder(). WithArguments(bigIntArg). WithRecipientAddr(test.ParentAddress). - WithGasProvided(testConfig.GasProvided). + WithGasProvided(testConfig.GasProvided + 20000). WithFunction("testFunction"). Build()). AndAssertResults(func(world *worldmock.MockWorld, verify *test.VMOutputVerifier) { @@ -1150,7 +1154,7 @@ func Test_ManagedDeleteContract(t *testing.T) { managedTypes := host.ManagedTypes() argumentsHandle := managedTypes.NewManagedBuffer() - managedTypes.WriteManagedVecOfManagedBuffers([][]byte{{1, 2}, {3, 4}}, argumentsHandle) + _ = managedTypes.WriteManagedVecOfManagedBuffers([][]byte{{1, 2}, {3, 4}}, argumentsHandle) destHandle := managedTypes.NewManagedBufferFromBytes(test.ParentAddress) From f8c50442abb877f868948ba144cc2183e65225f0 Mon Sep 17 00:00:00 2001 From: robertsasu Date: Thu, 8 Aug 2024 19:13:47 +0300 Subject: [PATCH 10/24] fixing tests --- .../json/scenariosAdderLog_test.go | 25 +++++++++++++++++++ vmhost/contexts/metering.go | 12 ++++----- vmhost/hosttest/execution_test.go | 21 +++------------- 3 files changed, 34 insertions(+), 24 deletions(-) diff --git a/integrationTests/json/scenariosAdderLog_test.go b/integrationTests/json/scenariosAdderLog_test.go index 2711f4741..ba7bbd206 100644 --- a/integrationTests/json/scenariosAdderLog_test.go +++ b/integrationTests/json/scenariosAdderLog_test.go @@ -13,28 +13,35 @@ HasFunction(init): true CallFunction(init): VM hook begin: CheckNoPayment() GetPointsUsed: 3 +GetPointsUsed: 3 SetPointsUsed: 103 VM hook end: CheckNoPayment() VM hook begin: GetNumArguments() GetPointsUsed: 110 +GetPointsUsed: 110 SetPointsUsed: 210 VM hook end: GetNumArguments() VM hook begin: BigIntGetUnsignedArgument(0, -101) GetPointsUsed: 249 +GetPointsUsed: 249 SetPointsUsed: 1249 VM hook end: BigIntGetUnsignedArgument(0, -101) VM hook begin: MBufferSetBytes(-102, 131097, 3) GetPointsUsed: 1289 +GetPointsUsed: 1289 SetPointsUsed: 3289 GetPointsUsed: 3289 +GetPointsUsed: 3289 SetPointsUsed: 6289 VM hook end: MBufferSetBytes(-102, 131097, 3) VM hook begin: MBufferFromBigIntUnsigned(-103, -101) GetPointsUsed: 6333 +GetPointsUsed: 6333 SetPointsUsed: 10333 VM hook end: MBufferFromBigIntUnsigned(-103, -101) VM hook begin: MBufferStorageStore(-102, -103) GetPointsUsed: 10345 +GetPointsUsed: 10345 SetPointsUsed: 85345 GetPointsUsed: 85345 GetPointsUsed: 85345 @@ -58,20 +65,25 @@ HasFunction(getSum): true CallFunction(getSum): VM hook begin: CheckNoPayment() GetPointsUsed: 3 +GetPointsUsed: 3 SetPointsUsed: 103 VM hook end: CheckNoPayment() VM hook begin: GetNumArguments() GetPointsUsed: 110 +GetPointsUsed: 110 SetPointsUsed: 210 VM hook end: GetNumArguments() VM hook begin: MBufferSetBytes(-101, 131097, 3) GetPointsUsed: 250 +GetPointsUsed: 250 SetPointsUsed: 2250 GetPointsUsed: 2250 +GetPointsUsed: 2250 SetPointsUsed: 5250 VM hook end: MBufferSetBytes(-101, 131097, 3) VM hook begin: MBufferStorageLoad(-101, -102) GetPointsUsed: 5291 +GetPointsUsed: 5291 SetPointsUsed: 6291 GetPointsUsed: 6291 GetPointsUsed: 6291 @@ -79,12 +91,15 @@ SetPointsUsed: 21578 VM hook end: MBufferStorageLoad(-101, -102) VM hook begin: MBufferToBigIntUnsigned(-102, -103) GetPointsUsed: 21611 +GetPointsUsed: 21611 SetPointsUsed: 25611 VM hook end: MBufferToBigIntUnsigned(-102, -103) VM hook begin: BigIntFinishUnsigned(-103) GetPointsUsed: 25622 +GetPointsUsed: 25622 SetPointsUsed: 26622 GetPointsUsed: 26622 +GetPointsUsed: 26622 SetPointsUsed: 36622 VM hook end: BigIntFinishUnsigned(-103) GetPointsUsed: 36624 @@ -103,24 +118,30 @@ HasFunction(add): true CallFunction(add): VM hook begin: CheckNoPayment() GetPointsUsed: 3 +GetPointsUsed: 3 SetPointsUsed: 103 VM hook end: CheckNoPayment() VM hook begin: GetNumArguments() GetPointsUsed: 110 +GetPointsUsed: 110 SetPointsUsed: 210 VM hook end: GetNumArguments() VM hook begin: BigIntGetUnsignedArgument(0, -101) GetPointsUsed: 249 +GetPointsUsed: 249 SetPointsUsed: 1249 VM hook end: BigIntGetUnsignedArgument(0, -101) VM hook begin: MBufferSetBytes(-102, 131097, 3) GetPointsUsed: 1289 +GetPointsUsed: 1289 SetPointsUsed: 3289 GetPointsUsed: 3289 +GetPointsUsed: 3289 SetPointsUsed: 6289 VM hook end: MBufferSetBytes(-102, 131097, 3) VM hook begin: MBufferStorageLoad(-102, -103) GetPointsUsed: 6333 +GetPointsUsed: 6333 SetPointsUsed: 7333 GetPointsUsed: 7333 GetPointsUsed: 7333 @@ -128,18 +149,22 @@ SetPointsUsed: 22620 VM hook end: MBufferStorageLoad(-102, -103) VM hook begin: MBufferToBigIntUnsigned(-103, -104) GetPointsUsed: 22653 +GetPointsUsed: 22653 SetPointsUsed: 26653 VM hook end: MBufferToBigIntUnsigned(-103, -104) VM hook begin: BigIntAdd(-104, -104, -101) GetPointsUsed: 26673 +GetPointsUsed: 26673 SetPointsUsed: 28673 VM hook end: BigIntAdd(-104, -104, -101) VM hook begin: MBufferFromBigIntUnsigned(-105, -104) GetPointsUsed: 28712 +GetPointsUsed: 28712 SetPointsUsed: 32712 VM hook end: MBufferFromBigIntUnsigned(-105, -104) VM hook begin: MBufferStorageStore(-102, -105) GetPointsUsed: 32724 +GetPointsUsed: 32724 SetPointsUsed: 107724 GetPointsUsed: 107724 GetPointsUsed: 107724 diff --git a/vmhost/contexts/metering.go b/vmhost/contexts/metering.go index 4a95fda27..83d846974 100644 --- a/vmhost/contexts/metering.go +++ b/vmhost/contexts/metering.go @@ -342,7 +342,6 @@ func (context *meteringContext) SetGasSchedule(gasMap config.GasScheduleMap) { func (context *meteringContext) useGas(gas uint64) { gasUsed := math.AddUint64(context.host.Runtime().GetPointsUsed(), gas) context.host.Runtime().SetPointsUsed(gasUsed) - logMetering.Trace("used gas", "gas", gas) } // useAndTraceGas sets in the runtime context the given gas as gas used and adds to current trace @@ -474,13 +473,12 @@ func (context *meteringContext) UseGasBounded(gasToUse uint64) error { } // UseGasBoundedAndAddTracedGas sets in the runtime context the given gas as gas used and adds to current trace -func (context *meteringContext) UseGasBoundedAndAddTracedGas(functionName string, gas uint64) error { - context.addToGasTrace(functionName, 0) - err := context.UseGasBounded(gas) - if err != nil { - return err +func (context *meteringContext) UseGasBoundedAndAddTracedGas(functionName string, gasToUse uint64) error { + if context.GasLeft() < gasToUse { + return vmhost.ErrNotEnoughGas } - + context.useGas(gasToUse) + context.addToGasTrace(functionName, gasToUse) return nil } diff --git a/vmhost/hosttest/execution_test.go b/vmhost/hosttest/execution_test.go index 8907ebe15..79fc50f25 100644 --- a/vmhost/hosttest/execution_test.go +++ b/vmhost/hosttest/execution_test.go @@ -3343,12 +3343,7 @@ func TestExecution_Mocked_ClearReturnData(t *testing.T) { assert.Equal(t, int32(0), returnValue) instance.BreakpointValue = 0 - returnData := vmhooks.GetReturnDataWithHostAndTypedArgs(host, -1) - assert.Equal(t, vmhost.BreakpointExecutionFailed, instance.BreakpointValue) - assert.Nil(t, returnData) - - instance.BreakpointValue = 0 - returnData = vmhooks.GetReturnDataWithHostAndTypedArgs(host, 0) + returnData := vmhooks.GetReturnDataWithHostAndTypedArgs(host, 0) assert.Equal(t, vmhost.BreakpointNone, instance.BreakpointValue) assert.Equal(t, zero, string(returnData)) @@ -3373,11 +3368,6 @@ func TestExecution_Mocked_ClearReturnData(t *testing.T) { assert.Equal(t, vmhost.BreakpointNone, instance.BreakpointValue) assert.Equal(t, two, string(returnData)) - instance.BreakpointValue = 0 - returnData = vmhooks.GetReturnDataWithHostAndTypedArgs(host, 2) - assert.Equal(t, vmhost.BreakpointExecutionFailed, instance.BreakpointValue) - assert.Nil(t, returnData) - instance.BreakpointValue = 0 vmhooks.DeleteFromReturnDataWithHost(host, 0) vmhooks.DeleteFromReturnDataWithHost(host, 0) @@ -3390,13 +3380,10 @@ func TestExecution_Mocked_ClearReturnData(t *testing.T) { returnData = vmhooks.GetReturnDataWithHostAndTypedArgs(host, 0) assert.Equal(t, vmhost.BreakpointExecutionFailed, instance.BreakpointValue) assert.Nil(t, returnData) + instance.BreakpointValue = 0 - returnData = vmhooks.GetReturnDataWithHostAndTypedArgs(host, 1) - assert.Equal(t, vmhost.BreakpointExecutionFailed, instance.BreakpointValue) - assert.Nil(t, returnData) - instance.BreakpointValue = 0 - returnData = vmhooks.GetReturnDataWithHostAndTypedArgs(host, 2) - assert.Equal(t, vmhost.BreakpointExecutionFailed, instance.BreakpointValue) + returnData = vmhooks.GetReturnDataWithHostAndTypedArgs(host, -1) + assert.Equal(t, vmhost.BreakpointOutOfGas, instance.BreakpointValue) assert.Nil(t, returnData) return instance From 13d98fc448d89418339a562dacb7c57acbdf8d3c Mon Sep 17 00:00:00 2001 From: robertsasu Date: Thu, 8 Aug 2024 19:24:44 +0300 Subject: [PATCH 11/24] fixing code after refactor --- vmhost/vmhooks/cryptoei.go | 2 +- vmhost/vmhooks/managedei.go | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/vmhost/vmhooks/cryptoei.go b/vmhost/vmhooks/cryptoei.go index f33e39bf5..4de67a9c4 100644 --- a/vmhost/vmhooks/cryptoei.go +++ b/vmhost/vmhooks/cryptoei.go @@ -796,7 +796,7 @@ func (context *VMHooksImpl) AddEC( } err = managedType.ConsumeGasForBigIntCopy(xResult, yResult, ec.P, ec.N, ec.B, ec.Gx, ec.Gy, x1, y1, x2, y2) - if context.WithFault(vmhost.ErrPointNotOnCurve, runtime.CryptoAPIErrorShouldFailExecution()) { + if context.WithFault(err, runtime.CryptoAPIErrorShouldFailExecution()) { return } xResultAdd, yResultAdd := ec.Add(x1, y1, x2, y2) diff --git a/vmhost/vmhooks/managedei.go b/vmhost/vmhooks/managedei.go index 74d3cd9fa..75e9fd750 100644 --- a/vmhost/vmhooks/managedei.go +++ b/vmhost/vmhooks/managedei.go @@ -408,29 +408,29 @@ func ManagedGetESDTTokenDataWithHost( if esdtToken.TokenMetaData != nil { managedType.SetBytes(hashHandle, esdtToken.TokenMetaData.Hash) err = managedType.ConsumeGasForBytes(esdtToken.TokenMetaData.Hash) - if WithFaultAndHost(host, vmhost.ErrArgOutOfRange, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { return } managedType.SetBytes(nameHandle, esdtToken.TokenMetaData.Name) err = managedType.ConsumeGasForBytes(esdtToken.TokenMetaData.Name) - if WithFaultAndHost(host, vmhost.ErrArgOutOfRange, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { return } managedType.SetBytes(attributesHandle, esdtToken.TokenMetaData.Attributes) err = managedType.ConsumeGasForBytes(esdtToken.TokenMetaData.Attributes) - if WithFaultAndHost(host, vmhost.ErrArgOutOfRange, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { return } managedType.SetBytes(creatorHandle, esdtToken.TokenMetaData.Creator) err = managedType.ConsumeGasForBytes(esdtToken.TokenMetaData.Creator) - if WithFaultAndHost(host, vmhost.ErrArgOutOfRange, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { return } royalties := managedType.GetBigIntOrCreate(royaltiesHandle) royalties.SetUint64(uint64(esdtToken.TokenMetaData.Royalties)) err = managedType.WriteManagedVecOfManagedBuffers(esdtToken.TokenMetaData.URIs, urisHandle) - if WithFaultAndHost(host, vmhost.ErrArgOutOfRange, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { return } } From 2beb7643a2c2b14e1b053d6519e2a1f0935c4d29 Mon Sep 17 00:00:00 2001 From: robertsasu Date: Thu, 8 Aug 2024 21:44:31 +0300 Subject: [PATCH 12/24] fixes after review --- vmhost/contexts/async_test.go | 4 ++-- vmhost/contexts/managedType.go | 6 ++---- vmhost/contexts/metering.go | 12 ------------ vmhost/hosttest/managedei_test.go | 2 +- vmhost/vmhooks/baseOps.go | 9 +++++++++ vmhost/vmhooks/bigIntOps.go | 4 ++-- vmhost/vmhooks/managedei.go | 4 ++-- 7 files changed, 18 insertions(+), 23 deletions(-) diff --git a/vmhost/contexts/async_test.go b/vmhost/contexts/async_test.go index 0093c7ca1..766b5a878 100644 --- a/vmhost/contexts/async_test.go +++ b/vmhost/contexts/async_test.go @@ -430,7 +430,7 @@ func TestAsyncContext_UpdateCurrentCallStatus(t *testing.T) { vmInput.CallType = vm.AsynchronousCallBack vmInput.Arguments = [][]byte{{0}} host.Runtime().InitStateFromContractCallInput(vmInput) - asyncCall, isLegacy, err = async.UpdateCurrentAsyncCallStatus(contract, []byte{}, &vmInput.VMInput) + _, isLegacy, err = async.UpdateCurrentAsyncCallStatus(contract, []byte{}, &vmInput.VMInput) require.NotNil(t, err) // CallType == AsynchronousCallback, and there is an AsyncCall registered, @@ -447,7 +447,7 @@ func TestAsyncContext_UpdateCurrentCallStatus(t *testing.T) { vmInput.CallType = vm.AsynchronousCallBack vmInput.Arguments = [][]byte{{0}} host.Runtime().InitStateFromContractCallInput(vmInput) - asyncCall, isLegacy, err = async.UpdateCurrentAsyncCallStatus(contract, []byte("callID_2"), &vmInput.VMInput) + _, isLegacy, err = async.UpdateCurrentAsyncCallStatus(contract, []byte("callID_2"), &vmInput.VMInput) require.NotNil(t, err) // CallType == AsynchronousCallback, but this time there is a corresponding AsyncCall diff --git a/vmhost/contexts/managedType.go b/vmhost/contexts/managedType.go index dc3175bba..78f54a6a1 100644 --- a/vmhost/contexts/managedType.go +++ b/vmhost/contexts/managedType.go @@ -266,8 +266,7 @@ func (context *managedTypesContext) ConsumeGasForThisIntNumberOfBytes(byteLen in func (context *managedTypesContext) ConsumeGasForBytes(bytes []byte) error { metering := context.host.Metering() gasToUse := math.MulUint64(uint64(len(bytes)), metering.GasSchedule().BaseOperationCost.DataCopyPerByte) - err := metering.UseGasBounded(gasToUse) - return err + return metering.UseGasBounded(gasToUse) } // ConsumeGasForThisBigIntNumberOfBytes uses gas for the number of bytes given that are being copied @@ -775,8 +774,7 @@ func (context *managedTypesContext) ManagedMapGet(mMapHandle int32, keyHandle in } context.SetBytes(outValueHandle, value) - err = context.ConsumeGasForBytes(value) - return err + return context.ConsumeGasForBytes(value) } // ManagedMapRemove removes the bytes stored as the key handle and returns it in an output value handle diff --git a/vmhost/contexts/metering.go b/vmhost/contexts/metering.go index 83d846974..3e5192917 100644 --- a/vmhost/contexts/metering.go +++ b/vmhost/contexts/metering.go @@ -344,18 +344,6 @@ func (context *meteringContext) useGas(gas uint64) { context.host.Runtime().SetPointsUsed(gasUsed) } -// useAndTraceGas sets in the runtime context the given gas as gas used and adds to current trace -func (context *meteringContext) useAndTraceGas(gas uint64) { - context.useGas(gas) - context.traceGas(gas) -} - -// useGasAndAddTracedGas sets in the runtime context the given gas as gas used and adds to current trace -func (context *meteringContext) useGasAndAddTracedGas(functionName string, gas uint64) { - context.useGas(gas) - context.addToGasTrace(functionName, gas) -} - // GetGasTrace returns the gasTrace map func (context *meteringContext) GetGasTrace() map[string]map[string][]uint64 { return context.gasTracer.GetGasTrace() diff --git a/vmhost/hosttest/managedei_test.go b/vmhost/hosttest/managedei_test.go index 687130d3d..291bb9d2e 100644 --- a/vmhost/hosttest/managedei_test.go +++ b/vmhost/hosttest/managedei_test.go @@ -368,7 +368,7 @@ func Test_BigIntToInt64_NotRepresentable(t *testing.T) { WithInput(test.CreateTestContractCallInputBuilder(). WithArguments(bigIntArg). WithRecipientAddr(test.ParentAddress). - WithGasProvided(testConfig.GasProvided + 20000). + WithGasProvided(testConfig.GasProvided). WithFunction("testFunction"). Build()). AndAssertResults(func(world *worldmock.MockWorld, verify *test.VMOutputVerifier) { diff --git a/vmhost/vmhooks/baseOps.go b/vmhost/vmhooks/baseOps.go index b1b673fab..a6add930e 100644 --- a/vmhost/vmhooks/baseOps.go +++ b/vmhost/vmhooks/baseOps.go @@ -1359,6 +1359,9 @@ func (context *VMHooksImpl) UpgradeContract( argumentsLengthOffset, dataOffset, ) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(actualLen)) err = metering.UseGasBounded(gasToUse) @@ -1429,6 +1432,9 @@ func (context *VMHooksImpl) UpgradeFromSourceContract( argumentsLengthOffset, dataOffset, ) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(actualLen)) err = metering.UseGasBounded(gasToUse) @@ -1548,6 +1554,9 @@ func (context *VMHooksImpl) DeleteContract( argumentsLengthOffset, dataOffset, ) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(actualLen)) err = metering.UseGasBounded(gasToUse) diff --git a/vmhost/vmhooks/bigIntOps.go b/vmhost/vmhooks/bigIntOps.go index 0153221b9..e28b5447f 100644 --- a/vmhost/vmhooks/bigIntOps.go +++ b/vmhost/vmhooks/bigIntOps.go @@ -412,8 +412,8 @@ func (context *VMHooksImpl) BigIntSetUnsignedBytes(destinationHandle int32, byte if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { return } - gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(len(bytes))) + gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(len(bytes))) err = metering.UseGasBounded(gasToUse) if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { return @@ -441,8 +441,8 @@ func (context *VMHooksImpl) BigIntSetSignedBytes(destinationHandle int32, byteOf if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { return } - gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(len(bytes))) + gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(len(bytes))) err = metering.UseGasBounded(gasToUse) if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { return diff --git a/vmhost/vmhooks/managedei.go b/vmhost/vmhooks/managedei.go index 75e9fd750..cf96d34fc 100644 --- a/vmhost/vmhooks/managedei.go +++ b/vmhost/vmhooks/managedei.go @@ -880,9 +880,9 @@ func setReturnDataIfExists( returnData := host.Output().ReturnData() if len(returnData) > oldLen { return host.ManagedTypes().WriteManagedVecOfManagedBuffers(returnData[oldLen:], resultHandle) - } else { - host.ManagedTypes().SetBytes(resultHandle, make([]byte, 0)) } + + host.ManagedTypes().SetBytes(resultHandle, make([]byte, 0)) return nil } From c196977d9ac3d3168c610459d23b0d4732454729 Mon Sep 17 00:00:00 2001 From: robertsasu Date: Thu, 8 Aug 2024 21:54:05 +0300 Subject: [PATCH 13/24] set use gas on context even in case of error. --- vmhost/contexts/metering.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/vmhost/contexts/metering.go b/vmhost/contexts/metering.go index 3e5192917..d419df0a8 100644 --- a/vmhost/contexts/metering.go +++ b/vmhost/contexts/metering.go @@ -452,7 +452,9 @@ func (context *meteringContext) UseGasForContractInit(gasToUse uint64) { // UseGasBounded consumes the specified amount of gas on the currently running // Wasmer instance, but returns an error if there is not enough gas left. func (context *meteringContext) UseGasBounded(gasToUse uint64) error { - if context.GasLeft() < gasToUse { + gasLeft := context.GasLeft() + if gasLeft < gasToUse { + context.useGas(gasLeft) return vmhost.ErrNotEnoughGas } context.useGas(gasToUse) @@ -462,9 +464,12 @@ func (context *meteringContext) UseGasBounded(gasToUse uint64) error { // UseGasBoundedAndAddTracedGas sets in the runtime context the given gas as gas used and adds to current trace func (context *meteringContext) UseGasBoundedAndAddTracedGas(functionName string, gasToUse uint64) error { - if context.GasLeft() < gasToUse { + gasLeft := context.GasLeft() + if gasLeft < gasToUse { + context.useGas(gasLeft) return vmhost.ErrNotEnoughGas } + context.useGas(gasToUse) context.addToGasTrace(functionName, gasToUse) return nil From 1dc750527d61861f01ca4ea294e9bfcd206077e3 Mon Sep 17 00:00:00 2001 From: robertsasu Date: Mon, 12 Aug 2024 10:25:13 +0300 Subject: [PATCH 14/24] fixes after review and fixes after tests --- vmhost/contexts/async_test.go | 4 ++-- vmhost/contexts/storage.go | 4 ++-- vmhost/hosttest/execution_gas_test.go | 4 ++++ vmhost/vmhooks/baseOps.go | 4 +++- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/vmhost/contexts/async_test.go b/vmhost/contexts/async_test.go index 766b5a878..f1a239331 100644 --- a/vmhost/contexts/async_test.go +++ b/vmhost/contexts/async_test.go @@ -430,7 +430,7 @@ func TestAsyncContext_UpdateCurrentCallStatus(t *testing.T) { vmInput.CallType = vm.AsynchronousCallBack vmInput.Arguments = [][]byte{{0}} host.Runtime().InitStateFromContractCallInput(vmInput) - _, isLegacy, err = async.UpdateCurrentAsyncCallStatus(contract, []byte{}, &vmInput.VMInput) + _, _, err = async.UpdateCurrentAsyncCallStatus(contract, []byte{}, &vmInput.VMInput) require.NotNil(t, err) // CallType == AsynchronousCallback, and there is an AsyncCall registered, @@ -447,7 +447,7 @@ func TestAsyncContext_UpdateCurrentCallStatus(t *testing.T) { vmInput.CallType = vm.AsynchronousCallBack vmInput.Arguments = [][]byte{{0}} host.Runtime().InitStateFromContractCallInput(vmInput) - _, isLegacy, err = async.UpdateCurrentAsyncCallStatus(contract, []byte("callID_2"), &vmInput.VMInput) + _, _, err = async.UpdateCurrentAsyncCallStatus(contract, []byte("callID_2"), &vmInput.VMInput) require.NotNil(t, err) // CallType == AsynchronousCallback, but this time there is a corresponding AsyncCall diff --git a/vmhost/contexts/storage.go b/vmhost/contexts/storage.go index dd3e538d3..e078fa9c2 100644 --- a/vmhost/contexts/storage.go +++ b/vmhost/contexts/storage.go @@ -121,12 +121,12 @@ func (context *storageContext) GetStorage(key []byte) ([]byte, uint32, bool, err errGas := context.useExtraGasForKeyIfNeeded(key, usedCache) if errGas != nil { - return nil, 0, false, nil + return nil, 0, false, errGas } errGas = context.useGasForValueIfNeeded(value, usedCache) if errGas != nil { - return nil, 0, false, nil + return nil, 0, false, errGas } logStorage.Trace("get", "key", key, "value", value) diff --git a/vmhost/hosttest/execution_gas_test.go b/vmhost/hosttest/execution_gas_test.go index 62bb80bbe..25e9ed9f0 100644 --- a/vmhost/hosttest/execution_gas_test.go +++ b/vmhost/hosttest/execution_gas_test.go @@ -2440,6 +2440,10 @@ func setZeroCodeCosts(host vmhost.VMHost) { host.Metering().GasSchedule().BaseOpsAPICost.StorageStore = 0 host.Metering().GasSchedule().BaseOpsAPICost.TransferValue = 0 host.Metering().GasSchedule().BaseOpsAPICost.CreateContract = 0 + host.Metering().GasSchedule().DynamicStorageLoad.MinGasCost = 0 + host.Metering().GasSchedule().DynamicStorageLoad.Linear = 0 + host.Metering().GasSchedule().DynamicStorageLoad.Constant = 0 + host.Metering().GasSchedule().DynamicStorageLoad.Quadratic = 0 } func setAsyncCosts(host vmhost.VMHost, gasLockCost uint64) { diff --git a/vmhost/vmhooks/baseOps.go b/vmhost/vmhooks/baseOps.go index a6add930e..200ce58df 100644 --- a/vmhost/vmhooks/baseOps.go +++ b/vmhost/vmhooks/baseOps.go @@ -3369,7 +3369,9 @@ func (context *VMHooksImpl) GetPrevTxHash(dataOffset executor.MemPtr) { gasToUse := metering.GasSchedule().BaseOpsAPICost.GetPrevTxHash err := metering.UseGasBoundedAndAddTracedGas(getPrevTxHashName, gasToUse) - context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } err = context.MemStore(dataOffset, runtime.GetPrevTxHash()) _ = context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) From 5957d551fdb26ec7ab3537e46038f28522474302 Mon Sep 17 00:00:00 2001 From: robertsasu Date: Mon, 12 Aug 2024 19:27:25 +0300 Subject: [PATCH 15/24] adding new flag --- mock/context/runtimeContextMock.go | 5 +++++ mock/context/runtimeContextWrapper.go | 5 +++++ vmhost/contexts/runtime.go | 8 ++++++++ vmhost/flags.go | 2 ++ vmhost/hostCore/host.go | 1 + vmhost/interface.go | 1 + 6 files changed, 22 insertions(+) diff --git a/mock/context/runtimeContextMock.go b/mock/context/runtimeContextMock.go index a0bd5fac6..99dd47e74 100644 --- a/mock/context/runtimeContextMock.go +++ b/mock/context/runtimeContextMock.go @@ -315,6 +315,11 @@ func (r *RuntimeContextMock) ManagedMapAPIErrorShouldFailExecution() bool { return r.FailManagedMapAPI } +// UseGasBoundedShouldFailExecution mocked method +func (r *RuntimeContextMock) UseGasBoundedShouldFailExecution() bool { + return true +} + // FailExecution mocked method func (r *RuntimeContextMock) FailExecution(_ error) { } diff --git a/mock/context/runtimeContextWrapper.go b/mock/context/runtimeContextWrapper.go index d6204227d..6e63c620c 100644 --- a/mock/context/runtimeContextWrapper.go +++ b/mock/context/runtimeContextWrapper.go @@ -533,6 +533,11 @@ func (contextWrapper *RuntimeContextWrapper) ManagedMapAPIErrorShouldFailExecuti return contextWrapper.runtimeContext.ManagedMapAPIErrorShouldFailExecution() } +// UseGasBoundedShouldFailExecution calls corresponding xxxFunc function, that by default in turn calls the original method of the wrapped RuntimeContext +func (contextWrapper *RuntimeContextWrapper) UseGasBoundedShouldFailExecution() bool { + return contextWrapper.runtimeContext.UseGasBoundedShouldFailExecution() +} + // GetVMExecutor calls corresponding xxxFunc function, that by default in turn calls the original method of the wrapped RuntimeContext func (contextWrapper *RuntimeContextWrapper) GetVMExecutor() executor.Executor { return contextWrapper.GetVMExecutorFunc() diff --git a/vmhost/contexts/runtime.go b/vmhost/contexts/runtime.go index f652c7425..fb1819931 100644 --- a/vmhost/contexts/runtime.go +++ b/vmhost/contexts/runtime.go @@ -719,6 +719,14 @@ func (context *runtimeContext) ManagedMapAPIErrorShouldFailExecution() bool { return true } +// UseGasBoundedShouldFailExecution returns true when flag activated +func (context *runtimeContext) UseGasBoundedShouldFailExecution() bool { + if !context.host.EnableEpochsHandler().IsFlagEnabled(vmhost.UseGasBoundedShouldFailExecutionFlag) { + return false + } + return true +} + // GetPointsUsed returns the gas amount spent by the currently running Wasmer instance. func (context *runtimeContext) GetPointsUsed() uint64 { if check.IfNil(context.iTracker.Instance()) { diff --git a/vmhost/flags.go b/vmhost/flags.go index ad1a4cbfe..1d9a32410 100644 --- a/vmhost/flags.go +++ b/vmhost/flags.go @@ -29,4 +29,6 @@ const ( FixOOGReturnCodeFlag core.EnableEpochFlag = "FixOOGReturnCodeFlag" // DynamicGasCostForDataTrieStorageLoadFlag defines the flag that activates the dynamic gas cost for data trie storage load DynamicGasCostForDataTrieStorageLoadFlag core.EnableEpochFlag = "DynamicGasCostForDataTrieStorageLoadFlag" + // UseGasBoundedShouldFailExecutionFlag defines the flag that activates failing of execution if gas bounded check fails + UseGasBoundedShouldFailExecutionFlag core.EnableEpochFlag = "UseGasBoundedShouldFailExecutionFlag" ) diff --git a/vmhost/hostCore/host.go b/vmhost/hostCore/host.go index e1742f630..43197baa9 100644 --- a/vmhost/hostCore/host.go +++ b/vmhost/hostCore/host.go @@ -52,6 +52,7 @@ var allFlags = []core.EnableEpochFlag{ vmhost.RuntimeCodeSizeFixFlag, vmhost.FixOOGReturnCodeFlag, vmhost.DynamicGasCostForDataTrieStorageLoadFlag, + vmhost.UseGasBoundedShouldFailExecutionFlag, } // vmHost implements HostContext interface. diff --git a/vmhost/interface.go b/vmhost/interface.go index 767068bbe..40e6aebdf 100644 --- a/vmhost/interface.go +++ b/vmhost/interface.go @@ -154,6 +154,7 @@ type RuntimeContext interface { BigFloatAPIErrorShouldFailExecution() bool ManagedBufferAPIErrorShouldFailExecution() bool ManagedMapAPIErrorShouldFailExecution() bool + UseGasBoundedShouldFailExecution() bool CleanInstance() AddError(err error, otherInfo ...string) From adc3bd3acd79f98057f25e67c6a6bba437a3ec1b Mon Sep 17 00:00:00 2001 From: robertsasu Date: Tue, 13 Aug 2024 11:24:55 +0300 Subject: [PATCH 16/24] backward compatibility --- vmhost/vmhooks/baseOps.go | 67 +++++++++++++++++------------------ vmhost/vmhooks/managedei.go | 37 ++++++++++--------- vmhost/vmhooks/vmHooksImpl.go | 12 +++---- 3 files changed, 56 insertions(+), 60 deletions(-) diff --git a/vmhost/vmhooks/baseOps.go b/vmhost/vmhooks/baseOps.go index 200ce58df..38dfb7789 100644 --- a/vmhost/vmhooks/baseOps.go +++ b/vmhost/vmhooks/baseOps.go @@ -240,8 +240,7 @@ func (context *VMHooksImpl) SignalError(messageOffset executor.MemPtr, messageLe gasToUse += metering.GasSchedule().BaseOperationCost.PersistPerByte * uint64(messageLength) err := metering.UseGasBounded(gasToUse) - if err != nil { - _ = context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) + if err != nil && context.WithFault(err, runtime.UseGasBoundedShouldFailExecution()) { return } @@ -581,7 +580,7 @@ func (context *VMHooksImpl) TransferValue( gasToUse := metering.GasSchedule().BaseOpsAPICost.TransferValue err := metering.UseGasBounded(gasToUse) - if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + if context.WithFault(err, runtime.UseGasBoundedShouldFailExecution()) { return 1 } @@ -598,7 +597,7 @@ func (context *VMHooksImpl) TransferValue( gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.PersistPerByte, uint64(length)) err = metering.UseGasBounded(gasToUse) - if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + if context.WithFault(err, runtime.UseGasBoundedShouldFailExecution()) { return 1 } @@ -718,7 +717,7 @@ func (context *VMHooksImpl) extractIndirectContractCallArguments( gasToUse := math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(actualLen)) err = metering.UseGasBounded(gasToUse) - if err != nil { + if err != nil && host.Runtime().UseGasBoundedShouldFailExecution() { return nil, err } @@ -775,7 +774,7 @@ func (context *VMHooksImpl) TransferValueExecuteWithHost( gasToUse := metering.GasSchedule().BaseOpsAPICost.TransferValue err := metering.UseGasBounded(gasToUse) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return 1 } @@ -810,7 +809,7 @@ func TransferValueExecuteWithTypedArgs( gasToUse := metering.GasSchedule().BaseOpsAPICost.TransferValue err := metering.UseGasBounded(gasToUse) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return 1 } @@ -860,7 +859,7 @@ func TransferValueExecuteWithTypedArgs( } err = metering.UseGasBounded(uint64(gasLimit)) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return 1 } @@ -965,7 +964,7 @@ func (context *VMHooksImpl) MultiTransferESDTNFTExecute( gasToUse := math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(callArgs.actualLen)) err = metering.UseGasBounded(gasToUse) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return 1 } @@ -982,7 +981,7 @@ func (context *VMHooksImpl) MultiTransferESDTNFTExecute( gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(actualLen)) err = metering.UseGasBounded(gasToUse) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return 1 } @@ -1042,7 +1041,7 @@ func (context *VMHooksImpl) TransferESDTNFTExecuteWithHost( gasToUse := math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(callArgs.actualLen)) err = metering.UseGasBounded(gasToUse) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return 1 } @@ -1083,7 +1082,7 @@ func TransferESDTNFTExecuteWithTypedArgs( gasToUse := metering.GasSchedule().BaseOpsAPICost.TransferValue * uint64(len(transfers)) err := metering.UseGasBounded(gasToUse) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return 1 } @@ -1239,7 +1238,7 @@ func CreateAsyncCallWithTypedArgs(host vmhost.VMHost, gasToUse := metering.GasSchedule().BaseOpsAPICost.CreateAsyncCall err := metering.UseGasBounded(gasToUse) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return 1 } @@ -1256,9 +1255,9 @@ func CreateAsyncCallWithTypedArgs(host vmhost.VMHost, } if asyncCall.HasDefinedAnyCallback() { - gasToUse := metering.GasSchedule().BaseOpsAPICost.SetAsyncCallback + gasToUse = metering.GasSchedule().BaseOpsAPICost.SetAsyncCallback err = metering.UseGasBounded(gasToUse) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return 1 } } @@ -1288,7 +1287,7 @@ func (context *VMHooksImpl) SetAsyncContextCallback( gasToUse := metering.GasSchedule().BaseOpsAPICost.SetAsyncContextCallback err := metering.UseGasBounded(gasToUse) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return 1 } @@ -1334,7 +1333,7 @@ func (context *VMHooksImpl) UpgradeContract( gasToUse := metering.GasSchedule().BaseOpsAPICost.CreateContract err := metering.UseGasBounded(gasToUse) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return } @@ -1359,13 +1358,13 @@ func (context *VMHooksImpl) UpgradeContract( argumentsLengthOffset, dataOffset, ) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return } gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(actualLen)) err = metering.UseGasBounded(gasToUse) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return } @@ -1381,7 +1380,7 @@ func (context *VMHooksImpl) UpgradeContract( gasSchedule := metering.GasSchedule() gasToUse = math.MulUint64(gasSchedule.BaseOperationCost.DataCopyPerByte, uint64(length)) err = metering.UseGasBounded(gasToUse) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return } @@ -1407,7 +1406,7 @@ func (context *VMHooksImpl) UpgradeFromSourceContract( gasToUse := metering.GasSchedule().BaseOpsAPICost.CreateContract err := metering.UseGasBounded(gasToUse) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return } @@ -1432,13 +1431,13 @@ func (context *VMHooksImpl) UpgradeFromSourceContract( argumentsLengthOffset, dataOffset, ) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return } gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(actualLen)) err = metering.UseGasBounded(gasToUse) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return } @@ -1544,7 +1543,7 @@ func (context *VMHooksImpl) DeleteContract( gasToUse := metering.GasSchedule().BaseOpsAPICost.CreateContract err := metering.UseGasBounded(gasToUse) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return } @@ -1554,13 +1553,13 @@ func (context *VMHooksImpl) DeleteContract( argumentsLengthOffset, dataOffset, ) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return } gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(actualLen)) err = metering.UseGasBounded(gasToUse) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return } @@ -1637,7 +1636,7 @@ func (context *VMHooksImpl) AsyncCall( gasSchedule := metering.GasSchedule() gasToUse := gasSchedule.BaseOpsAPICost.AsyncCallStep err := metering.UseGasBounded(gasToUse) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return } @@ -1653,7 +1652,7 @@ func (context *VMHooksImpl) AsyncCall( gasToUse = math.MulUint64(gasSchedule.BaseOperationCost.DataCopyPerByte, uint64(length)) err = metering.UseGasBounded(gasToUse) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return } @@ -2742,7 +2741,7 @@ func ExecuteOnSameContextWithTypedArgs( gasToUse := metering.GasSchedule().BaseOpsAPICost.ExecuteOnSameContext err := metering.UseGasBounded(gasToUse) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return -1 } @@ -2849,7 +2848,7 @@ func ExecuteOnDestContextWithTypedArgs( gasToUse := metering.GasSchedule().BaseOpsAPICost.ExecuteOnDestContext err := metering.UseGasBounded(gasToUse) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return -1 } @@ -3033,7 +3032,7 @@ func (context *VMHooksImpl) createContractWithHost( gasToUse := metering.GasSchedule().BaseOpsAPICost.CreateContract err := metering.UseGasBounded(gasToUse) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return -1 } @@ -3065,7 +3064,7 @@ func (context *VMHooksImpl) createContractWithHost( gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(actualLen)) err = metering.UseGasBounded(gasToUse) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return 1 } @@ -3103,7 +3102,7 @@ func (context *VMHooksImpl) DeployFromSourceContract( gasToUse := metering.GasSchedule().BaseOpsAPICost.CreateContract err := metering.UseGasBounded(gasToUse) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return 1 } @@ -3134,7 +3133,7 @@ func (context *VMHooksImpl) DeployFromSourceContract( gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(actualLen)) err = metering.UseGasBounded(gasToUse) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return 1 } diff --git a/vmhost/vmhooks/managedei.go b/vmhost/vmhooks/managedei.go index cf96d34fc..2ec35b024 100644 --- a/vmhost/vmhooks/managedei.go +++ b/vmhost/vmhooks/managedei.go @@ -114,7 +114,7 @@ func (context *VMHooksImpl) ManagedSignalError(errHandle int32) { gasToUse := metering.GasSchedule().BaseOpsAPICost.SignalError err := metering.UseGasBounded(gasToUse) - if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + if context.WithFault(err, runtime.UseGasBoundedShouldFailExecution()) { return } @@ -124,14 +124,13 @@ func (context *VMHooksImpl) ManagedSignalError(errHandle int32) { } err = managedType.ConsumeGasForBytes(errBytes) - if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + if context.WithFault(err, runtime.UseGasBoundedShouldFailExecution()) { return } gasToUse = metering.GasSchedule().BaseOperationCost.PersistPerByte * uint64(len(errBytes)) err = metering.UseGasBounded(gasToUse) - if err != nil { - _ = context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) + if err != nil && context.WithFault(err, runtime.UseGasBoundedShouldFailExecution()) { return } @@ -468,7 +467,7 @@ func ManagedAsyncCallWithHost( gasSchedule := metering.GasSchedule() gasToUse := gasSchedule.BaseOpsAPICost.AsyncCallStep err := metering.UseGasBounded(gasToUse) - if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return } @@ -487,7 +486,7 @@ func ManagedAsyncCallWithHost( gasToUse = math.MulUint64(gasSchedule.BaseOperationCost.DataCopyPerByte, uint64(len(data))) err = metering.UseGasBounded(gasToUse) - if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return } @@ -613,7 +612,7 @@ func (context *VMHooksImpl) ManagedUpgradeFromSourceContract( gasToUse := metering.GasSchedule().BaseOpsAPICost.CreateContract err := metering.UseGasBounded(gasToUse) - if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + if context.WithFault(err, runtime.UseGasBoundedShouldFailExecution()) { return } @@ -644,7 +643,7 @@ func (context *VMHooksImpl) ManagedUpgradeFromSourceContract( codeMetadata, ) err = setReturnDataIfExists(host, lenReturnData, resultHandle) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return } } @@ -668,7 +667,7 @@ func (context *VMHooksImpl) ManagedUpgradeContract( gasToUse := metering.GasSchedule().BaseOpsAPICost.CreateContract err := metering.UseGasBounded(gasToUse) - if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + if context.WithFault(err, runtime.UseGasBoundedShouldFailExecution()) { return } @@ -695,7 +694,7 @@ func (context *VMHooksImpl) ManagedUpgradeContract( upgradeContract(host, vmInput.destination, code, codeMetadata, vmInput.value.Bytes(), vmInput.arguments, gas) err = setReturnDataIfExists(host, lenReturnData, resultHandle) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return } } @@ -729,7 +728,7 @@ func ManagedDeleteContractWithHost( gasToUse := metering.GasSchedule().BaseOpsAPICost.CreateContract err := metering.UseGasBounded(gasToUse) - if WithFaultAndHost(host, err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return } @@ -770,7 +769,7 @@ func (context *VMHooksImpl) ManagedDeployFromSourceContract( gasToUse := metering.GasSchedule().BaseOpsAPICost.CreateContract err := metering.UseGasBounded(gasToUse) - if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + if context.WithFault(err, runtime.UseGasBoundedShouldFailExecution()) { return -1 } @@ -800,7 +799,7 @@ func (context *VMHooksImpl) ManagedDeployFromSourceContract( managedType.SetBytes(resultAddressHandle, newAddress) err = setReturnDataIfExists(host, lenReturnData, resultHandle) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return 1 } @@ -826,7 +825,7 @@ func (context *VMHooksImpl) ManagedCreateContract( gasToUse := metering.GasSchedule().BaseOpsAPICost.CreateContract err := metering.UseGasBounded(gasToUse) - if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + if context.WithFault(err, runtime.UseGasBoundedShouldFailExecution()) { return -1 } @@ -843,7 +842,7 @@ func (context *VMHooksImpl) ManagedCreateContract( gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, actualLen) err = metering.UseGasBounded(gasToUse) - if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + if context.WithFault(err, runtime.UseGasBoundedShouldFailExecution()) { return -1 } @@ -865,7 +864,7 @@ func (context *VMHooksImpl) ManagedCreateContract( managedType.SetBytes(resultAddressHandle, newAddress) err = setReturnDataIfExists(host, lenReturnData, resultHandle) - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return 1 } @@ -913,7 +912,7 @@ func (context *VMHooksImpl) ManagedExecuteReadOnly( vmInput.arguments, ) err = setReturnDataIfExists(host, lenReturnData, resultHandle) - if WithFaultAndHost(host, err, host.Runtime().BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, host.Runtime().UseGasBoundedShouldFailExecution()) { return -1 } @@ -949,7 +948,7 @@ func (context *VMHooksImpl) ManagedExecuteOnSameContext( vmInput.arguments, ) err = setReturnDataIfExists(host, lenReturnData, resultHandle) - if WithFaultAndHost(host, err, host.Runtime().BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, host.Runtime().UseGasBoundedShouldFailExecution()) { return -1 } @@ -985,7 +984,7 @@ func (context *VMHooksImpl) ManagedExecuteOnDestContext( vmInput.arguments, ) err = setReturnDataIfExists(host, lenReturnData, resultHandle) - if WithFaultAndHost(host, err, host.Runtime().BaseOpsErrorShouldFailExecution()) { + if WithFaultAndHost(host, err, host.Runtime().UseGasBoundedShouldFailExecution()) { return -1 } diff --git a/vmhost/vmhooks/vmHooksImpl.go b/vmhost/vmhooks/vmHooksImpl.go index c55fb00b9..2466eb2f1 100644 --- a/vmhost/vmhooks/vmHooksImpl.go +++ b/vmhost/vmhooks/vmHooksImpl.go @@ -100,16 +100,14 @@ func (context *VMHooksImpl) WithFault(err error, failExecution bool) bool { // WithFaultAndHost fails the execution with the provided error func WithFaultAndHost(host vmhost.VMHost, err error, failExecution bool) bool { - if err == nil { + if err == nil || !failExecution { return false } - if failExecution { - runtime := host.Runtime() - metering := host.Metering() - _ = metering.UseGasBounded(metering.GasLeft()) - runtime.FailExecution(err) - } + runtime := host.Runtime() + metering := host.Metering() + _ = metering.UseGasBounded(metering.GasLeft()) + runtime.FailExecution(err) return true } From 901dedbef9c9ed79b643ea37270dc01591e4d03f Mon Sep 17 00:00:00 2001 From: robertsasu Date: Tue, 13 Aug 2024 17:09:46 +0300 Subject: [PATCH 17/24] debugging --- vmhost/contexts/runtime.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/vmhost/contexts/runtime.go b/vmhost/contexts/runtime.go index fb1819931..575432269 100644 --- a/vmhost/contexts/runtime.go +++ b/vmhost/contexts/runtime.go @@ -6,6 +6,7 @@ import ( "fmt" builtinMath "math" "math/big" + "runtime/debug" "github.com/multiversx/mx-chain-core-go/core/check" logger "github.com/multiversx/mx-chain-logger-go" @@ -632,6 +633,11 @@ func (context *runtimeContext) SignalUserError(message string) { // immediately stopping the contract execution. func (context *runtimeContext) SetRuntimeBreakpointValue(value vmhost.BreakpointValue) { context.iTracker.Instance().SetBreakpointValue(uint64(value)) + + if value == vmhost.BreakpointOutOfGas { + debug.PrintStack() + } + logRuntime.Trace("runtime breakpoint set", "breakpoint", value) } From 31c6a6a559e9578e066e270bbb34f4f0cfa738aa Mon Sep 17 00:00:00 2001 From: robertsasu Date: Tue, 13 Aug 2024 17:37:40 +0300 Subject: [PATCH 18/24] debugging and fix --- vmhost/contexts/runtime.go | 11 ++--------- vmhost/vmhooks/managedConversions.go | 12 +++++++----- vmhost/vmhooks/managedei.go | 2 +- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/vmhost/contexts/runtime.go b/vmhost/contexts/runtime.go index 575432269..c5df4128e 100644 --- a/vmhost/contexts/runtime.go +++ b/vmhost/contexts/runtime.go @@ -4,15 +4,13 @@ import ( "bytes" "errors" "fmt" - builtinMath "math" - "math/big" - "runtime/debug" - "github.com/multiversx/mx-chain-core-go/core/check" logger "github.com/multiversx/mx-chain-logger-go" vmcommon "github.com/multiversx/mx-chain-vm-common-go" "github.com/multiversx/mx-chain-vm-go/executor" "github.com/multiversx/mx-chain-vm-go/vmhost" + builtinMath "math" + "math/big" ) var logRuntime = logger.GetOrCreate("vm/runtime") @@ -633,11 +631,6 @@ func (context *runtimeContext) SignalUserError(message string) { // immediately stopping the contract execution. func (context *runtimeContext) SetRuntimeBreakpointValue(value vmhost.BreakpointValue) { context.iTracker.Instance().SetBreakpointValue(uint64(value)) - - if value == vmhost.BreakpointOutOfGas { - debug.PrintStack() - } - logRuntime.Trace("runtime breakpoint set", "breakpoint", value) } diff --git a/vmhost/vmhooks/managedConversions.go b/vmhost/vmhooks/managedConversions.go index 29951f3b9..e2fb83f8f 100644 --- a/vmhost/vmhooks/managedConversions.go +++ b/vmhost/vmhooks/managedConversions.go @@ -16,6 +16,7 @@ const esdtTransferLen = 16 // Deserializes a vmcommon.ESDTTransfer object. func readESDTTransfer( managedType vmhost.ManagedTypesContext, + runtime vmhost.RuntimeContext, data []byte, ) (*vmcommon.ESDTTransfer, error) { if len(data) != esdtTransferLen { @@ -29,7 +30,7 @@ func readESDTTransfer( } err = managedType.ConsumeGasForBytes(tokenIdentifier) - if err != nil { + if err != nil && runtime.UseGasBoundedShouldFailExecution() { return nil, err } @@ -41,7 +42,7 @@ func readESDTTransfer( } err = managedType.ConsumeGasForBigIntCopy(value) - if err != nil { + if err != nil && runtime.UseGasBoundedShouldFailExecution() { return nil, err } @@ -66,6 +67,7 @@ func readESDTTransfer( // Total: 16 bytes. func readESDTTransfers( managedType vmhost.ManagedTypesContext, + runtime vmhost.RuntimeContext, managedVecHandle int32, ) ([]*vmcommon.ESDTTransfer, error) { managedVecBytes, err := managedType.GetBytes(managedVecHandle) @@ -74,7 +76,7 @@ func readESDTTransfers( } err = managedType.ConsumeGasForBytes(managedVecBytes) - if err != nil { + if err != nil && runtime.UseGasBoundedShouldFailExecution() { return nil, err } @@ -85,7 +87,7 @@ func readESDTTransfers( numTransfers := len(managedVecBytes) / esdtTransferLen result := make([]*vmcommon.ESDTTransfer, 0, numTransfers) for i := 0; i < len(managedVecBytes); i += esdtTransferLen { - esdtTransfer, err := readESDTTransfer(managedType, managedVecBytes[i:i+esdtTransferLen]) + esdtTransfer, err := readESDTTransfer(managedType, runtime, managedVecBytes[i:i+esdtTransferLen]) if err != nil { return nil, err } @@ -227,7 +229,7 @@ func readDestinationArguments( gasToUse := math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, actualLen) err = metering.UseGasBounded(gasToUse) - if err != nil { + if err != nil && host.Runtime().UseGasBoundedShouldFailExecution() { return nil, err } diff --git a/vmhost/vmhooks/managedei.go b/vmhost/vmhooks/managedei.go index 2ec35b024..b7bf6f0a3 100644 --- a/vmhost/vmhooks/managedei.go +++ b/vmhost/vmhooks/managedei.go @@ -1011,7 +1011,7 @@ func (context *VMHooksImpl) ManagedMultiTransferESDTNFTExecute( return -1 } - transfers, err := readESDTTransfers(managedType, tokenTransfersHandle) + transfers, err := readESDTTransfers(managedType, runtime, tokenTransfersHandle) if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { return -1 } From 6e516e240346df0984c2bccac0da44e31db3f9c5 Mon Sep 17 00:00:00 2001 From: robertsasu Date: Wed, 14 Aug 2024 09:27:09 +0300 Subject: [PATCH 19/24] debugging and fix --- vmhost/contexts/runtime.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/vmhost/contexts/runtime.go b/vmhost/contexts/runtime.go index c5df4128e..a756bd605 100644 --- a/vmhost/contexts/runtime.go +++ b/vmhost/contexts/runtime.go @@ -11,6 +11,7 @@ import ( "github.com/multiversx/mx-chain-vm-go/vmhost" builtinMath "math" "math/big" + "runtime/debug" ) var logRuntime = logger.GetOrCreate("vm/runtime") @@ -631,6 +632,11 @@ func (context *runtimeContext) SignalUserError(message string) { // immediately stopping the contract execution. func (context *runtimeContext) SetRuntimeBreakpointValue(value vmhost.BreakpointValue) { context.iTracker.Instance().SetBreakpointValue(uint64(value)) + + if value == vmhost.BreakpointOutOfGas { + debug.PrintStack() + } + logRuntime.Trace("runtime breakpoint set", "breakpoint", value) } @@ -720,10 +726,7 @@ func (context *runtimeContext) ManagedMapAPIErrorShouldFailExecution() bool { // UseGasBoundedShouldFailExecution returns true when flag activated func (context *runtimeContext) UseGasBoundedShouldFailExecution() bool { - if !context.host.EnableEpochsHandler().IsFlagEnabled(vmhost.UseGasBoundedShouldFailExecutionFlag) { - return false - } - return true + return context.host.EnableEpochsHandler().IsFlagEnabled(vmhost.UseGasBoundedShouldFailExecutionFlag) } // GetPointsUsed returns the gas amount spent by the currently running Wasmer instance. From 6b440d4bd1cccc4b2863fbdeb08ba31e806ae374 Mon Sep 17 00:00:00 2001 From: robertsasu Date: Wed, 14 Aug 2024 10:09:40 +0300 Subject: [PATCH 20/24] more backward compatibility --- vmhost/contexts/managedType.go | 18 +++++++++++++++--- vmhost/contexts/runtime.go | 6 ------ 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/vmhost/contexts/managedType.go b/vmhost/contexts/managedType.go index 78f54a6a1..32d1461f5 100644 --- a/vmhost/contexts/managedType.go +++ b/vmhost/contexts/managedType.go @@ -235,6 +235,18 @@ func (context *managedTypesContext) IsInterfaceNil() bool { return context == nil } +func (context *managedTypesContext) useGasBoundedWithBackwardCompatibility(gasToUse uint64) error { + metering := context.host.Metering() + runtime := context.host.Runtime() + + err := metering.UseGasBounded(gasToUse) + if err != nil && runtime.UseGasBoundedShouldFailExecution() { + return err + } + + return nil +} + // ConsumeGasForBigIntCopy uses gas for Copy operations func (context *managedTypesContext) ConsumeGasForBigIntCopy(values ...*big.Int) error { for _, val := range values { @@ -253,7 +265,7 @@ func (context *managedTypesContext) ConsumeGasForThisIntNumberOfBytes(byteLen in metering := context.host.Metering() if byteLen > maxBigIntByteLenForNormalCost { gasToUse = math.MulUint64(uint64(byteLen), metering.GasSchedule().BigIntAPICost.CopyPerByteForTooBig) - err := metering.UseGasBounded(gasToUse) + err := context.useGasBoundedWithBackwardCompatibility(gasToUse) if err != nil { return err } @@ -266,7 +278,7 @@ func (context *managedTypesContext) ConsumeGasForThisIntNumberOfBytes(byteLen in func (context *managedTypesContext) ConsumeGasForBytes(bytes []byte) error { metering := context.host.Metering() gasToUse := math.MulUint64(uint64(len(bytes)), metering.GasSchedule().BaseOperationCost.DataCopyPerByte) - return metering.UseGasBounded(gasToUse) + return context.useGasBoundedWithBackwardCompatibility(gasToUse) } // ConsumeGasForThisBigIntNumberOfBytes uses gas for the number of bytes given that are being copied @@ -279,7 +291,7 @@ func (context *managedTypesContext) ConsumeGasForThisBigIntNumberOfBytes(byteLen if gasToUseBigInt.Cmp(maxGasBigInt) < 0 { gasToUse = gasToUseBigInt.Uint64() } - return metering.UseGasBounded(gasToUse) + return context.useGasBoundedWithBackwardCompatibility(gasToUse) } // ConsumeGasForBigFloatCopy uses gas for the given big float values diff --git a/vmhost/contexts/runtime.go b/vmhost/contexts/runtime.go index a756bd605..96c5379d4 100644 --- a/vmhost/contexts/runtime.go +++ b/vmhost/contexts/runtime.go @@ -11,7 +11,6 @@ import ( "github.com/multiversx/mx-chain-vm-go/vmhost" builtinMath "math" "math/big" - "runtime/debug" ) var logRuntime = logger.GetOrCreate("vm/runtime") @@ -632,11 +631,6 @@ func (context *runtimeContext) SignalUserError(message string) { // immediately stopping the contract execution. func (context *runtimeContext) SetRuntimeBreakpointValue(value vmhost.BreakpointValue) { context.iTracker.Instance().SetBreakpointValue(uint64(value)) - - if value == vmhost.BreakpointOutOfGas { - debug.PrintStack() - } - logRuntime.Trace("runtime breakpoint set", "breakpoint", value) } From d8547b75a99099164736b37a69d70e31ae7c9615 Mon Sep 17 00:00:00 2001 From: robertsasu Date: Wed, 14 Aug 2024 10:19:24 +0300 Subject: [PATCH 21/24] debug --- vmhost/contexts/runtime.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/vmhost/contexts/runtime.go b/vmhost/contexts/runtime.go index 96c5379d4..a756bd605 100644 --- a/vmhost/contexts/runtime.go +++ b/vmhost/contexts/runtime.go @@ -11,6 +11,7 @@ import ( "github.com/multiversx/mx-chain-vm-go/vmhost" builtinMath "math" "math/big" + "runtime/debug" ) var logRuntime = logger.GetOrCreate("vm/runtime") @@ -631,6 +632,11 @@ func (context *runtimeContext) SignalUserError(message string) { // immediately stopping the contract execution. func (context *runtimeContext) SetRuntimeBreakpointValue(value vmhost.BreakpointValue) { context.iTracker.Instance().SetBreakpointValue(uint64(value)) + + if value == vmhost.BreakpointOutOfGas { + debug.PrintStack() + } + logRuntime.Trace("runtime breakpoint set", "breakpoint", value) } From a06f25e941b600b0a432e7b6a13077df7eefd760 Mon Sep 17 00:00:00 2001 From: robertsasu Date: Wed, 14 Aug 2024 14:15:02 +0300 Subject: [PATCH 22/24] delete debug --- vmhost/contexts/runtime.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/vmhost/contexts/runtime.go b/vmhost/contexts/runtime.go index a756bd605..96c5379d4 100644 --- a/vmhost/contexts/runtime.go +++ b/vmhost/contexts/runtime.go @@ -11,7 +11,6 @@ import ( "github.com/multiversx/mx-chain-vm-go/vmhost" builtinMath "math" "math/big" - "runtime/debug" ) var logRuntime = logger.GetOrCreate("vm/runtime") @@ -632,11 +631,6 @@ func (context *runtimeContext) SignalUserError(message string) { // immediately stopping the contract execution. func (context *runtimeContext) SetRuntimeBreakpointValue(value vmhost.BreakpointValue) { context.iTracker.Instance().SetBreakpointValue(uint64(value)) - - if value == vmhost.BreakpointOutOfGas { - debug.PrintStack() - } - logRuntime.Trace("runtime breakpoint set", "breakpoint", value) } From f5c5080c53e3bae03eb2a02e2fe5ec691c2beb2f Mon Sep 17 00:00:00 2001 From: robertsasu Date: Wed, 14 Aug 2024 19:07:27 +0300 Subject: [PATCH 23/24] fix and debug --- vmhost/contexts/runtime.go | 11 +++++++++-- vmhost/vmhooks/managedConversions.go | 8 ++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/vmhost/contexts/runtime.go b/vmhost/contexts/runtime.go index 96c5379d4..4a740f99c 100644 --- a/vmhost/contexts/runtime.go +++ b/vmhost/contexts/runtime.go @@ -4,13 +4,15 @@ import ( "bytes" "errors" "fmt" + builtinMath "math" + "math/big" + "runtime/debug" + "github.com/multiversx/mx-chain-core-go/core/check" logger "github.com/multiversx/mx-chain-logger-go" vmcommon "github.com/multiversx/mx-chain-vm-common-go" "github.com/multiversx/mx-chain-vm-go/executor" "github.com/multiversx/mx-chain-vm-go/vmhost" - builtinMath "math" - "math/big" ) var logRuntime = logger.GetOrCreate("vm/runtime") @@ -631,6 +633,11 @@ func (context *runtimeContext) SignalUserError(message string) { // immediately stopping the contract execution. func (context *runtimeContext) SetRuntimeBreakpointValue(value vmhost.BreakpointValue) { context.iTracker.Instance().SetBreakpointValue(uint64(value)) + + if value == vmhost.BreakpointOutOfGas { + debug.PrintStack() + } + logRuntime.Trace("runtime breakpoint set", "breakpoint", value) } diff --git a/vmhost/vmhooks/managedConversions.go b/vmhost/vmhooks/managedConversions.go index e2fb83f8f..ec7d67304 100644 --- a/vmhost/vmhooks/managedConversions.go +++ b/vmhost/vmhooks/managedConversions.go @@ -158,7 +158,7 @@ func readDestinationValueFunctionArguments( } vmInput.function = string(function) - return vmInput, err + return vmInput, nil } func readDestinationValueArguments( @@ -179,7 +179,7 @@ func readDestinationValueArguments( return nil, err } - return vmInput, err + return vmInput, nil } func readDestinationFunctionArguments( @@ -201,7 +201,7 @@ func readDestinationFunctionArguments( } vmInput.function = string(function) - return vmInput, err + return vmInput, nil } func readDestinationArguments( @@ -233,5 +233,5 @@ func readDestinationArguments( return nil, err } - return vmInput, err + return vmInput, nil } From 1ccc655c9f4f9f7ac63d4d240182347c36dace31 Mon Sep 17 00:00:00 2001 From: robertsasu Date: Thu, 15 Aug 2024 09:33:26 +0300 Subject: [PATCH 24/24] delete debug line --- vmhost/contexts/runtime.go | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/vmhost/contexts/runtime.go b/vmhost/contexts/runtime.go index 4a740f99c..96c5379d4 100644 --- a/vmhost/contexts/runtime.go +++ b/vmhost/contexts/runtime.go @@ -4,15 +4,13 @@ import ( "bytes" "errors" "fmt" - builtinMath "math" - "math/big" - "runtime/debug" - "github.com/multiversx/mx-chain-core-go/core/check" logger "github.com/multiversx/mx-chain-logger-go" vmcommon "github.com/multiversx/mx-chain-vm-common-go" "github.com/multiversx/mx-chain-vm-go/executor" "github.com/multiversx/mx-chain-vm-go/vmhost" + builtinMath "math" + "math/big" ) var logRuntime = logger.GetOrCreate("vm/runtime") @@ -633,11 +631,6 @@ func (context *runtimeContext) SignalUserError(message string) { // immediately stopping the contract execution. func (context *runtimeContext) SetRuntimeBreakpointValue(value vmhost.BreakpointValue) { context.iTracker.Instance().SetBreakpointValue(uint64(value)) - - if value == vmhost.BreakpointOutOfGas { - debug.PrintStack() - } - logRuntime.Trace("runtime breakpoint set", "breakpoint", value) }