diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index a48c83897..61c827a6e 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -12,7 +12,7 @@ jobs: strategy: matrix: go-version: [1.20.7] - os: [ubuntu-latest, macos-latest] + os: [ubuntu-latest, macos-13] runs-on: ${{ matrix.os }} steps: - name: Install Go diff --git a/integrationTests/json/scenariosAdderLog_test.go b/integrationTests/json/scenariosAdderLog_test.go index c9fd298b9..26a6c199f 100644 --- a/integrationTests/json/scenariosAdderLog_test.go +++ b/integrationTests/json/scenariosAdderLog_test.go @@ -12,28 +12,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 @@ -57,20 +64,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 @@ -78,12 +90,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 @@ -102,24 +117,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 @@ -127,18 +148,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/mock/context/meteringContextMock.go b/mock/context/meteringContextMock.go index 7fc82f008..bcbc28b3c 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 @@ -151,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 { @@ -159,7 +158,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/context/runtimeContextMock.go b/mock/context/runtimeContextMock.go index a132019f4..7f6771cc6 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 541cf6d3d..f44ca3fbd 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/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/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/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..32d1461f5 100644 --- a/vmhost/contexts/managedType.go +++ b/vmhost/contexts/managedType.go @@ -235,33 +235,54 @@ 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) { +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 := context.useGasBoundedWithBackwardCompatibility(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) + return context.useGasBoundedWithBackwardCompatibility(gasToUse) } // 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 +291,12 @@ func (context *managedTypesContext) ConsumeGasForThisBigIntNumberOfBytes(byteLen if gasToUseBigInt.Cmp(maxGasBigInt) < 0 { gasToUse = gasToUseBigInt.Uint64() } - metering.UseAndTraceGas(gasToUse) + return context.useGasBoundedWithBackwardCompatibility(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 +684,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 +703,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 +719,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 +732,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 +768,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 +786,7 @@ func (context *managedTypesContext) ManagedMapGet(mMapHandle int32, keyHandle in } context.SetBytes(outValueHandle, value) - context.ConsumeGasForBytes(value) - - return nil + return context.ConsumeGasForBytes(value) } // ManagedMapRemove removes the bytes stored as the key handle and returns it in an output value handle @@ -769,7 +797,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..d419df0a8 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" @@ -230,7 +229,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,34 +338,10 @@ 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) - 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) -} - -// 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 @@ -468,17 +443,38 @@ 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 { - if context.GasLeft() < gasToUse { + gasLeft := context.GasLeft() + if gasLeft < gasToUse { + context.useGas(gasLeft) return vmhost.ErrNotEnoughGas } - context.UseGas(gasToUse) + context.useGas(gasToUse) context.traceGas(gasToUse) 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, gasToUse uint64) error { + gasLeft := context.GasLeft() + if gasLeft < gasToUse { + context.useGas(gasLeft) + return vmhost.ErrNotEnoughGas + } + + context.useGas(gasToUse) + context.addToGasTrace(functionName, gasToUse) + 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/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 4e308ed00..fb77b9141 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/runtime.go b/vmhost/contexts/runtime.go index 1d2e85ade..22238a5e5 100644 --- a/vmhost/contexts/runtime.go +++ b/vmhost/contexts/runtime.go @@ -4,14 +4,13 @@ import ( "bytes" "errors" "fmt" - builtinMath "math" - "math/big" - "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") @@ -741,6 +740,11 @@ func (context *runtimeContext) ManagedMapAPIErrorShouldFailExecution() bool { return true } +// UseGasBoundedShouldFailExecution returns true when flag activated +func (context *runtimeContext) UseGasBoundedShouldFailExecution() bool { + return context.host.EnableEpochsHandler().IsFlagEnabled(vmhost.UseGasBoundedShouldFailExecutionFlag) +} + // 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/contexts/storage.go b/vmhost/contexts/storage.go index d4dd22ddc..b6e877865 100644 --- a/vmhost/contexts/storage.go +++ b/vmhost/contexts/storage.go @@ -119,34 +119,46 @@ 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, errGas + } + + errGas = context.useGasForValueIfNeeded(value, usedCache) + if errGas != nil { + return nil, 0, false, errGas + } + 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() if !usedCache { 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 } + if !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. @@ -154,7 +166,10 @@ 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 } @@ -163,15 +178,21 @@ func (context *storageContext) GetStorageFromAddress(address []byte, key []byte) metadata := vmcommon.CodeMetadataFromBytes(userAcc.GetCodeMetadata()) if !metadata.Readable && !isReadFromUserAddress { - context.useExtraGasForKeyIfNeeded(key, false) - return nil, 0, false, nil + errGas := context.useExtraGasForKeyIfNeeded(key, false) + return nil, 0, false, errGas } } 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, errGas + } + errGas = context.useGasForValueIfNeeded(value, usedCache) + if errGas != nil { + return nil, 0, false, errGas + } logStorage.Trace("get from address", "address", address, "key", key, "value", value) return value, trieDepth, usedCache, err diff --git a/vmhost/contexts/storage_test.go b/vmhost/contexts/storage_test.go index ed8ff1f1f..ef7dff1f5 100644 --- a/vmhost/contexts/storage_test.go +++ b/vmhost/contexts/storage_test.go @@ -469,6 +469,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/flags.go b/vmhost/flags.go index b9f4d008b..8d4891cb3 100644 --- a/vmhost/flags.go +++ b/vmhost/flags.go @@ -5,4 +5,10 @@ import "github.com/multiversx/mx-chain-core-go/core" const ( // CryptoOpcodesV2Flag defines the flag that activates the new crypto APIs for RC1.7 CryptoOpcodesV2Flag core.EnableEpochFlag = "CryptoOpcodesV2Flag" + + // MultiESDTNFTTransferAndExecuteByUserFlag defines the flag that activates the enshrined sovereign functions + MultiESDTNFTTransferAndExecuteByUserFlag core.EnableEpochFlag = "MultiESDTNFTTransferAndExecuteByUserFlag" + + // UseGasBoundedShouldFailExecutionFlag defines the flag that activates failing of execution if gas bounded check fails + UseGasBoundedShouldFailExecutionFlag core.EnableEpochFlag = "UseGasBoundedShouldFailExecutionFlag" ) diff --git a/vmhost/hostCore/execution.go b/vmhost/hostCore/execution.go index 9e03ea9ae..0cf57db5a 100644 --- a/vmhost/hostCore/execution.go +++ b/vmhost/hostCore/execution.go @@ -858,7 +858,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. - metering.UseGas(input.GasProvided) + metering.UseGasForContractInit(input.GasProvided) isUpgrade := input.Function == vmhost.UpgradeFunctionName if isUpgrade { @@ -1007,7 +1007,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 @@ -1018,7 +1022,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 } @@ -1043,13 +1047,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 } @@ -1226,7 +1230,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/hostCore/host.go b/vmhost/hostCore/host.go index 8ba4ec040..9b180c862 100644 --- a/vmhost/hostCore/host.go +++ b/vmhost/hostCore/host.go @@ -40,6 +40,8 @@ const internalVMErrors = "internalVMErrors" // allFlags must have all flags used by mx-chain-vm-go in the current version var allFlags = []core.EnableEpochFlag{ vmhost.CryptoOpcodesV2Flag, + vmhost.MultiESDTNFTTransferAndExecuteByUserFlag, + vmhost.UseGasBoundedShouldFailExecutionFlag, } // vmHost implements HostContext interface. 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/hosttest/execution_test.go b/vmhost/hosttest/execution_test.go index f2edcfdd0..79fc50f25 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 @@ -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 @@ -3645,7 +3632,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 +3643,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/hosttest/managedei_test.go b/vmhost/hosttest/managedei_test.go index 171054144..a6d089246 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 @@ -1314,7 +1318,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) diff --git a/vmhost/interface.go b/vmhost/interface.go index f7844c84b..ae122cea0 100644 --- a/vmhost/interface.go +++ b/vmhost/interface.go @@ -155,6 +155,7 @@ type RuntimeContext interface { BigFloatAPIErrorShouldFailExecution() bool ManagedBufferAPIErrorShouldFailExecution() bool ManagedMapAPIErrorShouldFailExecution() bool + UseGasBoundedShouldFailExecution() bool CleanInstance() AddError(err error, otherInfo ...string) @@ -182,11 +183,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 @@ -216,7 +217,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 @@ -274,9 +275,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) @@ -294,6 +292,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) diff --git a/vmhost/vmhooks/baseOps.go b/vmhost/vmhooks/baseOps.go index 52323f273..ba9efeb39 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()) { @@ -225,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 } @@ -245,7 +259,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 +285,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 +310,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 { @@ -524,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()) { @@ -554,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.UseGasBoundedShouldFailExecution()) { + return 1 + } sender := runtime.GetContextAddress() dest, err := context.MemLoad(destOffset, vmhost.AddressLen) @@ -568,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.UseGasBoundedShouldFailExecution()) { + return 1 + } data, err := context.MemLoad(dataOffset, length) if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -685,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 && host.Runtime().UseGasBoundedShouldFailExecution() { + return nil, err + } return &indirectContractCallArguments{ dest: dest, @@ -739,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.UseGasBoundedShouldFailExecution()) { + return 1 + } callArgs, err := context.extractIndirectContractCallArgumentsWithValue( host, destOffset, valueOffset, functionOffset, functionLength, numArguments, argumentsLengthOffset, dataOffset) @@ -771,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.UseGasBoundedShouldFailExecution()) { + return 1 + } sender := runtime.GetContextAddress() - var err error var contractCallInput *vmcommon.ContractCallInput - if len(function) > 0 { contractCallInput, err = prepareIndirectContractCallInput( host, @@ -820,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.UseGasBoundedShouldFailExecution()) { + return 1 + } + err = output.Transfer(dest, sender, uint64(gasLimit), 0, value, nil, []byte(data), vm.DirectCall) if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { return 1 @@ -921,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.UseGasBoundedShouldFailExecution()) { + return 1 + } transferArgs, actualLen, err := context.getArgumentsFromMemory( host, @@ -935,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.UseGasBoundedShouldFailExecution()) { + return 1 + } transfers := make([]*vmcommon.ESDTTransfer, numTokenTransfers) for i := int32(0); i < numTokenTransfers; i++ { @@ -992,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.UseGasBoundedShouldFailExecution()) { + return 1 + } transfer := &vmcommon.ESDTTransfer{ ESDTValue: callArgs.value, @@ -1030,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.UseGasBoundedShouldFailExecution()) { + return 1 + } sender := runtime.GetContextAddress() @@ -1106,7 +1161,10 @@ func TransferESDTNFTExecuteByUserWithTypedArgs( output := host.Output() gasToUse := metering.GasSchedule().BaseOpsAPICost.TransferValue * uint64(len(transfers)) - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.SyncExecAPIErrorShouldFailExecution()) { + return 1 + } sender := runtime.GetContextAddress() @@ -1272,7 +1330,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.UseGasBoundedShouldFailExecution()) { + return 1 + } asyncCall := &vmhost.AsyncCall{ Status: vmhost.AsyncCallPending, @@ -1287,11 +1348,14 @@ func CreateAsyncCallWithTypedArgs(host vmhost.VMHost, } if asyncCall.HasDefinedAnyCallback() { - gasToUse := metering.GasSchedule().BaseOpsAPICost.SetAsyncCallback - metering.UseAndTraceGas(gasToUse) + gasToUse = metering.GasSchedule().BaseOpsAPICost.SetAsyncCallback + err = metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { + return 1 + } } - err := async.RegisterAsyncCall("", asyncCall) + err = async.RegisterAsyncCall("", asyncCall) if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { return 1 } @@ -1315,7 +1379,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.UseGasBoundedShouldFailExecution()) { + return 1 + } callbackNameBytes, err := context.MemLoad(callback, callbackLength) if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -1358,7 +1425,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.UseGasBoundedShouldFailExecution()) { + return + } value, err := context.MemLoad(valueOffset, vmhost.BalanceLen) if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -1381,9 +1451,15 @@ func (context *VMHooksImpl) UpgradeContract( argumentsLengthOffset, dataOffset, ) + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { + return + } gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(actualLen)) - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { + return + } if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { return @@ -1396,7 +1472,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.UseGasBoundedShouldFailExecution()) { + return + } upgradeContract(host, calledSCAddress, code, codeMetadata, value, data, gasLimit) } @@ -1419,7 +1498,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.UseGasBoundedShouldFailExecution()) { + return + } value, err := context.MemLoad(valueOffset, vmhost.BalanceLen) if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -1442,9 +1524,15 @@ func (context *VMHooksImpl) UpgradeFromSourceContract( argumentsLengthOffset, dataOffset, ) + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { + return + } gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(actualLen)) - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { + return + } if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { return @@ -1547,7 +1635,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.UseGasBoundedShouldFailExecution()) { + return + } data, actualLen, err := context.getArgumentsFromMemory( host, @@ -1555,9 +1646,15 @@ func (context *VMHooksImpl) DeleteContract( argumentsLengthOffset, dataOffset, ) + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { + return + } gasToUse = math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, uint64(actualLen)) - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { + return + } if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { return @@ -1631,7 +1728,10 @@ func (context *VMHooksImpl) AsyncCall( gasSchedule := metering.GasSchedule() gasToUse := gasSchedule.BaseOpsAPICost.AsyncCallStep - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { + return + } calledSCAddress, err := context.MemLoad(destOffset, vmhost.AddressLen) if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -1644,7 +1744,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.UseGasBoundedShouldFailExecution()) { + return + } data, err := context.MemLoad(dataOffset, length) if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -1668,7 +1771,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 { @@ -1686,7 +1792,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 { @@ -1694,7 +1803,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 } @@ -1709,10 +1818,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 } @@ -1727,7 +1839,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)) @@ -1781,7 +1896,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()) { @@ -1964,7 +2082,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()) { @@ -1996,7 +2117,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()) { @@ -2056,11 +2180,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 } @@ -2073,7 +2200,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 { @@ -2093,12 +2223,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 } @@ -2123,7 +2256,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 @@ -2133,7 +2269,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 } @@ -2158,7 +2294,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 @@ -2166,7 +2305,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 } @@ -2190,7 +2329,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) @@ -2256,7 +2398,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 { @@ -2272,7 +2417,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)) } @@ -2298,7 +2446,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) @@ -2311,7 +2462,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 } @@ -2333,7 +2484,10 @@ func (context *VMHooksImpl) IsReservedFunctionName(nameHandle int32) int32 { metering := host.Metering() gasToUse := metering.GasSchedule().BaseOpsAPICost.IsReservedFunctionName - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return -1 + } name, err := managedTypes.GetBytes(nameHandle) if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -2363,7 +2517,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) - metering.UseGasAndAddTracedGas(writeLogName, gasToUse) if numTopics < 0 || dataLength < 0 { err := vmhost.ErrNegativeLength @@ -2371,6 +2524,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 @@ -2422,7 +2580,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}) } @@ -2434,7 +2595,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()) } @@ -2446,7 +2610,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()) } @@ -2458,7 +2625,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()) } @@ -2470,7 +2640,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()) } @@ -2483,10 +2656,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()) } @@ -2498,10 +2674,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()) } @@ -2512,7 +2691,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()) } @@ -2524,7 +2706,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()) } @@ -2536,7 +2721,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()) } @@ -2548,7 +2736,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()) } @@ -2561,10 +2752,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()) } @@ -2580,7 +2774,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 @@ -2666,7 +2859,10 @@ func ExecuteOnSameContextWithTypedArgs( metering := host.Metering() gasToUse := metering.GasSchedule().BaseOpsAPICost.ExecuteOnSameContext - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { + return -1 + } sender := runtime.GetContextAddress() @@ -2770,7 +2966,10 @@ func ExecuteOnDestContextWithTypedArgs( metering := host.Metering() gasToUse := metering.GasSchedule().BaseOpsAPICost.ExecuteOnDestContext - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { + return -1 + } sender := runtime.GetContextAddress() @@ -2866,7 +3065,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() @@ -2948,7 +3150,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.UseGasBoundedShouldFailExecution()) { + return -1 + } sender := runtime.GetContextAddress() value, err := context.MemLoad(valueOffset, vmhost.BalanceLen) @@ -2972,11 +3177,13 @@ 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) - - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + err = metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return 1 } @@ -3013,7 +3220,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.UseGasBoundedShouldFailExecution()) { + return 1 + } value, err := context.MemLoad(valueOffset, vmhost.BalanceLen) if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -3036,11 +3246,13 @@ 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) - - if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + err = metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { return 1 } @@ -3127,7 +3339,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)) @@ -3141,7 +3356,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 { @@ -3176,7 +3394,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 { @@ -3200,7 +3421,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() } @@ -3218,7 +3442,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)) { @@ -3233,9 +3460,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()) } @@ -3246,9 +3476,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()) } @@ -3259,9 +3492,12 @@ func (context *VMHooksImpl) GetPrevTxHash(dataOffset executor.MemPtr) { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetPrevTxHash - metering.UseGasAndAddTracedGas(getPrevTxHashName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(getPrevTxHashName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } - err := context.MemStore(dataOffset, runtime.GetPrevTxHash()) + err = context.MemStore(dataOffset, runtime.GetPrevTxHash()) _ = context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) } diff --git a/vmhost/vmhooks/bigFloatOps.go b/vmhost/vmhooks/bigFloatOps.go index 3fba2993f..647bb4f4f 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()) { @@ -433,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()) { @@ -470,7 +515,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()) { @@ -478,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 } @@ -497,7 +549,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()) { @@ -505,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 } @@ -524,7 +583,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()) { @@ -532,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. @@ -544,7 +610,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 +631,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,13 +655,21 @@ 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) 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) } @@ -601,7 +682,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 +702,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 c2dada30e..e28b5447f 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)) } @@ -361,14 +403,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 +432,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) @@ -404,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()) { @@ -424,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() { @@ -442,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) @@ -457,14 +522,22 @@ 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) 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) } @@ -477,14 +550,22 @@ 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) 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) } @@ -497,14 +578,21 @@ 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) 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) } @@ -518,14 +606,22 @@ 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) 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 @@ -542,14 +638,22 @@ 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) 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 @@ -566,14 +670,22 @@ 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) 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 @@ -590,14 +702,22 @@ 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) 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 @@ -614,14 +734,22 @@ 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) 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 @@ -638,7 +766,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) @@ -649,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()) @@ -669,13 +807,21 @@ 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()) { 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 @@ -693,14 +839,22 @@ 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) 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) } @@ -713,14 +867,22 @@ 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) 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) } @@ -733,13 +895,21 @@ 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()) { return -2 } - managedType.ConsumeGasForBigIntCopy(a) + + err = managedType.ConsumeGasForBigIntCopy(a) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return -2 + } + return int32(a.Sign()) } @@ -752,13 +922,21 @@ 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()) { return -2 } - managedType.ConsumeGasForBigIntCopy(a, b) + + err = managedType.ConsumeGasForBigIntCopy(a, b) + if context.WithFault(err, runtime.BigIntAPIErrorShouldFailExecution()) { + return -2 + } + return int32(a.Cmp(b)) } @@ -771,14 +949,22 @@ 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) 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 @@ -795,14 +981,22 @@ 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) 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 @@ -819,14 +1013,22 @@ 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) 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 @@ -843,14 +1045,22 @@ 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) 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 @@ -867,20 +1077,32 @@ 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) 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. @@ -892,21 +1114,32 @@ 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) 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. @@ -919,17 +1152,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. @@ -942,17 +1182,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. @@ -968,7 +1215,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()) { @@ -976,7 +1226,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)) } diff --git a/vmhost/vmhooks/cryptoei.go b/vmhost/vmhooks/cryptoei.go index 83a4686ac..5415f34b7 100644 --- a/vmhost/vmhooks/cryptoei.go +++ b/vmhost/vmhooks/cryptoei.go @@ -56,7 +56,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()) { @@ -85,13 +88,20 @@ 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()) { 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 { @@ -113,7 +123,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()) { @@ -142,13 +155,20 @@ 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()) { 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 { @@ -170,7 +190,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()) { @@ -205,13 +228,20 @@ 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()) { 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 { @@ -238,7 +268,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()) { @@ -246,7 +279,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()) { @@ -281,7 +317,7 @@ func (context *VMHooksImpl) ManagedVerifyBLS( func useGasForCryptoVerify( metering vmhost.MeteringContext, sigVerificationType string, -) { +) error { metering.StartGasTracing(sigVerificationType) gasToUse := metering.GasSchedule().CryptoAPICost.VerifyBLS @@ -297,7 +333,8 @@ func useGasForCryptoVerify( case verifyBLSAggregatedSignature: gasToUse = metering.GasSchedule().CryptoAPICost.VerifyBLSMultiSig } - metering.UseAndTraceGas(gasToUse) + + return metering.UseGasBounded(gasToUse) } // ManagedVerifyBLSWithHost VMHooks implementation. @@ -312,25 +349,40 @@ func ManagedVerifyBLSWithHost( metering := host.Metering() managedType := host.ManagedTypes() crypto := host.Crypto() - useGasForCryptoVerify(metering, sigVerificationType) + err := useGasForCryptoVerify(metering, sigVerificationType) + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { + return 1 + } keyBytes, err := managedType.GetBytes(keyHandle) 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 := vmhost.ErrInvalidArgument switch sigVerificationType { @@ -370,7 +422,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()) { @@ -378,7 +433,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()) { @@ -420,25 +478,40 @@ 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()) { 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 { @@ -465,7 +538,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()) @@ -478,7 +554,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()) { @@ -536,25 +615,40 @@ func ManagedVerifyCustomSecp256k1WithHost( managedType := host.ManagedTypes() crypto := host.Crypto() - useGasForCryptoVerify(metering, verifyCryptoFunc) + err := useGasForCryptoVerify(metering, verifyCryptoFunc) + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { + return 1 + } keyBytes, err := managedType.GetBytes(keyHandle) 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 := vmhost.ErrInvalidArgument switch verifyCryptoFunc { @@ -629,7 +723,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()) { @@ -670,7 +767,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()) { @@ -710,7 +810,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()) { @@ -738,7 +841,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(err, runtime.CryptoAPIErrorShouldFailExecution()) { + return + } xResultAdd, yResultAdd := ec.Add(x1, y1, x2, y2) xResult.Set(xResultAdd) yResult.Set(yResultAdd) @@ -764,7 +870,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()) { @@ -782,7 +891,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) @@ -807,7 +919,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()) { @@ -820,7 +935,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 } @@ -854,7 +973,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()) { @@ -909,7 +1031,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) } @@ -934,7 +1059,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) { @@ -975,7 +1103,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()) { @@ -1036,7 +1167,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) } @@ -1071,7 +1205,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()) @@ -1158,7 +1296,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 { @@ -1176,7 +1317,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 @@ -1257,7 +1401,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 { @@ -1275,7 +1422,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 @@ -1301,7 +1451,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()) { @@ -1349,7 +1502,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 { @@ -1384,7 +1540,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) { @@ -1417,7 +1576,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()) { @@ -1465,7 +1627,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()) { @@ -1500,7 +1665,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) { @@ -1590,7 +1758,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 { @@ -1601,7 +1772,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) @@ -1623,7 +1798,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()) @@ -1665,7 +1843,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()) { @@ -1699,7 +1880,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 { @@ -1717,7 +1901,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 { @@ -1735,7 +1922,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 88db1d5ef..f7b3ee650 100644 --- a/vmhost/vmhooks/manBufOps.go +++ b/vmhost/vmhooks/manBufOps.go @@ -45,7 +45,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() } @@ -58,7 +61,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()) { @@ -76,7 +82,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 { @@ -96,13 +105,19 @@ 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()) { 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()) { @@ -126,13 +141,19 @@ 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()) { 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 @@ -163,13 +184,19 @@ 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()) { 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 @@ -180,7 +207,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 } @@ -194,19 +224,28 @@ 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()) { 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 @@ -224,13 +263,21 @@ 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()) { return 1 } - managedType.ConsumeGasForBytes(data) + + err = managedType.ConsumeGasForBytes(data) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } + managedType.SetBytes(mBufferHandle, data) return 0 @@ -261,7 +308,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()) { @@ -278,7 +328,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()) { @@ -310,13 +363,20 @@ 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()) { return 1 } - managedType.ConsumeGasForBytes(dataBufferBytes) + + err = managedType.ConsumeGasForBytes(dataBufferBytes) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return 1 + } isSuccess := managedType.AppendBytes(accumulatorHandle, dataBufferBytes) if !isSuccess { @@ -336,7 +396,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()) { @@ -350,7 +413,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 } @@ -363,7 +429,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()) { @@ -384,7 +453,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()) { @@ -405,7 +477,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()) { @@ -425,7 +500,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()) { @@ -444,13 +522,16 @@ func (context *VMHooksImpl) MBufferToSmallIntUnsigned(mBufferHandle int32) int64 metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().ManagedBufferAPICost.MBufferToSmallIntUnsigned - metering.UseGasAndAddTracedGas(mBufferToSmallIntUnsignedName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(mBufferToSmallIntUnsignedName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return 0 + } - bytes, err := managedType.GetBytes(mBufferHandle) + data, err := managedType.GetBytes(mBufferHandle) if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { return 1 } - bigInt := big.NewInt(0).SetBytes(bytes) + bigInt := big.NewInt(0).SetBytes(data) if !bigInt.IsUint64() { _ = context.WithFault(vmhost.ErrBytesExceedUint64, runtime.BaseOpsErrorShouldFailExecution()) return 0 @@ -466,13 +547,16 @@ func (context *VMHooksImpl) MBufferToSmallIntSigned(mBufferHandle int32) int64 { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().ManagedBufferAPICost.MBufferToSmallIntSigned - metering.UseGasAndAddTracedGas(mBufferToSmallIntSignedName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(mBufferToSmallIntSignedName, gasToUse) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return 0 + } - bytes, err := managedType.GetBytes(mBufferHandle) + data, err := managedType.GetBytes(mBufferHandle) if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { return 1 } - bigInt := twos.SetBytes(big.NewInt(0), bytes) + bigInt := twos.SetBytes(big.NewInt(0), data) if !bigInt.IsInt64() { _ = context.WithFault(vmhost.ErrBytesExceedInt64, runtime.BaseOpsErrorShouldFailExecution()) return 0 @@ -487,7 +571,10 @@ func (context *VMHooksImpl) MBufferFromSmallIntUnsigned(mBufferHandle int32, val metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().ManagedBufferAPICost.MBufferFromSmallIntUnsigned - metering.UseGasAndAddTracedGas(mBufferFromSmallIntUnsignedName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(mBufferFromSmallIntUnsignedName, gasToUse) + if context.WithFault(err, context.GetRuntimeContext().BaseOpsErrorShouldFailExecution()) { + return + } valueBytes := big.NewInt(0).SetUint64(uint64(value)).Bytes() managedType.SetBytes(mBufferHandle, valueBytes) @@ -500,7 +587,10 @@ func (context *VMHooksImpl) MBufferFromSmallIntSigned(mBufferHandle int32, value metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().ManagedBufferAPICost.MBufferFromSmallIntSigned - metering.UseGasAndAddTracedGas(mBufferFromSmallIntSignedName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(mBufferFromSmallIntSignedName, gasToUse) + if context.WithFault(err, context.GetRuntimeContext().BaseOpsErrorShouldFailExecution()) { + return + } valueBytes := big.NewInt(0).SetInt64(value).Bytes() managedType.SetBytes(mBufferHandle, valueBytes) @@ -515,14 +605,21 @@ 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()) { 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 @@ -556,7 +653,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()) { @@ -567,7 +667,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) @@ -583,7 +687,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()) { @@ -669,7 +776,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 { @@ -690,7 +800,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()) { @@ -723,11 +836,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/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/managedConversions.go b/vmhost/vmhooks/managedConversions.go index 193333435..ec7d67304 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 { @@ -27,14 +28,23 @@ func readESDTTransfer( if err != nil { return nil, err } - managedType.ConsumeGasForBytes(tokenIdentifier) + + err = managedType.ConsumeGasForBytes(tokenIdentifier) + if err != nil && runtime.UseGasBoundedShouldFailExecution() { + 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 && runtime.UseGasBoundedShouldFailExecution() { + return nil, err + } tokenType := core.Fungible if nonce > 0 { @@ -57,13 +67,18 @@ func readESDTTransfer( // Total: 16 bytes. func readESDTTransfers( managedType vmhost.ManagedTypesContext, + runtime vmhost.RuntimeContext, managedVecHandle int32, ) ([]*vmcommon.ESDTTransfer, error) { managedVecBytes, err := managedType.GetBytes(managedVecHandle) if err != nil { return nil, err } - managedType.ConsumeGasForBytes(managedVecBytes) + + err = managedType.ConsumeGasForBytes(managedVecBytes) + if err != nil && runtime.UseGasBoundedShouldFailExecution() { + return nil, err + } if len(managedVecBytes)%esdtTransferLen != 0 { return nil, errors.New("invalid managed vector of ESDT transfers") @@ -72,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 } @@ -143,7 +158,7 @@ func readDestinationValueFunctionArguments( } vmInput.function = string(function) - return vmInput, err + return vmInput, nil } func readDestinationValueArguments( @@ -164,7 +179,7 @@ func readDestinationValueArguments( return nil, err } - return vmInput, err + return vmInput, nil } func readDestinationFunctionArguments( @@ -186,7 +201,7 @@ func readDestinationFunctionArguments( } vmInput.function = string(function) - return vmInput, err + return vmInput, nil } func readDestinationArguments( @@ -213,7 +228,10 @@ func readDestinationArguments( vmInput.arguments = data gasToUse := math.MulUint64(metering.GasSchedule().BaseOperationCost.DataCopyPerByte, actualLen) - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if err != nil && host.Runtime().UseGasBoundedShouldFailExecution() { + return nil, err + } - return vmInput, err + return vmInput, nil } diff --git a/vmhost/vmhooks/managedei.go b/vmhost/vmhooks/managedei.go index 03aa8bf19..5543bd876 100644 --- a/vmhost/vmhooks/managedei.go +++ b/vmhost/vmhooks/managedei.go @@ -56,7 +56,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() @@ -72,7 +75,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()) { @@ -90,7 +96,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) ManagedGetOriginalCallerAddr(destinationHandle int32 metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetCaller - metering.UseGasAndAddTracedGas(managedCallerName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(managedCallerName, gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return + } caller := runtime.GetVMInput().OriginalCallerAddr managedType.SetBytes(destinationHandle, caller) @@ -118,7 +130,10 @@ func (context *VMHooksImpl) ManagedGetRelayerAddr(destinationHandle int32) { metering := context.GetMeteringContext() gasToUse := metering.GasSchedule().BaseOpsAPICost.GetCaller - metering.UseGasAndAddTracedGas(managedCallerName, gasToUse) + err := metering.UseGasBoundedAndAddTracedGas(managedCallerName, gasToUse) + if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { + return + } caller := runtime.GetVMInput().RelayerAddr managedType.SetBytes(destinationHandle, caller) @@ -133,18 +148,24 @@ 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.UseGasBoundedShouldFailExecution()) { + return + } errBytes, err := managedType.GetBytes(errHandle) if context.WithFault(err, runtime.ManagedBufferAPIErrorShouldFailExecution()) { return } - managedType.ConsumeGasForBytes(errBytes) + + err = managedType.ConsumeGasForBytes(errBytes) + 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 } @@ -172,7 +193,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 @@ -180,7 +206,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}) } @@ -193,7 +222,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()) } @@ -206,7 +238,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()) } @@ -219,7 +254,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()) } @@ -232,7 +270,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()) } @@ -246,7 +287,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 { @@ -265,11 +309,17 @@ 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) - managedType.ConsumeGasForBytes(multiCallBytes) + err = managedType.ConsumeGasForBytes(multiCallBytes) + if context.WithFault(err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } managedType.SetBytes(multiCallValueHandle, multiCallBytes) } @@ -281,11 +331,17 @@ 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) - managedType.ConsumeGasForBytes(multiCallBytes) + err = managedType.ConsumeGasForBytes(multiCallBytes) + if context.WithFault(err, context.GetRuntimeContext().BaseOpsErrorShouldFailExecution()) { + return + } managedType.SetBytes(esdtTransfersValueHandle, multiCallBytes) egldValue := managedType.GetBigIntOrCreate(egldValueHandle) @@ -301,7 +357,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 { @@ -354,7 +413,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 { @@ -379,17 +441,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, err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } managedType.SetBytes(nameHandle, esdtToken.TokenMetaData.Name) - managedType.ConsumeGasForBytes(esdtToken.TokenMetaData.Name) + err = managedType.ConsumeGasForBytes(esdtToken.TokenMetaData.Name) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } managedType.SetBytes(attributesHandle, esdtToken.TokenMetaData.Attributes) - managedType.ConsumeGasForBytes(esdtToken.TokenMetaData.Attributes) + err = managedType.ConsumeGasForBytes(esdtToken.TokenMetaData.Attributes) + if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } managedType.SetBytes(creatorHandle, esdtToken.TokenMetaData.Creator) - managedType.ConsumeGasForBytes(esdtToken.TokenMetaData.Creator) + err = managedType.ConsumeGasForBytes(esdtToken.TokenMetaData.Creator) + if WithFaultAndHost(host, err, 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, err, runtime.BaseOpsErrorShouldFailExecution()) { + return + } } } @@ -424,7 +501,10 @@ func ManagedAsyncCallWithHost( gasSchedule := metering.GasSchedule() gasToUse := gasSchedule.BaseOpsAPICost.AsyncCallStep - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { + return + } vmInput, err := readDestinationFunctionArguments(host, destHandle, functionHandle, argumentsHandle) if WithFaultAndHost(host, err, host.Runtime().BaseOpsErrorShouldFailExecution()) { @@ -440,7 +520,10 @@ func ManagedAsyncCallWithHost( } gasToUse = math.MulUint64(gasSchedule.BaseOperationCost.DataCopyPerByte, uint64(len(data))) - metering.UseAndTraceGas(gasToUse) + err = metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { + return + } err = async.RegisterLegacyAsyncCall(vmInput.destination, []byte(data), value.Bytes()) if errors.Is(err, vmhost.ErrNotEnoughGas) { @@ -532,7 +615,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()) { @@ -560,7 +646,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.UseGasBoundedShouldFailExecution()) { + return + } vmInput, err := readDestinationValueArguments(host, destHandle, valueHandle, argumentsHandle) if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -588,7 +677,10 @@ func (context *VMHooksImpl) ManagedUpgradeFromSourceContract( gas, codeMetadata, ) - setReturnDataIfExists(host, lenReturnData, resultHandle) + err = setReturnDataIfExists(host, lenReturnData, resultHandle) + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { + return + } } // ManagedUpgradeContract VMHooks implementation. @@ -609,7 +701,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.UseGasBoundedShouldFailExecution()) { + return + } vmInput, err := readDestinationValueArguments(host, destHandle, valueHandle, argumentsHandle) if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -633,7 +728,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.UseGasBoundedShouldFailExecution()) { + return + } } // ManagedDeleteContract VMHooks implementation. @@ -664,7 +762,10 @@ func ManagedDeleteContractWithHost( metering.StartGasTracing(deleteContractName) gasToUse := metering.GasSchedule().BaseOpsAPICost.CreateContract - metering.UseAndTraceGas(gasToUse) + err := metering.UseGasBounded(gasToUse) + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { + return + } calledSCAddress, err := managedType.GetBytes(destHandle) if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -702,7 +803,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.UseGasBoundedShouldFailExecution()) { + return -1 + } vmInput, err := readDestinationValueArguments(host, addressHandle, valueHandle, argumentsHandle) if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -729,7 +833,10 @@ func (context *VMHooksImpl) ManagedDeployFromSourceContract( } managedType.SetBytes(resultAddressHandle, newAddress) - setReturnDataIfExists(host, lenReturnData, resultHandle) + err = setReturnDataIfExists(host, lenReturnData, resultHandle) + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { + return 1 + } return 0 } @@ -752,7 +859,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.UseGasBoundedShouldFailExecution()) { + return -1 + } sender := runtime.GetContextAddress() value, err := managedType.GetBigInt(valueHandle) @@ -766,7 +876,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.UseGasBoundedShouldFailExecution()) { + return -1 + } codeMetadata, err := managedType.GetBytes(codeMetadataHandle) if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { @@ -785,7 +898,10 @@ func (context *VMHooksImpl) ManagedCreateContract( } managedType.SetBytes(resultAddressHandle, newAddress) - setReturnDataIfExists(host, lenReturnData, resultHandle) + err = setReturnDataIfExists(host, lenReturnData, resultHandle) + if WithFaultAndHost(host, err, runtime.UseGasBoundedShouldFailExecution()) { + return 1 + } return 0 } @@ -794,13 +910,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) - } else { - host.ManagedTypes().SetBytes(resultHandle, make([]byte, 0)) + return host.ManagedTypes().WriteManagedVecOfManagedBuffers(returnData[oldLen:], resultHandle) } + + host.ManagedTypes().SetBytes(resultHandle, make([]byte, 0)) + return nil } // ManagedExecuteReadOnly VMHooks implementation. @@ -829,7 +946,11 @@ func (context *VMHooksImpl) ManagedExecuteReadOnly( vmInput.destination, vmInput.arguments, ) - setReturnDataIfExists(host, lenReturnData, resultHandle) + err = setReturnDataIfExists(host, lenReturnData, resultHandle) + if WithFaultAndHost(host, err, host.Runtime().UseGasBoundedShouldFailExecution()) { + return -1 + } + return returnVal } @@ -861,7 +982,11 @@ func (context *VMHooksImpl) ManagedExecuteOnSameContext( vmInput.destination, vmInput.arguments, ) - setReturnDataIfExists(host, lenReturnData, resultHandle) + err = setReturnDataIfExists(host, lenReturnData, resultHandle) + if WithFaultAndHost(host, err, host.Runtime().UseGasBoundedShouldFailExecution()) { + return -1 + } + return returnVal } @@ -893,7 +1018,11 @@ func (context *VMHooksImpl) ManagedExecuteOnDestContext( vmInput.destination, vmInput.arguments, ) - setReturnDataIfExists(host, lenReturnData, resultHandle) + err = setReturnDataIfExists(host, lenReturnData, resultHandle) + if WithFaultAndHost(host, err, host.Runtime().UseGasBoundedShouldFailExecution()) { + return -1 + } + return returnVal } @@ -917,7 +1046,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 } @@ -963,7 +1092,7 @@ func (context *VMHooksImpl) ManagedMultiTransferESDTNFTExecuteByUser( return -1 } - transfers, err := readESDTTransfers(managedType, tokenTransfersHandle) + transfers, err := readESDTTransfers(managedType, runtime, tokenTransfersHandle) if WithFaultAndHost(host, err, runtime.BaseOpsErrorShouldFailExecution()) { return -1 } @@ -1028,7 +1157,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 { @@ -1068,7 +1200,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 { @@ -1097,7 +1232,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 { @@ -1125,7 +1263,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 { @@ -1150,10 +1291,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 { @@ -1185,7 +1332,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 { 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()) { diff --git a/vmhost/vmhooks/vmHooksImpl.go b/vmhost/vmhooks/vmHooksImpl.go index 7cb0d9c50..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.UseGas(metering.GasLeft()) - runtime.FailExecution(err) - } + runtime := host.Runtime() + metering := host.Metering() + _ = metering.UseGasBounded(metering.GasLeft()) + runtime.FailExecution(err) return true }